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.

1691 lines
51 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #ifndef PLATFORM_H
  9. #define PLATFORM_H
  10. #if defined(__x86_64__) || defined(_WIN64)
  11. #define PLATFORM_64BITS 1
  12. #endif
  13. #if defined(__GCC__) || defined(__GNUC__)
  14. #define COMPILER_GCC 1
  15. #endif
  16. #ifdef __clang__
  17. #define COMPILER_CLANG 1
  18. #endif
  19. #if defined( _X360 )
  20. #define NO_STEAM
  21. #define NO_VOICE
  22. // for the 360, the ppc platform and the rtos are tightly coupled
  23. // setup the 360 environment here !once! for much less leaf module include wackiness
  24. // these are critical order and purposely appear *before* anything else
  25. #define _XBOX
  26. #include <xtl.h>
  27. #include <xaudio2.h>
  28. #include <xbdm.h>
  29. #include <Xgraphics.h>
  30. #include <xui.h>
  31. #include <pmcpbsetup.h>
  32. #include <XMAHardwareAbstraction.h>
  33. #undef _XBOX
  34. #endif
  35. #define __STDC_LIMIT_MACROS
  36. #include <stdint.h>
  37. #include "wchartypes.h"
  38. #include "basetypes.h"
  39. #include "tier0/valve_off.h"
  40. #ifdef _DEBUG
  41. #if !defined( PLAT_COMPILE_TIME_ASSERT )
  42. #define PLAT_COMPILE_TIME_ASSERT( pred ) switch(0){case 0:case pred:;}
  43. #endif
  44. #else
  45. #if !defined( PLAT_COMPILE_TIME_ASSERT )
  46. #define PLAT_COMPILE_TIME_ASSERT( pred )
  47. #endif
  48. #endif
  49. #ifdef _WIN32
  50. #pragma once
  51. #endif
  52. // feature enables
  53. #define NEW_SOFTWARE_LIGHTING
  54. #ifdef POSIX
  55. // need this for _alloca
  56. #include <alloca.h>
  57. #include <unistd.h>
  58. #include <signal.h>
  59. #include <time.h>
  60. #endif
  61. #include <malloc.h>
  62. #include <new>
  63. // need this for memset
  64. #include <string.h>
  65. #include "tier0/valve_minmax_on.h" // GCC 4.2.2 headers screw up our min/max defs.
  66. #ifdef _RETAIL
  67. #define IsRetail() true
  68. #else
  69. #define IsRetail() false
  70. #endif
  71. #ifdef _DEBUG
  72. #define IsRelease() false
  73. #define IsDebug() true
  74. #else
  75. #define IsRelease() true
  76. #define IsDebug() false
  77. #endif
  78. // Deprecating, infavor of IsX360() which will revert to IsXbox()
  79. // after confidence of xbox 1 code flush
  80. #define IsXbox() false
  81. #ifdef _WIN32
  82. #define IsLinux() false
  83. #define IsOSX() false
  84. #define IsPosix() false
  85. #define PLATFORM_WINDOWS 1 // Windows PC or Xbox 360
  86. #ifndef _X360
  87. #define IsWindows() true
  88. #define IsPC() true
  89. #define IsConsole() false
  90. #define IsX360() false
  91. #define IsPS3() false
  92. #define IS_WINDOWS_PC
  93. #define PLATFORM_WINDOWS_PC 1 // Windows PC
  94. #ifdef _WIN64
  95. #define IsPlatformWindowsPC64() true
  96. #define IsPlatformWindowsPC32() false
  97. #define PLATFORM_WINDOWS_PC64 1
  98. #else
  99. #define IsPlatformWindowsPC64() false
  100. #define IsPlatformWindowsPC32() true
  101. #define PLATFORM_WINDOWS_PC32 1
  102. #endif
  103. #else
  104. #define PLATFORM_X360 1
  105. #ifndef _CONSOLE
  106. #define _CONSOLE
  107. #endif
  108. #define IsWindows() false
  109. #define IsPC() false
  110. #define IsConsole() true
  111. #define IsX360() true
  112. #define IsPS3() false
  113. #endif
  114. // Adding IsPlatformOpenGL() to help fix a bunch of code that was using IsPosix() to infer if the DX->GL translation layer was being used.
  115. #if defined( DX_TO_GL_ABSTRACTION )
  116. #define IsPlatformOpenGL() true
  117. #else
  118. #define IsPlatformOpenGL() false
  119. #endif
  120. #elif defined(POSIX)
  121. #define IsPC() true
  122. #define IsWindows() false
  123. #define IsConsole() false
  124. #define IsX360() false
  125. #define IsPS3() false
  126. #if defined( LINUX )
  127. #define IsLinux() true
  128. #else
  129. #define IsLinux() false
  130. #endif
  131. #if defined( OSX )
  132. #define IsOSX() true
  133. #else
  134. #define IsOSX() false
  135. #endif
  136. #define IsPosix() true
  137. #define IsPlatformOpenGL() true
  138. #else
  139. #error
  140. #endif
  141. typedef unsigned char uint8;
  142. typedef signed char int8;
  143. #if defined( _WIN32 )
  144. typedef __int16 int16;
  145. typedef unsigned __int16 uint16;
  146. typedef __int32 int32;
  147. typedef unsigned __int32 uint32;
  148. typedef __int64 int64;
  149. typedef unsigned __int64 uint64;
  150. #ifdef PLATFORM_64BITS
  151. typedef __int64 intp; // intp is an integer that can accomodate a pointer
  152. typedef unsigned __int64 uintp; // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *)
  153. #else
  154. typedef __int32 intp;
  155. typedef unsigned __int32 uintp;
  156. #endif
  157. #if defined( _X360 )
  158. #ifdef __m128
  159. #undef __m128
  160. #endif
  161. #define __m128 __vector4
  162. #endif
  163. // Use this to specify that a function is an override of a virtual function.
  164. // This lets the compiler catch cases where you meant to override a virtual
  165. // function but you accidentally changed the function signature and created
  166. // an overloaded function. Usage in function declarations is like this:
  167. // int GetData() const OVERRIDE;
  168. #define OVERRIDE override
  169. #else // _WIN32
  170. typedef short int16;
  171. typedef unsigned short uint16;
  172. typedef int int32;
  173. typedef unsigned int uint32;
  174. typedef long long int64;
  175. typedef unsigned long long uint64;
  176. #ifdef PLATFORM_64BITS
  177. typedef long long intp;
  178. typedef unsigned long long uintp;
  179. #else
  180. typedef int intp;
  181. typedef unsigned int uintp;
  182. #endif
  183. typedef void *HWND;
  184. // Avoid redefinition warnings if a previous header defines this.
  185. #undef OVERRIDE
  186. #if __cplusplus >= 201103L
  187. #define OVERRIDE override
  188. #if defined(__clang__)
  189. // warning: 'override' keyword is a C++11 extension [-Wc++11-extensions]
  190. // Disabling this warning is less intrusive than enabling C++11 extensions
  191. #pragma GCC diagnostic ignored "-Wc++11-extensions"
  192. #endif
  193. #else
  194. #define OVERRIDE
  195. #endif
  196. #endif // else _WIN32
  197. //-----------------------------------------------------------------------------
  198. // Set up platform type defines.
  199. //-----------------------------------------------------------------------------
  200. #if defined( PLATFORM_X360 ) || defined( _PS3 )
  201. #if !defined( _GAMECONSOLE )
  202. #define _GAMECONSOLE
  203. #endif
  204. #define IsPC() false
  205. #define IsGameConsole() true
  206. #else
  207. #define IsPC() true
  208. #define IsGameConsole() false
  209. #endif
  210. #ifdef PLATFORM_64BITS
  211. #define IsPlatform64Bits() true
  212. #else
  213. #define IsPlatform64Bits() false
  214. #endif
  215. // From steam/steamtypes.h
  216. // RTime32
  217. // We use this 32 bit time representing real world time.
  218. // It offers 1 second resolution beginning on January 1, 1970 (Unix time)
  219. typedef uint32 RTime32;
  220. typedef float float32;
  221. typedef double float64;
  222. // for when we don't care about how many bits we use
  223. typedef unsigned int uint;
  224. #ifdef _MSC_VER
  225. #pragma once
  226. // Ensure that everybody has the right compiler version installed. The version
  227. // number can be obtained by looking at the compiler output when you type 'cl'
  228. // and removing the last two digits and the periods: 16.00.40219.01 becomes 160040219
  229. #if _MSC_FULL_VER > 180000000
  230. #if _MSC_FULL_VER < 180030723
  231. #error You must install VS 2013 Update 3
  232. #endif
  233. #elif _MSC_FULL_VER > 160000000
  234. #if _MSC_FULL_VER < 160040219
  235. #error You must install VS 2010 SP1
  236. #endif
  237. #else
  238. #if _MSC_FULL_VER < 140050727
  239. #error You must install VS 2005 SP1
  240. #endif
  241. #endif
  242. #endif
  243. // This can be used to ensure the size of pointers to members when declaring
  244. // a pointer type for a class that has only been forward declared
  245. #ifdef _MSC_VER
  246. #define SINGLE_INHERITANCE __single_inheritance
  247. #define MULTIPLE_INHERITANCE __multiple_inheritance
  248. #else
  249. #define SINGLE_INHERITANCE
  250. #define MULTIPLE_INHERITANCE
  251. #endif
  252. #ifdef _MSC_VER
  253. #define NO_VTABLE __declspec( novtable )
  254. #else
  255. #define NO_VTABLE
  256. #endif
  257. #ifdef _MSC_VER
  258. // This indicates that a function never returns, which helps with
  259. // generating accurate compiler warnings
  260. #define NORETURN __declspec( noreturn )
  261. #else
  262. #define NORETURN
  263. #endif
  264. // This can be used to declare an abstract (interface only) class.
  265. // Classes marked abstract should not be instantiated. If they are, and access violation will occur.
  266. //
  267. // Example of use:
  268. //
  269. // abstract_class CFoo
  270. // {
  271. // ...
  272. // }
  273. //
  274. // MSDN __declspec(novtable) documentation: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_langref_novtable.asp
  275. //
  276. // Note: NJS: This is not enabled for regular PC, due to not knowing the implications of exporting a class with no no vtable.
  277. // It's probable that this shouldn't be an issue, but an experiment should be done to verify this.
  278. //
  279. #ifndef _X360
  280. #define abstract_class class
  281. #else
  282. #define abstract_class class NO_VTABLE
  283. #endif
  284. // MSVC CRT uses 0x7fff while gcc uses MAX_INT, leading to mismatches between platforms
  285. // As a result, we pick the least common denominator here. This should be used anywhere
  286. // you might typically want to use RAND_MAX
  287. #define VALVE_RAND_MAX 0x7fff
  288. /*
  289. FIXME: Enable this when we no longer fear change =)
  290. // need these for the limits
  291. #include <limits.h>
  292. #include <float.h>
  293. // Maximum and minimum representable values
  294. #define INT8_MAX SCHAR_MAX
  295. #define INT16_MAX SHRT_MAX
  296. #define INT32_MAX LONG_MAX
  297. #define INT64_MAX (((int64)~0) >> 1)
  298. #define INT8_MIN SCHAR_MIN
  299. #define INT16_MIN SHRT_MIN
  300. #define INT32_MIN LONG_MIN
  301. #define INT64_MIN (((int64)1) << 63)
  302. #define UINT8_MAX ((uint8)~0)
  303. #define UINT16_MAX ((uint16)~0)
  304. #define UINT32_MAX ((uint32)~0)
  305. #define UINT64_MAX ((uint64)~0)
  306. #define UINT8_MIN 0
  307. #define UINT16_MIN 0
  308. #define UINT32_MIN 0
  309. #define UINT64_MIN 0
  310. #ifndef UINT_MIN
  311. #define UINT_MIN UINT32_MIN
  312. #endif
  313. #define FLOAT32_MAX FLT_MAX
  314. #define FLOAT64_MAX DBL_MAX
  315. #define FLOAT32_MIN FLT_MIN
  316. #define FLOAT64_MIN DBL_MIN
  317. */
  318. // portability / compiler settings
  319. #if defined(_WIN32) && !defined(WINDED)
  320. #if defined(_M_IX86)
  321. #define __i386__ 1
  322. #endif
  323. #elif POSIX
  324. #if defined( OSX ) && defined( CARBON_WORKAROUND )
  325. #define DWORD unsigned int
  326. #else
  327. typedef unsigned int DWORD;
  328. #endif
  329. typedef unsigned short WORD;
  330. typedef void * HINSTANCE;
  331. #define _MAX_PATH PATH_MAX
  332. #define __cdecl
  333. #define __stdcall
  334. #define __declspec
  335. #endif // defined(_WIN32) && !defined(WINDED)
  336. #define MAX_FILEPATH 512
  337. // Defines MAX_PATH
  338. #ifndef MAX_PATH
  339. #define MAX_PATH 260
  340. #endif
  341. #ifdef _WIN32
  342. #define MAX_UNICODE_PATH 32767
  343. #else
  344. #define MAX_UNICODE_PATH MAX_PATH
  345. #endif
  346. #define MAX_UNICODE_PATH_IN_UTF8 MAX_UNICODE_PATH*4
  347. #if !defined( offsetof )
  348. #ifdef __GNUC__
  349. #define offsetof( type, var ) __builtin_offsetof( type, var )
  350. #else
  351. #define offsetof(s,m) (size_t)&(((s *)0)->m)
  352. #endif
  353. #endif // !defined( offsetof )
  354. #define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) ) // need macro for constant expression
  355. // Used to step into the debugger
  356. #if defined( _WIN32 ) && !defined( _X360 )
  357. #define DebuggerBreak() __debugbreak()
  358. #elif defined( _X360 )
  359. #define DebuggerBreak() DebugBreak()
  360. #else
  361. // On OSX, SIGTRAP doesn't really stop the thread cold when debugging.
  362. // So if being debugged, use INT3 which is precise.
  363. #ifdef OSX
  364. #define DebuggerBreak() if ( Plat_IsInDebugSession() ) { __asm ( "int $3" ); } else { raise(SIGTRAP); }
  365. #else
  366. #define DebuggerBreak() raise(SIGTRAP)
  367. #endif
  368. #endif
  369. #define DebuggerBreakIfDebugging() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak()
  370. #ifdef STAGING_ONLY
  371. #define DebuggerBreakIfDebugging_StagingOnly() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak()
  372. #else
  373. #define DebuggerBreakIfDebugging_StagingOnly()
  374. #endif
  375. // Allows you to specify code that should only execute if we are in a staging build. Otherwise the code noops.
  376. #ifdef STAGING_ONLY
  377. #define STAGING_ONLY_EXEC( _exec ) do { _exec; } while (0)
  378. #else
  379. #define STAGING_ONLY_EXEC( _exec ) do { } while (0)
  380. #endif
  381. // C functions for external declarations that call the appropriate C++ methods
  382. #ifndef EXPORT
  383. #ifdef _WIN32
  384. #define EXPORT _declspec( dllexport )
  385. #else
  386. #define EXPORT /* */
  387. #endif
  388. #endif
  389. #if defined __i386__ && !defined __linux__
  390. #define id386 1
  391. #else
  392. #define id386 0
  393. #endif // __i386__
  394. // decls for aligning data
  395. #ifdef _WIN32
  396. #define DECL_ALIGN(x) __declspec(align(x))
  397. #elif GNUC
  398. #define DECL_ALIGN(x) __attribute__((aligned(x)))
  399. #else
  400. #define DECL_ALIGN(x) /* */
  401. #endif
  402. #ifdef _MSC_VER
  403. // MSVC has the align at the start of the struct
  404. #define ALIGN4 DECL_ALIGN(4)
  405. #define ALIGN8 DECL_ALIGN(8)
  406. #define ALIGN16 DECL_ALIGN(16)
  407. #define ALIGN32 DECL_ALIGN(32)
  408. #define ALIGN128 DECL_ALIGN(128)
  409. #define ALIGN4_POST
  410. #define ALIGN8_POST
  411. #define ALIGN16_POST
  412. #define ALIGN32_POST
  413. #define ALIGN128_POST
  414. #elif defined( GNUC )
  415. // gnuc has the align decoration at the end
  416. #define ALIGN4
  417. #define ALIGN8
  418. #define ALIGN16
  419. #define ALIGN32
  420. #define ALIGN128
  421. #define ALIGN4_POST DECL_ALIGN(4)
  422. #define ALIGN8_POST DECL_ALIGN(8)
  423. #define ALIGN16_POST DECL_ALIGN(16)
  424. #define ALIGN32_POST DECL_ALIGN(32)
  425. #define ALIGN128_POST DECL_ALIGN(128)
  426. #else
  427. #error
  428. #endif
  429. // Pull in the /analyze code annotations.
  430. #include "annotations.h"
  431. //-----------------------------------------------------------------------------
  432. // Convert int<-->pointer, avoiding 32/64-bit compiler warnings:
  433. //-----------------------------------------------------------------------------
  434. #define INT_TO_POINTER( i ) (void *)( ( i ) + (char *)NULL )
  435. #define POINTER_TO_INT( p ) ( (int)(uintp)( p ) )
  436. //-----------------------------------------------------------------------------
  437. // Stack-based allocation related helpers
  438. //-----------------------------------------------------------------------------
  439. #if defined( GNUC )
  440. #define stackalloc( _size ) alloca( ALIGN_VALUE( _size, 16 ) )
  441. #ifdef _LINUX
  442. #define mallocsize( _p ) ( malloc_usable_size( _p ) )
  443. #elif defined(OSX)
  444. #define mallocsize( _p ) ( malloc_size( _p ) )
  445. #else
  446. #error
  447. #endif
  448. #elif defined ( _WIN32 )
  449. #define stackalloc( _size ) _alloca( ALIGN_VALUE( _size, 16 ) )
  450. #define mallocsize( _p ) ( _msize( _p ) )
  451. #endif
  452. #define stackfree( _p ) 0
  453. // Linux had a few areas where it didn't construct objects in the same order that Windows does.
  454. // So when CVProfile::CVProfile() would access g_pMemAlloc, it would crash because the allocator wasn't initalized yet.
  455. #ifdef POSIX
  456. #define CONSTRUCT_EARLY __attribute__((init_priority(101)))
  457. #else
  458. #define CONSTRUCT_EARLY
  459. #endif
  460. #if defined(_MSC_VER)
  461. #define SELECTANY __declspec(selectany)
  462. #define RESTRICT __restrict
  463. #define RESTRICT_FUNC __declspec(restrict)
  464. #define FMTFUNCTION( a, b )
  465. #elif defined(GNUC)
  466. #define SELECTANY __attribute__((weak))
  467. #if defined(LINUX) && !defined(DEDICATED)
  468. #define RESTRICT
  469. #else
  470. #define RESTRICT __restrict
  471. #endif
  472. #define RESTRICT_FUNC
  473. // squirrel.h does a #define printf DevMsg which leads to warnings when we try
  474. // to use printf as the prototype format function. Using __printf__ instead.
  475. #define FMTFUNCTION( fmtargnumber, firstvarargnumber ) __attribute__ (( format( __printf__, fmtargnumber, firstvarargnumber )))
  476. #else
  477. #define SELECTANY static
  478. #define RESTRICT
  479. #define RESTRICT_FUNC
  480. #define FMTFUNCTION( a, b )
  481. #endif
  482. #if defined( _WIN32 )
  483. // Used for dll exporting and importing
  484. #define DLL_EXPORT extern "C" __declspec( dllexport )
  485. #define DLL_IMPORT extern "C" __declspec( dllimport )
  486. // Can't use extern "C" when DLL exporting a class
  487. #define DLL_CLASS_EXPORT __declspec( dllexport )
  488. #define DLL_CLASS_IMPORT __declspec( dllimport )
  489. // Can't use extern "C" when DLL exporting a global
  490. #define DLL_GLOBAL_EXPORT extern __declspec( dllexport )
  491. #define DLL_GLOBAL_IMPORT extern __declspec( dllimport )
  492. #define DLL_LOCAL
  493. #elif defined GNUC
  494. // Used for dll exporting and importing
  495. #define DLL_EXPORT extern "C" __attribute__ ((visibility("default")))
  496. #define DLL_IMPORT extern "C"
  497. // Can't use extern "C" when DLL exporting a class
  498. #define DLL_CLASS_EXPORT __attribute__ ((visibility("default")))
  499. #define DLL_CLASS_IMPORT
  500. // Can't use extern "C" when DLL exporting a global
  501. #define DLL_GLOBAL_EXPORT extern __attribute ((visibility("default")))
  502. #define DLL_GLOBAL_IMPORT extern
  503. #define DLL_LOCAL __attribute__ ((visibility("hidden")))
  504. #else
  505. #error "Unsupported Platform."
  506. #endif
  507. // Used for standard calling conventions
  508. #if defined( _WIN32 ) && !defined( _X360 )
  509. #define STDCALL __stdcall
  510. #define FASTCALL __fastcall
  511. #define FORCEINLINE __forceinline
  512. // GCC 3.4.1 has a bug in supporting forced inline of templated functions
  513. // this macro lets us not force inlining in that case
  514. #define FORCEINLINE_TEMPLATE __forceinline
  515. #elif defined( _X360 )
  516. #define STDCALL __stdcall
  517. #ifdef FORCEINLINE
  518. #undef FORCEINLINE
  519. #endif
  520. #define FORCEINLINE __forceinline
  521. #define FORCEINLINE_TEMPLATE __forceinline
  522. #else
  523. #define STDCALL
  524. #define FASTCALL
  525. #ifdef _LINUX_DEBUGGABLE
  526. #define FORCEINLINE
  527. #else
  528. #define FORCEINLINE inline __attribute__ ((always_inline))
  529. #endif
  530. // GCC 3.4.1 has a bug in supporting forced inline of templated functions
  531. // this macro lets us not force inlining in that case
  532. #define FORCEINLINE_TEMPLATE inline
  533. // #define __stdcall __attribute__ ((__stdcall__))
  534. #endif
  535. // Force a function call site -not- to inlined. (useful for profiling)
  536. #define DONT_INLINE(a) (((int)(a)+1)?(a):(a))
  537. // Pass hints to the compiler to prevent it from generating unnessecary / stupid code
  538. // in certain situations. Several compilers other than MSVC also have an equivilent
  539. // construct.
  540. //
  541. // Essentially the 'Hint' is that the condition specified is assumed to be true at
  542. // that point in the compilation. If '0' is passed, then the compiler assumes that
  543. // any subsequent code in the same 'basic block' is unreachable, and thus usually
  544. // removed.
  545. #ifdef _MSC_VER
  546. #define HINT(THE_HINT) __assume((THE_HINT))
  547. #else
  548. #define HINT(THE_HINT) 0
  549. #endif
  550. // Marks the codepath from here until the next branch entry point as unreachable,
  551. // and asserts if any attempt is made to execute it.
  552. #define UNREACHABLE() { Assert(0); HINT(0); }
  553. // In cases where no default is present or appropriate, this causes MSVC to generate
  554. // as little code as possible, and throw an assertion in debug.
  555. #define NO_DEFAULT default: UNREACHABLE();
  556. #ifdef _WIN32
  557. // Remove warnings from warning level 4.
  558. #pragma warning(disable : 4514) // warning C4514: 'acosl' : unreferenced inline function has been removed
  559. #pragma warning(disable : 4100) // warning C4100: 'hwnd' : unreferenced formal parameter
  560. #pragma warning(disable : 4127) // warning C4127: conditional expression is constant
  561. #pragma warning(disable : 4512) // warning C4512: 'InFileRIFF' : assignment operator could not be generated
  562. #pragma warning(disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
  563. #pragma warning(disable : 4710) // warning C4710: function 'x' not inlined
  564. #pragma warning(disable : 4702) // warning C4702: unreachable code
  565. #pragma warning(disable : 4505) // unreferenced local function has been removed
  566. #pragma warning(disable : 4239) // nonstandard extension used : 'argument' ( conversion from class Vector to class Vector& )
  567. #pragma warning(disable : 4097) // typedef-name 'BaseClass' used as synonym for class-name 'CFlexCycler::CBaseFlex'
  568. #pragma warning(disable : 4324) // Padding was added at the end of a structure
  569. #pragma warning(disable : 4244) // type conversion warning.
  570. #pragma warning(disable : 4305) // truncation from 'const double ' to 'float '
  571. #pragma warning(disable : 4786) // Disable warnings about long symbol names
  572. #pragma warning(disable : 4250) // 'X' : inherits 'Y::Z' via dominance
  573. #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
  574. #pragma warning(disable : 4481) // warning C4481: nonstandard extension used: override specifier 'override'
  575. #pragma warning(disable : 4748) // warning C4748: /GS can not protect parameters and local variables from local buffer overrun because optimizations are disabled in function
  576. #if _MSC_VER >= 1300
  577. #pragma warning(disable : 4511) // Disable warnings about private copy constructors
  578. #pragma warning(disable : 4121) // warning C4121: 'symbol' : alignment of a member was sensitive to packing
  579. #pragma warning(disable : 4530) // warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc (disabled due to std headers having exception syntax)
  580. #endif
  581. #if _MSC_VER >= 1400
  582. #pragma warning(disable : 4996) // functions declared deprecated
  583. #endif
  584. #endif // _WIN32
  585. #if defined( LINUX ) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
  586. // based on some Jonathan Wakely macros on the net...
  587. #define GCC_DIAG_STR(s) #s
  588. #define GCC_DIAG_JOINSTR(x,y) GCC_DIAG_STR(x ## y)
  589. #define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x)
  590. #define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
  591. #define GCC_DIAG_PUSH_OFF(x) GCC_DIAG_PRAGMA(push) GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x))
  592. #define GCC_DIAG_POP() GCC_DIAG_PRAGMA(pop)
  593. #else
  594. #define GCC_DIAG_PUSH_OFF(x)
  595. #define GCC_DIAG_POP()
  596. #endif
  597. #ifdef LINUX
  598. #pragma GCC diagnostic ignored "-Wconversion-null" // passing NULL to non-pointer argument 1
  599. #pragma GCC diagnostic ignored "-Wpointer-arith" // NULL used in arithmetic. Ie, vpanel == NULL where VPANEL is uint.
  600. #pragma GCC diagnostic ignored "-Wswitch" // enumeration values not handled in switch
  601. #endif
  602. #ifdef OSX
  603. #pragma GCC diagnostic ignored "-Wconversion-null" // passing NULL to non-pointer argument 1
  604. #pragma GCC diagnostic ignored "-Wnull-arithmetic" // NULL used in arithmetic. Ie, vpanel == NULL where VPANEL is uint.
  605. #pragma GCC diagnostic ignored "-Wswitch-enum" // enumeration values not handled in switch
  606. #pragma GCC diagnostic ignored "-Wswitch" // enumeration values not handled in switch
  607. #endif
  608. // When we port to 64 bit, we'll have to resolve the int, ptr vs size_t 32/64 bit problems...
  609. #if !defined( _WIN64 )
  610. #pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data
  611. #pragma warning( disable : 4311 ) // pointer truncation from 'char *' to 'int'
  612. #pragma warning( disable : 4312 ) // conversion from 'unsigned int' to 'memhandle_t' of greater size
  613. #endif
  614. #ifdef POSIX
  615. #define _stricmp stricmp
  616. #define strcmpi stricmp
  617. #define stricmp strcasecmp
  618. #define _vsnprintf vsnprintf
  619. #define _alloca alloca
  620. #ifdef _snprintf
  621. #undef _snprintf
  622. #endif
  623. #define _snprintf snprintf
  624. #define GetProcAddress dlsym
  625. #define _chdir chdir
  626. #define _strnicmp strnicmp
  627. #define strnicmp strncasecmp
  628. #define _getcwd getcwd
  629. #define _snwprintf swprintf
  630. #define swprintf_s swprintf
  631. #define wcsicmp _wcsicmp
  632. #define _wcsicmp wcscmp
  633. #define _finite finite
  634. #define _tempnam tempnam
  635. #define _unlink unlink
  636. #define _access access
  637. #define _mkdir(dir) mkdir( dir, S_IRWXU | S_IRWXG | S_IRWXO )
  638. #define _wtoi(arg) wcstol(arg, NULL, 10)
  639. #define _wtoi64(arg) wcstoll(arg, NULL, 10)
  640. typedef uint32 HMODULE;
  641. typedef void *HANDLE;
  642. #endif
  643. //-----------------------------------------------------------------------------
  644. // fsel
  645. //-----------------------------------------------------------------------------
  646. #ifndef _X360
  647. static FORCEINLINE float fsel(float fComparand, float fValGE, float fLT)
  648. {
  649. return fComparand >= 0 ? fValGE : fLT;
  650. }
  651. static FORCEINLINE double fsel(double fComparand, double fValGE, double fLT)
  652. {
  653. return fComparand >= 0 ? fValGE : fLT;
  654. }
  655. #else
  656. // __fsel(double fComparand, double fValGE, double fLT) == fComparand >= 0 ? fValGE : fLT
  657. // this is much faster than if ( aFloat > 0 ) { x = .. }
  658. #define fsel __fsel
  659. #endif
  660. //-----------------------------------------------------------------------------
  661. // FP exception handling
  662. //-----------------------------------------------------------------------------
  663. //#define CHECK_FLOAT_EXCEPTIONS 1
  664. #if !defined( _X360 )
  665. #if defined( _MSC_VER )
  666. #if defined( PLATFORM_WINDOWS_PC64 )
  667. inline void SetupFPUControlWord()
  668. {
  669. }
  670. #else
  671. inline void SetupFPUControlWordForceExceptions()
  672. {
  673. // use local to get and store control word
  674. uint16 tmpCtrlW;
  675. __asm
  676. {
  677. fnclex /* clear all current exceptions */
  678. fnstcw word ptr [tmpCtrlW] /* get current control word */
  679. and [tmpCtrlW], 0FCC0h /* Keep infinity control + rounding control */
  680. or [tmpCtrlW], 0230h /* set to 53-bit, mask only inexact, underflow */
  681. fldcw word ptr [tmpCtrlW] /* put new control word in FPU */
  682. }
  683. }
  684. #ifdef CHECK_FLOAT_EXCEPTIONS
  685. inline void SetupFPUControlWord()
  686. {
  687. SetupFPUControlWordForceExceptions();
  688. }
  689. #else
  690. inline void SetupFPUControlWord()
  691. {
  692. // use local to get and store control word
  693. uint16 tmpCtrlW;
  694. __asm
  695. {
  696. fnstcw word ptr [tmpCtrlW] /* get current control word */
  697. and [tmpCtrlW], 0FCC0h /* Keep infinity control + rounding control */
  698. or [tmpCtrlW], 023Fh /* set to 53-bit, mask only inexact, underflow */
  699. fldcw word ptr [tmpCtrlW] /* put new control word in FPU */
  700. }
  701. }
  702. #endif
  703. #endif
  704. #else
  705. inline void SetupFPUControlWord()
  706. {
  707. __volatile unsigned short int __cw;
  708. __asm __volatile ("fnstcw %0" : "=m" (__cw));
  709. __cw = __cw & 0x0FCC0; // keep infinity control, keep rounding mode
  710. __cw = __cw | 0x023F; // set 53-bit, no exceptions
  711. __asm __volatile ("fldcw %0" : : "m" (__cw));
  712. }
  713. #endif // _MSC_VER
  714. #else
  715. #ifdef _DEBUG
  716. FORCEINLINE bool IsFPUControlWordSet()
  717. {
  718. float f = 0.996f;
  719. union
  720. {
  721. double flResult;
  722. int pResult[2];
  723. };
  724. flResult = __fctiw( f );
  725. return ( pResult[1] == 1 );
  726. }
  727. #endif
  728. inline void SetupFPUControlWord()
  729. {
  730. // Set round-to-nearest in FPSCR
  731. // (cannot assemble, must use op-code form)
  732. __emit( 0xFF80010C ); // mtfsfi 7,0
  733. // Favour compatibility over speed (make sure the VPU set to Java-compliant mode)
  734. // NOTE: the VPU *always* uses round-to-nearest
  735. __vector4 a = { 0.0f, 0.0f, 0.0f, 0.0f };
  736. a; // Avoid compiler warning
  737. __asm
  738. {
  739. mtvscr a; // Clear the Vector Status & Control Register to zero
  740. }
  741. }
  742. #endif // _X360
  743. //-----------------------------------------------------------------------------
  744. // Purpose: Standard functions for handling endian-ness
  745. //-----------------------------------------------------------------------------
  746. //-------------------------------------
  747. // Basic swaps
  748. //-------------------------------------
  749. template <typename T>
  750. inline T WordSwapC( T w )
  751. {
  752. uint16 temp;
  753. temp = ((*((uint16 *)&w) & 0xff00) >> 8);
  754. temp |= ((*((uint16 *)&w) & 0x00ff) << 8);
  755. return *((T*)&temp);
  756. }
  757. template <typename T>
  758. inline T DWordSwapC( T dw )
  759. {
  760. uint32 temp;
  761. temp = *((uint32 *)&dw) >> 24;
  762. temp |= ((*((uint32 *)&dw) & 0x00FF0000) >> 8);
  763. temp |= ((*((uint32 *)&dw) & 0x0000FF00) << 8);
  764. temp |= ((*((uint32 *)&dw) & 0x000000FF) << 24);
  765. return *((T*)&temp);
  766. }
  767. template <typename T>
  768. inline T QWordSwapC( T dw )
  769. {
  770. // Assert sizes passed to this are already correct, otherwise
  771. // the cast to uint64 * below is unsafe and may have wrong results
  772. // or even crash.
  773. PLAT_COMPILE_TIME_ASSERT( sizeof( dw ) == sizeof(uint64) );
  774. uint64 temp;
  775. temp = *((uint64 *)&dw) >> 56;
  776. temp |= ((*((uint64 *)&dw) & 0x00FF000000000000ull) >> 40);
  777. temp |= ((*((uint64 *)&dw) & 0x0000FF0000000000ull) >> 24);
  778. temp |= ((*((uint64 *)&dw) & 0x000000FF00000000ull) >> 8);
  779. temp |= ((*((uint64 *)&dw) & 0x00000000FF000000ull) << 8);
  780. temp |= ((*((uint64 *)&dw) & 0x0000000000FF0000ull) << 24);
  781. temp |= ((*((uint64 *)&dw) & 0x000000000000FF00ull) << 40);
  782. temp |= ((*((uint64 *)&dw) & 0x00000000000000FFull) << 56);
  783. return *((T*)&temp);
  784. }
  785. //-------------------------------------
  786. // Fast swaps
  787. //-------------------------------------
  788. #if defined( _X360 )
  789. #define WordSwap WordSwap360Intr
  790. #define DWordSwap DWordSwap360Intr
  791. template <typename T>
  792. inline T WordSwap360Intr( T w )
  793. {
  794. T output;
  795. __storeshortbytereverse( w, 0, &output );
  796. return output;
  797. }
  798. template <typename T>
  799. inline T DWordSwap360Intr( T dw )
  800. {
  801. T output;
  802. __storewordbytereverse( dw, 0, &output );
  803. return output;
  804. }
  805. #elif defined( _MSC_VER ) && !defined( PLATFORM_WINDOWS_PC64 )
  806. #define WordSwap WordSwapAsm
  807. #define DWordSwap DWordSwapAsm
  808. #pragma warning(push)
  809. #pragma warning (disable:4035) // no return value
  810. template <typename T>
  811. inline T WordSwapAsm( T w )
  812. {
  813. __asm
  814. {
  815. mov ax, w
  816. xchg al, ah
  817. }
  818. }
  819. template <typename T>
  820. inline T DWordSwapAsm( T dw )
  821. {
  822. __asm
  823. {
  824. mov eax, dw
  825. bswap eax
  826. }
  827. }
  828. #pragma warning(pop)
  829. #else
  830. #define WordSwap WordSwapC
  831. #define DWordSwap DWordSwapC
  832. #endif
  833. // No ASM implementation for this yet
  834. #define QWordSwap QWordSwapC
  835. //-------------------------------------
  836. // The typically used methods.
  837. //-------------------------------------
  838. #if defined(__i386__) && !defined(VALVE_LITTLE_ENDIAN)
  839. #define VALVE_LITTLE_ENDIAN 1
  840. #endif
  841. #if defined( _SGI_SOURCE ) || defined( _X360 )
  842. #define VALVE_BIG_ENDIAN 1
  843. #endif
  844. // If a swapped float passes through the fpu, the bytes may get changed.
  845. // Prevent this by swapping floats as DWORDs.
  846. #define SafeSwapFloat( pOut, pIn ) (*((uint*)pOut) = DWordSwap( *((uint*)pIn) ))
  847. #if defined(VALVE_LITTLE_ENDIAN)
  848. #define BigShort( val ) WordSwap( val )
  849. #define BigWord( val ) WordSwap( val )
  850. #define BigLong( val ) DWordSwap( val )
  851. #define BigDWord( val ) DWordSwap( val )
  852. #define LittleShort( val ) ( val )
  853. #define LittleWord( val ) ( val )
  854. #define LittleLong( val ) ( val )
  855. #define LittleDWord( val ) ( val )
  856. #define LittleQWord( val ) ( val )
  857. #define SwapShort( val ) BigShort( val )
  858. #define SwapWord( val ) BigWord( val )
  859. #define SwapLong( val ) BigLong( val )
  860. #define SwapDWord( val ) BigDWord( val )
  861. // Pass floats by pointer for swapping to avoid truncation in the fpu
  862. #define BigFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn )
  863. #define LittleFloat( pOut, pIn ) ( *pOut = *pIn )
  864. #define SwapFloat( pOut, pIn ) BigFloat( pOut, pIn )
  865. #elif defined(VALVE_BIG_ENDIAN)
  866. #define BigShort( val ) ( val )
  867. #define BigWord( val ) ( val )
  868. #define BigLong( val ) ( val )
  869. #define BigDWord( val ) ( val )
  870. #define LittleShort( val ) WordSwap( val )
  871. #define LittleWord( val ) WordSwap( val )
  872. #define LittleLong( val ) DWordSwap( val )
  873. #define LittleDWord( val ) DWordSwap( val )
  874. #define LittleQWord( val ) QWordSwap( val )
  875. #define SwapShort( val ) LittleShort( val )
  876. #define SwapWord( val ) LittleWord( val )
  877. #define SwapLong( val ) LittleLong( val )
  878. #define SwapDWord( val ) LittleDWord( val )
  879. // Pass floats by pointer for swapping to avoid truncation in the fpu
  880. #define BigFloat( pOut, pIn ) ( *pOut = *pIn )
  881. #define LittleFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn )
  882. #define SwapFloat( pOut, pIn ) LittleFloat( pOut, pIn )
  883. #else
  884. // @Note (toml 05-02-02): this technique expects the compiler to
  885. // optimize the expression and eliminate the other path. On any new
  886. // platform/compiler this should be tested.
  887. inline short BigShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; }
  888. inline uint16 BigWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; }
  889. inline long BigLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; }
  890. inline uint32 BigDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; }
  891. inline short LittleShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); }
  892. inline uint16 LittleWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); }
  893. inline long LittleLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); }
  894. inline uint32 LittleDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); }
  895. inline uint64 LittleQWord( uint64 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : QWordSwap( val ); }
  896. inline short SwapShort( short val ) { return WordSwap( val ); }
  897. inline uint16 SwapWord( uint16 val ) { return WordSwap( val ); }
  898. inline long SwapLong( long val ) { return DWordSwap( val ); }
  899. inline uint32 SwapDWord( uint32 val ) { return DWordSwap( val ); }
  900. // Pass floats by pointer for swapping to avoid truncation in the fpu
  901. inline void BigFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? SafeSwapFloat( pOut, pIn ) : ( *pOut = *pIn ); }
  902. inline void LittleFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? ( *pOut = *pIn ) : SafeSwapFloat( pOut, pIn ); }
  903. inline void SwapFloat( float *pOut, const float *pIn ) { SafeSwapFloat( pOut, pIn ); }
  904. #endif
  905. #if _X360
  906. FORCEINLINE unsigned long LoadLittleDWord( const unsigned long *base, unsigned int dwordIndex )
  907. {
  908. return __loadwordbytereverse( dwordIndex<<2, base );
  909. }
  910. FORCEINLINE void StoreLittleDWord( unsigned long *base, unsigned int dwordIndex, unsigned long dword )
  911. {
  912. __storewordbytereverse( dword, dwordIndex<<2, base );
  913. }
  914. #else
  915. FORCEINLINE unsigned long LoadLittleDWord( const unsigned long *base, unsigned int dwordIndex )
  916. {
  917. return LittleDWord( base[dwordIndex] );
  918. }
  919. FORCEINLINE void StoreLittleDWord( unsigned long *base, unsigned int dwordIndex, unsigned long dword )
  920. {
  921. base[dwordIndex] = LittleDWord(dword);
  922. }
  923. #endif
  924. //-----------------------------------------------------------------------------
  925. // DLL export for platform utilities
  926. //-----------------------------------------------------------------------------
  927. #ifndef STATIC_TIER0
  928. #ifdef TIER0_DLL_EXPORT
  929. #define PLATFORM_INTERFACE DLL_EXPORT
  930. #define PLATFORM_OVERLOAD DLL_GLOBAL_EXPORT
  931. #define PLATFORM_CLASS DLL_CLASS_EXPORT
  932. #else
  933. #define PLATFORM_INTERFACE DLL_IMPORT
  934. #define PLATFORM_OVERLOAD DLL_GLOBAL_IMPORT
  935. #define PLATFORM_CLASS DLL_CLASS_IMPORT
  936. #endif
  937. #else // BUILD_AS_DLL
  938. #define PLATFORM_INTERFACE extern
  939. #define PLATFORM_OVERLOAD
  940. #define PLATFORM_CLASS
  941. #endif // BUILD_AS_DLL
  942. // When in benchmark mode, the timer returns a simple incremented value each time you call it.
  943. //
  944. // It should not be changed after startup unless you really know what you're doing. The only place
  945. // that should do this is the benchmark code itself so it can output a legit duration.
  946. PLATFORM_INTERFACE void Plat_SetBenchmarkMode( bool bBenchmarkMode );
  947. PLATFORM_INTERFACE bool Plat_IsInBenchmarkMode();
  948. PLATFORM_INTERFACE double Plat_FloatTime(); // Returns time in seconds since the module was loaded.
  949. PLATFORM_INTERFACE uint32 Plat_MSTime(); // Time in milliseconds.
  950. PLATFORM_INTERFACE uint64 Plat_USTime(); // Time in microseconds.
  951. PLATFORM_INTERFACE char * Plat_ctime( const time_t *timep, char *buf, size_t bufsize );
  952. PLATFORM_INTERFACE void Plat_GetModuleFilename( char *pOut, int nMaxBytes );
  953. PLATFORM_INTERFACE void Plat_ExitProcess( int nCode );
  954. //called to exit the process due to a fatal error. This allows for the application to handle providing a hook as well which can be called
  955. //before exiting
  956. PLATFORM_INTERFACE void Plat_ExitProcessWithError( int nCode, bool bGenerateMinidump = false );
  957. //sets the callback that will be triggered by Plat_ExitProcessWithError. NULL is valid. The return value true indicates that
  958. //the exit has been handled and no further processing should be performed. False will cause a minidump to be generated, and the process
  959. //to be terminated
  960. typedef bool (*ExitProcessWithErrorCBFn)( int nCode );
  961. PLATFORM_INTERFACE void Plat_SetExitProcessWithErrorCB( ExitProcessWithErrorCBFn pfnCB );
  962. PLATFORM_INTERFACE struct tm * Plat_gmtime( const time_t *timep, struct tm *result );
  963. PLATFORM_INTERFACE time_t Plat_timegm( struct tm *timeptr );
  964. PLATFORM_INTERFACE struct tm * Plat_localtime( const time_t *timep, struct tm *result );
  965. #if defined( _WIN32 ) && defined( _MSC_VER ) && ( _MSC_VER >= 1400 )
  966. extern "C" unsigned __int64 __rdtsc();
  967. #pragma intrinsic(__rdtsc)
  968. #endif
  969. inline uint64 Plat_Rdtsc()
  970. {
  971. #if defined( _X360 )
  972. return ( uint64 )__mftb32();
  973. #elif defined( _WIN64 )
  974. return ( uint64 )__rdtsc();
  975. #elif defined( _WIN32 )
  976. #if defined( _MSC_VER ) && ( _MSC_VER >= 1400 )
  977. return ( uint64 )__rdtsc();
  978. #else
  979. __asm rdtsc;
  980. __asm ret;
  981. #endif
  982. #elif defined( __i386__ )
  983. uint64 val;
  984. __asm__ __volatile__ ( "rdtsc" : "=A" (val) );
  985. return val;
  986. #elif defined( __x86_64__ )
  987. uint32 lo, hi;
  988. __asm__ __volatile__ ( "rdtsc" : "=a" (lo), "=d" (hi));
  989. return ( ( ( uint64 )hi ) << 32 ) | lo;
  990. #else
  991. #error
  992. #endif
  993. }
  994. // b/w compatibility
  995. #define Sys_FloatTime Plat_FloatTime
  996. // Protect against bad auto operator=
  997. #define DISALLOW_OPERATOR_EQUAL( _classname ) \
  998. private: \
  999. _classname &operator=( const _classname & ); \
  1000. public:
  1001. // Define a reasonable operator=
  1002. #define IMPLEMENT_OPERATOR_EQUAL( _classname ) \
  1003. public: \
  1004. _classname &operator=( const _classname &src ) \
  1005. { \
  1006. memcpy( this, &src, sizeof(_classname) ); \
  1007. return *this; \
  1008. }
  1009. // Processor Information:
  1010. struct CPUInformation
  1011. {
  1012. int m_Size; // Size of this structure, for forward compatability.
  1013. bool m_bRDTSC : 1, // Is RDTSC supported?
  1014. m_bCMOV : 1, // Is CMOV supported?
  1015. m_bFCMOV : 1, // Is FCMOV supported?
  1016. m_bSSE : 1, // Is SSE supported?
  1017. m_bSSE2 : 1, // Is SSE2 Supported?
  1018. m_b3DNow : 1, // Is 3DNow! Supported?
  1019. m_bMMX : 1, // Is MMX supported?
  1020. m_bHT : 1; // Is HyperThreading supported?
  1021. uint8 m_nLogicalProcessors; // Number op logical processors.
  1022. uint8 m_nPhysicalProcessors; // Number of physical processors
  1023. bool m_bSSE3 : 1,
  1024. m_bSSSE3 : 1,
  1025. m_bSSE4a : 1,
  1026. m_bSSE41 : 1,
  1027. m_bSSE42 : 1;
  1028. int64 m_Speed; // In cycles per second.
  1029. tchar* m_szProcessorID; // Processor vendor Identification.
  1030. uint32 m_nModel;
  1031. uint32 m_nFeatures[3];
  1032. CPUInformation(): m_Size(0){}
  1033. };
  1034. // Have to return a pointer, not a reference, because references are not compatible with the
  1035. // extern "C" implied by PLATFORM_INTERFACE.
  1036. PLATFORM_INTERFACE const CPUInformation* GetCPUInformation();
  1037. #define MEMORY_INFORMATION_VERSION 0
  1038. struct MemoryInformation
  1039. {
  1040. int m_nStructVersion;
  1041. uint m_nPhysicalRamMbTotal;
  1042. uint m_nPhysicalRamMbAvailable;
  1043. uint m_nVirtualRamMbTotal;
  1044. uint m_nVirtualRamMbAvailable;
  1045. inline MemoryInformation()
  1046. {
  1047. memset( this, 0, sizeof( *this ) );
  1048. m_nStructVersion = MEMORY_INFORMATION_VERSION;
  1049. }
  1050. };
  1051. // Returns true if the passed in MemoryInformation structure was filled out, otherwise false.
  1052. PLATFORM_INTERFACE bool GetMemoryInformation( MemoryInformation *pOutMemoryInfo );
  1053. PLATFORM_INTERFACE float GetCPUUsage();
  1054. PLATFORM_INTERFACE void GetCurrentDate( int *pDay, int *pMonth, int *pYear );
  1055. // ---------------------------------------------------------------------------------- //
  1056. // Performance Monitoring Events - L2 stats etc...
  1057. // ---------------------------------------------------------------------------------- //
  1058. PLATFORM_INTERFACE void InitPME();
  1059. PLATFORM_INTERFACE void ShutdownPME();
  1060. //-----------------------------------------------------------------------------
  1061. // Thread related functions
  1062. //-----------------------------------------------------------------------------
  1063. // Sets a hardware data breakpoint on the given address. Currently Win32-only.
  1064. // Specify 1, 2, or 4 bytes for nWatchBytes; pass 0 to unregister the address.
  1065. PLATFORM_INTERFACE void Plat_SetHardwareDataBreakpoint( const void *pAddress, int nWatchBytes, bool bBreakOnRead );
  1066. // Apply current hardware data breakpoints to a newly created thread.
  1067. PLATFORM_INTERFACE void Plat_ApplyHardwareDataBreakpointsToNewThread( unsigned long dwThreadID );
  1068. //-----------------------------------------------------------------------------
  1069. // Process related functions
  1070. //-----------------------------------------------------------------------------
  1071. PLATFORM_INTERFACE const tchar *Plat_GetCommandLine();
  1072. #ifndef _WIN32
  1073. // helper function for OS's that don't have a ::GetCommandLine() call
  1074. PLATFORM_INTERFACE void Plat_SetCommandLine( const char *cmdLine );
  1075. #endif
  1076. PLATFORM_INTERFACE const char *Plat_GetCommandLineA();
  1077. //-----------------------------------------------------------------------------
  1078. // Security related functions
  1079. //-----------------------------------------------------------------------------
  1080. // Ensure that the hardware key's drivers have been installed.
  1081. PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyDriver();
  1082. // Ok, so this isn't a very secure way to verify the hardware key for now. It
  1083. // is primarially depending on the fact that all the binaries have been wrapped
  1084. // with the secure wrapper provided by the hardware keys vendor.
  1085. PLATFORM_INTERFACE bool Plat_VerifyHardwareKey();
  1086. // The same as above, but notifies user with a message box when the key isn't in
  1087. // and gives him an opportunity to correct the situation.
  1088. PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyPrompt();
  1089. // Can be called in real time, doesn't perform the verify every frame. Mainly just
  1090. // here to allow the game to drop out quickly when the key is removed, rather than
  1091. // allowing the wrapper to pop up it's own blocking dialog, which the engine doesn't
  1092. // like much.
  1093. PLATFORM_INTERFACE bool Plat_FastVerifyHardwareKey();
  1094. //-----------------------------------------------------------------------------
  1095. // Just logs file and line to simple.log
  1096. //-----------------------------------------------------------------------------
  1097. PLATFORM_INTERFACE void* Plat_SimpleLog( const tchar* file, int line );
  1098. #if _X360
  1099. #define Plat_FastMemset XMemSet
  1100. #define Plat_FastMemcpy XMemCpy
  1101. #else
  1102. #define Plat_FastMemset memset
  1103. #define Plat_FastMemcpy memcpy
  1104. #endif
  1105. //-----------------------------------------------------------------------------
  1106. // Returns true if debugger attached, false otherwise
  1107. //-----------------------------------------------------------------------------
  1108. #if defined(_WIN32) || defined(LINUX) || defined(OSX)
  1109. PLATFORM_INTERFACE bool Plat_IsInDebugSession();
  1110. PLATFORM_INTERFACE void Plat_DebugString( const char * );
  1111. #else
  1112. inline bool Plat_IsInDebugSession( bool bForceRecheck = false ) { return false; }
  1113. #define Plat_DebugString(s) ((void)0)
  1114. #endif
  1115. //-----------------------------------------------------------------------------
  1116. // Returns true if running on a 64 bit (windows) OS
  1117. //-----------------------------------------------------------------------------
  1118. PLATFORM_INTERFACE bool Is64BitOS();
  1119. //-----------------------------------------------------------------------------
  1120. // XBOX Components valid in PC compilation space
  1121. //-----------------------------------------------------------------------------
  1122. #define XBOX_DVD_SECTORSIZE 2048
  1123. #define XBOX_DVD_ECC_SIZE 32768 // driver reads in quantum ECC blocks
  1124. #define XBOX_HDD_SECTORSIZE 512
  1125. // Custom windows messages for Xbox input
  1126. #define WM_XREMOTECOMMAND (WM_USER + 100)
  1127. #define WM_XCONTROLLER_KEY (WM_USER + 101)
  1128. #define WM_SYS_UI (WM_USER + 102)
  1129. #define WM_SYS_SIGNINCHANGED (WM_USER + 103)
  1130. #define WM_SYS_STORAGEDEVICESCHANGED (WM_USER + 104)
  1131. #define WM_SYS_PROFILESETTINGCHANGED (WM_USER + 105)
  1132. #define WM_SYS_MUTELISTCHANGED (WM_USER + 106)
  1133. #define WM_SYS_INPUTDEVICESCHANGED (WM_USER + 107)
  1134. #define WM_SYS_INPUTDEVICECONFIGCHANGED (WM_USER + 108)
  1135. #define WM_LIVE_CONNECTIONCHANGED (WM_USER + 109)
  1136. #define WM_LIVE_INVITE_ACCEPTED (WM_USER + 110)
  1137. #define WM_LIVE_LINK_STATE_CHANGED (WM_USER + 111)
  1138. #define WM_LIVE_CONTENT_INSTALLED (WM_USER + 112)
  1139. #define WM_LIVE_MEMBERSHIP_PURCHASED (WM_USER + 113)
  1140. #define WM_LIVE_VOICECHAT_AWAY (WM_USER + 114)
  1141. #define WM_LIVE_PRESENCE_CHANGED (WM_USER + 115)
  1142. #define WM_FRIENDS_PRESENCE_CHANGED (WM_USER + 116)
  1143. #define WM_FRIENDS_FRIEND_ADDED (WM_USER + 117)
  1144. #define WM_FRIENDS_FRIEND_REMOVED (WM_USER + 118)
  1145. #define WM_CUSTOM_GAMEBANNERPRESSED (WM_USER + 119)
  1146. #define WM_CUSTOM_ACTIONPRESSED (WM_USER + 120)
  1147. #define WM_XMP_STATECHANGED (WM_USER + 121)
  1148. #define WM_XMP_PLAYBACKBEHAVIORCHANGED (WM_USER + 122)
  1149. #define WM_XMP_PLAYBACKCONTROLLERCHANGED (WM_USER + 123)
  1150. inline const char *GetPlatformExt( void )
  1151. {
  1152. return IsX360() ? ".360" : "";
  1153. }
  1154. // flat view, 6 hw threads
  1155. #define XBOX_PROCESSOR_0 ( 1<<0 )
  1156. #define XBOX_PROCESSOR_1 ( 1<<1 )
  1157. #define XBOX_PROCESSOR_2 ( 1<<2 )
  1158. #define XBOX_PROCESSOR_3 ( 1<<3 )
  1159. #define XBOX_PROCESSOR_4 ( 1<<4 )
  1160. #define XBOX_PROCESSOR_5 ( 1<<5 )
  1161. // core view, 3 cores with 2 hw threads each
  1162. #define XBOX_CORE_0_HWTHREAD_0 XBOX_PROCESSOR_0
  1163. #define XBOX_CORE_0_HWTHREAD_1 XBOX_PROCESSOR_1
  1164. #define XBOX_CORE_1_HWTHREAD_0 XBOX_PROCESSOR_2
  1165. #define XBOX_CORE_1_HWTHREAD_1 XBOX_PROCESSOR_3
  1166. #define XBOX_CORE_2_HWTHREAD_0 XBOX_PROCESSOR_4
  1167. #define XBOX_CORE_2_HWTHREAD_1 XBOX_PROCESSOR_5
  1168. //-----------------------------------------------------------------------------
  1169. // Include additional dependant header components.
  1170. //-----------------------------------------------------------------------------
  1171. #include "tier0/fasttimer.h"
  1172. #if defined( _X360 )
  1173. #include "xbox/xbox_core.h"
  1174. #endif
  1175. //-----------------------------------------------------------------------------
  1176. // Methods to invoke the constructor, copy constructor, and destructor
  1177. //-----------------------------------------------------------------------------
  1178. template <class T>
  1179. inline T* Construct( T* pMemory )
  1180. {
  1181. return reinterpret_cast<T*>(::new( pMemory ) T);
  1182. }
  1183. template <class T, typename ARG1>
  1184. inline T* Construct( T* pMemory, ARG1 a1 )
  1185. {
  1186. return reinterpret_cast<T*>(::new( pMemory ) T( a1 ));
  1187. }
  1188. template <class T, typename ARG1, typename ARG2>
  1189. inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2 )
  1190. {
  1191. return reinterpret_cast<T*>(::new( pMemory ) T( a1, a2 ));
  1192. }
  1193. template <class T, typename ARG1, typename ARG2, typename ARG3>
  1194. inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3 )
  1195. {
  1196. return reinterpret_cast<T*>(::new( pMemory ) T( a1, a2, a3 ));
  1197. }
  1198. template <class T, typename ARG1, typename ARG2, typename ARG3, typename ARG4>
  1199. inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3, ARG4 a4 )
  1200. {
  1201. return reinterpret_cast<T*>(::new( pMemory ) T( a1, a2, a3, a4 ));
  1202. }
  1203. template <class T, typename ARG1, typename ARG2, typename ARG3, typename ARG4, typename ARG5>
  1204. inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3, ARG4 a4, ARG5 a5 )
  1205. {
  1206. return reinterpret_cast<T*>(::new( pMemory ) T( a1, a2, a3, a4, a5 ));
  1207. }
  1208. template <class T, class P>
  1209. inline void ConstructOneArg( T* pMemory, P const& arg)
  1210. {
  1211. ::new( pMemory ) T(arg);
  1212. }
  1213. template <class T, class P1, class P2 >
  1214. inline void ConstructTwoArg( T* pMemory, P1 const& arg1, P2 const& arg2)
  1215. {
  1216. ::new( pMemory ) T(arg1, arg2);
  1217. }
  1218. template <class T, class P1, class P2, class P3 >
  1219. inline void ConstructThreeArg( T* pMemory, P1 const& arg1, P2 const& arg2, P3 const& arg3)
  1220. {
  1221. ::new( pMemory ) T(arg1, arg2, arg3);
  1222. }
  1223. template <class T>
  1224. inline T* CopyConstruct( T* pMemory, T const& src )
  1225. {
  1226. return reinterpret_cast<T*>(::new( pMemory ) T(src));
  1227. }
  1228. template <class T>
  1229. inline void Destruct( T* pMemory )
  1230. {
  1231. pMemory->~T();
  1232. #ifdef _DEBUG
  1233. memset( reinterpret_cast<void*>( pMemory ), 0xDD, sizeof(T) );
  1234. #endif
  1235. }
  1236. // The above will error when binding to a type of: foo(*)[] -- there is no provision in c++ for knowing how many objects
  1237. // to destruct without preserving the count and calling the necessary destructors.
  1238. template <class T, size_t N>
  1239. inline void Destruct( T (*pMemory)[N] )
  1240. {
  1241. for ( size_t i = 0; i < N; i++ )
  1242. {
  1243. (pMemory[i])->~T();
  1244. }
  1245. #ifdef _DEBUG
  1246. memset( reinterpret_cast<void*>( pMemory ), 0xDD, sizeof(*pMemory) );
  1247. #endif
  1248. }
  1249. //
  1250. // GET_OUTER()
  1251. //
  1252. // A platform-independent way for a contained class to get a pointer to its
  1253. // owner. If you know a class is exclusively used in the context of some
  1254. // "outer" class, this is a much more space efficient way to get at the outer
  1255. // class than having the inner class store a pointer to it.
  1256. //
  1257. // class COuter
  1258. // {
  1259. // class CInner // Note: this does not need to be a nested class to work
  1260. // {
  1261. // void PrintAddressOfOuter()
  1262. // {
  1263. // printf( "Outer is at 0x%x\n", GET_OUTER( COuter, m_Inner ) );
  1264. // }
  1265. // };
  1266. //
  1267. // CInner m_Inner;
  1268. // friend class CInner;
  1269. // };
  1270. #define GET_OUTER( OuterType, OuterMember ) \
  1271. ( ( OuterType * ) ( (uint8 *)this - offsetof( OuterType, OuterMember ) ) )
  1272. /* TEMPLATE_FUNCTION_TABLE()
  1273. (Note added to platform.h so platforms that correctly support templated
  1274. functions can handle portions as templated functions rather than wrapped
  1275. functions)
  1276. Helps automate the process of creating an array of function
  1277. templates that are all specialized by a single integer.
  1278. This sort of thing is often useful in optimization work.
  1279. For example, using TEMPLATE_FUNCTION_TABLE, this:
  1280. TEMPLATE_FUNCTION_TABLE(int, Function, ( int blah, int blah ), 10)
  1281. {
  1282. return argument * argument;
  1283. }
  1284. is equivilent to the following:
  1285. (NOTE: the function has to be wrapped in a class due to code
  1286. generation bugs involved with directly specializing a function
  1287. based on a constant.)
  1288. template<int argument>
  1289. class FunctionWrapper
  1290. {
  1291. public:
  1292. int Function( int blah, int blah )
  1293. {
  1294. return argument*argument;
  1295. }
  1296. }
  1297. typedef int (*FunctionType)( int blah, int blah );
  1298. class FunctionName
  1299. {
  1300. public:
  1301. enum { count = 10 };
  1302. FunctionType functions[10];
  1303. };
  1304. FunctionType FunctionName::functions[] =
  1305. {
  1306. FunctionWrapper<0>::Function,
  1307. FunctionWrapper<1>::Function,
  1308. FunctionWrapper<2>::Function,
  1309. FunctionWrapper<3>::Function,
  1310. FunctionWrapper<4>::Function,
  1311. FunctionWrapper<5>::Function,
  1312. FunctionWrapper<6>::Function,
  1313. FunctionWrapper<7>::Function,
  1314. FunctionWrapper<8>::Function,
  1315. FunctionWrapper<9>::Function
  1316. };
  1317. */
  1318. PLATFORM_INTERFACE bool vtune( bool resume );
  1319. #define TEMPLATE_FUNCTION_TABLE(RETURN_TYPE, NAME, ARGS, COUNT) \
  1320. \
  1321. typedef RETURN_TYPE (FASTCALL *__Type_##NAME) ARGS; \
  1322. \
  1323. template<const int nArgument> \
  1324. struct __Function_##NAME \
  1325. { \
  1326. static RETURN_TYPE FASTCALL Run ARGS; \
  1327. }; \
  1328. \
  1329. template <const int i> \
  1330. struct __MetaLooper_##NAME : __MetaLooper_##NAME<i-1> \
  1331. { \
  1332. __Type_##NAME func; \
  1333. inline __MetaLooper_##NAME() { func = __Function_##NAME<i>::Run; } \
  1334. }; \
  1335. \
  1336. template<> \
  1337. struct __MetaLooper_##NAME<0> \
  1338. { \
  1339. __Type_##NAME func; \
  1340. inline __MetaLooper_##NAME() { func = __Function_##NAME<0>::Run; } \
  1341. }; \
  1342. \
  1343. class NAME \
  1344. { \
  1345. private: \
  1346. static const __MetaLooper_##NAME<COUNT> m; \
  1347. public: \
  1348. enum { count = COUNT }; \
  1349. static const __Type_##NAME* functions; \
  1350. }; \
  1351. const __MetaLooper_##NAME<COUNT> NAME::m; \
  1352. const __Type_##NAME* NAME::functions = (__Type_##NAME*)&m; \
  1353. template<const int nArgument> \
  1354. RETURN_TYPE FASTCALL __Function_##NAME<nArgument>::Run ARGS
  1355. #define LOOP_INTERCHANGE(BOOLEAN, CODE)\
  1356. if( (BOOLEAN) )\
  1357. {\
  1358. CODE;\
  1359. } else\
  1360. {\
  1361. CODE;\
  1362. }
  1363. //-----------------------------------------------------------------------------
  1364. // Dynamic libs support
  1365. //-----------------------------------------------------------------------------
  1366. #if 0 // defined( PLATFORM_WINDOWS_PC )
  1367. PLATFORM_INTERFACE void *Plat_GetProcAddress( const char *pszModule, const char *pszName );
  1368. template <typename FUNCPTR_TYPE>
  1369. class CDynamicFunction
  1370. {
  1371. public:
  1372. CDynamicFunction( const char *pszModule, const char *pszName, FUNCPTR_TYPE pfnFallback = NULL )
  1373. {
  1374. m_pfn = pfnFallback;
  1375. void *pAddr = Plat_GetProcAddress( pszModule, pszName );
  1376. if ( pAddr )
  1377. {
  1378. m_pfn = (FUNCPTR_TYPE)pAddr;
  1379. }
  1380. }
  1381. operator bool() { return m_pfn != NULL; }
  1382. bool operator !() { return !m_pfn; }
  1383. operator FUNCPTR_TYPE() { return m_pfn; }
  1384. private:
  1385. FUNCPTR_TYPE m_pfn;
  1386. };
  1387. #endif
  1388. // Watchdog timer support. Call Plat_BeginWatchdogTimer( nn ) to kick the timer off. if you don't call
  1389. // Plat_EndWatchdogTimer within nn seconds, the program will kick off an exception. This is for making
  1390. // sure that hung dedicated servers abort (and restart) instead of staying hung. Calling
  1391. // Plat_EndWatchdogTimer more than once or when there is no active watchdog is fine. Only does anything
  1392. // under linux right now. It should be possible to implement this functionality in windows via a
  1393. // thread, if desired.
  1394. PLATFORM_INTERFACE void Plat_BeginWatchdogTimer( int nSecs );
  1395. PLATFORM_INTERFACE void Plat_EndWatchdogTimer( void );
  1396. PLATFORM_INTERFACE int Plat_GetWatchdogTime( void );
  1397. typedef void (*Plat_WatchDogHandlerFunction_t)(void);
  1398. PLATFORM_INTERFACE void Plat_SetWatchdogHandlerFunction( Plat_WatchDogHandlerFunction_t function );
  1399. //-----------------------------------------------------------------------------
  1400. #include "tier0/valve_on.h"
  1401. #if defined(TIER0_DLL_EXPORT)
  1402. extern "C" int V_tier0_stricmp(const char *s1, const char *s2 );
  1403. #undef stricmp
  1404. #undef strcmpi
  1405. #define stricmp(s1,s2) V_tier0_stricmp( s1, s2 )
  1406. #define strcmpi(s1,s2) V_tier0_stricmp( s1, s2 )
  1407. #endif
  1408. #endif /* PLATFORM_H */