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.

2032 lines
61 KiB

  1. //===== Copyright 1997-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #ifndef PLATFORM_H
  9. #define PLATFORM_H
  10. #ifdef SN_TARGET_PS3
  11. #define _PS3 1
  12. #define COMPILER_PS3 1
  13. #define PLATFORM_PS3 1
  14. // There are 2 compilers for the PS3: GCC and the SN Systems compiler.
  15. // They are mostly similar, but in a few places we need to distinguish between the two.
  16. #if defined( __SNC__ )
  17. #define COMPILER_SNC 1
  18. #elif defined( __GCC__ )
  19. #define COMPILER_GCC 1
  20. #else
  21. #error "Unrecognized PS3 compiler; either __SNC__ or __GCC__ must be defined"
  22. #endif
  23. #endif // SN_TARGET_PS3
  24. #ifdef __GCC__
  25. #define COMPILER_GCC 1
  26. #endif
  27. #if defined( _X360 ) || defined( _PS3 )
  28. #define PLATFORM_PPC 1
  29. #endif
  30. #ifdef COMPILER_MSVC
  31. #pragma once
  32. #endif
  33. #if defined (_PS3)
  34. #include <ppu_intrinsics.h>
  35. // We want to force the assert to be redefined, because the STD assert might have been
  36. // included and redefined. ps3_assert.h will do a check for assert being redefined.
  37. // #include "ps3/ps3_assert.h"
  38. #ifndef COMPILER_PS3
  39. #error "for PS3, VPC must define COMPILER_PS3 macro just like it does for COMPILER_MSVCX360 macro"
  40. #endif
  41. #if !defined( COMPILER_SNC ) && !defined( COMPILER_GCC )
  42. #error "for PS3, VPC must define COMPILER_SNC or COMPILER_GCC macro, depending on the target compiler, just like it does for COMPILER_MSVCX360 macro"
  43. #endif
  44. #elif defined( _X360 )
  45. #define NO_STEAM
  46. #define NO_VOICE
  47. // for the 360, the ppc platform and the rtos are tightly coupled
  48. // setup the 360 environment here !once! for much less leaf module include wackiness
  49. // these are critical order and purposely appear *before* anything else
  50. #define _XBOX
  51. #include <xaudio2.h>
  52. #include <xbdm.h>
  53. #include <xgraphics.h>
  54. #include <xui.h>
  55. #include <pmcpbsetup.h>
  56. #include <xmahardwareabstraction.h>
  57. #undef _XBOX
  58. #endif
  59. #include "wchartypes.h"
  60. #include "tier0/valve_off.h"
  61. #ifdef _PS3
  62. #include "ps3/ps3_platform.h"
  63. #define NO_STEAM_GAMECOORDINATOR
  64. #else
  65. #include <malloc.h>
  66. #include <memory.h>
  67. #include <limits.h>
  68. #include <float.h>
  69. #include <stdlib.h>
  70. #include <string.h>
  71. #ifdef OSX
  72. #include <signal.h>
  73. #endif
  74. #endif
  75. // This macro
  76. #if defined( _PS3 ) && defined ( COMPILER_SNC )
  77. // There are known bugs in the PS3 optimizer. The following macros allow us to lower optimization for a subset of a file
  78. // If you run into build problems with optimization on, try turning off optimization for the selected file. If that
  79. // fixes the problem, use process of elimination and the below macros to find the bare minimum that needs to be
  80. // unoptimized and report the compiler issue to Sony as well.
  81. //
  82. // The correlation between optimization levels and numbers passed to the _Pragma xopt and postopt calls is as follows:
  83. // See: Control-group reference tables / -Xshow
  84. // .... xopt
  85. // -O1 0
  86. // -O2 5
  87. // -O3 5
  88. //
  89. // These macros MUST be used in pairs - Otherwise, the compiler will barf 'At end of source: error 67: expected a "}"'
  90. // xopt disables some of the miscellaneous optimizations
  91. #if __option(xopt)
  92. #define SN_OPT_DISABLE extern "C++" { _Pragma("control %push xopt=0")
  93. #define SN_OPT_ENABLE _Pragma("control %pop xopt") }
  94. #else // !__option(xopt)
  95. #define SN_OPT_DISABLE
  96. #define SN_OPT_ENABLE
  97. #endif // !__option(xopt)
  98. // postopt disables the main optimizer
  99. #if __option(postopt) > 0
  100. #define SN_MAIN_OPT_DISABLE extern "C++" { _Pragma("control %push postopt=0")
  101. #define SN_MAIN_OPT_ENABLE _Pragma("control %pop postopt") }
  102. #else // !__option(postopt) > 0
  103. #define SN_MAIN_OPT_DISABLE
  104. #define SN_MAIN_OPT_ENABLE
  105. #endif // !__option(postopt) > 0
  106. #else // ! ( _PS3 && COMPILER_SNC )
  107. #define SN_OPT_DISABLE
  108. #define SN_OPT_ENABLE
  109. #define SN_MAIN_OPT_DISABLE
  110. #define SN_MAIN_OPT_ENABLE
  111. #endif // ! ( _PS3 && COMPILER_SNC )
  112. #ifdef __cplusplus
  113. #if defined( COMPILER_GCC ) || defined( COMPILER_PS3 )
  114. #include <new>
  115. #else
  116. #include <new.h>
  117. #endif
  118. #endif
  119. //-----------------------------------------------------------------------------
  120. // Old-school defines we don't want to use moving forward
  121. //-----------------------------------------------------------------------------
  122. #if CROSS_PLATFORM_VERSION < 1
  123. // feature enables
  124. #define NEW_SOFTWARE_LIGHTING
  125. #if !defined( _X360 )
  126. #define SUPPORT_PACKED_STORE
  127. #endif
  128. #if defined( BINK_VIDEO ) && ( defined( _X360 ) || defined( _PS3 ) )
  129. #define BINK_ENABLED_FOR_CONSOLE
  130. #endif
  131. #if !defined( PORTAL2 )
  132. //#define PORTAL2
  133. #endif
  134. // C functions for external declarations that call the appropriate C++ methods
  135. #ifndef EXPORT
  136. #ifdef _WIN32
  137. #define EXPORT _declspec( dllexport )
  138. #else
  139. #define EXPORT /* */
  140. #endif
  141. #endif
  142. #endif // CROSS_PLATFORM_VERSION < 1
  143. #if defined(_STATIC_LINKED)
  144. #include "staticlink/system.h"
  145. #endif
  146. //-----------------------------------------------------------------------------
  147. // NOTE: All compiler defines are set up in the base VPC scripts
  148. // COMPILER_MSVC, COMPILER_MSVC32, COMPILER_MSVC64, COMPILER_MSVCX360
  149. // COMPILER_GCC
  150. // The rationale for this is that we need COMPILER_MSVC for the pragma blocks
  151. // #pragma once that occur at the top of all header files, therefore we can't
  152. // place the defines for these in here.
  153. //-----------------------------------------------------------------------------
  154. //-----------------------------------------------------------------------------
  155. // Set up platform defines.
  156. //-----------------------------------------------------------------------------
  157. #ifdef _WIN32
  158. #define IsPlatformLinux() 0
  159. #define IsPlatformPosix() 0
  160. #define IsPlatformOSX() 0
  161. #define IsOSXOpenGL() 0
  162. #define IsPlatformPS3() 0
  163. #define IsPlatformPS3_PPU() 0
  164. #define IsPlatformPS3_SPU() 0
  165. #define PLATFORM_WINDOWS 1
  166. #define PLATFORM_OPENGL 0
  167. #ifndef _X360
  168. #define IsPlatformX360() 0
  169. #define IsPlatformWindowsPC() 1
  170. #define PLATFORM_WINDOWS_PC 1
  171. #ifdef _WIN64
  172. #define IsPlatformWindowsPC64() 1
  173. #define IsPlatformWindowsPC32() 0
  174. #define PLATFORM_WINDOWS_PC64 1
  175. #else
  176. #define IsPlatformWindowsPC64() 0
  177. #define IsPlatformWindowsPC32() 1
  178. #define PLATFORM_WINDOWS_PC32 1
  179. #endif
  180. #else // _X360
  181. #define IsPlatformWindowsPC() 0
  182. #define IsPlatformWindowsPC64() 0
  183. #define IsPlatformWindowsPC32() 0
  184. #define IsPlatformX360() 1
  185. #define PLATFORM_X360 1
  186. #endif // _X360
  187. #elif defined(_PS3)
  188. #define IsPlatformX360() 0
  189. #define IsPlatformPS3() 1
  190. #ifdef SPU
  191. #define IsPlatformPS3_PPU() 0
  192. #define IsPlatformPS3_SPU() 1
  193. #else
  194. #define IsPlatformPS3_PPU() 1
  195. #define IsPlatformPS3_SPU() 0
  196. #endif
  197. #define IsPlatformWindowsPC() 0
  198. #define IsPlatformWindowsPC64() 0
  199. #define IsPlatformWindowsPC32() 0
  200. #define IsPlatformPosix() 1
  201. #define PLATFORM_POSIX 1
  202. #define PLATFORM_OPENGL 0
  203. #define IsPlatformLinux() 0
  204. #define IsPlatformOSX() 0
  205. #define IsOSXOpenGL() 0
  206. #elif defined(POSIX)
  207. #define IsPlatformX360() 0
  208. #define IsPlatformPS3() 0
  209. #define IsPlatformPS3_PPU() 0
  210. #define IsPlatformPS3_SPU() 0
  211. #define IsPlatformWindowsPC() 0
  212. #define IsPlatformWindowsPC64() 0
  213. #define IsPlatformWindowsPC32() 0
  214. #define IsPlatformPosix() 1
  215. #define PLATFORM_POSIX 1
  216. #if defined( LINUX ) && !defined( OSX ) // for havok we define both symbols, so don't let the osx build wander down here
  217. #define IsPlatformLinux() 1
  218. #define IsPlatformOSX() 0
  219. #define IsOSXOpenGL() 0
  220. #define PLATFORM_OPENGL 0
  221. #define PLATFORM_LINUX 1
  222. #elif defined ( OSX )
  223. #define IsPlatformLinux() 0
  224. #define IsPlatformOSX() 1
  225. #define IsOSXOpenGL() 1
  226. #define PLATFORM_OSX 1
  227. #define PLATFORM_OPENGL 1
  228. #else
  229. #define IsPlatformLinux() 0
  230. #define IsPlatformOSX() 0
  231. #define IsOSXOpenGL() 0
  232. #define PLATFORM_OPENGL 0
  233. #endif
  234. #else
  235. #error
  236. #endif
  237. // IsXXXX platform pseudo-functions
  238. #if ( defined( PLATFORM_WINDOWS ) && ( PLATFORM_WINDOWS ) )
  239. #define IsPlatformWindows() 1
  240. #else
  241. #define IsPlatformWindows() 0
  242. #endif
  243. #if ( defined( PLATFORM_OPENGL ) && PLATFORM_OPENGL )
  244. #define IsOpenGL() 1
  245. #else
  246. #define IsOpenGL() 0
  247. #endif
  248. #ifndef _PS3
  249. //#include <malloc.h>
  250. //#include <new.h>
  251. #else
  252. #include <stdlib.h> // For malloc()
  253. #include <alloca.h> // for alloca()
  254. #define _alloca alloca
  255. #ifdef __cplusplus
  256. #include <new>
  257. #endif
  258. #endif
  259. //-----------------------------------------------------------------------------
  260. // Old-school defines we're going to support since much code uses them
  261. //-----------------------------------------------------------------------------
  262. #if CROSS_PLATFORM_VERSION < 2
  263. #define IsLinux() IsPlatformLinux()
  264. #define IsOSX() IsPlatformOSX()
  265. #define IsPosix() IsPlatformPosix()
  266. #define IsX360() IsPlatformX360()
  267. #define IsPS3() IsPlatformPS3()
  268. // Setup platform defines.
  269. #ifdef COMPILER_MSVC
  270. #define MSVC 1
  271. #endif
  272. #ifdef COMPILER_GCC
  273. #define GNUC 1
  274. #endif
  275. #if defined( _WIN32 )
  276. #define _WINDOWS 1
  277. #endif
  278. #ifdef PLATFORM_WINDOWS_PC
  279. #define IS_WINDOWS_PC 1
  280. #endif
  281. #endif // CROSS_PLATFORM_VERSION < 2
  282. // VXConsole is enabled for...
  283. #if defined(_X360) || defined(_PS3)
  284. #define USE_VXCONSOLE 1
  285. #define HasVxConsole() 1
  286. #else
  287. #define HasVxConsole() 0
  288. #endif
  289. //-----------------------------------------------------------------------------
  290. // Set up platform type defines.
  291. //-----------------------------------------------------------------------------
  292. #if defined( PLATFORM_X360 ) || defined( _PS3 )
  293. #ifndef _GAMECONSOLE
  294. #define _GAMECONSOLE
  295. #endif
  296. #define IsPC() 0
  297. #define IsGameConsole() 1
  298. #else
  299. #define IsPC() 1
  300. #define IsGameConsole() 0
  301. #endif
  302. //-----------------------------------------------------------------------------
  303. // Set up build configuration defines.
  304. //-----------------------------------------------------------------------------
  305. #ifdef _CERT
  306. #define IsCert() 1
  307. #else
  308. #define IsCert() 0
  309. #endif
  310. #ifdef _DEBUG
  311. #define IsRelease() 0
  312. #define IsDebug() 1
  313. #else
  314. #define IsRelease() 1
  315. #define IsDebug() 0
  316. #endif
  317. #ifdef _RETAIL
  318. #define IsRetail() 1
  319. #else
  320. #define IsRetail() 0
  321. #endif
  322. //-----------------------------------------------------------------------------
  323. // Portable data types
  324. //-----------------------------------------------------------------------------
  325. typedef unsigned char uint8;
  326. typedef signed char int8;
  327. #if defined( COMPILER_MSVC )
  328. typedef __int16 int16;
  329. typedef unsigned __int16 uint16;
  330. typedef __int32 int32;
  331. typedef unsigned __int32 uint32;
  332. typedef __int64 int64;
  333. typedef unsigned __int64 uint64;
  334. // intp is an integer that can accomodate a pointer
  335. // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *)
  336. typedef intptr_t intp;
  337. typedef uintptr_t uintp;
  338. #if defined( COMPILER_MSVCX360 )
  339. #ifdef __m128
  340. #undef __m128
  341. #endif
  342. #define __m128 __vector4
  343. #endif
  344. #else // !COMPILER_MSVC
  345. typedef short int16;
  346. typedef unsigned short uint16;
  347. typedef int int32;
  348. typedef unsigned int uint32;
  349. typedef long long int64;
  350. typedef unsigned long long uint64;
  351. #ifdef PLATFORM_64BITS
  352. typedef long long intp;
  353. typedef unsigned long long uintp;
  354. #else
  355. typedef int intp;
  356. typedef unsigned int uintp;
  357. #endif
  358. typedef void *HWND;
  359. #endif // else COMPILER_MSVC
  360. #if defined(_PS3) && !defined(NO_SIMD)
  361. typedef union __attribute__ ((aligned (16)))
  362. {
  363. float m128_f32[4];
  364. } l_m128;
  365. typedef __vector float __vector4;
  366. typedef __vector4 __m128;
  367. const __m128 VMX_ZERO=(vector float)(0.0f);
  368. const __m128 VMX_ONE_HALF=(vector float)(0.5f);
  369. const __m128 VMX_ONE=(vector float)(1.0f);
  370. // Syntaxic sugar for multiply
  371. inline __attribute__ ((always_inline)) __m128 __vec_mul(const __m128 a, const __m128 b)
  372. {
  373. return vec_madd(a,b,VMX_ZERO);
  374. }
  375. // Refined reciprocal function
  376. inline __attribute__ ((always_inline)) __m128 __vec_rec(const __m128 a)
  377. {
  378. //Get the reciprocal estimate
  379. vector float estimate = vec_re( a );
  380. //One round of Newton-Raphson refinement
  381. return vec_madd( vec_nmsub( estimate, a, VMX_ONE ), estimate, estimate );
  382. }
  383. // refined reciprocal square root
  384. inline __attribute__ ((always_inline)) __m128 __vec_rsqrt(const __m128 a)
  385. {
  386. //Get the square root reciprocal estimate
  387. __m128 estimate = vec_rsqrte( a );
  388. //One round of Newton-Raphson refinement
  389. __m128 estimateSquared = __vec_mul( estimate, estimate);
  390. __m128 halfEstimate = __vec_mul( estimate, VMX_ONE_HALF);
  391. return vec_madd( vec_nmsub( a, estimateSquared, VMX_ONE ), halfEstimate, estimate );
  392. }
  393. // refined square root
  394. inline __attribute__ ((always_inline)) __m128 __vec_sqrt(const __m128 a)
  395. {
  396. return __vec_mul( a, __vec_rsqrt( a ));
  397. }
  398. // estimate square root
  399. inline __attribute__ ((always_inline)) __m128 __vec_sqrtest(const __m128 a)
  400. {
  401. return __vec_mul( a, vec_rsqrte( a ));
  402. }
  403. // Syntaxic sugar for multiply
  404. inline __attribute__ ((always_inline)) __m128 __vec_div(const __m128 a, const __m128 b)
  405. {
  406. return __vec_mul( a, __vec_rec( b ));
  407. }
  408. // load an unaligned array of float in a vector of floats
  409. inline __attribute__ ((always_inline)) __m128 __vec_ld_unaligned(const float* in)
  410. {
  411. return vec_perm(vec_ld(0,in),
  412. vec_ld(sizeof(__m128),in),
  413. vec_lvsl( 0, in ));
  414. }
  415. // load an unaligned array of 3 floats in a vector of floats, last member being 0.
  416. inline __attribute__ ((always_inline)) __m128 __vec_ld_unaligned3(const float* in)
  417. {
  418. return vec_and(__vec_ld_unaligned(in),(__m128)(vector unsigned int)(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF ,0));
  419. }
  420. // stores a vector of floats in an unaligned array of float
  421. inline __attribute__ ((always_inline)) void __vec_st_unaligned(__m128 in, float* out)
  422. {
  423. __m128 temp0 = vec_ld(0,out);
  424. __m128 temp1 = vec_ld(16,out);
  425. vector unsigned char align = vec_lvsr(0,out);
  426. vector unsigned char mask = vec_perm ((vector unsigned char)(0), (vector unsigned char)(0xFF), align);
  427. in = vec_perm ( in, in, align);
  428. temp0 = vec_sel ( temp0, in, (vector bool)mask);
  429. temp1 = vec_sel ( in, temp1, (vector bool)mask);
  430. vec_st ( temp0, 0, out);
  431. vec_st ( temp1, 16, out);
  432. }
  433. // stores x,y,z from a vector of floats in an unaligned array of 3 floats
  434. inline __attribute__ ((always_inline)) void __vec_st_unaligned3(__m128 in, float* out)
  435. {
  436. __m128 temp0 = vec_ld(0,out);
  437. __m128 temp1 = vec_ld(16,out);
  438. vector unsigned char align = vec_lvsr(0,out);
  439. vector unsigned char mask = vec_perm ((vector unsigned char)(0),
  440. (vector unsigned char)(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0,0,0),
  441. align);
  442. in = vec_perm ( in, in, align);
  443. temp0 = vec_sel ( temp0, in, (vector bool)mask);
  444. temp1 = vec_sel ( in, temp1, (vector bool)mask);
  445. vec_st ( temp0, 0, out);
  446. vec_st ( temp1, 16, out);
  447. }
  448. #endif // defined(NO_SIMD)
  449. typedef float float32;
  450. typedef double float64;
  451. // for when we don't care about how many bits we use
  452. typedef unsigned int uint;
  453. #ifdef PLATFORM_POSIX
  454. #ifndef _PS3
  455. typedef unsigned int DWORD;
  456. typedef unsigned int *LPDWORD;
  457. #endif
  458. typedef unsigned short WORD;
  459. typedef void * HINSTANCE;
  460. #define _MAX_PATH PATH_MAX
  461. #endif
  462. // MSVC CRT uses 0x7fff while gcc uses MAX_INT, leading to mismatches between platforms
  463. // As a result, we pick the least common denominator here. This should be used anywhere
  464. // you might typically want to use RAND_MAX
  465. #define VALVE_RAND_MAX 0x7fff
  466. // Maximum and minimum representable values
  467. #ifndef PLATFORM_OSX
  468. #define INT8_MAX SCHAR_MAX
  469. #define INT16_MAX SHRT_MAX
  470. #define INT32_MAX LONG_MAX
  471. #define INT64_MAX (((int64)~0) >> 1)
  472. #define INT8_MIN SCHAR_MIN
  473. #define INT16_MIN SHRT_MIN
  474. #define INT32_MIN LONG_MIN
  475. #define INT64_MIN (((int64)1) << 63)
  476. #define UINT8_MAX ((uint8)~0)
  477. #define UINT16_MAX ((uint16)~0)
  478. #define UINT32_MAX ((uint32)~0)
  479. #define UINT64_MAX ((uint64)~0)
  480. #define UINT8_MIN 0
  481. #define UINT16_MIN 0
  482. #define UINT32_MIN 0
  483. #define UINT64_MIN 0
  484. #endif // PLATFORM_OSX
  485. #ifndef UINT_MIN
  486. #define UINT_MIN UINT32_MIN
  487. #endif
  488. #define FLOAT32_MAX FLT_MAX
  489. #define FLOAT64_MAX DBL_MAX
  490. #ifdef GNUC
  491. #undef offsetof
  492. // Note: can't use builtin offsetof because many use cases (esp. in templates) wouldn't compile due to restrictions on the builtin offsetof
  493. //#define offsetof( type, var ) __builtin_offsetof( type, var )
  494. #define offsetof(s,m) ( (size_t)&(((s *)0x1000000)->m) - 0x1000000u )
  495. #else
  496. #include <stddef.h>
  497. #undef offsetof
  498. #define offsetof(s,m) (size_t)&(((s *)0)->m)
  499. #endif
  500. #define FLOAT32_MIN FLT_MIN
  501. #define FLOAT64_MIN DBL_MIN
  502. //-----------------------------------------------------------------------------
  503. // Long is evil because it's treated differently by different compilers
  504. // Preventing its use is nasty however. This #define, which should be
  505. // turned on in individual VPC files, causes you to include tier0/valve_off.h
  506. // before standard C + windows headers, and include tier0/valve_on.h after
  507. // standard C + windows headers. So, there's some painful overhead to disabling long
  508. //-----------------------------------------------------------------------------
  509. #ifdef DISALLOW_USE_OF_LONG
  510. #define long long_is_the_devil_stop_using_it_use_int32_or_int64
  511. #endif
  512. //-----------------------------------------------------------------------------
  513. // Various compiler-specific keywords
  514. //-----------------------------------------------------------------------------
  515. #ifdef COMPILER_MSVC
  516. #ifdef FORCEINLINE
  517. #undef FORCEINLINE
  518. #endif
  519. #define STDCALL __stdcall
  520. #ifndef FASTCALL
  521. #define FASTCALL __fastcall
  522. #endif
  523. #define FORCEINLINE __forceinline
  524. #define FORCEINLINE_TEMPLATE __forceinline
  525. #define NULLTERMINATED __nullterminated
  526. // This can be used to ensure the size of pointers to members when declaring
  527. // a pointer type for a class that has only been forward declared
  528. #define SINGLE_INHERITANCE __single_inheritance
  529. #define MULTIPLE_INHERITANCE __multiple_inheritance
  530. #define EXPLICIT explicit
  531. #define NO_VTABLE __declspec( novtable )
  532. // gcc doesn't allow storage specifiers on explicit template instatiation, but visual studio needs them to avoid link errors.
  533. #define TEMPLATE_STATIC static
  534. // Used for dll exporting and importing
  535. #define DLL_EXPORT extern "C" __declspec( dllexport )
  536. #define DLL_IMPORT extern "C" __declspec( dllimport )
  537. // Can't use extern "C" when DLL exporting a class
  538. #define DLL_CLASS_EXPORT __declspec( dllexport )
  539. #define DLL_CLASS_IMPORT __declspec( dllimport )
  540. // Can't use extern "C" when DLL exporting a global
  541. #define DLL_GLOBAL_EXPORT extern __declspec( dllexport )
  542. #define DLL_GLOBAL_IMPORT extern __declspec( dllimport )
  543. // Pass hints to the compiler to prevent it from generating unnessecary / stupid code
  544. // in certain situations. Several compilers other than MSVC also have an equivilent
  545. // construct.
  546. //
  547. // Essentially the 'Hint' is that the condition specified is assumed to be true at
  548. // that point in the compilation. If '0' is passed, then the compiler assumes that
  549. // any subsequent code in the same 'basic block' is unreachable, and thus usually
  550. // removed.
  551. #define HINT(THE_HINT) __assume((THE_HINT))
  552. // decls for aligning data
  553. #define DECL_ALIGN(x) __declspec( align( x ) )
  554. // GCC had a few areas where it didn't construct objects in the same order
  555. // that Windows does. So when CVProfile::CVProfile() would access g_pMemAlloc,
  556. // it would crash because the allocator wasn't initalized yet.
  557. #define CONSTRUCT_EARLY
  558. #define SELECTANY __declspec(selectany)
  559. #define RESTRICT __restrict
  560. #define RESTRICT_FUNC __declspec(restrict)
  561. #define FMTFUNCTION( a, b )
  562. #define NOINLINE
  563. #if !defined( NO_THREAD_LOCAL )
  564. #define DECL_THREAD_LOCAL __declspec(thread)
  565. #endif
  566. #define DISABLE_VC_WARNING( x ) __pragma(warning(disable:4310) )
  567. #define DEFAULT_VC_WARNING( x ) __pragma(warning(default:4310) )
  568. #elif defined ( COMPILER_GCC ) || defined( COMPILER_SNC )
  569. #if defined( COMPILER_SNC )
  570. #define STDCALL
  571. #define __stdcall
  572. #elif (CROSS_PLATFORM_VERSION >= 1) && !defined( PLATFORM_64BITS ) && !defined( COMPILER_PS3 )
  573. #define STDCALL __attribute__ ((__stdcall__))
  574. #else
  575. #define STDCALL
  576. #define __stdcall __attribute__ ((__stdcall__))
  577. #endif
  578. #define FASTCALL
  579. #ifdef _LINUX_DEBUGGABLE
  580. #define FORCEINLINE
  581. #else
  582. #ifdef _PS3
  583. // [IESTYN 7/29/2010] As of SDK 3.4.0, this causes bad code generation in NET_Tick::ReadFromBuffer in netmessages.cpp,
  584. // which caused (seeming) random network packet corruption. It probably causes other bugs too.
  585. #define FORCEINLINE inline /* __attribute__ ((always_inline)) */
  586. #else
  587. #define FORCEINLINE inline __attribute__ ((always_inline))
  588. #endif
  589. #endif
  590. // GCC 3.4.1 has a bug in supporting forced inline of templated functions
  591. // this macro lets us not force inlining in that case
  592. #define FORCEINLINE_TEMPLATE inline
  593. #define SINGLE_INHERITANCE
  594. #define MULTIPLE_INHERITANCE
  595. #define EXPLICIT
  596. #define NO_VTABLE
  597. #define NULLTERMINATED
  598. #if defined( COMPILER_SNC )
  599. #define TEMPLATE_STATIC static
  600. #else
  601. #define TEMPLATE_STATIC
  602. #endif
  603. // Used for dll exporting and importing
  604. #ifdef COMPILER_SNC
  605. #define DLL_DECLARATION_DEFAULT_VISIBILITY
  606. #else
  607. #define DLL_DECLARATION_DEFAULT_VISIBILITY __attribute__ ((visibility("default")))
  608. #endif
  609. #define DLL_EXPORT extern "C" DLL_DECLARATION_DEFAULT_VISIBILITY
  610. #define DLL_IMPORT extern "C"
  611. // Can't use extern "C" when DLL exporting a class
  612. #ifndef _PS3
  613. #define __stdcall __attribute__ ((__stdcall__))
  614. #endif
  615. #define DLL_CLASS_EXPORT DLL_DECLARATION_DEFAULT_VISIBILITY
  616. #define DLL_CLASS_IMPORT
  617. // Can't use extern "C" when DLL exporting a global
  618. #define DLL_GLOBAL_EXPORT DLL_DECLARATION_DEFAULT_VISIBILITY
  619. #define DLL_GLOBAL_IMPORT extern
  620. #define HINT(THE_HINT) __builtin_expect( THE_HINT, 1 )
  621. #define DECL_ALIGN(x) __attribute__( ( aligned( x ) ) )
  622. #define CONSTRUCT_EARLY __attribute__((init_priority(101)))
  623. #define SELECTANY __attribute__((weak))
  624. #define RESTRICT __restrict__
  625. #define RESTRICT_FUNC RESTRICT_FUNC_NOT_YET_DEFINED_FOR_THIS_COMPILER
  626. #define FMTFUNCTION( fmtargnumber, firstvarargnumber ) __attribute__ (( format( printf, fmtargnumber, firstvarargnumber )))
  627. #define NOINLINE __attribute__ ((noinline))
  628. #if !defined( NO_THREAD_LOCAL )
  629. #define DECL_THREAD_LOCAL __thread
  630. #endif
  631. #define DISABLE_VC_WARNING( x )
  632. #define DEFAULT_VC_WARNING( x )
  633. #else
  634. #define DECL_ALIGN(x) /* */
  635. #define SELECTANY static
  636. #endif
  637. #if defined( GNUC ) && !defined( COMPILER_PS3 ) // use pre-align on PS3
  638. // gnuc has the align decoration at the end
  639. #define ALIGN4
  640. #define ALIGN8
  641. #define ALIGN16
  642. #define ALIGN32
  643. #define ALIGN128
  644. #undef ALIGN16_POST
  645. #define ALIGN4_POST DECL_ALIGN(4)
  646. #define ALIGN8_POST DECL_ALIGN(8)
  647. #define ALIGN16_POST DECL_ALIGN(16)
  648. #define ALIGN32_POST DECL_ALIGN(32)
  649. #define ALIGN128_POST DECL_ALIGN(128)
  650. #else
  651. // MSVC has the align at the start of the struct
  652. // PS3 SNC supports both
  653. #define ALIGN4 DECL_ALIGN(4)
  654. #define ALIGN8 DECL_ALIGN(8)
  655. #define ALIGN16 DECL_ALIGN(16)
  656. #define ALIGN32 DECL_ALIGN(32)
  657. #define ALIGN128 DECL_ALIGN(128)
  658. #define ALIGN4_POST
  659. #define ALIGN8_POST
  660. #define ALIGN16_POST
  661. #define ALIGN32_POST
  662. #define ALIGN128_POST
  663. #endif
  664. // This can be used to declare an abstract (interface only) class.
  665. // Classes marked abstract should not be instantiated. If they are, and access violation will occur.
  666. //
  667. // Example of use:
  668. //
  669. // abstract_class CFoo
  670. // {
  671. // ...
  672. // }
  673. //
  674. // MSDN __declspec(novtable) documentation: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_langref_novtable.asp
  675. //
  676. // Note: NJS: This is not enabled for regular PC, due to not knowing the implications of exporting a class with no no vtable.
  677. // It's probable that this shouldn't be an issue, but an experiment should be done to verify this.
  678. //
  679. #ifndef COMPILER_MSVCX360
  680. #define abstract_class class
  681. #else
  682. #define abstract_class class NO_VTABLE
  683. #endif
  684. //-----------------------------------------------------------------------------
  685. // Why do we need this? It would be nice to make it die die die
  686. //-----------------------------------------------------------------------------
  687. // Alloca defined for this platform
  688. #if defined( COMPILER_MSVC ) && !defined( WINDED )
  689. #if defined(_M_IX86)
  690. #define __i386__ 1
  691. #endif
  692. #endif
  693. #if defined __i386__ && !defined __linux__
  694. #define id386 1
  695. #else
  696. #define id386 0
  697. #endif // __i386__
  698. //-----------------------------------------------------------------------------
  699. // Disable annoying unhelpful warnings
  700. //-----------------------------------------------------------------------------
  701. #ifdef COMPILER_MSVC
  702. // Remove warnings from warning level 4.
  703. #pragma warning(disable : 4514) // warning C4514: 'acosl' : unreferenced inline function has been removed
  704. #pragma warning(disable : 4100) // warning C4100: 'hwnd' : unreferenced formal parameter
  705. #pragma warning(disable : 4127) // warning C4127: conditional expression is constant
  706. #pragma warning(disable : 4512) // warning C4512: 'InFileRIFF' : assignment operator could not be generated
  707. #pragma warning(disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
  708. #pragma warning(disable : 4710) // warning C4710: function 'x' not inlined
  709. #pragma warning(disable : 4702) // warning C4702: unreachable code
  710. #pragma warning(disable : 4505) // unreferenced local function has been removed
  711. #pragma warning(disable : 4239) // nonstandard extension used : 'argument' ( conversion from class Vector to class Vector& )
  712. #pragma warning(disable : 4097) // typedef-name 'BaseClass' used as synonym for class-name 'CFlexCycler::CBaseFlex'
  713. #pragma warning(disable : 4324) // Padding was added at the end of a structure
  714. #pragma warning(disable : 4244) // type conversion warning.
  715. #pragma warning(disable : 4305) // truncation from 'const double ' to 'float '
  716. #pragma warning(disable : 4786) // Disable warnings about long symbol names
  717. #pragma warning(disable : 4250) // 'X' : inherits 'Y::Z' via dominance
  718. #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
  719. #if _MSC_VER >= 1300
  720. #pragma warning(disable : 4511) // Disable warnings about private copy constructors
  721. #pragma warning(disable : 4121) // warning C4121: 'symbol' : alignment of a member was sensitive to packing
  722. #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)
  723. #endif
  724. #if _MSC_VER >= 1400
  725. #pragma warning(disable : 4996) // functions declared deprecated
  726. #endif
  727. // When we port to 64 bit, we'll have to resolve the int, ptr vs size_t 32/64 bit problems...
  728. #if !defined( COMPILER_MSVC64 )
  729. #if ( CROSS_PLATFORM_VERSION < 1 )
  730. #pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data
  731. #pragma warning( disable : 4311 ) // pointer truncation from 'char *' to 'int'
  732. #pragma warning( disable : 4312 ) // conversion from 'unsigned int' to 'memhandle_t' of greater size
  733. #endif
  734. #endif
  735. #elif defined( COMPILER_SNC )
  736. #pragma diag_suppress=1700 // warning 1700: class "%s" has virtual functions but non-virtual destructor
  737. // Uncomment the following line if you want to investigate a specific compiler remark without all the noise:
  738. // #pragma diag_suppress=1700, 83, 162, 182, 192, 194, 229, 238, 262, 341, 382, 401, 402, 403, 481, 817, 828, 833, 1363, 1771, 1774, 1779, 1780, 1783, 1785, 1786, 1788
  739. #endif
  740. // Pull in the /analyze code annotations.
  741. #include "annotations.h"
  742. //-----------------------------------------------------------------------------
  743. // Convert int<-->pointer, avoiding 32/64-bit compiler warnings:
  744. //-----------------------------------------------------------------------------
  745. #define INT_TO_POINTER( i ) (void *)( ( i ) + (char *)NULL )
  746. #define POINTER_TO_INT( p ) ( (int)(uint64)( p ) )
  747. //-----------------------------------------------------------------------------
  748. // Stack-based allocation related helpers
  749. //-----------------------------------------------------------------------------
  750. #if defined( COMPILER_GCC ) || defined( COMPILER_SNC )
  751. #define stackalloc( _size ) alloca( ALIGN_VALUE( _size, 16 ) )
  752. #ifdef PLATFORM_OSX
  753. #define mallocsize( _p ) ( malloc_size( _p ) )
  754. #else
  755. #define mallocsize( _p ) ( malloc_usable_size( _p ) )
  756. #endif
  757. #elif defined ( COMPILER_MSVC )
  758. #define stackalloc( _size ) _alloca( ALIGN_VALUE( _size, 16 ) )
  759. #define mallocsize( _p ) ( _msize( _p ) )
  760. #endif
  761. #define stackfree( _p ) 0
  762. //-----------------------------------------------------------------------------
  763. // Used to break into the debugger
  764. //-----------------------------------------------------------------------------
  765. #ifdef COMPILER_MSVC64
  766. #define DebuggerBreak() __debugbreak()
  767. #elif COMPILER_MSVC32
  768. #define DebuggerBreak() __asm { int 3 }
  769. #elif COMPILER_MSVCX360
  770. #define DebuggerBreak() DebugBreak()
  771. #elif COMPILER_GCC
  772. #if defined( _PS3 )
  773. #define DebuggerBreak() { __asm volatile ("tw 31,1,1"); }
  774. #elif defined( OSX )
  775. #define DebuggerBreak() if ( Plat_IsInDebugSession() ) { __asm__ __volatile__ ( "int $3" ); } else { raise(SIGTRAP); }
  776. #elif defined( PLATFORM_CYGWIN ) || defined( PLATFORM_POSIX )
  777. #define DebuggerBreak() __asm__( "int $0x3;")
  778. #else
  779. #define DebuggerBreak() asm( "int3" )
  780. #endif
  781. #elif defined( COMPILER_SNC ) && defined( COMPILER_PS3 )
  782. static bool sPS3_SuppressAssertsInThisFile = false; // you can throw this in the debugger to temporarily disable asserts inside any particular .cpp module.
  783. #define DebuggerBreak() if (!sPS3_SuppressAssertsInThisFile) __builtin_snpause(); // <sergiy> from SNC Migration Guide, tw 31,1,1
  784. #else
  785. #error DebuggerBreak() is not defined for this platform!
  786. #endif
  787. #if defined( _X360 ) || defined( _PS3 )
  788. #if defined( fsel )
  789. #error
  790. #endif
  791. #else
  792. FORCEINLINE float fsel(float fComparand, float fValGE, float fLT)
  793. {
  794. return fComparand >= 0 ? fValGE : fLT;
  795. }
  796. FORCEINLINE double fsel(double fComparand, double fValGE, double fLT)
  797. {
  798. return fComparand >= 0 ? fValGE : fLT;
  799. }
  800. #endif
  801. //-----------------------------------------------------------------------------
  802. // DLL export for platform utilities
  803. //-----------------------------------------------------------------------------
  804. #ifndef STATIC_TIER0
  805. #ifdef TIER0_DLL_EXPORT
  806. #define PLATFORM_INTERFACE DLL_EXPORT
  807. #define PLATFORM_OVERLOAD DLL_GLOBAL_EXPORT
  808. #define PLATFORM_CLASS DLL_CLASS_EXPORT
  809. #else
  810. #define PLATFORM_INTERFACE DLL_IMPORT
  811. #define PLATFORM_OVERLOAD DLL_GLOBAL_IMPORT
  812. #define PLATFORM_CLASS DLL_CLASS_IMPORT
  813. #endif
  814. #else // BUILD_AS_DLL
  815. #define PLATFORM_INTERFACE extern
  816. #define PLATFORM_OVERLOAD
  817. #define PLATFORM_CLASS
  818. #endif // BUILD_AS_DLL
  819. //-----------------------------------------------------------------------------
  820. // Returns true if debugger attached, false otherwise
  821. //-----------------------------------------------------------------------------
  822. #if defined( PLATFORM_WINDOWS ) || defined( _PS3 )
  823. PLATFORM_INTERFACE void Plat_DebugString( const tchar * );
  824. #else
  825. #define Plat_DebugString(s) ((void)0)
  826. #endif
  827. PLATFORM_INTERFACE bool Plat_IsInDebugSession();
  828. #define DebuggerBreakIfDebugging() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak()
  829. //-----------------------------------------------------------------------------
  830. // Message Box
  831. //-----------------------------------------------------------------------------
  832. #if defined( PLATFORM_WINDOWS_PC )
  833. PLATFORM_INTERFACE void Plat_MessageBox( const char *pTitle, const tchar *pMessage );
  834. #else
  835. #define Plat_MessageBox( t, m ) ((void)0)
  836. #endif
  837. //-----------------------------------------------------------------------------
  838. // Posix platform helpers
  839. //-----------------------------------------------------------------------------
  840. #ifdef PLATFORM_POSIX
  841. // Visual Studio likes to put an underscore in front of anything that looks like a portable function.
  842. #define _strupr strupr
  843. #define _getcwd getcwd
  844. #define _open open
  845. #define _lseek lseek
  846. #define _read read
  847. #define _close close
  848. #define _vsnprintf vsnprintf
  849. #define _stat stat
  850. #define _O_RDONLY O_RDONLY
  851. #define _stricmp strcasecmp
  852. #define _finite finite
  853. #define _unlink unlink
  854. #define _putenv putenv
  855. #define _chdir chdir
  856. #define _access access
  857. #define strcmpi stricmp
  858. #define stricmp strcasecmp
  859. #define _alloca alloca
  860. #define GetProcAddress dlsym
  861. #define _chdir chdir
  862. #ifndef _PS3
  863. #define _strnicmp strnicmp
  864. #endif
  865. #define strnicmp strncasecmp
  866. #define _snwprintf swprintf
  867. #define swprintf_s swprintf
  868. #define wcsicmp _wcsicmp
  869. #define _wcsicmp wcscmp
  870. #define _tempnam tempnam
  871. #define strtok_s strtok_r
  872. #define _mkdir(dir) mkdir( dir, S_IRWXU | S_IRWXG | S_IRWXO )
  873. #define _wtoi(arg) wcstol(arg, NULL, 10)
  874. #define _wtoi64(arg) wcstoll(arg, NULL, 10)
  875. #ifndef _PS3
  876. typedef uint32 HMODULE;
  877. #endif
  878. typedef void *HANDLE;
  879. #define __cdecl
  880. #if !defined( _snprintf ) // some vpc's define this on the command line
  881. #define _snprintf snprintf
  882. #endif
  883. #include <alloca.h>
  884. #include <unistd.h> // get unlink
  885. #include <errno.h>
  886. #endif // PLATFORM_POSIX
  887. #ifdef PLATFORM_WINDOWS
  888. #ifndef SOCKLEN_T
  889. #define SOCKLEN_T
  890. typedef int socklen_t;
  891. #endif
  892. #endif
  893. //-----------------------------------------------------------------------------
  894. // Generally useful platform-independent macros (move to another file?)
  895. //-----------------------------------------------------------------------------
  896. // need macro for constant expression
  897. #define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) )
  898. // Force a function call site -not- to inlined. (useful for profiling)
  899. #define DONT_INLINE(a) (((int)(a)+1)?(a):(a))
  900. // Marks the codepath from here until the next branch entry point as unreachable,
  901. // and asserts if any attempt is made to execute it.
  902. #define UNREACHABLE() { Assert(0); HINT(0); }
  903. // In cases where no default is present or appropriate, this causes MSVC to generate
  904. // as little code as possible, and throw an assertion in debug.
  905. #define NO_DEFAULT default: UNREACHABLE();
  906. // Defines MAX_PATH
  907. #ifndef MAX_PATH
  908. #define MAX_PATH 260
  909. #endif
  910. //-----------------------------------------------------------------------------
  911. // FP exception handling
  912. //-----------------------------------------------------------------------------
  913. //#define CHECK_FLOAT_EXCEPTIONS 1
  914. //#define CHECK_FPU_CONTROL_WORD_SET 1 // x360 only
  915. #if defined( COMPILER_MSVC64 )
  916. inline void SetupFPUControlWord()
  917. {
  918. }
  919. #elif defined ( COMPILER_MSVC32 )
  920. inline void SetupFPUControlWordForceExceptions()
  921. {
  922. // use local to get and store control word
  923. uint16 tmpCtrlW;
  924. __asm
  925. {
  926. fnclex /* clear all current exceptions */
  927. fnstcw word ptr [tmpCtrlW] /* get current control word */
  928. and [tmpCtrlW], 0FCC0h /* Keep infinity control + rounding control */
  929. or [tmpCtrlW], 0230h /* set to 53-bit, mask only inexact, underflow */
  930. fldcw word ptr [tmpCtrlW] /* put new control word in FPU */
  931. }
  932. }
  933. #ifdef CHECK_FLOAT_EXCEPTIONS
  934. inline void SetupFPUControlWord()
  935. {
  936. SetupFPUControlWordForceExceptions();
  937. }
  938. #else
  939. inline void SetupFPUControlWord()
  940. {
  941. // use local to get and store control word
  942. uint16 tmpCtrlW;
  943. __asm
  944. {
  945. fnstcw word ptr [tmpCtrlW] /* get current control word */
  946. and [tmpCtrlW], 0FCC0h /* Keep infinity control + rounding control */
  947. or [tmpCtrlW], 023Fh /* set to 53-bit, mask only inexact, underflow */
  948. fldcw word ptr [tmpCtrlW] /* put new control word in FPU */
  949. }
  950. }
  951. #endif
  952. #elif defined ( COMPILER_GCC )
  953. // Works for PS3
  954. inline void SetupFPUControlWord()
  955. {
  956. #ifdef _PS3
  957. // TODO: PS3 compiler spits out the following errors:
  958. // C:/tmp/ccIN0aaa.s: Assembler messages:
  959. // C:/tmp/ccIN0aaa.s(80): Error: Unrecognized opcode: `fnstcw'
  960. // C:/tmp/ccIN0aaa.s(93): Error: Unrecognized opcode: `fldcw'
  961. #else
  962. __volatile unsigned short int __cw;
  963. __asm __volatile ("fnstcw %0" : "=m" (__cw));
  964. __cw = __cw & 0x0FCC0; // keep infinity control, keep rounding mode
  965. __cw = __cw | 0x023F; // set 53-bit, no exceptions
  966. __asm __volatile ("fldcw %0" : : "m" (__cw));
  967. #endif
  968. }
  969. #elif defined ( COMPILER_SNC )
  970. // Works for PS3
  971. inline void SetupFPUControlWord()
  972. {
  973. #ifdef _PS3
  974. // TODO: PS3 compiler spits out the following errors:
  975. // C:/tmp/ccIN0aaa.s: Assembler messages:
  976. // C:/tmp/ccIN0aaa.s(80): Error: Unrecognized opcode: `fnstcw'
  977. // C:/tmp/ccIN0aaa.s(93): Error: Unrecognized opcode: `fldcw'
  978. #else
  979. __volatile unsigned short int __cw;
  980. __asm __volatile ("fnstcw %0" : "=m" (__cw));
  981. __cw = __cw & 0x0FCC0; // keep infinity control, keep rounding mode
  982. __cw = __cw | 0x023F; // set 53-bit, no exceptions
  983. __asm __volatile ("fldcw %0" : : "m" (__cw));
  984. #endif
  985. }
  986. #elif defined( COMPILER_MSVCX360 )
  987. #ifdef CHECK_FPU_CONTROL_WORD_SET
  988. FORCEINLINE bool IsFPUControlWordSet()
  989. {
  990. float f = 0.996f;
  991. union
  992. {
  993. double flResult;
  994. int pResult[2];
  995. };
  996. flResult = __fctiw( f );
  997. return ( pResult[1] == 1 );
  998. }
  999. #else
  1000. #define IsFPUControlWordSet() 1
  1001. #endif
  1002. inline void SetupFPUControlWord()
  1003. {
  1004. // Set round-to-nearest in FPSCR
  1005. // (cannot assemble, must use op-code form)
  1006. __emit( 0xFF80010C ); // mtfsfi 7,0
  1007. // Favour compatibility over speed (make sure the VPU set to Java-compliant mode)
  1008. // NOTE: the VPU *always* uses round-to-nearest
  1009. __vector4 a = { 0.0f, 0.0f, 0.0f, 0.0f };
  1010. a; // Avoid compiler warning
  1011. __asm
  1012. {
  1013. mtvscr a; // Clear the Vector Status & Control Register to zero
  1014. }
  1015. }
  1016. #endif // COMPILER_MSVCX360
  1017. //-----------------------------------------------------------------------------
  1018. // Purpose: Standard functions for handling endian-ness
  1019. //-----------------------------------------------------------------------------
  1020. //-------------------------------------
  1021. // Basic swaps
  1022. //-------------------------------------
  1023. template <typename T>
  1024. inline T WordSwapC( T w )
  1025. {
  1026. uint16 temp;
  1027. temp = ((*((uint16 *)&w) & 0xff00) >> 8);
  1028. temp |= ((*((uint16 *)&w) & 0x00ff) << 8);
  1029. return *((T*)&temp);
  1030. }
  1031. template <typename T>
  1032. inline T DWordSwapC( T dw )
  1033. {
  1034. uint32 temp;
  1035. temp = *((uint32 *)&dw) >> 24;
  1036. temp |= ((*((uint32 *)&dw) & 0x00FF0000) >> 8);
  1037. temp |= ((*((uint32 *)&dw) & 0x0000FF00) << 8);
  1038. temp |= ((*((uint32 *)&dw) & 0x000000FF) << 24);
  1039. return *((T*)&temp);
  1040. }
  1041. //-------------------------------------
  1042. // Fast swaps
  1043. //-------------------------------------
  1044. #if defined( COMPILER_MSVCX360 )
  1045. #define WordSwap WordSwap360Intr
  1046. #define DWordSwap DWordSwap360Intr
  1047. template <typename T>
  1048. inline T WordSwap360Intr( T w )
  1049. {
  1050. T output;
  1051. __storeshortbytereverse( w, 0, &output );
  1052. return output;
  1053. }
  1054. template <typename T>
  1055. inline T DWordSwap360Intr( T dw )
  1056. {
  1057. T output;
  1058. __storewordbytereverse( dw, 0, &output );
  1059. return output;
  1060. }
  1061. #elif defined( COMPILER_MSVC32 )
  1062. #define WordSwap WordSwapAsm
  1063. #define DWordSwap DWordSwapAsm
  1064. #pragma warning(push)
  1065. #pragma warning (disable:4035) // no return value
  1066. template <typename T>
  1067. inline T WordSwapAsm( T w )
  1068. {
  1069. __asm
  1070. {
  1071. mov ax, w
  1072. xchg al, ah
  1073. }
  1074. }
  1075. template <typename T>
  1076. inline T DWordSwapAsm( T dw )
  1077. {
  1078. __asm
  1079. {
  1080. mov eax, dw
  1081. bswap eax
  1082. }
  1083. }
  1084. #pragma warning(pop)
  1085. #else
  1086. #define WordSwap WordSwapC
  1087. #define DWordSwap DWordSwapC
  1088. #endif
  1089. //-------------------------------------
  1090. // The typically used methods.
  1091. //-------------------------------------
  1092. #if defined( _SGI_SOURCE ) || defined( PLATFORM_X360 ) || defined( _PS3 )
  1093. #define PLAT_BIG_ENDIAN 1
  1094. #else
  1095. #define PLAT_LITTLE_ENDIAN 1
  1096. #endif
  1097. // If a swapped float passes through the fpu, the bytes may get changed.
  1098. // Prevent this by swapping floats as DWORDs.
  1099. #define SafeSwapFloat( pOut, pIn ) (*((uint*)pOut) = DWordSwap( *((uint*)pIn) ))
  1100. #if defined(PLAT_LITTLE_ENDIAN)
  1101. #define BigShort( val ) WordSwap( val )
  1102. #define BigWord( val ) WordSwap( val )
  1103. #define BigLong( val ) DWordSwap( val )
  1104. #define BigDWord( val ) DWordSwap( val )
  1105. #define LittleShort( val ) ( val )
  1106. #define LittleWord( val ) ( val )
  1107. #define LittleLong( val ) ( val )
  1108. #define LittleDWord( val ) ( val )
  1109. #define SwapShort( val ) BigShort( val )
  1110. #define SwapWord( val ) BigWord( val )
  1111. #define SwapLong( val ) BigLong( val )
  1112. #define SwapDWord( val ) BigDWord( val )
  1113. // Pass floats by pointer for swapping to avoid truncation in the fpu
  1114. #define BigFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn )
  1115. #define LittleFloat( pOut, pIn ) ( *pOut = *pIn )
  1116. #define SwapFloat( pOut, pIn ) BigFloat( pOut, pIn )
  1117. #elif defined(PLAT_BIG_ENDIAN)
  1118. #define BigShort( val ) ( val )
  1119. #define BigWord( val ) ( val )
  1120. #define BigLong( val ) ( val )
  1121. #define BigDWord( val ) ( val )
  1122. #define LittleShort( val ) WordSwap( val )
  1123. #define LittleWord( val ) WordSwap( val )
  1124. #define LittleLong( val ) DWordSwap( val )
  1125. #define LittleDWord( val ) DWordSwap( val )
  1126. #define SwapShort( val ) LittleShort( val )
  1127. #define SwapWord( val ) LittleWord( val )
  1128. #define SwapLong( val ) LittleLong( val )
  1129. #define SwapDWord( val ) LittleDWord( val )
  1130. // Pass floats by pointer for swapping to avoid truncation in the fpu
  1131. #define BigFloat( pOut, pIn ) ( *pOut = *pIn )
  1132. #define LittleFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn )
  1133. #define SwapFloat( pOut, pIn ) LittleFloat( pOut, pIn )
  1134. #else
  1135. // @Note (toml 05-02-02): this technique expects the compiler to
  1136. // optimize the expression and eliminate the other path. On any new
  1137. // platform/compiler this should be tested.
  1138. inline short BigShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; }
  1139. inline uint16 BigWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; }
  1140. inline long BigLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; }
  1141. inline uint32 BigDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; }
  1142. inline short LittleShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); }
  1143. inline uint16 LittleWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); }
  1144. inline long LittleLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); }
  1145. inline uint32 LittleDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); }
  1146. inline short SwapShort( short val ) { return WordSwap( val ); }
  1147. inline uint16 SwapWord( uint16 val ) { return WordSwap( val ); }
  1148. inline long SwapLong( long val ) { return DWordSwap( val ); }
  1149. inline uint32 SwapDWord( uint32 val ) { return DWordSwap( val ); }
  1150. // Pass floats by pointer for swapping to avoid truncation in the fpu
  1151. inline void BigFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? SafeSwapFloat( pOut, pIn ) : ( *pOut = *pIn ); }
  1152. inline void LittleFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? ( *pOut = *pIn ) : SafeSwapFloat( pOut, pIn ); }
  1153. inline void SwapFloat( float *pOut, const float *pIn ) { SafeSwapFloat( pOut, pIn ); }
  1154. #endif
  1155. #if PLAT_BIG_ENDIAN
  1156. #if defined( _PS3 )
  1157. inline uint32 LoadLittleDWord( uint32 *base, unsigned int dwordIndex )
  1158. {
  1159. return __lwbrx( base + dwordIndex );
  1160. }
  1161. inline void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
  1162. {
  1163. __stwbrx( base + dwordIndex, dword );
  1164. }
  1165. inline uint64 LoadLittleInt64( uint64 *base, unsigned int nWordIndex )
  1166. {
  1167. return __ldbrx( base + nWordIndex );
  1168. }
  1169. inline void StoreLittleInt64( uint64 *base, unsigned int nWordIndex, uint64 nWord )
  1170. {
  1171. __stdbrx( base + nWordIndex, nWord );
  1172. }
  1173. #else
  1174. inline uint32 LoadLittleDWord( uint32 *base, unsigned int dwordIndex )
  1175. {
  1176. return __loadwordbytereverse( dwordIndex<<2, base );
  1177. }
  1178. inline void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
  1179. {
  1180. __storewordbytereverse( dword, dwordIndex<<2, base );
  1181. }
  1182. inline uint64 LoadLittleInt64( uint64 *base, unsigned int nWordIndex )
  1183. {
  1184. return __loaddoublewordbytereverse( nWordIndex<<2, base );
  1185. }
  1186. inline void StoreLittleInt64( uint64 *base, unsigned int nWordIndex, uint64 nWord )
  1187. {
  1188. __storedoublewordbytereverse( nWord, nWordIndex<<2, base );
  1189. }
  1190. #endif
  1191. #else
  1192. inline uint32 LoadLittleDWord( uint32 *base, unsigned int dwordIndex )
  1193. {
  1194. return LittleDWord( base[dwordIndex] );
  1195. }
  1196. inline void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
  1197. {
  1198. base[dwordIndex] = LittleDWord(dword);
  1199. }
  1200. #endif
  1201. // When in benchmark mode, the timer returns a simple incremented value each time you call it.
  1202. //
  1203. // It should not be changed after startup unless you really know what you're doing. The only place
  1204. // that should do this is the benchmark code itself so it can output a legit duration.
  1205. PLATFORM_INTERFACE void Plat_SetBenchmarkMode( bool bBenchmarkMode );
  1206. PLATFORM_INTERFACE bool Plat_IsInBenchmarkMode();
  1207. PLATFORM_INTERFACE double Plat_FloatTime(); // Returns time in seconds since the module was loaded.
  1208. PLATFORM_INTERFACE uint32 Plat_MSTime(); // Time in milliseconds.
  1209. PLATFORM_INTERFACE uint64 Plat_GetClockStart(); // Snapshot of the clock when app started.
  1210. PLATFORM_INTERFACE uint64 Timer_GetTimeUS();
  1211. // Get the local calendar time.
  1212. // Same as time() followed by localtime(), but non-crash-prone and threadsafe.
  1213. PLATFORM_INTERFACE void Plat_GetLocalTime( struct tm *pNow );
  1214. // Convert a time_t (specified in nTime - seconds since Jan 1, 1970 UTC) to a local calendar time in a threadsafe and non-crash-prone way.
  1215. PLATFORM_INTERFACE void Plat_ConvertToLocalTime( uint64 nTime, struct tm *pNow );
  1216. // Get a time string (same as ascstring, but threadsafe).
  1217. PLATFORM_INTERFACE void Plat_GetTimeString( struct tm *pTime, char *pOut, int nMaxBytes );
  1218. // converts a time_t to a struct tm without the local time conversion of ConvertToLocalTime
  1219. PLATFORM_INTERFACE void Plat_gmtime( uint64 nTime, struct tm *pTime );
  1220. PLATFORM_INTERFACE time_t Plat_timegm( struct tm *timeptr );
  1221. // Get the process' executable filename.
  1222. PLATFORM_INTERFACE void Plat_GetModuleFilename( char *pOut, int nMaxBytes );
  1223. PLATFORM_INTERFACE void Plat_ExitProcess( int nCode );
  1224. // b/w compatibility
  1225. #define Sys_FloatTime Plat_FloatTime
  1226. // Protect against bad auto operator=
  1227. #define DISALLOW_OPERATOR_EQUAL( _classname ) \
  1228. private: \
  1229. _classname &operator=( const _classname & ); \
  1230. public:
  1231. // Define a reasonable operator=
  1232. #define IMPLEMENT_OPERATOR_EQUAL( _classname ) \
  1233. public: \
  1234. _classname &operator=( const _classname &src ) \
  1235. { \
  1236. memcpy( this, &src, sizeof(_classname) ); \
  1237. return *this; \
  1238. }
  1239. // Processor Information:
  1240. struct CPUInformation
  1241. {
  1242. int m_Size; // Size of this structure, for forward compatability.
  1243. bool m_bRDTSC : 1, // Is RDTSC supported?
  1244. m_bCMOV : 1, // Is CMOV supported?
  1245. m_bFCMOV : 1, // Is FCMOV supported?
  1246. m_bSSE : 1, // Is SSE supported?
  1247. m_bSSE2 : 1, // Is SSE2 Supported?
  1248. m_b3DNow : 1, // Is 3DNow! Supported?
  1249. m_bMMX : 1, // Is MMX supported?
  1250. m_bHT : 1; // Is HyperThreading supported?
  1251. uint8 m_nLogicalProcessors; // Number op logical processors.
  1252. uint8 m_nPhysicalProcessors; // Number of physical processors
  1253. bool m_bSSE3 : 1,
  1254. m_bSSSE3 : 1,
  1255. m_bSSE4a : 1,
  1256. m_bSSE41 : 1,
  1257. m_bSSE42 : 1;
  1258. int64 m_Speed; // In cycles per second.
  1259. tchar* m_szProcessorID; // Processor vendor Identification.
  1260. CPUInformation(): m_Size(0){}
  1261. };
  1262. PLATFORM_INTERFACE const CPUInformation& GetCPUInformation();
  1263. PLATFORM_INTERFACE void GetCurrentDate( int *pDay, int *pMonth, int *pYear );
  1264. PLATFORM_INTERFACE void GetCurrentDayOfTheWeek( int *pDay ); // 0 = Sunday
  1265. PLATFORM_INTERFACE void GetCurrentDayOfTheYear( int *pDay ); // 0 = Jan 1
  1266. // ---------------------------------------------------------------------------------- //
  1267. // Performance Monitoring Events - L2 stats etc...
  1268. // ---------------------------------------------------------------------------------- //
  1269. PLATFORM_INTERFACE void InitPME();
  1270. PLATFORM_INTERFACE void ShutdownPME();
  1271. //-----------------------------------------------------------------------------
  1272. // Security related functions
  1273. //-----------------------------------------------------------------------------
  1274. // Ensure that the hardware key's drivers have been installed.
  1275. PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyDriver();
  1276. // Ok, so this isn't a very secure way to verify the hardware key for now. It
  1277. // is primarially depending on the fact that all the binaries have been wrapped
  1278. // with the secure wrapper provided by the hardware keys vendor.
  1279. PLATFORM_INTERFACE bool Plat_VerifyHardwareKey();
  1280. // The same as above, but notifies user with a message box when the key isn't in
  1281. // and gives him an opportunity to correct the situation.
  1282. PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyPrompt();
  1283. // Can be called in real time, doesn't perform the verify every frame. Mainly just
  1284. // here to allow the game to drop out quickly when the key is removed, rather than
  1285. // allowing the wrapper to pop up it's own blocking dialog, which the engine doesn't
  1286. // like much.
  1287. PLATFORM_INTERFACE bool Plat_FastVerifyHardwareKey();
  1288. //-----------------------------------------------------------------------------
  1289. // Just logs file and line to simple.log
  1290. //-----------------------------------------------------------------------------
  1291. PLATFORM_INTERFACE void* Plat_SimpleLog( const tchar* file, int line );
  1292. #if defined( _X360 )
  1293. #define Plat_FastMemset XMemSet
  1294. #define Plat_FastMemcpy XMemCpy
  1295. #else
  1296. #define Plat_FastMemset memset
  1297. #define Plat_FastMemcpy memcpy
  1298. #endif
  1299. //-----------------------------------------------------------------------------
  1300. // XBOX Components valid in PC compilation space
  1301. //-----------------------------------------------------------------------------
  1302. #define XBOX_DVD_SECTORSIZE 2048
  1303. #define XBOX_DVD_ECC_SIZE 32768 // driver reads in quantum ECC blocks
  1304. #define XBOX_HDD_SECTORSIZE 512
  1305. // Custom windows messages for Xbox input
  1306. #define WM_XREMOTECOMMAND (WM_USER + 100)
  1307. #define WM_XCONTROLLER_KEY (WM_USER + 101)
  1308. #define WM_SYS_UI (WM_USER + 102)
  1309. #define WM_SYS_SIGNINCHANGED (WM_USER + 103)
  1310. #define WM_SYS_STORAGEDEVICESCHANGED (WM_USER + 104)
  1311. #define WM_SYS_PROFILESETTINGCHANGED (WM_USER + 105)
  1312. #define WM_SYS_MUTELISTCHANGED (WM_USER + 106)
  1313. #define WM_SYS_INPUTDEVICESCHANGED (WM_USER + 107)
  1314. #define WM_SYS_INPUTDEVICECONFIGCHANGED (WM_USER + 108)
  1315. #define WM_LIVE_CONNECTIONCHANGED (WM_USER + 109)
  1316. #define WM_LIVE_INVITE_ACCEPTED (WM_USER + 110)
  1317. #define WM_LIVE_LINK_STATE_CHANGED (WM_USER + 111)
  1318. #define WM_LIVE_CONTENT_INSTALLED (WM_USER + 112)
  1319. #define WM_LIVE_MEMBERSHIP_PURCHASED (WM_USER + 113)
  1320. #define WM_LIVE_VOICECHAT_AWAY (WM_USER + 114)
  1321. #define WM_LIVE_PRESENCE_CHANGED (WM_USER + 115)
  1322. #define WM_FRIENDS_PRESENCE_CHANGED (WM_USER + 116)
  1323. #define WM_FRIENDS_FRIEND_ADDED (WM_USER + 117)
  1324. #define WM_FRIENDS_FRIEND_REMOVED (WM_USER + 118)
  1325. #define WM_CUSTOM_GAMEBANNERPRESSED (WM_USER + 119)
  1326. #define WM_CUSTOM_ACTIONPRESSED (WM_USER + 120)
  1327. #define WM_XMP_STATECHANGED (WM_USER + 121)
  1328. #define WM_XMP_PLAYBACKBEHAVIORCHANGED (WM_USER + 122)
  1329. #define WM_XMP_PLAYBACKCONTROLLERCHANGED (WM_USER + 123)
  1330. #define WM_SYS_SHUTDOWNREQUEST (WM_USER + 124)
  1331. #if defined( _PS3 )
  1332. #define PLATFORM_EXT ".ps3"
  1333. #elif defined( PLATFORM_X360 )
  1334. #define PLATFORM_EXT ".360"
  1335. #else
  1336. #define PLATFORM_EXT ""
  1337. #endif
  1338. inline const char *GetPlatformExt( void )
  1339. {
  1340. return PLATFORM_EXT;
  1341. }
  1342. // flat view, 6 hw threads
  1343. #define XBOX_PROCESSOR_0 ( 1<<0 )
  1344. #define XBOX_PROCESSOR_1 ( 1<<1 )
  1345. #define XBOX_PROCESSOR_2 ( 1<<2 )
  1346. #define XBOX_PROCESSOR_3 ( 1<<3 )
  1347. #define XBOX_PROCESSOR_4 ( 1<<4 )
  1348. #define XBOX_PROCESSOR_5 ( 1<<5 )
  1349. // core view, 3 cores with 2 hw threads each
  1350. #define XBOX_CORE_0_HWTHREAD_0 XBOX_PROCESSOR_0
  1351. #define XBOX_CORE_0_HWTHREAD_1 XBOX_PROCESSOR_1
  1352. #define XBOX_CORE_1_HWTHREAD_0 XBOX_PROCESSOR_2
  1353. #define XBOX_CORE_1_HWTHREAD_1 XBOX_PROCESSOR_3
  1354. #define XBOX_CORE_2_HWTHREAD_0 XBOX_PROCESSOR_4
  1355. #define XBOX_CORE_2_HWTHREAD_1 XBOX_PROCESSOR_5
  1356. //-----------------------------------------------------------------------------
  1357. // Include additional dependant header components.
  1358. //-----------------------------------------------------------------------------
  1359. #if defined( PLATFORM_X360 )
  1360. #include "xbox/xbox_core.h"
  1361. #elif defined( PLATFORM_PS3 )
  1362. #include "ps3/ps3_core.h"
  1363. #endif
  1364. //-----------------------------------------------------------------------------
  1365. // Methods to invoke the constructor, copy constructor, and destructor
  1366. //-----------------------------------------------------------------------------
  1367. template <class T>
  1368. inline T* Construct( T* pMemory )
  1369. {
  1370. return ::new( pMemory ) T;
  1371. }
  1372. template <class T, typename ARG1>
  1373. inline T* Construct( T* pMemory, ARG1 a1 )
  1374. {
  1375. return ::new( pMemory ) T( a1 );
  1376. }
  1377. template <class T, typename ARG1, typename ARG2>
  1378. inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2 )
  1379. {
  1380. return ::new( pMemory ) T( a1, a2 );
  1381. }
  1382. template <class T, typename ARG1, typename ARG2, typename ARG3>
  1383. inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3 )
  1384. {
  1385. return ::new( pMemory ) T( a1, a2, a3 );
  1386. }
  1387. template <class T, typename ARG1, typename ARG2, typename ARG3, typename ARG4>
  1388. inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3, ARG4 a4 )
  1389. {
  1390. return ::new( pMemory ) T( a1, a2, a3, a4 );
  1391. }
  1392. template <class T, typename ARG1, typename ARG2, typename ARG3, typename ARG4, typename ARG5>
  1393. inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3, ARG4 a4, ARG5 a5 )
  1394. {
  1395. return ::new( pMemory ) T( a1, a2, a3, a4, a5 );
  1396. }
  1397. template <class T>
  1398. inline T* CopyConstruct( T* pMemory, T const& src )
  1399. {
  1400. return ::new( pMemory ) T(src);
  1401. }
  1402. template <class T>
  1403. inline void Destruct( T* pMemory )
  1404. {
  1405. pMemory->~T();
  1406. #ifdef _DEBUG
  1407. memset( pMemory, 0xDD, sizeof(T) );
  1408. #endif
  1409. }
  1410. //
  1411. // GET_OUTER()
  1412. //
  1413. // A platform-independent way for a contained class to get a pointer to its
  1414. // owner. If you know a class is exclusively used in the context of some
  1415. // "outer" class, this is a much more space efficient way to get at the outer
  1416. // class than having the inner class store a pointer to it.
  1417. //
  1418. // class COuter
  1419. // {
  1420. // class CInner // Note: this does not need to be a nested class to work
  1421. // {
  1422. // void PrintAddressOfOuter()
  1423. // {
  1424. // printf( "Outer is at 0x%x\n", GET_OUTER( COuter, m_Inner ) );
  1425. // }
  1426. // };
  1427. //
  1428. // CInner m_Inner;
  1429. // friend class CInner;
  1430. // };
  1431. #define GET_OUTER( OuterType, OuterMember ) \
  1432. ( ( OuterType * ) ( (uint8 *)this - offsetof( OuterType, OuterMember ) ) )
  1433. /* TEMPLATE_FUNCTION_TABLE()
  1434. (Note added to platform.h so platforms that correctly support templated
  1435. functions can handle portions as templated functions rather than wrapped
  1436. functions)
  1437. Helps automate the process of creating an array of function
  1438. templates that are all specialized by a single integer.
  1439. This sort of thing is often useful in optimization work.
  1440. For example, using TEMPLATE_FUNCTION_TABLE, this:
  1441. TEMPLATE_FUNCTION_TABLE(int, Function, ( int blah, int blah ), 10)
  1442. {
  1443. return argument * argument;
  1444. }
  1445. is equivilent to the following:
  1446. (NOTE: the function has to be wrapped in a class due to code
  1447. generation bugs involved with directly specializing a function
  1448. based on a constant.)
  1449. template<int argument>
  1450. class FunctionWrapper
  1451. {
  1452. public:
  1453. int Function( int blah, int blah )
  1454. {
  1455. return argument*argument;
  1456. }
  1457. }
  1458. typedef int (*FunctionType)( int blah, int blah );
  1459. class FunctionName
  1460. {
  1461. public:
  1462. enum { count = 10 };
  1463. FunctionType functions[10];
  1464. };
  1465. FunctionType FunctionName::functions[] =
  1466. {
  1467. FunctionWrapper<0>::Function,
  1468. FunctionWrapper<1>::Function,
  1469. FunctionWrapper<2>::Function,
  1470. FunctionWrapper<3>::Function,
  1471. FunctionWrapper<4>::Function,
  1472. FunctionWrapper<5>::Function,
  1473. FunctionWrapper<6>::Function,
  1474. FunctionWrapper<7>::Function,
  1475. FunctionWrapper<8>::Function,
  1476. FunctionWrapper<9>::Function
  1477. };
  1478. */
  1479. PLATFORM_INTERFACE bool vtune( bool resume );
  1480. #define TEMPLATE_FUNCTION_TABLE(RETURN_TYPE, NAME, ARGS, COUNT) \
  1481. \
  1482. typedef RETURN_TYPE (FASTCALL *__Type_##NAME) ARGS; \
  1483. \
  1484. template<const int nArgument> \
  1485. struct __Function_##NAME \
  1486. { \
  1487. static RETURN_TYPE FASTCALL Run ARGS; \
  1488. }; \
  1489. \
  1490. template <const int i> \
  1491. struct __MetaLooper_##NAME : __MetaLooper_##NAME<i-1> \
  1492. { \
  1493. __Type_##NAME func; \
  1494. inline __MetaLooper_##NAME() { func = __Function_##NAME<i>::Run; } \
  1495. }; \
  1496. \
  1497. template<> \
  1498. struct __MetaLooper_##NAME<0> \
  1499. { \
  1500. __Type_##NAME func; \
  1501. inline __MetaLooper_##NAME() { func = __Function_##NAME<0>::Run; } \
  1502. }; \
  1503. \
  1504. class NAME \
  1505. { \
  1506. private: \
  1507. static const __MetaLooper_##NAME<COUNT> m; \
  1508. public: \
  1509. enum { count = COUNT }; \
  1510. static const __Type_##NAME* functions; \
  1511. }; \
  1512. const __MetaLooper_##NAME<COUNT> NAME::m; \
  1513. const __Type_##NAME* NAME::functions = (__Type_##NAME*)&m; \
  1514. template<const int nArgument> \
  1515. RETURN_TYPE FASTCALL __Function_##NAME<nArgument>::Run ARGS
  1516. #define LOOP_INTERCHANGE(BOOLEAN, CODE)\
  1517. if( (BOOLEAN) )\
  1518. {\
  1519. CODE;\
  1520. } else\
  1521. {\
  1522. CODE;\
  1523. }
  1524. //-----------------------------------------------------------------------------
  1525. // Dynamic libs support
  1526. //-----------------------------------------------------------------------------
  1527. #if defined( PLATFORM_WINDOWS )
  1528. PLATFORM_INTERFACE void *Plat_GetProcAddress( const char *pszModule, const char *pszName );
  1529. template <typename FUNCPTR_TYPE>
  1530. class CDynamicFunction
  1531. {
  1532. public:
  1533. CDynamicFunction( const char *pszModule, const char *pszName, FUNCPTR_TYPE pfnFallback = NULL )
  1534. {
  1535. m_pfn = pfnFallback;
  1536. void *pAddr = Plat_GetProcAddress( pszModule, pszName );
  1537. if ( pAddr )
  1538. {
  1539. m_pfn = (FUNCPTR_TYPE)pAddr;
  1540. }
  1541. }
  1542. operator bool() { return m_pfn != NULL; }
  1543. bool operator !() { return !m_pfn; }
  1544. operator FUNCPTR_TYPE() { return m_pfn; }
  1545. private:
  1546. FUNCPTR_TYPE m_pfn;
  1547. };
  1548. #endif
  1549. //-----------------------------------------------------------------------------
  1550. // What OS version are we?
  1551. //-----------------------------------------------------------------------------
  1552. enum PlatOSVersion_t
  1553. {
  1554. PLAT_OS_VERSION_UNKNOWN = -1,
  1555. // X360-specific versions
  1556. PLAT_OS_VERSION_XBOX360 = 0,
  1557. // PC-specific OS versions
  1558. PLAT_OS_VERSION_XP = 5,
  1559. PLAT_OS_VERSION_VISTA = 6,
  1560. };
  1561. PLATFORM_INTERFACE PlatOSVersion_t Plat_GetOSVersion();
  1562. // Watchdog timer support. Call BeginWatchdogTimer( nn ) to kick the timer off. if you don't call
  1563. // EndWatchdogTimer within nn seconds, the program will kick off an exception. This is for making
  1564. // sure that hung dedicated servers abort (and restart) instead of staying hung. Calling
  1565. // EndWatchdogTimer more than once or when there is no active watchdog is fine. Only does anything
  1566. // under linux right now. It should be possible to implement this functionality in windows via a
  1567. // thread, if desired.
  1568. #if defined( POSIX ) && !defined( _PS3 )
  1569. PLATFORM_INTERFACE void BeginWatchdogTimer( int nSecs );
  1570. PLATFORM_INTERFACE void EndWatchdogTimer( void );
  1571. PLATFORM_INTERFACE void ResetBaseTime( void ); // reset plat_floattime to 0 for a subprocess
  1572. #else
  1573. FORCEINLINE void BeginWatchdogTimer( int nSecs )
  1574. {
  1575. }
  1576. FORCEINLINE void EndWatchdogTimer( void )
  1577. {
  1578. }
  1579. FORCEINLINE void ResetBaseTime( void ) // reset plat_floattime to 0 for a subprocess
  1580. {
  1581. }
  1582. #endif
  1583. #ifdef COMPILER_MSVC
  1584. /*
  1585. FORCEINLINE uint8 RotateBitsLeft8( uint8 nValue, int nRotateBits )
  1586. {
  1587. return _rotl8( nValue, nRotateBits );
  1588. }
  1589. FORCEINLINE uint16 RotateBitsLeft16( uint16 nValue, int nRotateBits )
  1590. {
  1591. return _rotl( nValue, nRotateBits );
  1592. }
  1593. FORCEINLINE uint8 RotateBitsRight8( uint8 nValue, int nRotateBits )
  1594. {
  1595. return _rotr8( nValue, nRotateBits );
  1596. }
  1597. FORCEINLINE uint16 RotateBitsRight16( uint16 nValue, int nRotateBits )
  1598. {
  1599. return _rotr16( nValue, nRotateBits );
  1600. }
  1601. */
  1602. FORCEINLINE uint32 RotateBitsLeft32( uint32 nValue, int nRotateBits )
  1603. {
  1604. return _rotl( nValue, nRotateBits );
  1605. }
  1606. FORCEINLINE uint64 RotateBitsLeft64( uint64 nValue, int nRotateBits )
  1607. {
  1608. return _rotl64( nValue, nRotateBits );
  1609. }
  1610. FORCEINLINE uint32 RotateBitsRight32( uint32 nValue, int nRotateBits )
  1611. {
  1612. return _rotr( nValue, nRotateBits );
  1613. }
  1614. FORCEINLINE uint64 RotateBitsRight64( uint64 nValue, int nRotateBits )
  1615. {
  1616. return _rotr64( nValue, nRotateBits );
  1617. }
  1618. #else
  1619. // GCC should compile this all into single instruction
  1620. /*
  1621. FORCEINLINE uint8 RotateBitsLeft8( uint8 nValue, int nRotateBits )
  1622. {
  1623. return ( nValue << nRotateBits ) | ( nValue >> ( ( -nRotateBits ) & 7 ) );
  1624. }
  1625. FORCEINLINE uint16 RotateBitsLeft16( uint16 nValue, int nRotateBits )
  1626. {
  1627. return ( nValue << nRotateBits ) | ( nValue >> ( ( -nRotateBits ) & 15 ) );
  1628. }
  1629. FORCEINLINE uint8 RotateBitsRight8( uint8 nValue, int nRotateBits )
  1630. {
  1631. return ( nValue >> nRotateBits ) | ( nValue << ( ( -nRotateBits ) & 7 ) );
  1632. }
  1633. FORCEINLINE uint16 RotateBitsRight16( uint16 nValue, int nRotateBits )
  1634. {
  1635. return ( nValue >> nRotateBits ) | ( nValue << ( ( -nRotateBits ) & 15 ) );
  1636. }
  1637. */
  1638. FORCEINLINE uint32 RotateBitsLeft32( uint32 nValue, int nRotateBits )
  1639. {
  1640. return ( nValue << nRotateBits ) | ( nValue >> ( ( -nRotateBits ) & 31 ) );
  1641. }
  1642. FORCEINLINE uint64 RotateBitsLeft64( uint64 nValue, int nRotateBits )
  1643. {
  1644. return ( nValue << nRotateBits ) | ( nValue >> ( ( - nRotateBits ) & 63 ) );
  1645. }
  1646. FORCEINLINE uint32 RotateBitsRight32( uint32 nValue, int nRotateBits )
  1647. {
  1648. return ( nValue >> nRotateBits ) | ( nValue << ( ( -nRotateBits ) & 31 ) );
  1649. }
  1650. FORCEINLINE uint64 RotateBitsRight64( uint64 nValue, int nRotateBits )
  1651. {
  1652. return ( nValue >> nRotateBits ) | ( nValue << ( ( - nRotateBits ) & 63 ) );
  1653. }
  1654. #endif
  1655. PLATFORM_INTERFACE const char * GetPlatformSpecificFileName(const char * FileName);
  1656. #include "tier0/valve_on.h"
  1657. #if defined(TIER0_DLL_EXPORT)
  1658. extern "C" int V_tier0_stricmp(const char *s1, const char *s2 );
  1659. #undef stricmp
  1660. #undef strcmpi
  1661. #define stricmp(s1,s2) V_tier0_stricmp( s1, s2 )
  1662. #define strcmpi(s1,s2) V_tier0_stricmp( s1, s2 )
  1663. #else
  1664. int _V_stricmp (const char *s1, const char *s2 );
  1665. int V_strncasecmp (const char *s1, const char *s2, int n);
  1666. // A special high-performance case-insensitive compare function that in
  1667. // a single call distinguishes between exactly matching strings,
  1668. // strings equal in case-insensitive way, and not equal strings:
  1669. // returns 0 if strings match exactly
  1670. // returns >0 if strings match in a case-insensitive way, but do not match exactly
  1671. // returns <0 if strings do not match even in a case-insensitive way
  1672. int _V_stricmp_NegativeForUnequal ( const char *s1, const char *s2 );
  1673. #undef stricmp
  1674. #undef strcmpi
  1675. #define stricmp(s1,s2) _V_stricmp(s1, s2)
  1676. #define strcmpi(s1,s2) _V_stricmp(s1, s2)
  1677. #undef strnicmp
  1678. #define strnicmp V_strncasecmp
  1679. #endif
  1680. #endif /* PLATFORM_H */