Counter Strike : Global Offensive Source Code
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.

2568 lines
82 KiB

  1. //===== Copyright 1996-2005, 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( LINUX ) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
  14. // based on some Jonathan Wakely macros on the net...
  15. #define GCC_DIAG_STR(s) #s
  16. #define GCC_DIAG_JOINSTR(x,y) GCC_DIAG_STR(x ## y)
  17. #define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x)
  18. #define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
  19. #define GCC_DIAG_PUSH_OFF(x) GCC_DIAG_PRAGMA(push) GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x))
  20. #define GCC_DIAG_POP() GCC_DIAG_PRAGMA(pop)
  21. #else
  22. #define GCC_DIAG_PUSH_OFF(x)
  23. #define GCC_DIAG_POP()
  24. #endif
  25. #ifdef LINUX
  26. #pragma GCC diagnostic ignored "-Wconversion-null" // passing NULL to non-pointer argument 1
  27. #pragma GCC diagnostic ignored "-Wpointer-arith" // NULL used in arithmetic. Ie, vpanel == NULL where VPANEL is uint.
  28. #endif
  29. #ifdef _DEBUG
  30. #if !defined( PLAT_COMPILE_TIME_ASSERT )
  31. #define PLAT_COMPILE_TIME_ASSERT( pred ) switch(0){case 0:case pred:;}
  32. #endif
  33. #else
  34. #if !defined( PLAT_COMPILE_TIME_ASSERT )
  35. #define PLAT_COMPILE_TIME_ASSERT( pred )
  36. #endif
  37. #endif
  38. #ifdef SN_TARGET_PS3
  39. //#define NO_STEAM
  40. #define NO_STEAM_PS3_OVERLAY
  41. #define _PS3 1
  42. #define COMPILER_PS3 1
  43. #define PLATFORM_PS3 1
  44. // There are 2 compilers for the PS3: GCC and the SN Systems compiler.
  45. // They are mostly similar, but in a few places we need to distinguish between the two.
  46. #if defined( __SNC__ )
  47. #define COMPILER_SNC 1
  48. #elif defined( __GCC__ )
  49. #define COMPILER_GCC 1
  50. #else
  51. #error "Unrecognized PS3 compiler; either __SNC__ or __GCC__ must be defined"
  52. #endif
  53. #endif // SN_TARGET_PS3
  54. #ifdef __GCC__
  55. #define COMPILER_GCC 1
  56. #endif
  57. #if defined( _X360 ) || defined( _PS3 )
  58. #define PLATFORM_PPC 1
  59. #endif
  60. #ifdef COMPILER_MSVC
  61. #pragma once
  62. #endif
  63. #if defined (_PS3)
  64. #if defined( __SPU__ )
  65. #include <spu_intrinsics.h>
  66. #include <vmx2spu.h>
  67. #include <vec_types.h>
  68. #else
  69. #include <ppu_intrinsics.h>
  70. // We want to force the assert to be redefined, because the STD assert might have been
  71. // included and redefined. ps3_assert.h will do a check for assert being redefined.
  72. // #include "ps3/ps3_assert.h"
  73. #ifndef COMPILER_PS3
  74. #error "for PS3, VPC must define COMPILER_PS3 macro just like it does for COMPILER_MSVCX360 macro"
  75. #endif
  76. #if !defined( COMPILER_SNC ) && !defined( COMPILER_GCC )
  77. #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"
  78. #endif
  79. #endif
  80. #elif defined( _X360 )
  81. #define NO_STEAM
  82. #define NO_VOICE
  83. // for the 360, the ppc platform and the rtos are tightly coupled
  84. // setup the 360 environment here !once! for much less leaf module include wackiness
  85. // these are critical order and purposely appear *before* anything else
  86. #define _XBOX
  87. #include <xaudio2.h>
  88. #include <xbdm.h>
  89. #include <xgraphics.h>
  90. #include <xui.h>
  91. #include <pmcpbsetup.h>
  92. #include <xmahardwareabstraction.h>
  93. #undef _XBOX
  94. #endif
  95. #include "wchartypes.h"
  96. #include "tier0/valve_off.h"
  97. #ifdef _PS3
  98. #include "ps3/ps3_platform.h"
  99. // symbol redefinition was the source of many PS3 compile warnings
  100. #if !defined( NO_STEAM_GAMECOORDINATOR )
  101. #define NO_STEAM_GAMECOORDINATOR
  102. #endif
  103. #else
  104. // No game coordinator for Partner depot
  105. #if !defined( NO_STEAM_GAMECOORDINATOR )
  106. #define NO_STEAM_GAMECOORDINATOR
  107. #endif
  108. #include <malloc.h>
  109. #include <memory.h>
  110. #include <limits.h>
  111. #include <float.h>
  112. #include <stdlib.h>
  113. #include <string.h>
  114. #if defined( OSX ) || defined ( _LINUX )
  115. #include <signal.h>
  116. #include <stdarg.h>
  117. #endif
  118. #endif
  119. // This macro
  120. #if defined( _PS3 ) && defined ( COMPILER_SNC )
  121. // There are known bugs in the PS3 optimizer. The following macros allow us to lower optimization for a subset of a file
  122. // If you run into build problems with optimization on, try turning off optimization for the selected file. If that
  123. // fixes the problem, use process of elimination and the below macros to find the bare minimum that needs to be
  124. // unoptimized and report the compiler issue to Sony as well.
  125. //
  126. // The correlation between optimization levels and numbers passed to the _Pragma xopt and postopt calls is as follows:
  127. // See: Control-group reference tables / -Xshow
  128. // .... xopt
  129. // -O1 0
  130. // -O2 5
  131. // -O3 5
  132. //
  133. // These macros MUST be used in pairs - Otherwise, the compiler will barf 'At end of source: error 67: expected a "}"'
  134. // xopt disables some of the miscellaneous optimizations
  135. #if __option(xopt)
  136. #define SN_OPT_DISABLE extern "C++" { _Pragma("control %push xopt=0")
  137. #define SN_OPT_ENABLE _Pragma("control %pop xopt") }
  138. #else // !__option(xopt)
  139. #define SN_OPT_DISABLE
  140. #define SN_OPT_ENABLE
  141. #endif // !__option(xopt)
  142. // postopt disables the main optimizer
  143. #if __option(postopt) > 0
  144. #define SN_MAIN_OPT_DISABLE extern "C++" { _Pragma("control %push postopt=0")
  145. #define SN_MAIN_OPT_ENABLE _Pragma("control %pop postopt") }
  146. #else // !__option(postopt) > 0
  147. #define SN_MAIN_OPT_DISABLE
  148. #define SN_MAIN_OPT_ENABLE
  149. #endif // !__option(postopt) > 0
  150. #else // ! ( _PS3 && COMPILER_SNC )
  151. #define SN_OPT_DISABLE
  152. #define SN_OPT_ENABLE
  153. #define SN_MAIN_OPT_DISABLE
  154. #define SN_MAIN_OPT_ENABLE
  155. #endif // ! ( _PS3 && COMPILER_SNC )
  156. #ifdef __cplusplus
  157. #if defined( COMPILER_GCC ) || defined( COMPILER_PS3 )
  158. #include <new>
  159. #else
  160. #include <new.h>
  161. #endif
  162. #endif
  163. //-----------------------------------------------------------------------------
  164. // Old-school defines we don't want to use moving forward
  165. //-----------------------------------------------------------------------------
  166. #if CROSS_PLATFORM_VERSION < 1
  167. // feature enables
  168. #define NEW_SOFTWARE_LIGHTING
  169. #if !defined( _X360 )
  170. #define SUPPORT_PACKED_STORE
  171. #endif
  172. #if defined( BINK_VIDEO ) && ( defined( _X360 ) || defined( _PS3 ) )
  173. #define BINK_ENABLED_FOR_CONSOLE
  174. #endif
  175. #if defined( _MSC_VER )
  176. #define OVERRIDE override
  177. // warning C4481: nonstandard extension used: override specifier 'override'
  178. #pragma warning(disable : 4481)
  179. #elif defined( __clang__ )
  180. #define OVERRIDE override
  181. // warning: 'override' keyword is a C++11 extension [-Wc++11-extensions]
  182. // Disabling this warning is less intrusive than enabling C++11 extensions
  183. #pragma GCC diagnostic ignored "-Wc++11-extensions"
  184. #else
  185. #define OVERRIDE
  186. #endif
  187. #if _MSC_VER >= 1800
  188. #define VECTORCALL __vectorcall
  189. #else
  190. #define VECTORCALL
  191. #endif
  192. // C functions for external declarations that call the appropriate C++ methods
  193. #ifndef EXPORT
  194. #ifdef _WIN32
  195. #define EXPORT _declspec( dllexport )
  196. #else
  197. #define EXPORT /* */
  198. #endif
  199. #endif
  200. #endif // CROSS_PLATFORM_VERSION < 1
  201. #if defined(_STATIC_LINKED)
  202. #include "staticlink/system.h"
  203. #endif
  204. //-----------------------------------------------------------------------------
  205. // NOTE: All compiler defines are set up in the base VPC scripts
  206. // COMPILER_MSVC, COMPILER_MSVC32, COMPILER_MSVC64, COMPILER_MSVCX360
  207. // COMPILER_GCC
  208. // The rationale for this is that we need COMPILER_MSVC for the pragma blocks
  209. // #pragma once that occur at the top of all header files, therefore we can't
  210. // place the defines for these in here.
  211. //-----------------------------------------------------------------------------
  212. //-----------------------------------------------------------------------------
  213. // Set up platform defines.
  214. //-----------------------------------------------------------------------------
  215. #ifdef _WIN32
  216. #define IsPlatformLinux() 0
  217. #define IsPlatformPosix() 0
  218. #define IsPlatformOSX() 0
  219. #define IsOSXOpenGL() 0
  220. #define IsPlatformPS3() 0
  221. #define IsPlatformPS3_PPU() 0
  222. #define IsPlatformPS3_SPU() 0
  223. #define PLATFORM_WINDOWS 1
  224. #define PLATFORM_OPENGL 0
  225. #ifndef _X360
  226. #define IsPlatformX360() 0
  227. #define IsPlatformWindowsPC() 1
  228. #define PLATFORM_WINDOWS_PC 1
  229. #ifdef _WIN64
  230. #define IsPlatformWindowsPC64() 1
  231. #define IsPlatformWindowsPC32() 0
  232. #define PLATFORM_WINDOWS_PC64 1
  233. #else
  234. #define IsPlatformWindowsPC64() 0
  235. #define IsPlatformWindowsPC32() 1
  236. #define PLATFORM_WINDOWS_PC32 1
  237. #endif
  238. #else // _X360
  239. #define IsPlatformWindowsPC() 0
  240. #define IsPlatformWindowsPC64() 0
  241. #define IsPlatformWindowsPC32() 0
  242. #define IsPlatformX360() 1
  243. #define PLATFORM_X360 1
  244. #endif // _X360
  245. #elif defined(_PS3)
  246. // Adding IsPlatformOpenGL() to help fix a bunch of code that was using IsPosix() to infer if the DX->GL translation layer was being used.
  247. #if defined( DX_TO_GL_ABSTRACTION )
  248. #define IsPlatformOpenGL() true
  249. #else
  250. #define IsPlatformOpenGL() false
  251. #endif
  252. #define IsPlatformX360() 0
  253. #define IsPlatformPS3() 1
  254. #ifdef SPU
  255. #define IsPlatformPS3_PPU() 0
  256. #define IsPlatformPS3_SPU() 1
  257. #else
  258. #define IsPlatformPS3_PPU() 1
  259. #define IsPlatformPS3_SPU() 0
  260. #endif
  261. #define IsPlatformWindowsPC() 0
  262. #define IsPlatformWindowsPC64() 0
  263. #define IsPlatformWindowsPC32() 0
  264. #define IsPlatformPosix() 1
  265. #define PLATFORM_POSIX 1
  266. #define PLATFORM_OPENGL 0
  267. #define IsPlatformLinux() 0
  268. #define IsPlatformOSX() 0
  269. #define IsOSXOpenGL() 0
  270. #elif defined(POSIX)
  271. #define IsPlatformX360() 0
  272. #define IsPlatformPS3() 0
  273. #define IsPlatformPS3_PPU() 0
  274. #define IsPlatformPS3_SPU() 0
  275. #define IsPlatformWindowsPC() 0
  276. #define IsPlatformWindowsPC64() 0
  277. #define IsPlatformWindowsPC32() 0
  278. #define IsPlatformPosix() 1
  279. #define PLATFORM_POSIX 1
  280. #if defined( LINUX ) && !defined( OSX ) // for havok we define both symbols, so don't let the osx build wander down here
  281. #define IsPlatformLinux() 1
  282. #define IsPlatformOSX() 0
  283. #define IsOSXOpenGL() 0
  284. #define PLATFORM_OPENGL 0
  285. #define PLATFORM_LINUX 1
  286. #elif defined ( OSX )
  287. #define IsPlatformLinux() 0
  288. #define IsPlatformOSX() 1
  289. #define IsOSXOpenGL() 1
  290. #define PLATFORM_OSX 1
  291. #define PLATFORM_OPENGL 1
  292. #else
  293. #define IsPlatformLinux() 0
  294. #define IsPlatformOSX() 0
  295. #define IsOSXOpenGL() 0
  296. #define PLATFORM_OPENGL 0
  297. #endif
  298. #else
  299. #error
  300. #endif
  301. // IsXXXX platform pseudo-functions
  302. #if ( defined( PLATFORM_WINDOWS ) && ( PLATFORM_WINDOWS ) )
  303. #define IsPlatformWindows() 1
  304. #else
  305. #define IsPlatformWindows() 0
  306. #endif
  307. #ifndef _PS3
  308. //#include <malloc.h>
  309. //#include <new.h>
  310. #else
  311. #include <stdlib.h> // For malloc()
  312. #include <alloca.h> // for alloca()
  313. #define _alloca alloca
  314. #ifdef __cplusplus
  315. #include <new>
  316. #endif
  317. #endif
  318. #ifndef _PS3
  319. //#include <malloc.h>
  320. //#include <new.h>
  321. #else
  322. #include <stdlib.h> // For malloc()
  323. #include <alloca.h> // for alloca()
  324. #define _alloca alloca
  325. #ifdef __cplusplus
  326. #include <new>
  327. #endif
  328. #endif
  329. //-----------------------------------------------------------------------------
  330. // Old-school defines we're going to support since much code uses them
  331. //-----------------------------------------------------------------------------
  332. #if CROSS_PLATFORM_VERSION < 2
  333. #define IsLinux() IsPlatformLinux()
  334. #define IsOSX() IsPlatformOSX()
  335. #define IsPosix() IsPlatformPosix()
  336. #define IsX360() IsPlatformX360()
  337. #define IsPS3() IsPlatformPS3()
  338. // Setup platform defines.
  339. #ifdef COMPILER_MSVC
  340. #define MSVC 1
  341. #endif
  342. #ifdef COMPILER_GCC
  343. #define GNUC 1
  344. #endif
  345. #if defined( _WIN32 )
  346. #define _WINDOWS 1
  347. #endif
  348. #ifdef PLATFORM_WINDOWS_PC
  349. #define IS_WINDOWS_PC 1
  350. #endif
  351. #endif // CROSS_PLATFORM_VERSION < 2
  352. // VXConsole is enabled for...
  353. #if defined(_X360) || defined(_PS3)
  354. #define USE_VXCONSOLE 1
  355. #define HasVxConsole() 1
  356. #else
  357. #define HasVxConsole() 0
  358. #endif
  359. //-----------------------------------------------------------------------------
  360. // Set up platform type defines.
  361. //-----------------------------------------------------------------------------
  362. #if defined( PLATFORM_X360 ) || defined( _PS3 )
  363. #ifndef _GAMECONSOLE
  364. #define _GAMECONSOLE
  365. #endif
  366. #define IsPC() 0
  367. #define IsGameConsole() 1
  368. #else
  369. #define IsPC() 1
  370. #define IsGameConsole() 0
  371. #endif
  372. //-----------------------------------------------------------------------------
  373. // Set up build configuration defines.
  374. //-----------------------------------------------------------------------------
  375. #ifdef _CERT
  376. #define IsCert() 1
  377. #else
  378. #define IsCert() 0
  379. #endif
  380. #ifdef _DEBUG
  381. #define IsRelease() 0
  382. #define IsDebug() 1
  383. #else
  384. #define IsRelease() 1
  385. #define IsDebug() 0
  386. #endif
  387. #ifdef _RETAIL
  388. #define IsRetail() 1
  389. #else
  390. #define IsRetail() 0
  391. #endif
  392. //-----------------------------------------------------------------------------
  393. // Portable data types
  394. //-----------------------------------------------------------------------------
  395. typedef unsigned char uint8;
  396. typedef signed char int8;
  397. #if defined( COMPILER_MSVC )
  398. typedef __int16 int16;
  399. typedef unsigned __int16 uint16;
  400. typedef __int32 int32;
  401. typedef unsigned __int32 uint32;
  402. typedef __int64 int64;
  403. typedef unsigned __int64 uint64;
  404. // intp is an integer that can accomodate a pointer
  405. // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *)
  406. typedef intptr_t intp;
  407. typedef uintptr_t uintp;
  408. #if defined( COMPILER_MSVCX360 )
  409. #ifdef __m128
  410. #undef __m128
  411. #endif
  412. #define __m128 __vector4
  413. #endif
  414. // Use this to specify that a function is an override of a virtual function.
  415. // This lets the compiler catch cases where you meant to override a virtual
  416. // function but you accidentally changed the function signature and created
  417. // an overloaded function. Usage in function declarations is like this:
  418. // int GetData() const OVERRIDE;
  419. #define OVERRIDE override
  420. #else // !COMPILER_MSVC
  421. typedef short int16;
  422. typedef unsigned short uint16;
  423. typedef int int32;
  424. typedef unsigned int uint32;
  425. typedef long long int64;
  426. typedef unsigned long long uint64;
  427. #ifdef PLATFORM_64BITS
  428. typedef long long intp;
  429. typedef unsigned long long uintp;
  430. #else
  431. typedef int intp;
  432. typedef unsigned int uintp;
  433. #endif
  434. typedef void *HWND;
  435. // [u]int64 are actually defined as 'long long' and gcc 64-bit
  436. // doesn't automatically consider them the same as 'long int'.
  437. // Changing the types for [u]int64 is complicated by
  438. // there being many definitions, so we just
  439. // define a 'long int' here and use it in places that would
  440. // otherwise confuse the compiler.
  441. typedef long int lint64;
  442. typedef unsigned long int ulint64;
  443. #ifndef OVERRIDE // suppress redifinition warning (because we don't have CROSS_PLATFORM_VERSION defined)
  444. #define OVERRIDE
  445. #endif
  446. #endif // else COMPILER_MSVC
  447. #if defined(_PS3) && !defined(NO_SIMD)
  448. typedef union __attribute__ ((aligned (16)))
  449. {
  450. float m128_f32[4];
  451. } l_m128;
  452. typedef __vector float __vector4;
  453. typedef __vector4 __m128;
  454. const __m128 VMX_ZERO=(vector float)(0.0f);
  455. const __m128 VMX_ONE_HALF=(vector float)(0.5f);
  456. const __m128 VMX_ONE=(vector float)(1.0f);
  457. // Syntaxic sugar for multiply
  458. inline __attribute__ ((always_inline)) __m128 __vec_mul(const __m128 a, const __m128 b)
  459. {
  460. return vec_madd(a,b,VMX_ZERO);
  461. }
  462. // Refined reciprocal function
  463. inline __attribute__ ((always_inline)) __m128 __vec_rec(const __m128 a)
  464. {
  465. //Get the reciprocal estimate
  466. vector float estimate = vec_re( a );
  467. //One round of Newton-Raphson refinement
  468. return vec_madd( vec_nmsub( estimate, a, VMX_ONE ), estimate, estimate );
  469. }
  470. // refined reciprocal square root
  471. inline __attribute__ ((always_inline)) __m128 __vec_rsqrt(const __m128 a)
  472. {
  473. //Get the square root reciprocal estimate
  474. __m128 estimate = vec_rsqrte( a );
  475. //One round of Newton-Raphson refinement
  476. __m128 estimateSquared = __vec_mul( estimate, estimate);
  477. __m128 halfEstimate = __vec_mul( estimate, VMX_ONE_HALF);
  478. return vec_madd( vec_nmsub( a, estimateSquared, VMX_ONE ), halfEstimate, estimate );
  479. }
  480. // refined square root
  481. inline __attribute__ ((always_inline)) __m128 __vec_sqrt(const __m128 a)
  482. {
  483. return __vec_mul( a, __vec_rsqrt( a ));
  484. }
  485. // estimate square root
  486. inline __attribute__ ((always_inline)) __m128 __vec_sqrtest(const __m128 a)
  487. {
  488. return __vec_mul( a, vec_rsqrte( a ));
  489. }
  490. // Syntaxic sugar for multiply
  491. inline __attribute__ ((always_inline)) __m128 __vec_div(const __m128 a, const __m128 b)
  492. {
  493. return __vec_mul( a, __vec_rec( b ));
  494. }
  495. // load an unaligned array of float in a vector of floats
  496. #if defined( __SPU__ )
  497. inline __attribute__ ((always_inline)) __m128 __vec_ld_unaligned(float* in)
  498. #else
  499. inline __attribute__ ((always_inline)) __m128 __vec_ld_unaligned(const float* in)
  500. #endif
  501. {
  502. return vec_perm(vec_ld(0,in),
  503. vec_ld(sizeof(__m128),in),
  504. vec_lvsl( 0, in ));
  505. }
  506. // load an unaligned array of 3 floats in a vector of floats, last member being 0.
  507. #if defined( __SPU__ )
  508. inline __attribute__ ((always_inline)) __m128 __vec_ld_unaligned3(float* in)
  509. #else
  510. inline __attribute__ ((always_inline)) __m128 __vec_ld_unaligned3(const float* in)
  511. #endif
  512. {
  513. return vec_and(__vec_ld_unaligned(in),(__m128)(vector unsigned int)(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF ,0));
  514. }
  515. // stores a vector of floats in an unaligned array of float
  516. inline __attribute__ ((always_inline)) void __vec_st_unaligned(__m128 in, float* out)
  517. {
  518. __m128 temp0 = vec_ld(0,out);
  519. __m128 temp1 = vec_ld(16,out);
  520. vector unsigned char align = vec_lvsr(0,out);
  521. vector unsigned char mask = vec_perm ((vector unsigned char)(0), (vector unsigned char)(0xFF), align);
  522. in = vec_perm ( in, in, align);
  523. #if defined(__SPU__)
  524. temp0 = vec_sel ( temp0, in, (vec_bint4)mask);
  525. temp1 = vec_sel ( in, temp1, (vec_bint4)mask);
  526. #else
  527. temp0 = vec_sel ( temp0, in, (vector bool)mask);
  528. temp1 = vec_sel ( in, temp1, (vector bool)mask);
  529. #endif
  530. vec_st ( temp0, 0, out);
  531. vec_st ( temp1, 16, out);
  532. }
  533. // stores x,y,z from a vector of floats in an unaligned array of 3 floats
  534. inline __attribute__ ((always_inline)) void __vec_st_unaligned3(__m128 in, float* out)
  535. {
  536. __m128 temp0 = vec_ld(0,out);
  537. __m128 temp1 = vec_ld(16,out);
  538. vector unsigned char align = vec_lvsr(0,out);
  539. vector unsigned char mask = vec_perm ((vector unsigned char)(0),
  540. (vector unsigned char)(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0,0,0),
  541. align);
  542. in = vec_perm ( in, in, align);
  543. #if defined(__SPU__)
  544. temp0 = vec_sel ( temp0, in, (vec_bint4)mask);
  545. temp1 = vec_sel ( in, temp1, (vec_bint4)mask);
  546. #else
  547. temp0 = vec_sel ( temp0, in, (vector bool)mask);
  548. temp1 = vec_sel ( in, temp1, (vector bool)mask);
  549. #endif
  550. vec_st ( temp0, 0, out);
  551. vec_st ( temp1, 16, out);
  552. }
  553. #endif // defined(NO_SIMD)
  554. typedef float float32;
  555. typedef double float64;
  556. // for when we don't care about how many bits we use
  557. typedef unsigned int uint;
  558. #ifdef PLATFORM_POSIX
  559. #ifndef _PS3
  560. typedef unsigned int DWORD;
  561. typedef unsigned int *LPDWORD;
  562. #endif
  563. typedef unsigned short WORD;
  564. typedef void * HINSTANCE;
  565. #define _MAX_PATH PATH_MAX
  566. #endif
  567. // MSVC CRT uses 0x7fff while gcc uses MAX_INT, leading to mismatches between platforms
  568. // As a result, we pick the least common denominator here. This should be used anywhere
  569. // you might typically want to use RAND_MAX
  570. #define VALVE_RAND_MAX 0x7fff
  571. // Maximum and minimum representable values
  572. #ifndef PLATFORM_OSX
  573. #if _MSC_VER >= 1800 // VS 2013 or higher
  574. // Copied from stdint.h
  575. #define INT8_MIN (-127i8 - 1)
  576. #define INT16_MIN (-32767i16 - 1)
  577. #define INT32_MIN (-2147483647i32 - 1)
  578. #define INT64_MIN (-9223372036854775807i64 - 1)
  579. #define INT8_MAX 127i8
  580. #define INT16_MAX 32767i16
  581. #define INT32_MAX 2147483647i32
  582. #define INT64_MAX 9223372036854775807i64
  583. #define UINT8_MAX 0xffui8
  584. #define UINT16_MAX 0xffffui16
  585. #define UINT32_MAX 0xffffffffui32
  586. #define UINT64_MAX 0xffffffffffffffffui64
  587. #else // _MSC_VER
  588. #define INT8_MAX SCHAR_MAX
  589. #define INT16_MAX SHRT_MAX
  590. #define INT32_MAX LONG_MAX
  591. #define INT64_MAX ((int64)0x7fffffffffffffffll)
  592. #define INT8_MIN SCHAR_MIN
  593. #define INT16_MIN SHRT_MIN
  594. #define INT32_MIN LONG_MIN
  595. #define INT64_MIN (((int64)1) << 63)
  596. #define UINT8_MAX ((uint8)~0)
  597. #define UINT16_MAX ((uint16)~0)
  598. #define UINT32_MAX ((uint32)~0)
  599. #define UINT64_MAX ((uint64)~0)
  600. #endif
  601. #define UINT8_MIN 0
  602. #define UINT16_MIN 0
  603. #define UINT32_MIN 0
  604. #define UINT64_MIN 0
  605. #endif // PLATFORM_OSX
  606. #ifndef UINT_MIN
  607. #define UINT_MIN UINT32_MIN
  608. #endif
  609. #define FLOAT32_MAX FLT_MAX
  610. #define FLOAT64_MAX DBL_MAX
  611. #ifdef GNUC
  612. #undef offsetof
  613. // Note: can't use builtin offsetof because many use cases (esp. in templates) wouldn't compile due to restrictions on the builtin offsetof
  614. //#define offsetof( type, var ) __builtin_offsetof( type, var )
  615. #define offsetof(s,m) ( (size_t)&(((s *)0x1000000)->m) - 0x1000000u )
  616. #else
  617. #include <stddef.h>
  618. #undef offsetof
  619. #define offsetof(s,m) (size_t)&(((s *)0)->m)
  620. #endif
  621. #define FLOAT32_MIN FLT_MIN
  622. #define FLOAT64_MIN DBL_MIN
  623. //-----------------------------------------------------------------------------
  624. // Long is evil because it's treated differently by different compilers
  625. // Preventing its use is nasty however. This #define, which should be
  626. // turned on in individual VPC files, causes you to include tier0/valve_off.h
  627. // before standard C + windows headers, and include tier0/valve_on.h after
  628. // standard C + windows headers. So, there's some painful overhead to disabling long
  629. //-----------------------------------------------------------------------------
  630. #ifdef DISALLOW_USE_OF_LONG
  631. #define long long_is_the_devil_stop_using_it_use_int32_or_int64
  632. #endif
  633. //-----------------------------------------------------------------------------
  634. // Various compiler-specific keywords
  635. //-----------------------------------------------------------------------------
  636. #ifdef COMPILER_MSVC
  637. #ifdef FORCEINLINE
  638. #undef FORCEINLINE
  639. #endif
  640. #define STDCALL __stdcall
  641. #ifndef FASTCALL
  642. #define FASTCALL __fastcall
  643. #endif
  644. #define FORCEINLINE __forceinline
  645. #define FORCEINLINE_TEMPLATE __forceinline
  646. #define NULLTERMINATED __nullterminated
  647. // This can be used to ensure the size of pointers to members when declaring
  648. // a pointer type for a class that has only been forward declared
  649. #define SINGLE_INHERITANCE __single_inheritance
  650. #define MULTIPLE_INHERITANCE __multiple_inheritance
  651. #define EXPLICIT explicit
  652. #define NO_VTABLE __declspec( novtable )
  653. // gcc doesn't allow storage specifiers on explicit template instatiation, but visual studio needs them to avoid link errors.
  654. #define TEMPLATE_STATIC static
  655. // Used for dll exporting and importing
  656. #define DLL_EXPORT extern "C" __declspec( dllexport )
  657. #define DLL_IMPORT extern "C" __declspec( dllimport )
  658. // Can't use extern "C" when DLL exporting a class
  659. #define DLL_CLASS_EXPORT __declspec( dllexport )
  660. #define DLL_CLASS_IMPORT __declspec( dllimport )
  661. // Can't use extern "C" when DLL exporting a global
  662. #define DLL_GLOBAL_EXPORT extern __declspec( dllexport )
  663. #define DLL_GLOBAL_IMPORT extern __declspec( dllimport )
  664. // Pass hints to the compiler to prevent it from generating unnessecary / stupid code
  665. // in certain situations. Several compilers other than MSVC also have an equivilent
  666. // construct.
  667. //
  668. // Essentially the 'Hint' is that the condition specified is assumed to be true at
  669. // that point in the compilation. If '0' is passed, then the compiler assumes that
  670. // any subsequent code in the same 'basic block' is unreachable, and thus usually
  671. // removed.
  672. #define HINT(THE_HINT) __assume((THE_HINT))
  673. // decls for aligning data
  674. #define DECL_ALIGN(x) __declspec( align( x ) )
  675. // GCC had a few areas where it didn't construct objects in the same order
  676. // that Windows does. So when CVProfile::CVProfile() would access g_pMemAlloc,
  677. // it would crash because the allocator wasn't initalized yet.
  678. #define CONSTRUCT_EARLY
  679. #define SELECTANY __declspec(selectany)
  680. #define RESTRICT __restrict
  681. #define RESTRICT_FUNC __declspec(restrict)
  682. #define FMTFUNCTION( a, b )
  683. #define NOINLINE
  684. #if !defined( NO_THREAD_LOCAL )
  685. #define DECL_THREAD_LOCAL __declspec(thread)
  686. #endif
  687. #define DISABLE_VC_WARNING( x ) __pragma(warning(disable:4310) )
  688. #define DEFAULT_VC_WARNING( x ) __pragma(warning(default:4310) )
  689. #elif defined ( COMPILER_GCC ) || defined( COMPILER_SNC )
  690. #if defined( COMPILER_SNC ) || defined( PLATFORM_64BITS )
  691. #define STDCALL
  692. #define __stdcall
  693. #elif (CROSS_PLATFORM_VERSION >= 1) && !defined( PLATFORM_64BITS ) && !defined( COMPILER_PS3 )
  694. #define STDCALL __attribute__ ((__stdcall__))
  695. #else
  696. #define STDCALL
  697. #define __stdcall __attribute__ ((__stdcall__))
  698. #endif
  699. #define FASTCALL
  700. #ifdef _LINUX_DEBUGGABLE
  701. #define FORCEINLINE
  702. #else
  703. #ifdef _PS3
  704. // [IESTYN 7/29/2010] As of SDK 3.4.0, this causes bad code generation in NET_Tick::ReadFromBuffer in netmessages.cpp,
  705. // which caused (seeming) random network packet corruption. It probably causes other bugs too.
  706. #define FORCEINLINE inline /* __attribute__ ((always_inline)) */
  707. #else
  708. #define FORCEINLINE inline __attribute__ ((always_inline))
  709. #endif
  710. #endif
  711. // GCC 3.4.1 has a bug in supporting forced inline of templated functions
  712. // this macro lets us not force inlining in that case
  713. #define FORCEINLINE_TEMPLATE inline
  714. #define SINGLE_INHERITANCE
  715. #define MULTIPLE_INHERITANCE
  716. #define EXPLICIT
  717. #define NO_VTABLE
  718. #define NULLTERMINATED
  719. #if defined( COMPILER_SNC )
  720. #define TEMPLATE_STATIC static
  721. #else
  722. #define TEMPLATE_STATIC
  723. #endif
  724. // Used for dll exporting and importing
  725. #ifdef COMPILER_SNC
  726. #define DLL_DECLARATION_DEFAULT_VISIBILITY
  727. #else
  728. #define DLL_DECLARATION_DEFAULT_VISIBILITY __attribute__ ((visibility("default")))
  729. #endif
  730. #define DLL_EXPORT extern "C" DLL_DECLARATION_DEFAULT_VISIBILITY
  731. #define DLL_IMPORT extern "C"
  732. // Can't use extern "C" when DLL exporting a class
  733. #if !defined( _PS3 ) && !defined( LINUX ) && !defined( PLATFORM_64BITS )
  734. #define __stdcall __attribute__ ((__stdcall__))
  735. #endif
  736. #define DLL_CLASS_EXPORT DLL_DECLARATION_DEFAULT_VISIBILITY
  737. #define DLL_CLASS_IMPORT
  738. // Can't use extern "C" when DLL exporting a global
  739. #define DLL_GLOBAL_EXPORT DLL_DECLARATION_DEFAULT_VISIBILITY
  740. #define DLL_GLOBAL_IMPORT extern
  741. #define HINT(THE_HINT) __builtin_expect( THE_HINT, 1 )
  742. #define DECL_ALIGN(x) __attribute__( ( aligned( x ) ) )
  743. #define CONSTRUCT_EARLY __attribute__((init_priority(101)))
  744. #define SELECTANY __attribute__((weak))
  745. #if defined(__clang__)
  746. // [will] - clang is very strict about restrict, and we have a bunch of core functions that use the keyword which have issues with it.
  747. // This seemed to be a cleaner solution for now so we don't have to fill core code with tons of #ifdefs.
  748. #define RESTRICT
  749. #else
  750. #define RESTRICT __restrict__
  751. #endif
  752. #define RESTRICT_FUNC RESTRICT_FUNC_NOT_YET_DEFINED_FOR_THIS_COMPILER
  753. #define FMTFUNCTION( fmtargnumber, firstvarargnumber ) __attribute__ (( format( printf, fmtargnumber, firstvarargnumber )))
  754. #define NOINLINE __attribute__ ((noinline))
  755. #if !defined( NO_THREAD_LOCAL )
  756. #define DECL_THREAD_LOCAL __thread
  757. #endif
  758. #define DISABLE_VC_WARNING( x )
  759. #define DEFAULT_VC_WARNING( x )
  760. #else
  761. #define DECL_ALIGN(x) /* */
  762. #define SELECTANY static
  763. #endif
  764. #if defined( GNUC ) && !defined( COMPILER_PS3 ) // use pre-align on PS3
  765. // gnuc has the align decoration at the end
  766. #define ALIGN4
  767. #define ALIGN8
  768. #define ALIGN16
  769. #define ALIGN32
  770. #define ALIGN128
  771. #undef ALIGN16_POST
  772. #define ALIGN4_POST DECL_ALIGN(4)
  773. #define ALIGN8_POST DECL_ALIGN(8)
  774. #define ALIGN16_POST DECL_ALIGN(16)
  775. #define ALIGN32_POST DECL_ALIGN(32)
  776. #define ALIGN128_POST DECL_ALIGN(128)
  777. #else
  778. // MSVC has the align at the start of the struct
  779. // PS3 SNC supports both
  780. #define ALIGN4 DECL_ALIGN(4)
  781. #define ALIGN8 DECL_ALIGN(8)
  782. #define ALIGN16 DECL_ALIGN(16)
  783. #define ALIGN32 DECL_ALIGN(32)
  784. #define ALIGN128 DECL_ALIGN(128)
  785. #define ALIGN4_POST
  786. #define ALIGN8_POST
  787. #define ALIGN16_POST
  788. #define ALIGN32_POST
  789. #define ALIGN128_POST
  790. #endif
  791. //-----------------------------------------------------------------------------
  792. // Macro to assist in asserting constant invariants during compilation
  793. // This implementation of compile time assert has zero cost (so it can safely be
  794. // included in release builds) and can be used at file scope or function scope.
  795. #ifdef __GNUC__
  796. #define COMPILE_TIME_ASSERT( pred ) typedef int UNIQUE_ID[ (pred) ? 1 : -1 ]
  797. #else
  798. #if _MSC_VER >= 1600
  799. // If available use static_assert instead of weird language tricks. This
  800. // leads to much more readable messages when compile time assert constraints
  801. // are violated.
  802. #define COMPILE_TIME_ASSERT( pred ) static_assert( pred, "Compile time assert constraint is not true: " #pred )
  803. #else
  804. // Due to gcc bugs this can in rare cases (some template functions) cause redeclaration
  805. // errors when used multiple times in one scope. Fix by adding extra scoping.
  806. #define COMPILE_TIME_ASSERT( pred ) typedef char compile_time_assert_type[(pred) ? 1 : -1];
  807. #endif
  808. #endif
  809. // ASSERT_INVARIANT used to be needed in order to allow COMPILE_TIME_ASSERTs at global
  810. // scope. However the new COMPILE_TIME_ASSERT macro supports that by default.
  811. #define ASSERT_INVARIANT( pred ) COMPILE_TIME_ASSERT( pred )
  812. // This can be used to declare an abstract (interface only) class.
  813. // Classes marked abstract should not be instantiated. If they are, and access violation will occur.
  814. //
  815. // Example of use:
  816. //
  817. // abstract_class CFoo
  818. // {
  819. // ...
  820. // }
  821. //
  822. // MSDN __declspec(novtable) documentation: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_langref_novtable.asp
  823. //
  824. // Note: NJS: This is not enabled for regular PC, due to not knowing the implications of exporting a class with no no vtable.
  825. // It's probable that this shouldn't be an issue, but an experiment should be done to verify this.
  826. //
  827. #ifndef COMPILER_MSVCX360
  828. #define abstract_class class
  829. #else
  830. #define abstract_class class NO_VTABLE
  831. #endif
  832. //-----------------------------------------------------------------------------
  833. // Why do we need this? It would be nice to make it die die die
  834. //-----------------------------------------------------------------------------
  835. // Alloca defined for this platform
  836. #if defined( COMPILER_MSVC ) && !defined( WINDED )
  837. #if defined(_M_IX86)
  838. #define __i386__ 1
  839. #endif
  840. #endif
  841. #if defined __i386__ && !defined __linux__
  842. #define id386 1
  843. #else
  844. #define id386 0
  845. #endif // __i386__
  846. //-----------------------------------------------------------------------------
  847. // Disable annoying unhelpful warnings
  848. //-----------------------------------------------------------------------------
  849. #ifdef COMPILER_MSVC
  850. // Remove warnings from warning level 4.
  851. #pragma warning(disable : 4514) // warning C4514: 'acosl' : unreferenced inline function has been removed
  852. #pragma warning(disable : 4100) // warning C4100: 'hwnd' : unreferenced formal parameter
  853. #pragma warning(disable : 4127) // warning C4127: conditional expression is constant
  854. #pragma warning(disable : 4512) // warning C4512: 'InFileRIFF' : assignment operator could not be generated
  855. #pragma warning(disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
  856. #pragma warning(disable : 4710) // warning C4710: function 'x' not inlined
  857. #pragma warning(disable : 4702) // warning C4702: unreachable code
  858. #pragma warning(disable : 4505) // unreferenced local function has been removed
  859. #pragma warning(disable : 4239) // nonstandard extension used : 'argument' ( conversion from class Vector to class Vector& )
  860. #pragma warning(disable : 4097) // typedef-name 'BaseClass' used as synonym for class-name 'CFlexCycler::CBaseFlex'
  861. #pragma warning(disable : 4324) // Padding was added at the end of a structure
  862. #pragma warning(disable : 4244) // type conversion warning.
  863. #pragma warning(disable : 4305) // truncation from 'const double ' to 'float '
  864. #pragma warning(disable : 4786) // Disable warnings about long symbol names
  865. #pragma warning(disable : 4250) // 'X' : inherits 'Y::Z' via dominance
  866. #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
  867. #pragma warning(disable : 4481) // warning C4481: nonstandard extension used: override specifier 'override'
  868. #if _MSC_VER >= 1300
  869. #pragma warning(disable : 4511) // Disable warnings about private copy constructors
  870. #pragma warning(disable : 4121) // warning C4121: 'symbol' : alignment of a member was sensitive to packing
  871. #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)
  872. #endif
  873. #if _MSC_VER >= 1400
  874. #pragma warning(disable : 4996) // functions declared deprecated
  875. #endif
  876. // When we port to 64 bit, we'll have to resolve the int, ptr vs size_t 32/64 bit problems...
  877. #if !defined( COMPILER_MSVC64 )
  878. #if ( CROSS_PLATFORM_VERSION < 1 )
  879. #pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data
  880. #pragma warning( disable : 4311 ) // pointer truncation from 'char *' to 'int'
  881. #pragma warning( disable : 4312 ) // conversion from 'unsigned int' to 'memhandle_t' of greater size
  882. #endif
  883. #endif
  884. #elif defined( COMPILER_SNC )
  885. #pragma diag_suppress=1700 // warning 1700: class "%s" has virtual functions but non-virtual destructor
  886. // Uncomment the following line if you want to investigate a specific compiler remark without all the noise:
  887. // #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
  888. #endif
  889. // Pull in the /analyze code annotations.
  890. #include "annotations.h"
  891. #ifdef POSIX
  892. #pragma GCC diagnostic ignored "-Wswitch-enum" // enumeration values not handled in switch
  893. #pragma GCC diagnostic ignored "-Wparentheses" // using the result of an assignment as a condition without parentheses
  894. #endif
  895. #ifdef OSX
  896. #pragma GCC diagnostic ignored "-Wconversion-null" // passing NULL to non-pointer argument 1
  897. #pragma GCC diagnostic ignored "-Wnull-arithmetic" // NULL used in arithmetic. Ie, vpanel == NULL where VPANEL is uint.
  898. #pragma GCC diagnostic ignored "-Wlogical-op-parentheses" // '&&' within '||' (wants parenthesis)
  899. #pragma GCC diagnostic ignored "-Wconstant-conversion" // implicit truncation from x to y (where y is smaller size than x) changes value
  900. #pragma GCC diagnostic ignored "-Wformat-security" // format string is not a string literal (potentially insecure)
  901. #pragma GCC diagnostic ignored "-Wreturn-type-c-linkage" // C-linkage specified, but returns user-defined type
  902. #pragma GCC diagnostic ignored "-Wswitch" // enumeration values not handled in switch
  903. #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" // virtual functions but non-virtual destructor
  904. #pragma GCC diagnostic ignored "-Wformat" // type conversion, format/argument conflict
  905. #pragma GCC diagnostic ignored "-Wbool-conversions" // type conversion
  906. #endif
  907. //-----------------------------------------------------------------------------
  908. // Convert int<-->pointer, avoiding 32/64-bit compiler warnings:
  909. //-----------------------------------------------------------------------------
  910. #define INT_TO_POINTER( i ) (void *)( ( i ) + (char *)NULL )
  911. #define POINTER_TO_INT( p ) ( (int)(uint64)( p ) )
  912. //-----------------------------------------------------------------------------
  913. // Stack-based allocation related helpers
  914. //-----------------------------------------------------------------------------
  915. #if defined( COMPILER_GCC ) || defined( COMPILER_SNC )
  916. #define stackalloc( _size ) alloca( ALIGN_VALUE( _size, 16 ) )
  917. #ifdef PLATFORM_OSX
  918. #define mallocsize( _p ) ( malloc_size( _p ) )
  919. #else
  920. #define mallocsize( _p ) ( malloc_usable_size( _p ) )
  921. #endif
  922. #elif defined ( COMPILER_MSVC )
  923. #define stackalloc( _size ) _alloca( ALIGN_VALUE( _size, 16 ) )
  924. #define mallocsize( _p ) ( _msize( _p ) )
  925. #endif
  926. #define stackalloc_aligned( _size, _align ) (void*)( ( ((uintp)alloca( ALIGN_VALUE( ( _size ) + (_align ), ( _align ) ) )) + ( _align ) ) & ~_align )
  927. // We should probably always just align to 16 bytes, stackalloc just causes too many problems without this behavior. Source2 does it already.
  928. // #define stackalloc( _size ) stackalloc_aligned( _size, 16 )
  929. #define stackfree( _p ) 0
  930. // two-argument ( type, #elements) stackalloc
  931. #define StackAlloc( typ, nelements ) ( ( typ * ) stackalloc_aligned( ( nelements ) * sizeof(typ), 16 ) )
  932. //-----------------------------------------------------------------------------
  933. // Used to break into the debugger
  934. //-----------------------------------------------------------------------------
  935. #ifdef COMPILER_MSVC64
  936. #define DebuggerBreak() __debugbreak()
  937. #elif COMPILER_MSVC32
  938. #define DebuggerBreak() __asm { int 3 }
  939. #elif COMPILER_MSVCX360
  940. #define DebuggerBreak() DebugBreak()
  941. #elif COMPILER_GCC
  942. #if defined( _PS3 )
  943. #if defined( __SPU__ )
  944. #define DebuggerBreak() __asm volatile ("stopd $0,$0,$0")
  945. #else
  946. #define DebuggerBreak() { __asm volatile ("tw 31,1,1"); }
  947. #endif
  948. #elif defined( OSX )
  949. #define DebuggerBreak() if ( Plat_IsInDebugSession() ) asm( "int3" ); else { raise(SIGTRAP); }
  950. #elif defined( PLATFORM_CYGWIN ) || defined( PLATFORM_POSIX )
  951. #define DebuggerBreak() __asm__( "int $0x3;")
  952. #else
  953. #define DebuggerBreak() raise(SIGTRAP)
  954. #endif
  955. #elif defined( COMPILER_SNC ) && defined( COMPILER_PS3 )
  956. static bool sPS3_SuppressAssertsInThisFile = false; // you can throw this in the debugger to temporarily disable asserts inside any particular .cpp module.
  957. #define DebuggerBreak() if (!sPS3_SuppressAssertsInThisFile) __builtin_snpause(); // <sergiy> from SNC Migration Guide, tw 31,1,1
  958. #else
  959. #error DebuggerBreak() is not defined for this platform!
  960. #endif
  961. #if defined( _X360 ) || defined( _PS3 )
  962. #if defined( fsel )
  963. #error
  964. #endif
  965. #else
  966. FORCEINLINE float fsel(float fComparand, float fValGE, float fLT)
  967. {
  968. return fComparand >= 0 ? fValGE : fLT;
  969. }
  970. FORCEINLINE double fsel(double fComparand, double fValGE, double fLT)
  971. {
  972. return fComparand >= 0 ? fValGE : fLT;
  973. }
  974. #endif
  975. //-----------------------------------------------------------------------------
  976. // DLL export for platform utilities
  977. //-----------------------------------------------------------------------------
  978. #ifndef STATIC_TIER0
  979. #ifdef TIER0_DLL_EXPORT
  980. #define PLATFORM_INTERFACE DLL_EXPORT
  981. #define PLATFORM_OVERLOAD DLL_GLOBAL_EXPORT
  982. #define PLATFORM_CLASS DLL_CLASS_EXPORT
  983. #else
  984. #define PLATFORM_INTERFACE DLL_IMPORT
  985. #define PLATFORM_OVERLOAD DLL_GLOBAL_IMPORT
  986. #define PLATFORM_CLASS DLL_CLASS_IMPORT
  987. #endif
  988. #else // BUILD_AS_DLL
  989. #define PLATFORM_INTERFACE extern
  990. #define PLATFORM_OVERLOAD
  991. #define PLATFORM_CLASS
  992. #endif // BUILD_AS_DLL
  993. //-----------------------------------------------------------------------------
  994. // Returns true if debugger attached, false otherwise
  995. //-----------------------------------------------------------------------------
  996. #if defined( PLATFORM_WINDOWS ) || defined( _PS3 )
  997. PLATFORM_INTERFACE void Plat_DebugString( const tchar * );
  998. #else
  999. #define Plat_DebugString(s) ((void)0)
  1000. #endif
  1001. PLATFORM_INTERFACE bool Plat_IsInDebugSession();
  1002. #define DebuggerBreakIfDebugging() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak()
  1003. //-----------------------------------------------------------------------------
  1004. // Message Box
  1005. //-----------------------------------------------------------------------------
  1006. #if defined( PLATFORM_WINDOWS_PC )
  1007. PLATFORM_INTERFACE void Plat_MessageBox( const char *pTitle, const tchar *pMessage );
  1008. #else
  1009. #define Plat_MessageBox( t, m ) ((void)0)
  1010. #endif
  1011. //-----------------------------------------------------------------------------
  1012. // Posix platform helpers
  1013. //-----------------------------------------------------------------------------
  1014. #ifdef PLATFORM_POSIX
  1015. // Visual Studio likes to put an underscore in front of anything that looks like a portable function.
  1016. #define _strupr strupr
  1017. #define _getcwd getcwd
  1018. #define _open open
  1019. #define _lseek lseek
  1020. #define _read read
  1021. #define _close close
  1022. #define _vsnprintf vsnprintf
  1023. #define _stat stat
  1024. #define _O_RDONLY O_RDONLY
  1025. #define _stricmp strcasecmp
  1026. #define _finite finite
  1027. #define _unlink unlink
  1028. #define _putenv putenv
  1029. #define _chdir chdir
  1030. #define _access access
  1031. #define strcmpi stricmp
  1032. #define stricmp strcasecmp
  1033. #define _alloca alloca
  1034. #define GetProcAddress dlsym
  1035. #define _chdir chdir
  1036. #ifndef _PS3
  1037. #define _strnicmp strnicmp
  1038. #endif
  1039. #define strnicmp strncasecmp
  1040. #define _snwprintf swprintf
  1041. #define swprintf_s swprintf
  1042. #define wcsicmp _wcsicmp
  1043. #define _wcsicmp wcscmp
  1044. #define _tempnam tempnam
  1045. #define strtok_s strtok_r
  1046. #define _mkdir(dir) mkdir( dir, S_IRWXU | S_IRWXG | S_IRWXO )
  1047. #define _wtoi(arg) wcstol(arg, NULL, 10)
  1048. #define _wtoi64(arg) wcstoll(arg, NULL, 10)
  1049. #ifndef _PS3
  1050. typedef uintp HMODULE;
  1051. #endif
  1052. typedef void *HANDLE;
  1053. #define __cdecl
  1054. #if !defined( _snprintf ) // some vpc's define this on the command line
  1055. #define _snprintf snprintf
  1056. #endif
  1057. #if !defined( __SPU__ )
  1058. #include <alloca.h>
  1059. #include <unistd.h> // get unlink
  1060. #include <errno.h>
  1061. #endif
  1062. #endif // PLATFORM_POSIX
  1063. #ifdef PLATFORM_WINDOWS
  1064. #ifndef SOCKLEN_T
  1065. #define SOCKLEN_T
  1066. typedef int socklen_t;
  1067. #endif
  1068. #endif
  1069. //-----------------------------------------------------------------------------
  1070. // Generally useful platform-independent macros (move to another file?)
  1071. //-----------------------------------------------------------------------------
  1072. // need macro for constant expression
  1073. #define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) )
  1074. // Force a function call site -not- to inlined. (useful for profiling)
  1075. #define DONT_INLINE(a) (((int)(a)+1)?(a):(a))
  1076. // Marks the codepath from here until the next branch entry point as unreachable,
  1077. // and asserts if any attempt is made to execute it.
  1078. #define UNREACHABLE() { Assert(0); HINT(0); }
  1079. // In cases where no default is present or appropriate, this causes MSVC to generate
  1080. // as little code as possible, and throw an assertion in debug.
  1081. #define NO_DEFAULT default: UNREACHABLE();
  1082. #define MAX_FILEPATH 512
  1083. // Defines MAX_PATH
  1084. #ifndef MAX_PATH
  1085. #define MAX_PATH 260
  1086. #endif
  1087. #ifdef _WIN32
  1088. #define MAX_UNICODE_PATH 32767
  1089. #else
  1090. #define MAX_UNICODE_PATH MAX_PATH
  1091. #endif
  1092. #define MAX_UNICODE_PATH_IN_UTF8 MAX_UNICODE_PATH*4
  1093. //-----------------------------------------------------------------------------
  1094. // FP exception handling
  1095. //-----------------------------------------------------------------------------
  1096. //#define CHECK_FLOAT_EXCEPTIONS 1
  1097. //#define CHECK_FPU_CONTROL_WORD_SET 1 // x360 only
  1098. #if defined( COMPILER_MSVC64 )
  1099. inline void SetupFPUControlWord()
  1100. {
  1101. }
  1102. #elif defined ( COMPILER_MSVC32 )
  1103. inline void SetupFPUControlWordForceExceptions()
  1104. {
  1105. // use local to get and store control word
  1106. uint16 tmpCtrlW;
  1107. __asm
  1108. {
  1109. fnclex /* clear all current exceptions */
  1110. fnstcw word ptr [tmpCtrlW] /* get current control word */
  1111. and [tmpCtrlW], 0FCC0h /* Keep infinity control + rounding control */
  1112. or [tmpCtrlW], 0230h /* set to 53-bit, mask only inexact, underflow */
  1113. fldcw word ptr [tmpCtrlW] /* put new control word in FPU */
  1114. }
  1115. }
  1116. #ifdef CHECK_FLOAT_EXCEPTIONS
  1117. inline void SetupFPUControlWord()
  1118. {
  1119. SetupFPUControlWordForceExceptions();
  1120. }
  1121. #else
  1122. inline void SetupFPUControlWord()
  1123. {
  1124. // use local to get and store control word
  1125. uint16 tmpCtrlW;
  1126. __asm
  1127. {
  1128. fnstcw word ptr [tmpCtrlW] /* get current control word */
  1129. and [tmpCtrlW], 0FCC0h /* Keep infinity control + rounding control */
  1130. or [tmpCtrlW], 023Fh /* set to 53-bit, mask only inexact, underflow */
  1131. fldcw word ptr [tmpCtrlW] /* put new control word in FPU */
  1132. }
  1133. }
  1134. #endif
  1135. #elif defined ( COMPILER_GCC )
  1136. // Works for PS3
  1137. inline void SetupFPUControlWord()
  1138. {
  1139. #ifdef _PS3
  1140. // TODO: PS3 compiler spits out the following errors:
  1141. // C:/tmp/ccIN0aaa.s: Assembler messages:
  1142. // C:/tmp/ccIN0aaa.s(80): Error: Unrecognized opcode: `fnstcw'
  1143. // C:/tmp/ccIN0aaa.s(93): Error: Unrecognized opcode: `fldcw'
  1144. #else
  1145. __volatile unsigned short int __cw;
  1146. __asm __volatile ("fnstcw %0" : "=m" (__cw));
  1147. __cw = __cw & 0x0FCC0; // keep infinity control, keep rounding mode
  1148. __cw = __cw | 0x023F; // set 53-bit, no exceptions
  1149. __asm __volatile ("fldcw %0" : : "m" (__cw));
  1150. #endif
  1151. }
  1152. #elif defined ( COMPILER_SNC )
  1153. // Works for PS3
  1154. inline void SetupFPUControlWord()
  1155. {
  1156. #ifdef _PS3
  1157. // TODO: PS3 compiler spits out the following errors:
  1158. // C:/tmp/ccIN0aaa.s: Assembler messages:
  1159. // C:/tmp/ccIN0aaa.s(80): Error: Unrecognized opcode: `fnstcw'
  1160. // C:/tmp/ccIN0aaa.s(93): Error: Unrecognized opcode: `fldcw'
  1161. #else
  1162. __volatile unsigned short int __cw;
  1163. __asm __volatile ("fnstcw %0" : "=m" (__cw));
  1164. __cw = __cw & 0x0FCC0; // keep infinity control, keep rounding mode
  1165. __cw = __cw | 0x023F; // set 53-bit, no exceptions
  1166. __asm __volatile ("fldcw %0" : : "m" (__cw));
  1167. #endif
  1168. }
  1169. #elif defined( COMPILER_MSVCX360 )
  1170. #ifdef CHECK_FPU_CONTROL_WORD_SET
  1171. FORCEINLINE bool IsFPUControlWordSet()
  1172. {
  1173. float f = 0.996f;
  1174. union
  1175. {
  1176. double flResult;
  1177. int pResult[2];
  1178. };
  1179. flResult = __fctiw( f );
  1180. return ( pResult[1] == 1 );
  1181. }
  1182. #else
  1183. #define IsFPUControlWordSet() 1
  1184. #endif
  1185. inline void SetupFPUControlWord()
  1186. {
  1187. // Set round-to-nearest in FPSCR
  1188. // (cannot assemble, must use op-code form)
  1189. __emit( 0xFF80010C ); // mtfsfi 7,0
  1190. // Favour compatibility over speed (make sure the VPU set to Java-compliant mode)
  1191. // NOTE: the VPU *always* uses round-to-nearest
  1192. __vector4 a = { 0.0f, 0.0f, 0.0f, 0.0f };
  1193. a; // Avoid compiler warning
  1194. __asm
  1195. {
  1196. mtvscr a; // Clear the Vector Status & Control Register to zero
  1197. }
  1198. }
  1199. #endif // COMPILER_MSVCX360
  1200. //-----------------------------------------------------------------------------
  1201. // Portability casting
  1202. //-----------------------------------------------------------------------------
  1203. template < typename Tdst, typename Tsrc > FORCEINLINE Tdst size_cast( Tsrc val )
  1204. {
  1205. static_assert( sizeof( Tdst ) <= sizeof( uint64 ) && sizeof( Tsrc ) <= sizeof( uint64 ), "Okay in my defense there weren't any types larger than 64-bits when this code was written." );
  1206. #ifdef DEBUG
  1207. if ( sizeof ( Tdst ) < sizeof ( Tsrc ) )
  1208. {
  1209. Tdst cmpValDst = ( Tdst )val;
  1210. // If this fails, the source value didn't actually fit in the destination value--you'll need to
  1211. // change the return type's size to match the source type in the calling code.
  1212. if ( val != ( Tsrc )cmpValDst )
  1213. {
  1214. // Can't use assert here, and if this happens when running on a machine internally we should crash
  1215. // in preference to missing the problem ( so not DebuggerBreakIfDebugging() ).
  1216. DebuggerBreak();
  1217. }
  1218. }
  1219. #endif
  1220. return ( Tdst )val;
  1221. }
  1222. //-----------------------------------------------------------------------------
  1223. // Purpose: Standard functions for handling endian-ness
  1224. //-----------------------------------------------------------------------------
  1225. //-------------------------------------
  1226. // Basic swaps
  1227. //-------------------------------------
  1228. template <typename T>
  1229. inline T WordSwapC( T w )
  1230. {
  1231. uint16 temp;
  1232. PLAT_COMPILE_TIME_ASSERT( sizeof( T ) == sizeof(uint16) );
  1233. temp = ((*((uint16 *)&w) & 0xff00) >> 8);
  1234. temp |= ((*((uint16 *)&w) & 0x00ff) << 8);
  1235. return *((T*)&temp);
  1236. }
  1237. template <typename T>
  1238. inline T DWordSwapC( T dw )
  1239. {
  1240. uint32 temp;
  1241. PLAT_COMPILE_TIME_ASSERT( sizeof( T ) == sizeof(uint32) );
  1242. temp = *((uint32 *)&dw) >> 24;
  1243. temp |= ((*((uint32 *)&dw) & 0x00FF0000) >> 8);
  1244. temp |= ((*((uint32 *)&dw) & 0x0000FF00) << 8);
  1245. temp |= ((*((uint32 *)&dw) & 0x000000FF) << 24);
  1246. return *((T*)&temp);
  1247. }
  1248. template <typename T>
  1249. inline T QWordSwapC( T dw )
  1250. {
  1251. // Assert sizes passed to this are already correct, otherwise
  1252. // the cast to uint64 * below is unsafe and may have wrong results
  1253. // or even crash.
  1254. PLAT_COMPILE_TIME_ASSERT( sizeof( dw ) == sizeof(uint64) );
  1255. uint64 temp;
  1256. temp = *((uint64 *)&dw) >> 56;
  1257. temp |= ((*((uint64 *)&dw) & 0x00FF000000000000ull) >> 40);
  1258. temp |= ((*((uint64 *)&dw) & 0x0000FF0000000000ull) >> 24);
  1259. temp |= ((*((uint64 *)&dw) & 0x000000FF00000000ull) >> 8);
  1260. temp |= ((*((uint64 *)&dw) & 0x00000000FF000000ull) << 8);
  1261. temp |= ((*((uint64 *)&dw) & 0x0000000000FF0000ull) << 24);
  1262. temp |= ((*((uint64 *)&dw) & 0x000000000000FF00ull) << 40);
  1263. temp |= ((*((uint64 *)&dw) & 0x00000000000000FFull) << 56);
  1264. return *((T*)&temp);
  1265. }
  1266. //-------------------------------------
  1267. // Fast swaps
  1268. //-------------------------------------
  1269. #if defined( COMPILER_MSVCX360 )
  1270. #define WordSwap WordSwap360Intr
  1271. #define DWordSwap DWordSwap360Intr
  1272. template <typename T>
  1273. inline T WordSwap360Intr( T w )
  1274. {
  1275. T output;
  1276. __storeshortbytereverse( w, 0, &output );
  1277. return output;
  1278. }
  1279. template <typename T>
  1280. inline T DWordSwap360Intr( T dw )
  1281. {
  1282. T output;
  1283. __storewordbytereverse( dw, 0, &output );
  1284. return output;
  1285. }
  1286. #elif defined( COMPILER_MSVC32 )
  1287. #define WordSwap WordSwapAsm
  1288. #define DWordSwap DWordSwapAsm
  1289. #pragma warning(push)
  1290. #pragma warning (disable:4035) // no return value
  1291. template <typename T>
  1292. inline T WordSwapAsm( T w )
  1293. {
  1294. __asm
  1295. {
  1296. mov ax, w
  1297. xchg al, ah
  1298. }
  1299. }
  1300. template <typename T>
  1301. inline T DWordSwapAsm( T dw )
  1302. {
  1303. __asm
  1304. {
  1305. mov eax, dw
  1306. bswap eax
  1307. }
  1308. }
  1309. #pragma warning(pop)
  1310. #else
  1311. #define WordSwap WordSwapC
  1312. #define DWordSwap DWordSwapC
  1313. #endif
  1314. // No ASM implementation for this yet
  1315. #define QWordSwap QWordSwapC
  1316. //-------------------------------------
  1317. // The typically used methods.
  1318. //-------------------------------------
  1319. #if defined( _SGI_SOURCE ) || defined( PLATFORM_X360 ) || defined( _PS3 )
  1320. #define PLAT_BIG_ENDIAN 1
  1321. #else
  1322. #define PLAT_LITTLE_ENDIAN 1
  1323. #endif
  1324. // If a swapped float passes through the fpu, the bytes may get changed.
  1325. // Prevent this by swapping floats as DWORDs.
  1326. #define SafeSwapFloat( pOut, pIn ) (*((uint*)pOut) = DWordSwap( *((uint*)pIn) ))
  1327. #if defined(PLAT_LITTLE_ENDIAN)
  1328. #define BigShort( val ) WordSwap( val )
  1329. #define BigWord( val ) WordSwap( val )
  1330. #define BigLong( val ) DWordSwap( val )
  1331. #define BigDWord( val ) DWordSwap( val )
  1332. #define BigQWord( val ) QWordSwap( val )
  1333. #define LittleShort( val ) ( val )
  1334. #define LittleWord( val ) ( val )
  1335. #define LittleLong( val ) ( val )
  1336. #define LittleDWord( val ) ( val )
  1337. #define LittleQWord( val ) ( val )
  1338. #define SwapShort( val ) BigShort( val )
  1339. #define SwapWord( val ) BigWord( val )
  1340. #define SwapLong( val ) BigLong( val )
  1341. #define SwapDWord( val ) BigDWord( val )
  1342. // Pass floats by pointer for swapping to avoid truncation in the fpu
  1343. #define BigFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn )
  1344. #define LittleFloat( pOut, pIn ) ( *pOut = *pIn )
  1345. #define SwapFloat( pOut, pIn ) BigFloat( pOut, pIn )
  1346. #elif defined(PLAT_BIG_ENDIAN)
  1347. #define BigShort( val ) ( val )
  1348. #define BigWord( val ) ( val )
  1349. #define BigLong( val ) ( val )
  1350. #define BigDWord( val ) ( val )
  1351. #define BigQWord( val ) ( val )
  1352. #define LittleShort( val ) WordSwap( val )
  1353. #define LittleWord( val ) WordSwap( val )
  1354. #define LittleLong( val ) DWordSwap( val )
  1355. #define LittleDWord( val ) DWordSwap( val )
  1356. #define LittleQWord( val ) QWordSwap( val )
  1357. #define SwapShort( val ) LittleShort( val )
  1358. #define SwapWord( val ) LittleWord( val )
  1359. #define SwapLong( val ) LittleLong( val )
  1360. #define SwapDWord( val ) LittleDWord( val )
  1361. // Pass floats by pointer for swapping to avoid truncation in the fpu
  1362. #define BigFloat( pOut, pIn ) ( *pOut = *pIn )
  1363. #define LittleFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn )
  1364. #define SwapFloat( pOut, pIn ) LittleFloat( pOut, pIn )
  1365. #else
  1366. // @Note (toml 05-02-02): this technique expects the compiler to
  1367. // optimize the expression and eliminate the other path. On any new
  1368. // platform/compiler this should be tested.
  1369. inline short BigShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; }
  1370. inline uint16 BigWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; }
  1371. inline long BigLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; }
  1372. inline uint32 BigDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; }
  1373. inline uint64 BigQWord( uint64 val ) { int test = 1; return ( *(char *)&test == 1 ) ? QWordSwap( val ) : val; }
  1374. inline short LittleShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); }
  1375. inline uint16 LittleWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); }
  1376. inline long LittleLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); }
  1377. inline uint32 LittleDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); }
  1378. inline uint64 LittleQWord( uint64 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : QWordSwap( val ); }
  1379. inline short SwapShort( short val ) { return WordSwap( val ); }
  1380. inline uint16 SwapWord( uint16 val ) { return WordSwap( val ); }
  1381. inline long SwapLong( long val ) { return DWordSwap( val ); }
  1382. inline uint32 SwapDWord( uint32 val ) { return DWordSwap( val ); }
  1383. // Pass floats by pointer for swapping to avoid truncation in the fpu
  1384. inline void BigFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? SafeSwapFloat( pOut, pIn ) : ( *pOut = *pIn ); }
  1385. inline void LittleFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? ( *pOut = *pIn ) : SafeSwapFloat( pOut, pIn ); }
  1386. inline void SwapFloat( float *pOut, const float *pIn ) { SafeSwapFloat( pOut, pIn ); }
  1387. #endif
  1388. #if !defined( __SPU__ )
  1389. #if PLAT_BIG_ENDIAN
  1390. #if defined( _PS3 )
  1391. inline uint32 LoadLittleDWord( uint32 *base, unsigned int dwordIndex )
  1392. {
  1393. return __lwbrx( base + dwordIndex );
  1394. }
  1395. inline void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
  1396. {
  1397. __stwbrx( base + dwordIndex, dword );
  1398. }
  1399. inline uint64 LoadLittleInt64( uint64 *base, unsigned int nWordIndex )
  1400. {
  1401. return __ldbrx( base + nWordIndex );
  1402. }
  1403. inline void StoreLittleInt64( uint64 *base, unsigned int nWordIndex, uint64 nWord )
  1404. {
  1405. __stdbrx( base + nWordIndex, nWord );
  1406. }
  1407. #else
  1408. inline uint32 LoadLittleDWord( uint32 *base, unsigned int dwordIndex )
  1409. {
  1410. return __loadwordbytereverse( dwordIndex<<2, base );
  1411. }
  1412. inline void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
  1413. {
  1414. __storewordbytereverse( dword, dwordIndex<<2, base );
  1415. }
  1416. inline uint64 LoadLittleInt64( uint64 *base, unsigned int nWordIndex )
  1417. {
  1418. return __loaddoublewordbytereverse( nWordIndex<<2, base );
  1419. }
  1420. inline void StoreLittleInt64( uint64 *base, unsigned int nWordIndex, uint64 nWord )
  1421. {
  1422. __storedoublewordbytereverse( nWord, nWordIndex<<2, base );
  1423. }
  1424. #endif
  1425. #else
  1426. inline uint32 LoadLittleDWord( uint32 *base, unsigned int dwordIndex )
  1427. {
  1428. return LittleDWord( base[dwordIndex] );
  1429. }
  1430. inline void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
  1431. {
  1432. base[dwordIndex] = LittleDWord(dword);
  1433. }
  1434. #endif
  1435. // Silences a number of warnings on 360 compiles.
  1436. inline uint64 CastPtrToUint64( const void *p )
  1437. {
  1438. return (uint64)( (uintp)p );
  1439. }
  1440. inline int64 CastPtrToInt64( const void *p )
  1441. {
  1442. return (int64)( (uintp)p );
  1443. }
  1444. // When in benchmark mode, the timer returns a simple incremented value each time you call it.
  1445. //
  1446. // It should not be changed after startup unless you really know what you're doing. The only place
  1447. // that should do this is the benchmark code itself so it can output a legit duration.
  1448. PLATFORM_INTERFACE void Plat_SetBenchmarkMode( bool bBenchmarkMode );
  1449. PLATFORM_INTERFACE bool Plat_IsInBenchmarkMode();
  1450. // Same as time()
  1451. PLATFORM_INTERFACE uint64 Plat_GetTime();
  1452. PLATFORM_INTERFACE double Plat_FloatTime(); // Returns time in seconds since the module was loaded.
  1453. PLATFORM_INTERFACE uint32 Plat_MSTime(); // Time in milliseconds.
  1454. PLATFORM_INTERFACE uint64 Plat_USTime(); // Time in microseconds.
  1455. PLATFORM_INTERFACE uint64 Plat_GetClockStart(); // Snapshot of the clock when app started.
  1456. PLATFORM_INTERFACE int32 Plat_timezone( void );
  1457. PLATFORM_INTERFACE int32 Plat_daylight( void );
  1458. // Get the local calendar time.
  1459. // Same as time() followed by localtime(), but non-crash-prone and threadsafe.
  1460. PLATFORM_INTERFACE void Plat_GetLocalTime( struct tm *pNow );
  1461. // 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.
  1462. PLATFORM_INTERFACE void Plat_ConvertToLocalTime( uint64 nTime, struct tm *pNow );
  1463. PLATFORM_INTERFACE struct tm * Plat_localtime( const time_t *timep, struct tm *result );
  1464. // Get a time string (same as ascstring, but threadsafe).
  1465. PLATFORM_INTERFACE void Plat_GetTimeString( struct tm *pTime, char *pOut, int nMaxBytes );
  1466. // converts a time_t to a struct tm without the local time conversion of ConvertToLocalTime
  1467. PLATFORM_INTERFACE void Platform_gmtime( uint64 nTime, struct tm *pTime );
  1468. PLATFORM_INTERFACE time_t Plat_timegm( struct tm *timeptr );
  1469. // Compatibility definition:
  1470. inline struct tm * Plat_gmtime( const time_t *timep, struct tm *result ) { Platform_gmtime( *timep, result ); return result; }
  1471. // Other time functions
  1472. PLATFORM_INTERFACE char *Plat_ctime( const time_t *timep, char *buf, size_t bufsize );
  1473. typedef class CSysModule* PlatModule_t;
  1474. #define PLAT_MODULE_INVALID ((PlatModule_t)0)
  1475. // Get the process' executable filename.
  1476. PLATFORM_INTERFACE void Plat_GetModuleFilename( char *pOut, int nMaxBytes );
  1477. PLATFORM_INTERFACE void Plat_ExitProcess( int nCode );
  1478. //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
  1479. //before exiting
  1480. PLATFORM_INTERFACE void Plat_ExitProcessWithError( int nCode, bool bGenerateMinidump = false );
  1481. //sets the callback that will be triggered by Plat_ExitProcessWithError. NULL is valid. The return value true indicates that
  1482. //the exit has been handled and no further processing should be performed. False will cause a minidump to be generated, and the process
  1483. //to be terminated
  1484. typedef bool (*ExitProcessWithErrorCBFn)( int nCode );
  1485. PLATFORM_INTERFACE void Plat_SetExitProcessWithErrorCB( ExitProcessWithErrorCBFn pfnCB );
  1486. // If OSX or Linux have 2GB of address space for 32-bit apps, then return true here when that case is detected
  1487. #if defined( OSX )
  1488. // make memory tradeoffs for low-fragmentation (compact memory, use different patterns, etc)
  1489. inline bool Plat_NeedsLowFragmentation() { return true; }
  1490. #else
  1491. inline bool Plat_NeedsLowFragmentation() { return false; }
  1492. #endif
  1493. PLATFORM_INTERFACE int Plat_chmod(const char *filename, int pmode);
  1494. PLATFORM_INTERFACE bool Plat_FileExists(const char *pFileName);
  1495. PLATFORM_INTERFACE size_t Plat_FileSize(const char *pFileName);
  1496. PLATFORM_INTERFACE bool Plat_IsDirectory(const char *pFilepath);
  1497. PLATFORM_INTERFACE bool Plat_FileIsReadOnly(const char *pFileName);
  1498. #if defined( _WIN32 ) && defined( _MSC_VER ) && ( _MSC_VER >= 1400 )
  1499. extern "C" unsigned __int64 __rdtsc();
  1500. #pragma intrinsic(__rdtsc)
  1501. #endif
  1502. inline uint64 Plat_Rdtsc()
  1503. {
  1504. #if defined( _X360 )
  1505. return ( uint64 )__mftb32();
  1506. #elif defined( _WIN64 )
  1507. return ( uint64 )__rdtsc();
  1508. #elif defined( _WIN32 )
  1509. #if defined( _MSC_VER ) && ( _MSC_VER >= 1400 )
  1510. return ( uint64 )__rdtsc();
  1511. #else
  1512. __asm rdtsc;
  1513. __asm ret;
  1514. #endif
  1515. #elif defined( __i386__ )
  1516. uint64 val;
  1517. __asm__ __volatile__ ( "rdtsc" : "=A" (val) );
  1518. return val;
  1519. #elif defined( __x86_64__ )
  1520. uint32 lo, hi;
  1521. __asm__ __volatile__ ( "rdtsc" : "=a" (lo), "=d" (hi));
  1522. return ( ( ( uint64 )hi ) << 32 ) | lo;
  1523. #else
  1524. #error
  1525. #endif
  1526. }
  1527. // b/w compatibility
  1528. #define Sys_FloatTime Plat_FloatTime
  1529. // Protect against bad auto operator=
  1530. #define DISALLOW_OPERATOR_EQUAL( _classname ) \
  1531. private: \
  1532. _classname &operator=( const _classname & ); \
  1533. public:
  1534. // Define a reasonable operator=
  1535. #define IMPLEMENT_OPERATOR_EQUAL( _classname ) \
  1536. public: \
  1537. _classname &operator=( const _classname &src ) \
  1538. { \
  1539. memcpy( this, &src, sizeof(_classname) ); \
  1540. return *this; \
  1541. }
  1542. // Processor Information:
  1543. struct CPUInformation
  1544. {
  1545. int m_Size; // Size of this structure, for forward compatability.
  1546. uint8 m_nLogicalProcessors; // Number op logical processors.
  1547. uint8 m_nPhysicalProcessors; // Number of physical processors
  1548. bool m_bRDTSC : 1, // Is RDTSC supported?
  1549. m_bCMOV : 1, // Is CMOV supported?
  1550. m_bFCMOV : 1, // Is FCMOV supported?
  1551. m_bSSE : 1, // Is SSE supported?
  1552. m_bSSE2 : 1, // Is SSE2 Supported?
  1553. m_b3DNow : 1, // Is 3DNow! Supported?
  1554. m_bMMX : 1, // Is MMX supported?
  1555. m_bHT : 1; // Is HyperThreading supported?
  1556. bool m_bSSE3 : 1,
  1557. m_bSSSE3 : 1,
  1558. m_bSSE4a : 1,
  1559. m_bSSE41 : 1,
  1560. m_bSSE42 : 1,
  1561. m_bAVX : 1; // Is AVX supported?
  1562. int64 m_Speed; // In cycles per second.
  1563. tchar* m_szProcessorID; // Processor vendor Identification.
  1564. tchar* m_szProcessorBrand; // Processor brand string, if available
  1565. uint32 m_nModel;
  1566. uint32 m_nFeatures[ 3 ];
  1567. uint32 m_nL1CacheSizeKb;
  1568. uint32 m_nL1CacheDesc;
  1569. uint32 m_nL2CacheSizeKb;
  1570. uint32 m_nL2CacheDesc;
  1571. uint32 m_nL3CacheSizeKb;
  1572. uint32 m_nL3CacheDesc;
  1573. CPUInformation(): m_Size(0){}
  1574. };
  1575. PLATFORM_INTERFACE const CPUInformation& GetCPUInformation();
  1576. PLATFORM_INTERFACE void GetCurrentDate( int *pDay, int *pMonth, int *pYear );
  1577. PLATFORM_INTERFACE void GetCurrentDayOfTheWeek( int *pDay ); // 0 = Sunday
  1578. PLATFORM_INTERFACE void GetCurrentDayOfTheYear( int *pDay ); // 0 = Jan 1
  1579. // ---------------------------------------------------------------------------------- //
  1580. // Performance Monitoring Events - L2 stats etc...
  1581. // ---------------------------------------------------------------------------------- //
  1582. PLATFORM_INTERFACE void InitPME();
  1583. PLATFORM_INTERFACE void ShutdownPME();
  1584. //-----------------------------------------------------------------------------
  1585. // Security related functions
  1586. //-----------------------------------------------------------------------------
  1587. // Ensure that the hardware key's drivers have been installed.
  1588. PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyDriver();
  1589. // Ok, so this isn't a very secure way to verify the hardware key for now. It
  1590. // is primarially depending on the fact that all the binaries have been wrapped
  1591. // with the secure wrapper provided by the hardware keys vendor.
  1592. PLATFORM_INTERFACE bool Plat_VerifyHardwareKey();
  1593. // The same as above, but notifies user with a message box when the key isn't in
  1594. // and gives him an opportunity to correct the situation.
  1595. PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyPrompt();
  1596. // Can be called in real time, doesn't perform the verify every frame. Mainly just
  1597. // here to allow the game to drop out quickly when the key is removed, rather than
  1598. // allowing the wrapper to pop up it's own blocking dialog, which the engine doesn't
  1599. // like much.
  1600. PLATFORM_INTERFACE bool Plat_FastVerifyHardwareKey();
  1601. //-----------------------------------------------------------------------------
  1602. // The following are low-level OS-independent wrappers around actual OS file calls.
  1603. //-----------------------------------------------------------------------------
  1604. PLATFORM_INTERFACE void Plat_getwd( char *pWorkingDirectory, size_t nBufLen );
  1605. //-----------------------------------------------------------------------------
  1606. // Just logs file and line to simple.log
  1607. //-----------------------------------------------------------------------------
  1608. PLATFORM_INTERFACE void* Plat_SimpleLog( const tchar* file, int line );
  1609. #endif // #if !defined( __SPU__ )
  1610. #if defined( _X360 )
  1611. #define Plat_FastMemset XMemSet
  1612. #define Plat_FastMemcpy XMemCpy
  1613. #else
  1614. #define Plat_FastMemset memset
  1615. #define Plat_FastMemcpy memcpy
  1616. #endif
  1617. //-----------------------------------------------------------------------------
  1618. // XBOX Components valid in PC compilation space
  1619. //-----------------------------------------------------------------------------
  1620. #define XBOX_DVD_SECTORSIZE 2048
  1621. #define XBOX_DVD_ECC_SIZE 32768 // driver reads in quantum ECC blocks
  1622. #define XBOX_HDD_SECTORSIZE 512
  1623. // Custom windows messages for Xbox input
  1624. #define WM_XREMOTECOMMAND (WM_USER + 100)
  1625. #define WM_XCONTROLLER_KEY (WM_USER + 101)
  1626. #define WM_SYS_UI (WM_USER + 102)
  1627. #define WM_SYS_SIGNINCHANGED (WM_USER + 103)
  1628. #define WM_SYS_STORAGEDEVICESCHANGED (WM_USER + 104)
  1629. #define WM_SYS_PROFILESETTINGCHANGED (WM_USER + 105)
  1630. #define WM_SYS_MUTELISTCHANGED (WM_USER + 106)
  1631. #define WM_SYS_INPUTDEVICESCHANGED (WM_USER + 107)
  1632. #define WM_SYS_INPUTDEVICECONFIGCHANGED (WM_USER + 108)
  1633. #define WM_LIVE_CONNECTIONCHANGED (WM_USER + 109)
  1634. #define WM_LIVE_INVITE_ACCEPTED (WM_USER + 110)
  1635. #define WM_LIVE_LINK_STATE_CHANGED (WM_USER + 111)
  1636. #define WM_LIVE_CONTENT_INSTALLED (WM_USER + 112)
  1637. #define WM_LIVE_MEMBERSHIP_PURCHASED (WM_USER + 113)
  1638. #define WM_LIVE_VOICECHAT_AWAY (WM_USER + 114)
  1639. #define WM_LIVE_PRESENCE_CHANGED (WM_USER + 115)
  1640. #define WM_FRIENDS_PRESENCE_CHANGED (WM_USER + 116)
  1641. #define WM_FRIENDS_FRIEND_ADDED (WM_USER + 117)
  1642. #define WM_FRIENDS_FRIEND_REMOVED (WM_USER + 118)
  1643. #define WM_CUSTOM_GAMEBANNERPRESSED (WM_USER + 119)
  1644. #define WM_CUSTOM_ACTIONPRESSED (WM_USER + 120)
  1645. #define WM_XMP_STATECHANGED (WM_USER + 121)
  1646. #define WM_XMP_PLAYBACKBEHAVIORCHANGED (WM_USER + 122)
  1647. #define WM_XMP_PLAYBACKCONTROLLERCHANGED (WM_USER + 123)
  1648. #define WM_SYS_SHUTDOWNREQUEST (WM_USER + 124)
  1649. #if defined( _PS3 )
  1650. #define PLATFORM_EXT ".ps3"
  1651. #elif defined( PLATFORM_X360 )
  1652. #define PLATFORM_EXT ".360"
  1653. #else
  1654. #define PLATFORM_EXT ""
  1655. #endif
  1656. inline const char *GetPlatformExt( void )
  1657. {
  1658. return PLATFORM_EXT;
  1659. }
  1660. // flat view, 6 hw threads
  1661. #define XBOX_PROCESSOR_0 ( 1<<0 )
  1662. #define XBOX_PROCESSOR_1 ( 1<<1 )
  1663. #define XBOX_PROCESSOR_2 ( 1<<2 )
  1664. #define XBOX_PROCESSOR_3 ( 1<<3 )
  1665. #define XBOX_PROCESSOR_4 ( 1<<4 )
  1666. #define XBOX_PROCESSOR_5 ( 1<<5 )
  1667. // core view, 3 cores with 2 hw threads each
  1668. #define XBOX_CORE_0_HWTHREAD_0 XBOX_PROCESSOR_0
  1669. #define XBOX_CORE_0_HWTHREAD_1 XBOX_PROCESSOR_1
  1670. #define XBOX_CORE_1_HWTHREAD_0 XBOX_PROCESSOR_2
  1671. #define XBOX_CORE_1_HWTHREAD_1 XBOX_PROCESSOR_3
  1672. #define XBOX_CORE_2_HWTHREAD_0 XBOX_PROCESSOR_4
  1673. #define XBOX_CORE_2_HWTHREAD_1 XBOX_PROCESSOR_5
  1674. //-----------------------------------------------------------------------------
  1675. // Include additional dependant header components.
  1676. //-----------------------------------------------------------------------------
  1677. #if defined( PLATFORM_X360 )
  1678. #include "xbox/xbox_core.h"
  1679. #elif defined( PLATFORM_PS3 )
  1680. #include "ps3/ps3_core.h"
  1681. #endif
  1682. //-----------------------------------------------------------------------------
  1683. // There is no requirement that a va_list be usable in multiple calls,
  1684. // but the Steam code does this. Linux64 does not support reuse, whereas
  1685. // Windows does, so Linux64 breaks on code that was written and working
  1686. // on Windows. Fortunately Linux has va_copy, which provides a simple
  1687. // way to let a va_list be used multiple times. Unfortunately Windows
  1688. // does not have va_copy, so here we provide things to hide the difference.
  1689. //-----------------------------------------------------------------------------
  1690. class CReuseVaList
  1691. {
  1692. public:
  1693. CReuseVaList( va_list List )
  1694. {
  1695. #if defined(LINUX) || defined(OSX)
  1696. va_copy( m_ReuseList, List );
  1697. #else
  1698. m_ReuseList = List;
  1699. #endif
  1700. }
  1701. ~CReuseVaList()
  1702. {
  1703. #if defined(LINUX) || defined(OSX)
  1704. va_end( m_ReuseList );
  1705. #endif
  1706. }
  1707. va_list m_ReuseList;
  1708. };
  1709. //-----------------------------------------------------------------------------
  1710. // C++11 helpers
  1711. //-----------------------------------------------------------------------------
  1712. #define VALVE_CPP11 1
  1713. #if VALVE_CPP11
  1714. template <class T> struct C11RemoveReference { typedef T Type; };
  1715. template <class T> struct C11RemoveReference<T&> { typedef T Type; };
  1716. template <class T> struct C11RemoveReference<T&&> { typedef T Type; };
  1717. template <class T>
  1718. inline typename C11RemoveReference<T>::Type&& Move( T&& obj )
  1719. {
  1720. return static_cast< typename C11RemoveReference<T>::Type&& >( obj );
  1721. }
  1722. template <class T>
  1723. inline T&& Forward( typename C11RemoveReference<T>::Type& obj )
  1724. {
  1725. return static_cast< T&& >( obj );
  1726. }
  1727. template <class T>
  1728. inline T&& Forward( typename C11RemoveReference<T>::Type&& obj )
  1729. {
  1730. return static_cast< T&& >( obj );
  1731. }
  1732. #endif
  1733. //-----------------------------------------------------------------------------
  1734. // Methods to invoke the constructor, copy constructor, and destructor
  1735. //-----------------------------------------------------------------------------
  1736. template <class T>
  1737. inline T* Construct( T* pMemory )
  1738. {
  1739. return ::new( pMemory ) T;
  1740. }
  1741. template <class T, typename ARG1>
  1742. inline T* Construct( T* pMemory, ARG1 a1 )
  1743. {
  1744. return ::new( pMemory ) T( a1 );
  1745. }
  1746. template <class T, typename ARG1, typename ARG2>
  1747. inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2 )
  1748. {
  1749. return ::new( pMemory ) T( a1, a2 );
  1750. }
  1751. template <class T, typename ARG1, typename ARG2, typename ARG3>
  1752. inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3 )
  1753. {
  1754. return ::new( pMemory ) T( a1, a2, a3 );
  1755. }
  1756. template <class T, typename ARG1, typename ARG2, typename ARG3, typename ARG4>
  1757. inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3, ARG4 a4 )
  1758. {
  1759. return ::new( pMemory ) T( a1, a2, a3, a4 );
  1760. }
  1761. template <class T, typename ARG1, typename ARG2, typename ARG3, typename ARG4, typename ARG5>
  1762. inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3, ARG4 a4, ARG5 a5 )
  1763. {
  1764. return ::new( pMemory ) T( a1, a2, a3, a4, a5 );
  1765. }
  1766. template <class T>
  1767. inline T* CopyConstruct( T* pMemory, T const& src )
  1768. {
  1769. return ::new( pMemory ) T(src);
  1770. }
  1771. template <class T>
  1772. inline T* MoveConstruct( T* pMemory, T&& src )
  1773. {
  1774. return ::new( pMemory ) T( Move(src) );
  1775. }
  1776. // [will] - Fixing a clang compile: unable to create a pseudo-destructor (aka a destructor that does nothing) for float __attribute__((__vector_size__(16)))
  1777. // Fixed by specializing the Destroy function to not call destructor for that type.
  1778. #if defined( __clang__ ) || defined (LINUX)
  1779. template <class T>
  1780. inline void Destruct( T* pMemory );
  1781. template <>
  1782. inline void Destruct( float __attribute__((__vector_size__(16)))* pMemory );
  1783. #endif // __clang__
  1784. template <class T>
  1785. inline void Destruct( T* pMemory )
  1786. {
  1787. pMemory->~T();
  1788. #ifdef _DEBUG
  1789. memset( pMemory, 0xDD, sizeof(T) );
  1790. #endif
  1791. }
  1792. // [will] - Fixing a clang compile: unable to create a pseudo-destructor (aka a destructor that does nothing) for float __attribute__((__vector_size__(16)))
  1793. // Fixed by specializing the Destroy function to not call destructor for that type.
  1794. #if defined( __clang__ ) || defined (LINUX)
  1795. template <>
  1796. inline void Destruct( float __attribute__((__vector_size__(16)))* pMemory )
  1797. {
  1798. #ifdef _DEBUG
  1799. memset( pMemory, 0xDD, sizeof( float __attribute__((__vector_size__(16))) ) );
  1800. #endif
  1801. }
  1802. #endif // __clang__
  1803. //
  1804. // GET_OUTER()
  1805. //
  1806. // A platform-independent way for a contained class to get a pointer to its
  1807. // owner. If you know a class is exclusively used in the context of some
  1808. // "outer" class, this is a much more space efficient way to get at the outer
  1809. // class than having the inner class store a pointer to it.
  1810. //
  1811. // class COuter
  1812. // {
  1813. // class CInner // Note: this does not need to be a nested class to work
  1814. // {
  1815. // void PrintAddressOfOuter()
  1816. // {
  1817. // printf( "Outer is at 0x%x\n", GET_OUTER( COuter, m_Inner ) );
  1818. // }
  1819. // };
  1820. //
  1821. // CInner m_Inner;
  1822. // friend class CInner;
  1823. // };
  1824. #define GET_OUTER( OuterType, OuterMember ) \
  1825. ( ( OuterType * ) ( (uint8 *)this - offsetof( OuterType, OuterMember ) ) )
  1826. /* TEMPLATE_FUNCTION_TABLE()
  1827. (Note added to platform.h so platforms that correctly support templated
  1828. functions can handle portions as templated functions rather than wrapped
  1829. functions)
  1830. Helps automate the process of creating an array of function
  1831. templates that are all specialized by a single integer.
  1832. This sort of thing is often useful in optimization work.
  1833. For example, using TEMPLATE_FUNCTION_TABLE, this:
  1834. TEMPLATE_FUNCTION_TABLE(int, Function, ( int blah, int blah ), 10)
  1835. {
  1836. return argument * argument;
  1837. }
  1838. is equivilent to the following:
  1839. (NOTE: the function has to be wrapped in a class due to code
  1840. generation bugs involved with directly specializing a function
  1841. based on a constant.)
  1842. template<int argument>
  1843. class FunctionWrapper
  1844. {
  1845. public:
  1846. int Function( int blah, int blah )
  1847. {
  1848. return argument*argument;
  1849. }
  1850. }
  1851. typedef int (*FunctionType)( int blah, int blah );
  1852. class FunctionName
  1853. {
  1854. public:
  1855. enum { count = 10 };
  1856. FunctionType functions[10];
  1857. };
  1858. FunctionType FunctionName::functions[] =
  1859. {
  1860. FunctionWrapper<0>::Function,
  1861. FunctionWrapper<1>::Function,
  1862. FunctionWrapper<2>::Function,
  1863. FunctionWrapper<3>::Function,
  1864. FunctionWrapper<4>::Function,
  1865. FunctionWrapper<5>::Function,
  1866. FunctionWrapper<6>::Function,
  1867. FunctionWrapper<7>::Function,
  1868. FunctionWrapper<8>::Function,
  1869. FunctionWrapper<9>::Function
  1870. };
  1871. */
  1872. PLATFORM_INTERFACE bool vtune( bool resume );
  1873. #define TEMPLATE_FUNCTION_TABLE(RETURN_TYPE, NAME, ARGS, COUNT) \
  1874. \
  1875. typedef RETURN_TYPE (FASTCALL *__Type_##NAME) ARGS; \
  1876. \
  1877. template<const int nArgument> \
  1878. struct __Function_##NAME \
  1879. { \
  1880. static RETURN_TYPE FASTCALL Run ARGS; \
  1881. }; \
  1882. \
  1883. template <const int i> \
  1884. struct __MetaLooper_##NAME : __MetaLooper_##NAME<i-1> \
  1885. { \
  1886. __Type_##NAME func; \
  1887. inline __MetaLooper_##NAME() { func = __Function_##NAME<i>::Run; } \
  1888. }; \
  1889. \
  1890. template<> \
  1891. struct __MetaLooper_##NAME<0> \
  1892. { \
  1893. __Type_##NAME func; \
  1894. inline __MetaLooper_##NAME() { func = __Function_##NAME<0>::Run; } \
  1895. }; \
  1896. \
  1897. class NAME \
  1898. { \
  1899. private: \
  1900. static const __MetaLooper_##NAME<COUNT> m; \
  1901. public: \
  1902. enum { count = COUNT }; \
  1903. static const __Type_##NAME* functions; \
  1904. }; \
  1905. const __MetaLooper_##NAME<COUNT> NAME::m; \
  1906. const __Type_##NAME* NAME::functions = (__Type_##NAME*)&m; \
  1907. template<const int nArgument> \
  1908. RETURN_TYPE FASTCALL __Function_##NAME<nArgument>::Run ARGS
  1909. #define LOOP_INTERCHANGE(BOOLEAN, CODE)\
  1910. if( (BOOLEAN) )\
  1911. {\
  1912. CODE;\
  1913. } else\
  1914. {\
  1915. CODE;\
  1916. }
  1917. //-----------------------------------------------------------------------------
  1918. // What OS version are we?
  1919. //-----------------------------------------------------------------------------
  1920. enum PlatOSVersion_t
  1921. {
  1922. PLAT_OS_VERSION_UNKNOWN = -1,
  1923. // X360-specific versions
  1924. PLAT_OS_VERSION_XBOX360 = 0,
  1925. // PC-specific OS versions (single byte)
  1926. PLAT_OS_VERSION_WIN2K = 50,
  1927. PLAT_OS_VERSION_XP = 51,
  1928. PLAT_OS_VERSION_WIN2003 = 52,
  1929. PLAT_OS_VERSION_VISTA = 60,
  1930. PLAT_OS_VERSION_WIN7 = 61,
  1931. PLAT_OS_VERSION_WIN8 = 62,
  1932. PLAT_OS_VERSION_WIN81 = 63,
  1933. PLAT_OS_VERSION_WIN10 = 100,
  1934. };
  1935. PLATFORM_INTERFACE PlatOSVersion_t Plat_GetOSVersion();
  1936. // Watchdog timer support. Call BeginWatchdogTimer( nn ) to kick the timer off. if you don't call
  1937. // EndWatchdogTimer within nn seconds, the program will kick off an exception. This is for making
  1938. // sure that hung dedicated servers abort (and restart) instead of staying hung. Calling
  1939. // EndWatchdogTimer more than once or when there is no active watchdog is fine. Only does anything
  1940. // under linux right now. It should be possible to implement this functionality in windows via a
  1941. // thread, if desired.
  1942. #if defined( POSIX ) && !defined( _PS3 )
  1943. PLATFORM_INTERFACE void BeginWatchdogTimer( int nSecs );
  1944. PLATFORM_INTERFACE void EndWatchdogTimer( void );
  1945. PLATFORM_INTERFACE void ResetBaseTime( void ); // reset plat_floattime to 0 for a subprocess
  1946. #else
  1947. FORCEINLINE void BeginWatchdogTimer( int nSecs )
  1948. {
  1949. }
  1950. FORCEINLINE void EndWatchdogTimer( void )
  1951. {
  1952. }
  1953. FORCEINLINE void ResetBaseTime( void ) // reset plat_floattime to 0 for a subprocess
  1954. {
  1955. }
  1956. #endif
  1957. #ifdef COMPILER_MSVC
  1958. /*
  1959. FORCEINLINE uint8 RotateBitsLeft8( uint8 nValue, int nRotateBits )
  1960. {
  1961. return _rotl8( nValue, nRotateBits );
  1962. }
  1963. FORCEINLINE uint16 RotateBitsLeft16( uint16 nValue, int nRotateBits )
  1964. {
  1965. return _rotl( nValue, nRotateBits );
  1966. }
  1967. FORCEINLINE uint8 RotateBitsRight8( uint8 nValue, int nRotateBits )
  1968. {
  1969. return _rotr8( nValue, nRotateBits );
  1970. }
  1971. FORCEINLINE uint16 RotateBitsRight16( uint16 nValue, int nRotateBits )
  1972. {
  1973. return _rotr16( nValue, nRotateBits );
  1974. }
  1975. */
  1976. FORCEINLINE uint32 RotateBitsLeft32( uint32 nValue, int nRotateBits )
  1977. {
  1978. return _rotl( nValue, nRotateBits );
  1979. }
  1980. FORCEINLINE uint64 RotateBitsLeft64( uint64 nValue, int nRotateBits )
  1981. {
  1982. return _rotl64( nValue, nRotateBits );
  1983. }
  1984. FORCEINLINE uint32 RotateBitsRight32( uint32 nValue, int nRotateBits )
  1985. {
  1986. return _rotr( nValue, nRotateBits );
  1987. }
  1988. FORCEINLINE uint64 RotateBitsRight64( uint64 nValue, int nRotateBits )
  1989. {
  1990. return _rotr64( nValue, nRotateBits );
  1991. }
  1992. #else
  1993. // GCC should compile this all into single instruction
  1994. /*
  1995. FORCEINLINE uint8 RotateBitsLeft8( uint8 nValue, int nRotateBits )
  1996. {
  1997. return ( nValue << nRotateBits ) | ( nValue >> ( ( -nRotateBits ) & 7 ) );
  1998. }
  1999. FORCEINLINE uint16 RotateBitsLeft16( uint16 nValue, int nRotateBits )
  2000. {
  2001. return ( nValue << nRotateBits ) | ( nValue >> ( ( -nRotateBits ) & 15 ) );
  2002. }
  2003. FORCEINLINE uint8 RotateBitsRight8( uint8 nValue, int nRotateBits )
  2004. {
  2005. return ( nValue >> nRotateBits ) | ( nValue << ( ( -nRotateBits ) & 7 ) );
  2006. }
  2007. FORCEINLINE uint16 RotateBitsRight16( uint16 nValue, int nRotateBits )
  2008. {
  2009. return ( nValue >> nRotateBits ) | ( nValue << ( ( -nRotateBits ) & 15 ) );
  2010. }
  2011. */
  2012. FORCEINLINE uint32 RotateBitsLeft32( uint32 nValue, int nRotateBits )
  2013. {
  2014. return ( nValue << nRotateBits ) | ( nValue >> ( ( -nRotateBits ) & 31 ) );
  2015. }
  2016. FORCEINLINE uint64 RotateBitsLeft64( uint64 nValue, int nRotateBits )
  2017. {
  2018. return ( nValue << nRotateBits ) | ( nValue >> ( ( - nRotateBits ) & 63 ) );
  2019. }
  2020. FORCEINLINE uint32 RotateBitsRight32( uint32 nValue, int nRotateBits )
  2021. {
  2022. return ( nValue >> nRotateBits ) | ( nValue << ( ( -nRotateBits ) & 31 ) );
  2023. }
  2024. FORCEINLINE uint64 RotateBitsRight64( uint64 nValue, int nRotateBits )
  2025. {
  2026. return ( nValue >> nRotateBits ) | ( nValue << ( ( - nRotateBits ) & 63 ) );
  2027. }
  2028. #endif
  2029. PLATFORM_INTERFACE const char * GetPlatformSpecificFileName(const char * FileName);
  2030. #include "tier0/valve_on.h"
  2031. #if defined(TIER0_DLL_EXPORT)
  2032. #undef stricmp
  2033. #undef strcmpi
  2034. #define stricmp(s1,s2) V_tier0_stricmp( s1, s2 )
  2035. #define strcmpi(s1,s2) V_tier0_stricmp( s1, s2 )
  2036. #else
  2037. int _V_stricmp (const char *s1, const char *s2 );
  2038. int V_strncasecmp (const char *s1, const char *s2, int n);
  2039. // A special high-performance case-insensitive compare function that in
  2040. // a single call distinguishes between exactly matching strings,
  2041. // strings equal in case-insensitive way, and not equal strings:
  2042. // returns 0 if strings match exactly
  2043. // returns >0 if strings match in a case-insensitive way, but do not match exactly
  2044. // returns <0 if strings do not match even in a case-insensitive way
  2045. int _V_stricmp_NegativeForUnequal ( const char *s1, const char *s2 );
  2046. #undef stricmp
  2047. #undef strcmpi
  2048. #define stricmp(s1,s2) _V_stricmp(s1, s2)
  2049. #define strcmpi(s1,s2) _V_stricmp(s1, s2)
  2050. #undef strnicmp
  2051. #define strnicmp V_strncasecmp
  2052. #endif
  2053. // Use AlignedByteArray_t if you need an appropriately aligned array of T with no constructor (e.g CUtlMemoryFixed):
  2054. // - usage: AlignedByteArray_t< NUM, T >
  2055. // - same as: byte[ NUM*sizeof(T) ]
  2056. // - BUT: avoids calling T's constructor
  2057. // - AND: has same alignment as T
  2058. // [ Thanks to CygnusX1: http://stackoverflow.com/questions/5134217/aligning-data-on-the-stack-c ]
  2059. #if defined( GNUC )
  2060. // gnuc has the align decoration at the end
  2061. #define ALIGN4
  2062. #define ALIGN8
  2063. #define ALIGN16
  2064. #define ALIGN32
  2065. #define ALIGN128
  2066. #define ALIGN_N( _align_ )
  2067. #undef ALIGN16_POST
  2068. #define ALIGN4_POST DECL_ALIGN(4)
  2069. #define ALIGN8_POST DECL_ALIGN(8)
  2070. #define ALIGN16_POST DECL_ALIGN(16)
  2071. #define ALIGN32_POST DECL_ALIGN(32)
  2072. #define ALIGN128_POST DECL_ALIGN(128)
  2073. #define ALIGN_N_POST( _align_ ) DECL_ALIGN( _align_ )
  2074. #else
  2075. // MSVC has the align at the start of the struct
  2076. // PS3 SNC supports both
  2077. #define ALIGN4 DECL_ALIGN(4)
  2078. #define ALIGN8 DECL_ALIGN(8)
  2079. #define ALIGN16 DECL_ALIGN(16)
  2080. #define ALIGN32 DECL_ALIGN(32)
  2081. #define ALIGN128 DECL_ALIGN(128)
  2082. #define ALIGN_N( _align_ ) DECL_ALIGN( _align_ )
  2083. #define ALIGN4_POST
  2084. #define ALIGN8_POST
  2085. #define ALIGN16_POST
  2086. #define ALIGN32_POST
  2087. #define ALIGN128_POST
  2088. #define ALIGN_N_POST( _align_ )
  2089. #endif
  2090. // !!! NOTE: if you get a compile error here, you are using VALIGNOF on an abstract type :NOTE !!!
  2091. #define VALIGNOF_PORTABLE( type ) ( sizeof( AlignOf_t<type> ) - sizeof( type ) )
  2092. #if defined( COMPILER_GCC ) || defined( COMPILER_MSVC )
  2093. #define VALIGNOF( type ) __alignof( type )
  2094. #define VALIGNOF_TEMPLATE_SAFE( type ) VALIGNOF_PORTABLE( type )
  2095. #else
  2096. #error "PORT: Code only tested with MSVC! Must validate with new compiler, and use built-in keyword if available."
  2097. #endif
  2098. // Use ValidateAlignment to sanity-check alignment usage when allocating arrays of an aligned type
  2099. #define ALIGN_ASSERT( pred ) { COMPILE_TIME_ASSERT( pred ); }
  2100. template< class T, int ALIGN >
  2101. inline void ValidateAlignmentExplicit(void)
  2102. {
  2103. // Alignment must be a power of two
  2104. ALIGN_ASSERT((ALIGN & (ALIGN - 1)) == 0);
  2105. // Alignment must not imply gaps in the array (which the CUtlMemory pattern does not allow for)
  2106. ALIGN_ASSERT(ALIGN <= sizeof(T));
  2107. // Alignment must be a multiple of the size of the object type, or elements will *NOT* be aligned!
  2108. ALIGN_ASSERT((sizeof(T) % ALIGN) == 0);
  2109. // Alignment should be a multiple of the base alignment of T
  2110. // ALIGN_ASSERT((ALIGN % VALIGNOF(T)) == 0);
  2111. }
  2112. template< class T > inline void ValidateAlignment(void) { ValidateAlignmentExplicit<T, VALIGNOF(T)>(); }
  2113. // Portable alternative to __alignof
  2114. template<class T> struct AlignOf_t { AlignOf_t(){} AlignOf_t & operator=(const AlignOf_t &) { return *this; } byte b; T t; };
  2115. template < size_t NUM, class T, int ALIGN > struct AlignedByteArrayExplicit_t{};
  2116. template < size_t NUM, class T > struct AlignedByteArray_t : public AlignedByteArrayExplicit_t< NUM, T, VALIGNOF_TEMPLATE_SAFE(T) > {};
  2117. #define DECLARE_ALIGNED_BYTE_ARRAY( ALIGN ) \
  2118. template < size_t NUM, class T > \
  2119. struct ALIGN_N( ALIGN ) AlignedByteArrayExplicit_t< NUM, T, ALIGN > \
  2120. { \
  2121. /* NOTE: verify alignment in the constructor (which may be wrong if this is heap-allocated, for ALIGN > MEMALLOC_MAX_AUTO_ALIGN) */ \
  2122. AlignedByteArrayExplicit_t() { if ( (ALIGN-1) & (size_t)this ) DebuggerBreakIfDebugging(); } \
  2123. T * Base( void ) { ValidateAlignmentExplicit<T,ALIGN>(); return (T *)&m_Data; } \
  2124. const T * Base( void ) const { ValidateAlignmentExplicit<T,ALIGN>(); return (const T *)&m_Data; } \
  2125. private: \
  2126. byte m_Data[ NUM*sizeof( T ) ]; \
  2127. } ALIGN_N_POST( ALIGN );
  2128. DECLARE_ALIGNED_BYTE_ARRAY(1);
  2129. DECLARE_ALIGNED_BYTE_ARRAY(2);
  2130. DECLARE_ALIGNED_BYTE_ARRAY(4);
  2131. DECLARE_ALIGNED_BYTE_ARRAY(8);
  2132. DECLARE_ALIGNED_BYTE_ARRAY(16);
  2133. DECLARE_ALIGNED_BYTE_ARRAY(32);
  2134. DECLARE_ALIGNED_BYTE_ARRAY(64);
  2135. DECLARE_ALIGNED_BYTE_ARRAY(128);
  2136. // Tier0 uses this for faster stricmp.
  2137. PLATFORM_INTERFACE int V_tier0_stricmp( const char *a, const char *b );
  2138. PLATFORM_INTERFACE void V_tier0_strncpy( char *a, const char *b, int n );
  2139. PLATFORM_INTERFACE char *V_tier0_strncat( char *a, const char *b, int n, int m = -1 );
  2140. PLATFORM_INTERFACE int V_tier0_vsnprintf( char *a, int n, PRINTF_FORMAT_STRING const char *f, va_list l ) FMTFUNCTION( 3, 0 );
  2141. PLATFORM_INTERFACE int V_tier0_snprintf( char *a, int n, PRINTF_FORMAT_STRING const char *f, ... ) FMTFUNCTION( 3, 4 );
  2142. //-----------------------------------------------------------------------------
  2143. PLATFORM_INTERFACE char const * Plat_GetEnv(char const *pEnvVarName);
  2144. PLATFORM_INTERFACE bool Plat_GetExecutablePath(char* pBuff, size_t nBuff);
  2145. #endif /* PLATFORM_H */