|
|
//======= Copyright (c) 1996-2009, Valve Corporation, All rights reserved. ======
//
// Purpose: Video configuration management (split out from tier2)
//
//===============================================================================
#include "tier2/fileutils.h"
#include "tier2/tier2.h"
#include "videocfg.h"
#include "tier1/tier1.h"
#include "tier1/strtools.h"
#include "filesystem.h"
#include "tier1/keyvalues.h"
#include "utlbuffer.h"
#include "mathlib/IceKey.H"
#include "tier0/icommandline.h"
// Video Config Filenames
#ifdef POSIX
#define VIDEOCONFIG_DEFAULT_FILENAME "cfg/videodefaults.txt"
#define VIDEOCONFIG_FILENAME "cfg/video.txt"
#define VIDEOCONFIG_FILENAME_BACKUP "cfg/video.bak"
#else
#define VIDEOCONFIG_DEFAULT_FILENAME "cfg\\videodefaults.txt"
#define VIDEOCONFIG_FILENAME "cfg\\video.txt"
#define VIDEOCONFIG_FILENAME_BACKUP "cfg\\video.bak"
#endif
#define VIDEOCONFIG_PATHID "USRLOCAL"
static void WriteVideoCfgDataToFile( char const *pszFile, CUtlBuffer &buf ) { // Video defaults and video settings detection runs very early, so we need to create cfg path in USRLOCAL storage
g_pFullFileSystem->CreateDirHierarchy( "cfg", "USRLOCAL" ); g_pFullFileSystem->WriteFile( pszFile, VIDEOCONFIG_PATHID, buf ); }
enum AspectRatioMode_t { ASPECT_RATIO_OTHER = -1, ASPECT_RATIO_4x3 = 0, ASPECT_RATIO_16x9, ASPECT_RATIO_16x10, };
struct VideoConfigSetting_t { const char *m_pSettingVar; bool m_bChooseLower; bool m_bSaved; bool m_bConVar; bool m_bUseAutoOption; };
struct RatioToAspectMode_t { AspectRatioMode_t m_Mode; int m_nWidth; int m_nHeight; };
static VideoConfigSetting_t s_pVideoConfigSettingsWhitelist[] = { // ConVars.
{ "setting.cpu_level", true, true, true, true }, { "setting.gpu_level", true, true, true, true }, { "setting.mat_antialias", true, true, true, true }, { "setting.mat_aaquality", true, true, true, true }, { "setting.mat_forceaniso", true, true, true, true }, { "setting.mat_vsync", true, true, true }, { "setting.mat_triplebuffered", true, true, true }, { "setting.mat_grain_scale_override", true, true, true }, // { "setting.mat_monitorgamma", true, true, true },
{ "setting.gpu_mem_level", true, true, true, true }, { "setting.mem_level", true, true, true }, { "setting.videoconfig_version", true, true, true }, { "setting.mat_queue_mode", true, true, true }, { "setting.mat_tonemapping_occlusion_use_stencil", false, false, true }, { "setting.csm_quality_level", true, true, true, true }, { "setting.mat_software_aa_strength", true, true, true }, { "setting.mat_motion_blur_enabled", true, true, true },
// Settings.
{ "setting.fullscreen", true, true, false }, { "setting.nowindowborder", true, true, false }, { "setting.aspectratiomode", true, true, false }, { "setting.defaultres", true, true, false }, { "setting.defaultresheight", true, true, false }, { "setting.dxlevel", true, false, false }, { "setting.mindxlevel", true, false, false }, { "setting.maxdxlevel", true, false, false }, { "setting.preferhardwaresync", true, false, false }, { "setting.centroidhack", true, false, false }, { "setting.preferzprepass", true, false, false }, { "setting.prefertexturesinhwmemory", true, false, false }, { "setting.laptop", true, false, false }, { "setting.suppresspixelshadercentroidhackfixup", true, false, false }, { "setting.nouserclipplanes", true, false, false }, { "setting.unsupported", true, false, false }, }; static VideoConfigSetting_t const * VideoConfigSettingFindWhitelistEntryByName( char const *szSettingName ) { for ( int k = 0; k < Q_ARRAYSIZE( s_pVideoConfigSettingsWhitelist ); ++ k ) { if ( !V_stricmp( szSettingName, s_pVideoConfigSettingsWhitelist[k].m_pSettingVar ) ) return &s_pVideoConfigSettingsWhitelist[k]; } return NULL; }
static RatioToAspectMode_t g_pRatioToAspectModes[] = { { ASPECT_RATIO_4x3, 4, 3 }, { ASPECT_RATIO_16x9, 16, 9 }, { ASPECT_RATIO_16x10, 16, 10 }, };
//--------------------------------------------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
static AspectRatioMode_t GetScreenAspectMode( int width, int height ) { for (int i = 0; i < ARRAYSIZE(g_pRatioToAspectModes); i++) { int nFactor = width / g_pRatioToAspectModes[i].m_nWidth; if ( nFactor * g_pRatioToAspectModes[i].m_nHeight == height ) return g_pRatioToAspectModes[i].m_Mode; }
return ASPECT_RATIO_OTHER; } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
static inline int ReadHexValue( KeyValues *pVal, const char *pName ) { const char *pString = pVal->GetString( pName, NULL ); if (!pString) { return -1; }
char *pTemp; int nVal = strtol( pString, &pTemp, 16 ); return (pTemp != pString) ? nVal : -1; } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
void AddNewKeysUsingVideoWhitelist( KeyValues *pModKeys, KeyValues *pConfigKeys ) { for( KeyValues *pSubKey = pModKeys->GetFirstSubKey(); pSubKey; pSubKey = pSubKey->GetNextKey() ) { const char *pSubKeyName = pSubKey->GetName();
// Find all the "setting" keys that are white-listed and add them to the
// Video Config keys.
int iVar; bool bWhiteListedVar = false; int nVideoConfigCount = ARRAYSIZE( s_pVideoConfigSettingsWhitelist ); for ( iVar = 0; iVar < nVideoConfigCount; ++iVar ) { if ( !V_stricmp( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar, pSubKeyName ) ) { bWhiteListedVar = true; break; } }
// This is not a valid key.
if ( !bWhiteListedVar ) continue;
// See if the key already exists - if it doesn't add it.
if ( pConfigKeys->FindKey( pSubKeyName ) ) continue;
const char *pValue = pSubKey->GetString(); pConfigKeys->SetString( pSubKeyName, pValue ); } } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
void CopySettingKeysUsingVideoWhitelist( KeyValues *pModKeys, KeyValues *pConfigKeys ) { for( KeyValues *pSubKey = pModKeys->GetFirstSubKey(); pSubKey; pSubKey = pSubKey->GetNextKey() ) { const char *pSubKeyName = pSubKey->GetName();
// Find all the "setting" keys that are white-listed and add them to the
// Video Config keys.
int iVar; bool bWhiteListedVar = false; int nVideoConfigCount = ARRAYSIZE( s_pVideoConfigSettingsWhitelist ); for ( iVar = 0; iVar < nVideoConfigCount; ++iVar ) { if ( !V_stricmp( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar, pSubKeyName ) ) { bWhiteListedVar = true; break; } }
// This is not a valid key.
if ( !bWhiteListedVar ) continue;
if ( pConfigKeys->FindKey( pSubKeyName ) ) { float flOldValue = pConfigKeys->GetFloat( pSubKeyName ); float flNewValue = pSubKey->GetFloat(); if ( s_pVideoConfigSettingsWhitelist[iVar].m_bChooseLower ) { if ( flNewValue >= flOldValue ) continue; } else { if ( flNewValue <= flOldValue ) continue; } }
const char *pValue = pSubKey->GetString(); pConfigKeys->SetString( pSubKeyName, pValue ); } } #endif
//-----------------------------------------------------------------------------
// Purpose: Match the CPU data and add all the "setting" data to the Video Config Keys.
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
void AddCPULevelKeys( KeyValues *pModKeys, KeyValues *pVideoConfigKeys ) { // Get the number of physical processors in the machine.
const CPUInformation &cpuInfo = GetCPUInformation(); int nProcessorCount = cpuInfo.m_nPhysicalProcessors;
// Test all "cpu_level_*" blocks to determine the correct block to copy data from.
for( KeyValues *pModKey = pModKeys->GetFirstSubKey(); pModKey; pModKey = pModKey->GetNextKey() ) { KeyValues *pMinKey = pModKey->FindKey( "min_processor_count" ); KeyValues *pMaxKey = pModKey->FindKey( "max_processor_count" ); if ( pMinKey && pMaxKey ) { int nMin = pMinKey->GetInt(); int nMax = pMaxKey->GetInt();
// Is this the correct cpu_level setting.
if ( nMin <= nProcessorCount && nProcessorCount <= nMax ) { CopySettingKeysUsingVideoWhitelist( pModKey, pVideoConfigKeys ); } } } } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
void AddMemoryKeys( KeyValues *pModKeys, int nMemory, KeyValues *pVideoConfigKeys ) { for( KeyValues *pModKey = pModKeys->GetFirstSubKey(); pModKey; pModKey = pModKey->GetNextKey() ) { KeyValues *pMinMegabytes = pModKey->FindKey( "min megabytes" ); KeyValues *pMaxMegabytes = pModKey->FindKey( "max megabytes" ); if ( pMinMegabytes && pMaxMegabytes ) { int nMin = pMinMegabytes->GetInt(); int nMax = pMaxMegabytes->GetInt();
// Is this the correct cpu_level setting.
if ( nMin <= nMemory && nMemory <= nMax ) { CopySettingKeysUsingVideoWhitelist( pModKey, pVideoConfigKeys ); } } } } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
void AddVideoMemoryKeys( KeyValues *pModKeys, int nVidMemory, KeyValues *pVideoConfigKeys ) { for( KeyValues *pModKey = pModKeys->GetFirstSubKey(); pModKey; pModKey = pModKey->GetNextKey() ) { KeyValues *pMinMegaTexels = pModKey->FindKey( "min megatexels" ); KeyValues *pMaxMegaTexels = pModKey->FindKey( "max megatexels" ); if ( pMinMegaTexels && pMaxMegaTexels ) { int nMin = pMinMegaTexels->GetInt(); int nMax = pMaxMegaTexels->GetInt();
// Is this the correct cpu_level setting.
if ( nMin <= nVidMemory && nVidMemory <= nMax ) { CopySettingKeysUsingVideoWhitelist( pModKey, pVideoConfigKeys ); } } } } #endif
//-----------------------------------------------------------------------------
// Purpose: Match the device and vendor id and add all the "setting" data to
// the Video Config Keys.
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
bool AddVideoCardKeys( KeyValues *pModKeys, int nVendorID, int nDeviceID, KeyValues *pVideoConfigKeys ) { bool bFoundDevice = false;
// Test all video card blocks to determine the correct blocks to copy data from.
for( KeyValues *pModKey = pModKeys->GetFirstSubKey(); pModKey; pModKey = pModKey->GetNextKey() ) { // Get and match the vendor and device id.
int iVender = ReadHexValue( pModKey, "vendorid" ); if ( iVender == -1 ) continue;
int iDeviceMin = ReadHexValue( pModKey, "mindeviceid" ); int iDeviceMax = ReadHexValue( pModKey, "maxdeviceid" ); if ( iDeviceMin == -1 || iDeviceMax == -1 ) continue;
// Only initialize with unknown data if we didn't find the actual card.
bool bUnknownDevice = ( pModKey->FindKey( "makemelast" ) != NULL );
// Fixed for CS:GO - Don't apply this node's keys at all unless the node's vendor ID matches (for example, some NVidia device ID's, such as the 6800's, alias a few Intel ID's).
if ( ( iDeviceMin <= nDeviceID ) && ( nDeviceID <= iDeviceMax ) && ( nVendorID == iVender ) ) { if ( !bUnknownDevice ) { CopySettingKeysUsingVideoWhitelist( pModKey, pVideoConfigKeys ); bFoundDevice = true; } else { AddNewKeysUsingVideoWhitelist( pModKey, pVideoConfigKeys ); } } }
return bFoundDevice; } #endif
//-----------------------------------------------------------------------------
// Purpose: Match the device and vendor id and add all the "setting" data to
// the Video Config Keys.
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
void AddDXLevelKeys( KeyValues *pModKeys, int nDXLevel, KeyValues *pVideoConfigKeys ) { // Test all video card blocks to determine the correct blocks to copy data from.
for( KeyValues *pModKey = pModKeys->GetFirstSubKey(); pModKey; pModKey = pModKey->GetNextKey() ) { KeyValues *pDXLevelKey = pModKey->FindKey( "setting.maxdxlevel" ); if ( !pDXLevelKey ) continue;
if ( pDXLevelKey->GetInt() == nDXLevel ) { AddNewKeysUsingVideoWhitelist( pModKey, pVideoConfigKeys ); } } } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
bool ParseConfigKeys( VidMatConfigData_t &configData ) { // Does the file exist?
bool bFileExists = g_pFullFileSystem->FileExists( configData.szFileName, configData.szPathID ); if ( !bFileExists ) return false;
// Get the key values in the file.
KeyValues *pFileKeys = new KeyValues( "FileKeys" ); if ( !pFileKeys ) return false;
if ( !pFileKeys->LoadFromFile( g_pFullFileSystem, configData.szFileName, configData.szPathID ) ) { pFileKeys->deleteThis(); return false; }
#ifdef _DEBUG
Msg( "VIDEOCFG.ParseConfigKeys: (start)\n" ); KeyValuesDumpAsDevMsg( configData.pConfigKeys, 0, 0 ); #endif
// Add Config Keys based on cpu.
AddCPULevelKeys( pFileKeys, configData.pConfigKeys ); #ifdef _DEBUG
Msg( "VIDEOCFG.ParseConfigKeys: (+cpu_level)\n" ); KeyValuesDumpAsDevMsg( configData.pConfigKeys, 0, 0 ); #endif
// Add Config Keys based on memory.
AddMemoryKeys( pFileKeys, configData.nSystemMemory, configData.pConfigKeys ); #ifdef _DEBUG
Msg( "VIDEOCFG.ParseConfigKeys: (+memory)\n" ); KeyValuesDumpAsDevMsg( configData.pConfigKeys, 0, 0 ); #endif
// Add Config Keys based on video memory.
AddVideoMemoryKeys( pFileKeys, configData.nVideoMemory, configData.pConfigKeys ); #ifdef _DEBUG
Msg( "VIDEOCFG.ParseConfigKeys: (+video memory)\n" ); KeyValuesDumpAsDevMsg( configData.pConfigKeys, 0, 0 ); #endif
// Add Config Keys based on video card.
bool bFoundDevice = AddVideoCardKeys( pFileKeys, configData.nVendorID, configData.nDeviceID, configData.pConfigKeys ); #ifdef _DEBUG
Msg( "VIDEOCFG.ParseConfigKeys: (+video card)\n" ); KeyValuesDumpAsDevMsg( configData.pConfigKeys, 0, 0 ); #endif
// Add Config Keys based on DXLevel.
if ( !bFoundDevice ) { //
// This actually doesn't work for CS:GO the way moddefaults.txt is setup
//
AddDXLevelKeys( pFileKeys, configData.nDXLevel, configData.pConfigKeys ); }
// Destroy the file keys.
pFileKeys->deleteThis();
return true; } #endif
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
static bool GetNearestFullscreenResolution( int& nWidth, int& nHeight, VidMatConfigData_t &configData ) { float flDesiredArea = nWidth * nHeight; int nBestWidth = 0; int nBestHeight = 0; float flBestDelta = FLT_MAX;
AspectRatioMode_t nRequiredAspectMode = GetScreenAspectMode( configData.nPhysicalScreenWidth, configData.nPhysicalScreenHeight );
// Iterate modes, looking for one that is just smaller than currentWidth and currentHeight while retaining the aspect ratio
while ( true ) { for ( int i = 0; i < configData.displayModes.Count(); i++ ) { const ShaderDisplayMode_t &mode = configData.displayModes[i];
if ( nRequiredAspectMode != ASPECT_RATIO_OTHER ) { AspectRatioMode_t nAspectMode = GetScreenAspectMode( mode.m_nWidth, mode.m_nHeight ); if ( nRequiredAspectMode != nAspectMode ) continue; }
float flArea = mode.m_nWidth * mode.m_nHeight; if ( flArea > flDesiredArea * 1.35f ) continue;
float flDelta = fabs( flDesiredArea - flArea ); if ( flDelta >= flBestDelta ) continue;
flBestDelta = flDelta; nBestWidth = mode.m_nWidth; nBestHeight = mode.m_nHeight; }
if ( nBestWidth != 0 ) break;
if ( nRequiredAspectMode == ASPECT_RATIO_OTHER ) return false;
nRequiredAspectMode = ASPECT_RATIO_OTHER; }
nWidth = nBestWidth; nHeight = nBestHeight; return true; } #endif
//-----------------------------------------------------------------------------
// Purpose: Create the video config file and fill it in with default data.
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
bool CreateDefaultVideoKeyValues( VidMatConfigData_t &configData ) { // Sets the highest CSM quality level and enabled FXAA, then let the csm_quality_level settings in moddefaults override these settings with lower values.
configData.pConfigKeys->SetInt( "setting.csm_quality_level", CSMQUALITY_HIGH ); //g_pHardwareConfig->GetCSMQuality() );
configData.pConfigKeys->SetInt( "setting.mat_software_aa_strength", 1 );
// Set the vendor and device id key values.
configData.pConfigKeys->SetInt( "VendorID", configData.nVendorID ); configData.pConfigKeys->SetInt( "DeviceID", configData.nDeviceID );
// Initial config always assume v-sync, normal aspect ratio, and fullscreen.
configData.pConfigKeys->SetInt( "setting.fullscreen", 1 ); configData.pConfigKeys->SetInt( "setting.nowindowborder", 0 ); configData.pConfigKeys->SetInt( "setting.aspectratiomode", GetScreenAspectMode( configData.nPhysicalScreenWidth, configData.nPhysicalScreenHeight ) ); configData.pConfigKeys->SetInt( "setting.mat_vsync", IsGameConsole() ? 1 : 0 ); configData.pConfigKeys->SetInt( "setting.mat_triplebuffered", 0 ); configData.pConfigKeys->SetFloat( "setting.mat_monitorgamma", 2.2f ); configData.pConfigKeys->SetInt( "setting.mat_queue_mode", -1 ); // Before, mat_motion_blur_enabled came from gpu_level.csv (it was set to 0 at GPU levels 0 and 1, and 1 at higher levels).
// These GPU levels are not that useful in CS:GO any longer (because we've dumped a bunch of old cards not capable of at least shader model 3), and
// it's now a video option, so we need a better way of defaulting mat_motion_blur_enabled in fresh installs. For now, the safest choice on all cards is
// disabled.
configData.pConfigKeys->SetInt( "setting.mat_motion_blur_enabled", 0 ); // Not all video card DXSupport configs define GPU mem level, default it to High
#if defined( DX_TO_GL_ABSTRACTION )
configData.pConfigKeys->SetInt( "setting.gpu_mem_level", 3 ); #else
configData.pConfigKeys->SetInt( "setting.gpu_mem_level", 2 ); #endif
// Assume if we don't find a GPU level then it's a high level recent GPU
configData.pConfigKeys->SetInt( "setting.gpu_level", 3 );
// Assume if we don't find a lower mat_antialias value then we will run at the highest support MSAA setting
#if defined( DX_TO_GL_ABSTRACTION )
configData.pConfigKeys->SetInt( "setting.mat_antialias", 0 );
#else
if ( materials->SupportsMSAAMode( 8 ) ) configData.pConfigKeys->SetInt( "setting.mat_antialias", 8 ); else if ( materials->SupportsMSAAMode( 4 ) ) configData.pConfigKeys->SetInt( "setting.mat_antialias", 4 ); else if ( materials->SupportsMSAAMode( 2 ) ) configData.pConfigKeys->SetInt( "setting.mat_antialias", 2 ); else configData.pConfigKeys->SetInt( "setting.mat_antialias", 0 ); #endif
// None of our moddefaults.txt specify CSAA settings, so default quality to zero
configData.pConfigKeys->SetInt( "setting.mat_aaquality", 0 );
// Get the key value you data from the defined file.
if ( !ParseConfigKeys( configData ) ) return false;
// LEGACY: mat_antialias = 1 - if such configuration is found just set it to zero (CS:GO video options interpret NONE that way)
if ( configData.pConfigKeys->GetInt( "setting.mat_antialias", 0 ) == 1 ) configData.pConfigKeys->SetInt( "setting.mat_antialias", 0 );
// Set the default resolution based on the aspect ratio mode
// int nWidth = configData.pConfigKeys->GetInt( "setting.defaultres" );
// int nHeight = configData.pConfigKeys->GetInt( "setting.defaultresheight" );
// Ignore moddefaults configuration that might be outdated, just default to user's desktop resolution
int nWidth = configData.nPhysicalScreenWidth; int nHeight = configData.nPhysicalScreenHeight; if ( GetNearestFullscreenResolution( nWidth, nHeight, configData ) ) { configData.pConfigKeys->SetInt( "setting.defaultres", nWidth ); configData.pConfigKeys->SetInt( "setting.defaultresheight", nHeight ); } return true; } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
static bool VerifyVideoConfigSettingRequired( char const *szSetting ) { static char const * arrIgnoredSettings[] = { "setting.mem_level" }; for ( int j = 0; j < Q_ARRAYSIZE( arrIgnoredSettings ); ++ j ) { if ( !V_stricmp( arrIgnoredSettings[j], szSetting ) ) return false; } return true; } bool VerifyDefaultVideoConfig( VidMatConfigData_t &configData ) { // Make sure the file exists to verify.
bool bFileExists = g_pFullFileSystem->FileExists( VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_PATHID ); if ( !bFileExists ) return false;
// Open the moddefaults.cfg file and load it into key values.
KeyValues *pDefaultKeys = new KeyValues( "DefaultKeys" ); if ( !pDefaultKeys ) return false;
if ( !pDefaultKeys->LoadFromFile( g_pFullFileSystem, VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_PATHID ) ) { pDefaultKeys->deleteThis(); return false; }
// Derive the default state from dxsupport.cfg and moddefaults.txt.
if ( !CreateDefaultVideoKeyValues( configData ) ) { pDefaultKeys->deleteThis(); return false; }
// Diagnostic buffer
CUtlBuffer bufDiagnostic( 0, 0, CUtlBuffer::TEXT_BUFFER );
// Start with the assumption they are the same.
bool bEqual = true; for( KeyValues *pTestKey = configData.pConfigKeys->GetFirstSubKey(); pTestKey; pTestKey = pTestKey->GetNextKey() ) { const char *pszTestName = pTestKey->GetName(); KeyValues *pFindKey = pDefaultKeys->FindKey( pszTestName ); if ( !pFindKey ) { Warning( "The default video config has changed, config key '%s=%s' is no longer default.\n", pszTestName, pTestKey->GetString() ); bufDiagnostic.Printf( "config key '%s=%s' is no longer default.\n", pszTestName, pTestKey->GetString() ); if ( VerifyVideoConfigSettingRequired( pszTestName ) ) bEqual = false; } else if ( V_stricmp( pFindKey->GetString(), pTestKey->GetString() ) ) { Warning( "The default video config has changed, config key '%s=%s' is no longer default '%s'.\n", pszTestName, pTestKey->GetString(), pFindKey->GetString() ); bufDiagnostic.Printf( "config key '%s=%s' is no longer default '%s'.\n", pszTestName, pTestKey->GetString(), pFindKey->GetString() ); if ( VerifyVideoConfigSettingRequired( pszTestName ) ) bEqual = false; } }
// If we are still equal - test to see if the default file has any keys that have been removed by the default config.
if ( bEqual ) { for( KeyValues *pTestKey = pDefaultKeys->GetFirstSubKey(); pTestKey; pTestKey = pTestKey->GetNextKey() ) { const char *pszTestName = pTestKey->GetName(); KeyValues *pFindKey = configData.pConfigKeys->FindKey( pszTestName ); if ( !pFindKey ) { Warning( "The default video config has changed, config key '%s=%s' has been added.\n", pszTestName, pTestKey->GetString() ); bufDiagnostic.Printf( "config key '%s=%s' has been added.\n", pszTestName, pTestKey->GetString() ); if ( VerifyVideoConfigSettingRequired( pszTestName ) ) bEqual = false; } } }
// If we are not equal, put up some warning and reset the current video config file.
if ( !bEqual ) { Warning( "VerifyDefaultVideoConfig: The default video config for the machine has changed, updating the current config to match.\n" );
bufDiagnostic.Printf( "--ConfigData--\n" ); configData.pConfigKeys->RecursiveSaveToFile( bufDiagnostic, 0 ); bufDiagnostic.Printf( "--Defaults--\n" ); pDefaultKeys->RecursiveSaveToFile( bufDiagnostic, 0 ); bufDiagnostic.Printf( "----\n" ); char chBuffer[64] = {}; struct tm tmNow; Plat_GetLocalTime( &tmNow ); V_sprintf_safe( chBuffer, "cfg\\video.change%u.txt", Plat_timegm( &tmNow ) ); WriteVideoCfgDataToFile( chBuffer, bufDiagnostic );
// Create the file.
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); configData.pConfigKeys->RecursiveSaveToFile( buf, 0 ); WriteVideoCfgDataToFile( VIDEOCONFIG_DEFAULT_FILENAME, buf );
//
// Upgrade user's video preferences with new default autoconfig
//
KeyValues *kvPreviousVideoCfg = new KeyValues( "videocfg" ); if ( kvPreviousVideoCfg->LoadFromFile( g_pFullFileSystem, VIDEOCONFIG_FILENAME, VIDEOCONFIG_PATHID ) ) { // Preserve all settings that support auto, but user had on a custom setting
for ( int k = 0; k < Q_ARRAYSIZE( s_pVideoConfigSettingsWhitelist ); ++ k ) { if ( !s_pVideoConfigSettingsWhitelist[k].m_bUseAutoOption ) continue; int nUserPreferenceValue = kvPreviousVideoCfg->GetInt( s_pVideoConfigSettingsWhitelist[k].m_pSettingVar, 9999999 ); if ( nUserPreferenceValue != 9999999 ) { // User had explicit value, so store same explicit value in new video config
configData.pConfigKeys->SetInt( s_pVideoConfigSettingsWhitelist[ k ].m_pSettingVar, nUserPreferenceValue ); } else { // User had auto configured value or no value at all, if the new default config has a value then
// make sure it is set on auto here
if ( KeyValues *kvSubKey = configData.pConfigKeys->FindKey( s_pVideoConfigSettingsWhitelist[ k ].m_pSettingVar ) ) { char chNewAutoName[ 128 ]; // e.g.: "setting.cpu_level" -> "setauto.cpu_level"
V_sprintf_safe( chNewAutoName, "setauto.%s", s_pVideoConfigSettingsWhitelist[ k ].m_pSettingVar + 8 ); kvSubKey->SetName( chNewAutoName ); } } } } else { FOR_EACH_SUBKEY( configData.pConfigKeys, kvSubKey ) { if ( VideoConfigSetting_t const *pSetting = VideoConfigSettingFindWhitelistEntryByName( kvSubKey->GetName() ) ) { if ( pSetting->m_bUseAutoOption ) { char chNewAutoName[ 128 ]; // e.g.: "setting.cpu_level" -> "setauto.cpu_level"
V_sprintf_safe( chNewAutoName, "setauto.%s", pSetting->m_pSettingVar + 8 ); kvSubKey->SetName( chNewAutoName ); } } } } kvPreviousVideoCfg->deleteThis(); buf.Purge(); configData.pConfigKeys->RecursiveSaveToFile( buf, 0 ); WriteVideoCfgDataToFile( VIDEOCONFIG_FILENAME, buf ); }
// Destroy keys.
configData.pConfigKeys->Clear(); pDefaultKeys->deleteThis();
return true; } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
bool CopyDefaultVideoToCurrentVideoConfig( const char *pszDefaultFileName, const char *pszCurrentFileName ) { bool bFileExists = g_pFullFileSystem->FileExists( pszDefaultFileName, VIDEOCONFIG_PATHID ); if ( !bFileExists ) return false;
// Open the moddefaults.cfg file and load it into key values.
KeyValues *pDefaultKeys = new KeyValues( "DefaultKeys" ); if ( !pDefaultKeys ) return false;
if ( !pDefaultKeys->LoadFromFile( g_pFullFileSystem, pszDefaultFileName, VIDEOCONFIG_PATHID ) ) { pDefaultKeys->deleteThis(); return false; }
// Create the file.
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); pDefaultKeys->RecursiveSaveToFile( buf, 0 ); WriteVideoCfgDataToFile( pszCurrentFileName, buf );
// Destroy the keys.
pDefaultKeys->deleteThis();
return true; } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
bool CreateDefaultVideoConfig( VidMatConfigData_t &configData ) { // Create the default video keys.
if ( !CreateDefaultVideoKeyValues( configData ) ) return false;
// Create the file with default settings
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); configData.pConfigKeys->RecursiveSaveToFile( buf, 0 ); WriteVideoCfgDataToFile( VIDEOCONFIG_DEFAULT_FILENAME, buf );
//
// Now write the file with user settings skipping the settings that support "AUTO" in options
//
FOR_EACH_SUBKEY( configData.pConfigKeys, kvSubKey ) { if ( VideoConfigSetting_t const *pSetting = VideoConfigSettingFindWhitelistEntryByName( kvSubKey->GetName() ) ) { if ( pSetting->m_bUseAutoOption ) { char chNewAutoName[128]; // e.g.: "setting.cpu_level" -> "setauto.cpu_level"
V_sprintf_safe( chNewAutoName, "setauto.%s", pSetting->m_pSettingVar + 8 ); kvSubKey->SetName( chNewAutoName ); } } } buf.Purge(); configData.pConfigKeys->RecursiveSaveToFile( buf, 0 ); WriteVideoCfgDataToFile( VIDEOCONFIG_FILENAME, buf );
// Clear out the data after writing the file.
configData.pConfigKeys->Clear();
return true; } #endif
//-----------------------------------------------------------------------------
// Purpose: Look for a video config file to setup the system defaults. Create the
// file if one doesn't already exist.
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
bool BLoadUserVideoConfigFileFromDisk( KeyValues *pConfigKeys ) { // Parse current video file, note that some settings will be on AUTO with setauto
// their values are ensured by code above to match the default autoconfig values
if ( !pConfigKeys->LoadFromFile( g_pFullFileSystem, VIDEOCONFIG_FILENAME, VIDEOCONFIG_PATHID ) ) return false;
// load the default config as well to expand setauto. fields
KeyValues *kvDefaultSettings = new KeyValues( "default" ); if ( !kvDefaultSettings->LoadFromFile( g_pFullFileSystem, VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_PATHID ) ) { kvDefaultSettings->deleteThis(); kvDefaultSettings = NULL; }
// bloat the AUTO detected settings for compatibility as proper 'setting.' fields
FOR_EACH_SUBKEY( pConfigKeys, kvSubKey ) { if ( char const *szSetting = StringAfterPrefix( kvSubKey->GetName(), "setauto." ) ) { char chNewAutoName[ 128 ]; // e.g.: "setauto.cpu_level" -> "setting.cpu_level"
V_sprintf_safe( chNewAutoName, "setting.%s", szSetting ); if ( KeyValues *kvValueDefault = kvDefaultSettings->FindKey( chNewAutoName ) ) { pConfigKeys->AddSubKey( kvValueDefault->MakeCopy() ); } } }
if ( kvDefaultSettings ) { kvDefaultSettings->deleteThis(); kvDefaultSettings = NULL; }
return true; } bool RecommendedVideoConfig( VidMatConfigData_t &configData ) { // Get the default video config file if it exists, create it otherwise.
bool bFileExists = g_pFullFileSystem->FileExists( VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_PATHID ); if ( !bFileExists ) { if ( !CreateDefaultVideoConfig( configData ) ) return false; } else { // Verify the default data is up to date.
VerifyDefaultVideoConfig( configData ); }
return BLoadUserVideoConfigFileFromDisk( configData.pConfigKeys ); } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
bool RecommendedConfig( VidMatConfigData_t &configData ) { // Verify that the file system has been created.
Assert( g_pFullFileSystem != NULL );
// If we are a video - this is a special case.
if ( configData.bIsVideo ) { return RecommendedVideoConfig( configData ); }
// Parse the configuration keys.
return ParseConfigKeys( configData ); } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
bool ResetVideoConfigToDefaults( KeyValues *pConfigKeys ) { // Copy the defaults settings into the current = Reset.
if ( !CopyDefaultVideoToCurrentVideoConfig( VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_FILENAME ) ) return false;
// Copy the new key values if there the config keys exist.
if ( pConfigKeys ) { return pConfigKeys->LoadFromFile( g_pFullFileSystem, VIDEOCONFIG_FILENAME, VIDEOCONFIG_PATHID ); } return true; } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
bool UpdateCurrentVideoConfig( int nWidth, int nHeight, int nAspectRatioMode, bool bFullscreen, bool bNoWindow, bool bUseRestartConvars ) { // Create and Init the video config block.
KeyValues *pVideoConfigKeys = new KeyValues( "VideoConfig" ); if ( !pVideoConfigKeys ) return false;
// Go through each of the video settings and save off all necessary data.
int nVideoConfigCount = ARRAYSIZE( s_pVideoConfigSettingsWhitelist ); for ( int iVar = 0; iVar < nVideoConfigCount; ++iVar ) { // Do we need to save this setting?
if ( !s_pVideoConfigSettingsWhitelist[iVar].m_bSaved ) continue;
// Strip off the "setting." prefix and check for a ConVar
// Strip off the "setting." prefix and check for a ConVar
char szConVarName[256]; int nStringLength = V_strlen( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar ); nStringLength -= 8; if ( nStringLength <= 0 ) continue;
V_StrRight( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar, nStringLength, szConVarName, sizeof( szConVarName ) );
bool bAutodetectedSetting = false; { char szConVarRestart[ 256 ]; if ( s_pVideoConfigSettingsWhitelist[ iVar ].m_bUseAutoOption ) { V_snprintf( szConVarRestart, sizeof( szConVarRestart ), "%s_optionsui", szConVarName ); ConVarRef cvOptionsUi( szConVarRestart ); if ( cvOptionsUi.IsValid() ) { bAutodetectedSetting = ( cvOptionsUi.GetInt() == 9999999 ); } } if ( bUseRestartConvars ) { V_snprintf( szConVarRestart, sizeof( szConVarRestart ), "%s_restart", szConVarName );
if ( g_pCVar->FindVar( szConVarRestart ) ) { V_strncpy( szConVarName, szConVarRestart, sizeof( szConVarName ) ); } } }
// Is it a CVar? If so, get the value.
const ConVar *pVar = g_pCVar->FindVar( szConVarName ); if ( pVar ) { if ( bAutodetectedSetting ) { char chSettingAutoName[ 128 ]; V_sprintf_safe( chSettingAutoName, "setauto.%s", s_pVideoConfigSettingsWhitelist[ iVar ].m_pSettingVar + 8 ); pVideoConfigKeys->SetString( chSettingAutoName, pVar->GetString() ); } else { pVideoConfigKeys->SetString( s_pVideoConfigSettingsWhitelist[ iVar ].m_pSettingVar, pVar->GetString() ); } } } // Set these window settings.
pVideoConfigKeys->SetInt( "setting.defaultres", nWidth ); pVideoConfigKeys->SetInt( "setting.defaultresheight", nHeight ); pVideoConfigKeys->SetInt( "setting.aspectratiomode", nAspectRatioMode ); pVideoConfigKeys->SetInt( "setting.fullscreen", static_cast<int>( bFullscreen ) ); pVideoConfigKeys->SetInt( "setting.nowindowborder", static_cast<int>( bNoWindow ) );
// Write out the file.
// Create the file.
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); pVideoConfigKeys->RecursiveSaveToFile( buf, 0 ); WriteVideoCfgDataToFile( VIDEOCONFIG_FILENAME, buf );
// Destroy keys.
pVideoConfigKeys->deleteThis();
return true; } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
bool UpdateVideoConfigConVars( KeyValues *pConfigKeys ) { bool bAllocConfig = false; if ( !pConfigKeys ) { // Create and Init the video config block.
pConfigKeys = new KeyValues( "VideoConfig" ); if ( !pConfigKeys ) return false;
if ( !BLoadUserVideoConfigFileFromDisk( pConfigKeys ) ) { pConfigKeys->deleteThis(); return false; }
bAllocConfig = true; }
#ifdef _DEBUG
Msg( "UpdateVideoConfigConVars:\n" ); KeyValuesDumpAsDevMsg( pConfigKeys, 0, 0 ); #endif
ConVar *pVarOptionsUiCallback = g_pCVar->FindVar( "videooptions_optionsui_callback_disabled" );
int nVideoConfigCount = ARRAYSIZE( s_pVideoConfigSettingsWhitelist ); for ( int iVar = 0; iVar < nVideoConfigCount; ++iVar ) { // Do we need to save this setting?
if ( !s_pVideoConfigSettingsWhitelist[iVar].m_bConVar ) continue;
// Strip off the "setting." prefix and check for a ConVar
char szConVarName[256]; int nStringLength = V_strlen( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar ); nStringLength -= 8; if ( nStringLength <= 0 ) continue;
V_StrRight( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar, nStringLength, szConVarName, sizeof( szConVarName ) );
ConVar *pVar = g_pCVar->FindVar( szConVarName ); if ( !pVar ) continue;
KeyValues *pFindKey = pConfigKeys->FindKey( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar ); if ( !pFindKey ) continue;
// Always allow the command line to totally override whatever convars come from the videocfg system.
char szOption[256]; V_snprintf( szOption, sizeof( szOption ), "+%s", szConVarName ); if ( CommandLine()->CheckParm( szOption ) ) { const char *pOverrideValue = CommandLine()->ParmValue( szOption, pFindKey->GetString() ); pVar->SetValue( pOverrideValue );
Warning( "UpdateVideoConfigConVars: Value of convar \"%s\" is being set from the cmd line, so this value will not be set by the video config system\n", szConVarName ); continue; }
pVar->SetValue( pFindKey->GetString() );
{ char szConVarRestart[ 256 ]; V_sprintf_safe( szConVarRestart, "%s_restart", szConVarName ); if ( ConVar *pVarRestart = g_pCVar->FindVar( szConVarRestart ) ) { pVarRestart->SetValue( pFindKey->GetString() ); } }
if ( s_pVideoConfigSettingsWhitelist[iVar].m_bUseAutoOption ) { char szConVarOptionsUi[ 256 ]; V_sprintf_safe( szConVarOptionsUi, "%s_optionsui", szConVarName ); if ( ConVar *pVarOptionsUi = g_pCVar->FindVar( szConVarOptionsUi ) ) { if ( pVarOptionsUiCallback ) pVarOptionsUiCallback->SetValue( 1 );
// Check if the config instructs the convar to list as "AUTO"?
char chSettingAutoName[128]; V_sprintf_safe( chSettingAutoName, "setauto.%s", s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar + 8 ); if ( pConfigKeys->FindKey( chSettingAutoName ) ) pVarOptionsUi->SetValue( 9999999 ); else pVarOptionsUi->SetValue( pFindKey->GetString() );
if ( pVarOptionsUiCallback ) pVarOptionsUiCallback->SetValue( 0 ); } } }
// If we created it - destroy it!
if ( bAllocConfig ) { pConfigKeys->deleteThis(); }
return true; } #endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#if !defined( _GAMECONSOLE )
bool ReadCurrentVideoConfig( KeyValues *pConfigKeys, bool bDefault ) { if ( !pConfigKeys ) return false;
if ( !bDefault ) { // Do we have a current video config file? If not, copy the defaults file.
if ( !g_pFullFileSystem->FileExists( VIDEOCONFIG_FILENAME, VIDEOCONFIG_PATHID ) ) return false;
// Parse current video file.
return BLoadUserVideoConfigFileFromDisk( pConfigKeys ); } else { // Do we have a current video config file? If not, copy the defaults file.
if ( !g_pFullFileSystem->FileExists( VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_PATHID ) ) return false;
// Parse current video file.
return pConfigKeys->LoadFromFile( g_pFullFileSystem, VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_PATHID ); } } #endif
const unsigned char *GetModEncryptionKey( const char *pModName ) { if ( !V_strnicmp( "left4dead", pModName, V_strlen("left4dead") ) ) return (unsigned char*)"zp14Hi(]"; else if ( !V_strnicmp( "portal2", pModName, V_strlen("portal2") ) ) return (unsigned char *)"UrE66!Ap"; else if ( !V_strnicmp( "csgo", pModName, V_strlen("csgo") ) ) return (unsigned char *)"aY7!rn[z"; else if ( !V_strnicmp( "infested", pModName, V_strlen("infested") ) ) return (unsigned char *)"sW9.JupP"; else if ( !V_strnicmp( "ep2", pModName, V_strlen("ep2") ) ) return (unsigned char *)"Xx81uBl)"; else if ( !V_strnicmp( "tf", pModName, V_strlen("tf") ) ) return (unsigned char *)"E2NcUkG2"; else if ( !V_strnicmp( "nimbus", pModName, V_strlen("nimbus") ) ) return (unsigned char *)"E2NcUkG2"; else if ( !V_strnicmp( "dota", pModName, V_strlen( "dota" ) ) ) return (unsigned char *)"dAIt1IL!"; else return (unsigned char*)"X8bU2qll"; }
KeyValues* ReadEncryptedKVFile( const char *pRelativePath, const char *pPathID, const char *pModName ) { // Open the keyvalues, and abort if we can't
FileHandle_t f = g_pFullFileSystem->Open( pRelativePath, "rb", pPathID ); if ( !f ) { return NULL; }
// load file into a null-terminated buffer
int fileSize = g_pFullFileSystem->Size( f ); char *buffer = (char*)stackalloc( fileSize + 1 ); g_pFullFileSystem->Read( buffer, fileSize, f ); buffer[fileSize] = 0; g_pFullFileSystem->Close( f );
DecodeICE( (unsigned char*)buffer, fileSize, GetModEncryptionKey( pModName ) );
KeyValues *pKV = new KeyValues( "kv" ); bool retOK = pKV->LoadFromBuffer( pRelativePath, buffer, g_pFullFileSystem ); if ( !retOK ) { pKV->deleteThis(); return NULL; }
return pKV; }
struct SystemLevelConvar_t { const char *m_pConVar; bool m_bChooseLower; bool m_bAllowed; };
SystemLevelConvar_t s_pConVarsAllowedInSystemLevel[] = { { "lower_body", true, true }, { "r_shadow_half_update_rate", false, true }, { "r_rainparticledensity", true, true }, { "cl_particle_fallback_base", false, true }, { "cl_particle_fallback_multiplier",false, true }, { "r_flashlightdepthtexture", true, true }, { "r_shadowrendertotexture", true, true }, { "r_shadowfromworldlights", true, true }, { "cl_detaildist", true, true }, { "cl_detailfade", true, true }, { "r_drawmodeldecals", true, false }, // force consistency across all levels
#ifndef _PS3
{ "r_decalstaticprops", true, false }, // force consistency across all levels
#endif
{ "ragdoll_sleepaftertime", true, true }, { "cl_phys_maxticks", true, true }, { "r_worldlightmin", true, true }, { "props_break_max_pieces", true, true }, { "r_worldlights", true, true }, { "r_decals", true, false }, // force consistency across all levels
{ "r_decal_overlap_count", true, false }, // force consistency across all levels
{ "mat_bumpmap", true, true }, { "mat_detail_tex", true, true }, { "mat_specular", true, true }, { "mat_phong", true, true }, { "mat_grain_enable", true, true }, { "mat_local_contrast_enable", true, true }, { "mat_motion_blur_enabled", true, true }, { "mat_disablehwmorph", false, true }, { "r_overlayfademin", true, true }, { "r_overlayfademax", true, true }, { "z_mob_simple_shadows", false, true }, { "cl_ragdoll_maxcount", true, true }, { "cl_ragdoll_maxcount_gib", true, true }, { "cl_ragdoll_maxcount_generic", true, true }, { "cl_ragdoll_maxcount_special", true, true }, { "sv_ragdoll_maxcount", true, true }, { "sv_ragdoll_maxcount_gib", true, true }, { "sv_ragdoll_maxcount_generic", true, true }, { "sv_ragdoll_maxcount_special", true, true }, { "z_infected_decals", true, true }, { "cl_impacteffects_limit_general", true, true }, { "cl_impacteffects_limit_exit", true, true }, { "cl_impacteffects_limit_water", true, true }, { "cl_ragdoll_self_collision", true, true }, { "cl_player_max_decal_count", true, true }, { "cl_footstep_fx", true, true }, { "mp_usehwmvcds", true, true }, { "mp_usehwmmodels", true, true }, { "mat_depthfeather_enable", true, true }, { "mat_dxlevel", true, true }, { "r_flashlightinfectedfov", true, true }, { "r_flashlightinfectedfar", true, true }, { "r_flashlightinfectedlinear", true, true }, { "r_rootlod", false, true }, { "mat_picmip", false, true }, { "mat_force_vertexfog", false, true }, { "r_simpleworldmodel_waterreflections_fullscreen", false, true }, { "r_simpleworldmodel_drawforrecursionlevel_fullscreen", true, true }, { "r_simpleworldmodel_drawbeyonddistance_fullscreen", true, true }, { "r_simpleworldmodel_waterreflections_splitscreen", true, true }, { "r_simpleworldmodel_drawforrecursionlevel_splitscreen",true, true }, { "r_simpleworldmodel_drawbeyonddistance_splitscreen", true, true }, { "r_simpleworldmodel_waterreflections_pip", true, true }, { "r_simpleworldmodel_drawforrecursionlevel_pip", true, true }, { "r_simpleworldmodel_drawbeyonddistance_pip", true, true }, { "r_lod_switch_scale", true, true }, { "r_lod", false, true }, { "r_paintblob_highres_cube", false, true }, { "r_paintblob_force_single_pass", true, true }, { "r_paintblob_max_number_of_threads", true, true }, { "cl_csm_enabled", true, true }, };
void PerformSystemConfiguration( KeyValues *pResult, int nSystemLevel, const char *pConfigFile, const char *pModName, bool bUseSplitScreenCfg, bool bVGUIIsSplitscreen ) { char pCfgFile[MAX_PATH]; if ( nSystemLevel == CONSOLE_SYSTEM_LEVEL_PS3 ) { // PS3
Q_snprintf( pCfgFile, sizeof(pCfgFile), "cfg\\%s_ps3", pConfigFile ); } else { // everything else
Q_snprintf( pCfgFile, sizeof(pCfgFile), "cfg\\%s_%d", pConfigFile, nSystemLevel ); } if ( !IsGameConsole() ) { Q_strncat( pCfgFile, "_pc", sizeof(pCfgFile) ); } if ( bUseSplitScreenCfg && bVGUIIsSplitscreen ) { Q_strncat( pCfgFile, "_ss", sizeof(pCfgFile) ); } Q_strncat( pCfgFile, ".ekv", sizeof(pCfgFile) );
KeyValues *pKeyValues = ReadEncryptedKVFile( pCfgFile, "GAME", pModName ); if ( !pKeyValues ) { DevWarning( "PerformSystemConfiguration: Missing %s\n", pCfgFile ); return; }
for( KeyValues *pKey = pKeyValues->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() ) { const char *pCVarName = pKey->GetName();
// Check if legal
int i; bool bLegalVar = false; for( i=0; i < ARRAYSIZE( s_pConVarsAllowedInSystemLevel ); i++ ) { if ( !Q_stricmp( s_pConVarsAllowedInSystemLevel[i].m_pConVar, pCVarName ) ) { bLegalVar = true; break; } } if ( !bLegalVar ) { DevWarning("PerformSystemConfiguration: Bad convar found in %s - %s\n", pConfigFile, pCVarName ); continue; } if ( !s_pConVarsAllowedInSystemLevel[i].m_bAllowed ) { #ifdef _DEBUG
DevWarning("PerformSystemConfiguration: Skipping convar found in %s - %s\n", pConfigFile, pCVarName ); #endif
continue; }
if ( pResult->FindKey( pCVarName ) ) { float flOldValue = pResult->GetFloat( pCVarName ); float flNewValue = pKey->GetFloat(); if ( s_pConVarsAllowedInSystemLevel[i].m_bChooseLower ) { if ( flNewValue >= flOldValue ) continue; } else { if ( flNewValue <= flOldValue ) continue; } }
const char *pValue = pKey->GetString(); pResult->SetString( pCVarName, pValue ); }
pKeyValues->deleteThis(); }
void UpdateSystemLevel( int nCPULevel, int nGPULevel, int nMemLevel, int nGPUMemLevel, bool bVGUIIsSplitscreen, const char *pModName ) { KeyValues *pKeyValues = new KeyValues( "kv" ); PerformSystemConfiguration( pKeyValues, nCPULevel, "cpu_level", pModName, true, bVGUIIsSplitscreen ); PerformSystemConfiguration( pKeyValues, nGPULevel, "gpu_level", pModName, false, bVGUIIsSplitscreen ); PerformSystemConfiguration( pKeyValues, nMemLevel, "mem_level", pModName, false, bVGUIIsSplitscreen ); PerformSystemConfiguration( pKeyValues, nGPUMemLevel, "gpu_mem_level", pModName, false, bVGUIIsSplitscreen );
for( KeyValues *pKey = pKeyValues->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() ) { const char *pCVarName = pKey->GetName(); ConVar *pConVar = g_pCVar->FindVar( pCVarName ); if ( !pConVar ) continue; // We want this on all platforms now - having the config system always slam convars being defined on the cmd line is just too confusing.
//if ( IsX360() )
{ bool bFound = false; for ( int i=1; !bFound && i < CommandLine()->ParmCount(); i++ ) { const char *szParm = CommandLine()->GetParm(i); if ( szParm && szParm[0] == '+' ) { bFound = ( V_stricmp( pCVarName, szParm + 1 ) == 0 ); } } if ( bFound ) { // found on command line, ignore any value the script would have set
Warning( "UpdateSystemLevel: System configuration ignoring %s due to command line override\n", pCVarName ); continue; } }
if ( pConVar->GetFlags() & ( FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE | FCVAR_CHEAT ) ) { Warning( "UpdateSystemLevel: ConVar %s controlled by gpu_level/cpu_level must not be marked as FCVAR_ARCHIVE or FCVAR_CHEAT!\n", pCVarName ); continue; }
pConVar->SetValue( pKey->GetString() ); } pKeyValues->deleteThis(); }
|