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.
1426 lines
48 KiB
1426 lines
48 KiB
//======= 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();
|
|
}
|