diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /tier0/platform.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'tier0/platform.cpp')
| -rw-r--r-- | tier0/platform.cpp | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/tier0/platform.cpp b/tier0/platform.cpp new file mode 100644 index 0000000..2ffd536 --- /dev/null +++ b/tier0/platform.cpp @@ -0,0 +1,478 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "pch_tier0.h" +#include <time.h> + +#if defined(_WIN32) && !defined(_X360) +#include <errno.h> +#endif +#include <assert.h> +#include "tier0/platform.h" +#include "tier0/minidump.h" +#ifdef _X360 +#include "xbox/xbox_console.h" +#include "xbox/xbox_win32stubs.h" +#else +#include "tier0/vcrmode.h" +#endif +#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) +#include "tier0/memalloc.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" +#endif + +//our global error callback function. Note that this is not initialized, but static space guarantees this is NULL at app start. +//If you initialize, it will set to zero again when the CPP runs its static initializers, which could stomp the value if another +//CPP sets this value while initializing its static space +static ExitProcessWithErrorCBFn g_pfnExitProcessWithErrorCB; //= NULL + +#ifndef _X360 +extern VCRMode_t g_VCRMode; +#endif +static LARGE_INTEGER g_PerformanceFrequency; +static double g_PerformanceCounterToS; +static double g_PerformanceCounterToMS; +static double g_PerformanceCounterToUS; +static LARGE_INTEGER g_ClockStart; +static bool s_bTimeInitted; + +// Benchmark mode uses this heavy-handed method +static bool g_bBenchmarkMode = false; +static double g_FakeBenchmarkTime = 0; +static double g_FakeBenchmarkTimeInc = 1.0 / 66.0; + +static void InitTime() +{ + if( !s_bTimeInitted ) + { + s_bTimeInitted = true; + QueryPerformanceFrequency(&g_PerformanceFrequency); + g_PerformanceCounterToS = 1.0 / g_PerformanceFrequency.QuadPart; + g_PerformanceCounterToMS = 1e3 / g_PerformanceFrequency.QuadPart; + g_PerformanceCounterToUS = 1e6 / g_PerformanceFrequency.QuadPart; + QueryPerformanceCounter(&g_ClockStart); + } +} + +bool Plat_IsInBenchmarkMode() +{ + return g_bBenchmarkMode; +} + +void Plat_SetBenchmarkMode( bool bBenchmark ) +{ + g_bBenchmarkMode = bBenchmark; +} + +double Plat_FloatTime() +{ + if (! s_bTimeInitted ) + InitTime(); + if ( g_bBenchmarkMode ) + { + g_FakeBenchmarkTime += g_FakeBenchmarkTimeInc; + return g_FakeBenchmarkTime; + } + + LARGE_INTEGER CurrentTime; + + QueryPerformanceCounter( &CurrentTime ); + + double fRawSeconds = (double)( CurrentTime.QuadPart - g_ClockStart.QuadPart ) * g_PerformanceCounterToS; + + return fRawSeconds; +} + +uint32 Plat_MSTime() +{ + if (! s_bTimeInitted ) + InitTime(); + if ( g_bBenchmarkMode ) + { + g_FakeBenchmarkTime += g_FakeBenchmarkTimeInc; + return (uint32)(g_FakeBenchmarkTime * 1000.0); + } + + LARGE_INTEGER CurrentTime; + + QueryPerformanceCounter( &CurrentTime ); + + return (uint32) ( ( CurrentTime.QuadPart - g_ClockStart.QuadPart ) * g_PerformanceCounterToMS ); +} + +uint64 Plat_USTime() +{ + if (! s_bTimeInitted ) + InitTime(); + if ( g_bBenchmarkMode ) + { + g_FakeBenchmarkTime += g_FakeBenchmarkTimeInc; + return (uint64)(g_FakeBenchmarkTime * 1e6); + } + + LARGE_INTEGER CurrentTime; + + QueryPerformanceCounter( &CurrentTime ); + + return (uint64) ( ( CurrentTime.QuadPart - g_ClockStart.QuadPart ) * g_PerformanceCounterToUS ); +} + +void GetCurrentDate( int *pDay, int *pMonth, int *pYear ) +{ + struct tm *pNewTime; + time_t long_time; + + time( &long_time ); /* Get time as long integer. */ + pNewTime = localtime( &long_time ); /* Convert to local time. */ + + *pDay = pNewTime->tm_mday; + *pMonth = pNewTime->tm_mon + 1; + *pYear = pNewTime->tm_year + 1900; +} + + +// Wraps the thread-safe versions of ctime. buf must be at least 26 bytes +char *Plat_ctime( const time_t *timep, char *buf, size_t bufsize ) +{ + if ( EINVAL == ctime_s( buf, bufsize, timep ) ) + return NULL; + else + return buf; +} + +void Plat_GetModuleFilename( char *pOut, int nMaxBytes ) +{ +#ifdef PLATFORM_WINDOWS_PC + SetLastError( ERROR_SUCCESS ); // clear the error code + GetModuleFileName( NULL, pOut, nMaxBytes ); + if ( GetLastError() != ERROR_SUCCESS ) + Error( "Plat_GetModuleFilename: The buffer given is too small (%d bytes).", nMaxBytes ); +#elif PLATFORM_X360 + pOut[0] = 0x00; // return null string on Xbox 360 +#else + // We shouldn't need this on POSIX. + Assert( false ); + pOut[0] = 0x00; // Null the returned string in release builds +#endif +} + +void Plat_ExitProcess( int nCode ) +{ +#if defined( _WIN32 ) && !defined( _X360 ) + // We don't want global destructors in our process OR in any DLL to get executed. + // _exit() avoids calling global destructors in our module, but not in other DLLs. + const char *pchCmdLineA = Plat_GetCommandLineA(); + if ( nCode || ( strstr( pchCmdLineA, "gc.exe" ) && strstr( pchCmdLineA, "gc.dll" ) && strstr( pchCmdLineA, "-gc" ) ) ) + { + int *x = NULL; *x = 1; // cause a hard crash, GC is not allowed to exit voluntarily from gc.dll + } + TerminateProcess( GetCurrentProcess(), nCode ); +#elif defined(_PS3) + // We do not use this path to exit on PS3 (naturally), rather we want a clear crash: + int *x = NULL; *x = 1; +#else + _exit( nCode ); +#endif +} + +void Plat_ExitProcessWithError( int nCode, bool bGenerateMinidump ) +{ + //try to delegate out if they have registered a callback + if( g_pfnExitProcessWithErrorCB ) + { + if( g_pfnExitProcessWithErrorCB( nCode ) ) + return; + } + + //handle default behavior + if( bGenerateMinidump ) + { + //don't generate mini dumps in the debugger + if( !Plat_IsInDebugSession() ) + { + WriteMiniDump(); + } + } + + //and exit our process + Plat_ExitProcess( nCode ); +} + +void Plat_SetExitProcessWithErrorCB( ExitProcessWithErrorCBFn pfnCB ) +{ + g_pfnExitProcessWithErrorCB = pfnCB; +} + +// Wraps the thread-safe versions of gmtime +struct tm *Plat_gmtime( const time_t *timep, struct tm *result ) +{ + if ( EINVAL == gmtime_s( result, timep ) ) + return NULL; + else + return result; +} + + +time_t Plat_timegm( struct tm *timeptr ) +{ + return _mkgmtime( timeptr ); +} + + +// Wraps the thread-safe versions of localtime +struct tm *Plat_localtime( const time_t *timep, struct tm *result ) +{ + if ( EINVAL == localtime_s( result, timep ) ) + return NULL; + else + return result; +} + + +bool vtune( bool resume ) +{ +#ifndef _X360 + static bool bInitialized = false; + static void (__cdecl *VTResume)(void) = NULL; + static void (__cdecl *VTPause) (void) = NULL; + + // Grab the Pause and Resume function pointers from the VTune DLL the first time through: + if( !bInitialized ) + { + bInitialized = true; + + HINSTANCE pVTuneDLL = LoadLibrary( "vtuneapi.dll" ); + + if( pVTuneDLL ) + { + VTResume = (void(__cdecl *)())GetProcAddress( pVTuneDLL, "VTResume" ); + VTPause = (void(__cdecl *)())GetProcAddress( pVTuneDLL, "VTPause" ); + } + } + + // Call the appropriate function, as indicated by the argument: + if( resume && VTResume ) + { + VTResume(); + return true; + + } + else if( !resume && VTPause ) + { + VTPause(); + return true; + } +#endif + return false; +} + +bool Plat_IsInDebugSession() +{ +#if defined( _WIN32 ) && !defined( _X360 ) + return (IsDebuggerPresent() != 0); +#elif defined( _WIN32 ) && defined( _X360 ) + return (XBX_IsDebuggerPresent() != 0); +#elif defined( LINUX ) + #error This code is implemented in platform_posix.cpp +#else + return false; +#endif +} + +void Plat_DebugString( const char * psz ) +{ +#if defined( _WIN32 ) && !defined( _X360 ) + ::OutputDebugStringA( psz ); +#elif defined( _WIN32 ) && defined( _X360 ) + XBX_OutputDebugString( psz ); +#endif +} + + +const tchar *Plat_GetCommandLine() +{ +#ifdef TCHAR_IS_WCHAR + return GetCommandLineW(); +#else + return GetCommandLine(); +#endif +} + +bool GetMemoryInformation( MemoryInformation *pOutMemoryInfo ) +{ + if ( !pOutMemoryInfo ) + return false; + + MEMORYSTATUSEX memStat; + ZeroMemory( &memStat, sizeof( MEMORYSTATUSEX ) ); + memStat.dwLength = sizeof( MEMORYSTATUSEX ); + + if ( !GlobalMemoryStatusEx( &memStat ) ) + return false; + + const uint cOneMb = 1024 * 1024; + + switch ( pOutMemoryInfo->m_nStructVersion ) + { + case 0: + ( *pOutMemoryInfo ).m_nPhysicalRamMbTotal = memStat.ullTotalPhys / cOneMb; + ( *pOutMemoryInfo ).m_nPhysicalRamMbAvailable = memStat.ullAvailPhys / cOneMb; + + ( *pOutMemoryInfo ).m_nVirtualRamMbTotal = memStat.ullTotalVirtual / cOneMb; + ( *pOutMemoryInfo ).m_nVirtualRamMbAvailable = memStat.ullAvailVirtual / cOneMb; + break; + + default: + return false; + }; + + return true; +} + + +const char *Plat_GetCommandLineA() +{ + return GetCommandLineA(); +} + +//-------------------------------------------------------------------------------------------------- +// Watchdog timer +//-------------------------------------------------------------------------------------------------- +void Plat_BeginWatchdogTimer( int nSecs ) +{ +} +void Plat_EndWatchdogTimer( void ) +{ +} +int Plat_GetWatchdogTime( void ) +{ + return 0; +} +void Plat_SetWatchdogHandlerFunction( Plat_WatchDogHandlerFunction_t function ) +{ +} + +bool Is64BitOS() +{ + typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + static LPFN_ISWOW64PROCESS pfnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( GetModuleHandle("kernel32"), "IsWow64Process" ); + + static BOOL bIs64bit = FALSE; + static bool bInitialized = false; + if ( bInitialized ) + return bIs64bit == (BOOL)TRUE; + else + { + bInitialized = true; + return pfnIsWow64Process && pfnIsWow64Process(GetCurrentProcess(), &bIs64bit) && bIs64bit; + } +} + + +// -------------------------------------------------------------------------------------------------- // +// Memory stuff. +// +// DEPRECATED. Still here to support binary back compatability of tier0.dll +// +// -------------------------------------------------------------------------------------------------- // +#ifndef _X360 +#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) + +typedef void (*Plat_AllocErrorFn)( unsigned long size ); + +void Plat_DefaultAllocErrorFn( unsigned long size ) +{ +} + +Plat_AllocErrorFn g_AllocError = Plat_DefaultAllocErrorFn; +#endif + +#ifndef _X360 +CRITICAL_SECTION g_AllocCS; +class CAllocCSInit +{ +public: + CAllocCSInit() + { + InitializeCriticalSection( &g_AllocCS ); + } +} g_AllocCSInit; +#endif + +#ifndef _X360 +PLATFORM_INTERFACE void* Plat_Alloc( unsigned long size ) +{ + EnterCriticalSection( &g_AllocCS ); +#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) + void *pRet = g_pMemAlloc->Alloc( size ); +#else + void *pRet = malloc( size ); +#endif + LeaveCriticalSection( &g_AllocCS ); + if ( pRet ) + { + return pRet; + } + else + { +#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) + g_AllocError( size ); +#endif + return 0; + } +} +#endif + +#ifndef _X360 +PLATFORM_INTERFACE void* Plat_Realloc( void *ptr, unsigned long size ) +{ + EnterCriticalSection( &g_AllocCS ); +#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) + void *pRet = g_pMemAlloc->Realloc( ptr, size ); +#else + void *pRet = realloc( ptr, size ); +#endif + LeaveCriticalSection( &g_AllocCS ); + if ( pRet ) + { + return pRet; + } + else + { +#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) + g_AllocError( size ); +#endif + return 0; + } +} +#endif + +#ifndef _X360 +PLATFORM_INTERFACE void Plat_Free( void *ptr ) +{ + EnterCriticalSection( &g_AllocCS ); +#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) + g_pMemAlloc->Free( ptr ); +#else + free( ptr ); +#endif + LeaveCriticalSection( &g_AllocCS ); +} +#endif + +#ifndef _X360 +#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) +PLATFORM_INTERFACE void Plat_SetAllocErrorFn( Plat_AllocErrorFn fn ) +{ + g_AllocError = fn; +} +#endif +#endif + +#endif |