Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1426 lines
48 KiB

  1. //======= Copyright (c) 1996-2009, Valve Corporation, All rights reserved. ======
  2. //
  3. // Purpose: Video configuration management (split out from tier2)
  4. //
  5. //===============================================================================
  6. #include "tier2/fileutils.h"
  7. #include "tier2/tier2.h"
  8. #include "videocfg.h"
  9. #include "tier1/tier1.h"
  10. #include "tier1/strtools.h"
  11. #include "filesystem.h"
  12. #include "tier1/keyvalues.h"
  13. #include "utlbuffer.h"
  14. #include "mathlib/IceKey.H"
  15. #include "tier0/icommandline.h"
  16. // Video Config Filenames
  17. #ifdef POSIX
  18. #define VIDEOCONFIG_DEFAULT_FILENAME "cfg/videodefaults.txt"
  19. #define VIDEOCONFIG_FILENAME "cfg/video.txt"
  20. #define VIDEOCONFIG_FILENAME_BACKUP "cfg/video.bak"
  21. #else
  22. #define VIDEOCONFIG_DEFAULT_FILENAME "cfg\\videodefaults.txt"
  23. #define VIDEOCONFIG_FILENAME "cfg\\video.txt"
  24. #define VIDEOCONFIG_FILENAME_BACKUP "cfg\\video.bak"
  25. #endif
  26. #define VIDEOCONFIG_PATHID "USRLOCAL"
  27. static void WriteVideoCfgDataToFile( char const *pszFile, CUtlBuffer &buf )
  28. {
  29. // Video defaults and video settings detection runs very early, so we need to create cfg path in USRLOCAL storage
  30. g_pFullFileSystem->CreateDirHierarchy( "cfg", "USRLOCAL" );
  31. g_pFullFileSystem->WriteFile( pszFile, VIDEOCONFIG_PATHID, buf );
  32. }
  33. enum AspectRatioMode_t
  34. {
  35. ASPECT_RATIO_OTHER = -1,
  36. ASPECT_RATIO_4x3 = 0,
  37. ASPECT_RATIO_16x9,
  38. ASPECT_RATIO_16x10,
  39. };
  40. struct VideoConfigSetting_t
  41. {
  42. const char *m_pSettingVar;
  43. bool m_bChooseLower;
  44. bool m_bSaved;
  45. bool m_bConVar;
  46. bool m_bUseAutoOption;
  47. };
  48. struct RatioToAspectMode_t
  49. {
  50. AspectRatioMode_t m_Mode;
  51. int m_nWidth;
  52. int m_nHeight;
  53. };
  54. static VideoConfigSetting_t s_pVideoConfigSettingsWhitelist[] =
  55. {
  56. // ConVars.
  57. { "setting.cpu_level", true, true, true, true },
  58. { "setting.gpu_level", true, true, true, true },
  59. { "setting.mat_antialias", true, true, true, true },
  60. { "setting.mat_aaquality", true, true, true, true },
  61. { "setting.mat_forceaniso", true, true, true, true },
  62. { "setting.mat_vsync", true, true, true },
  63. { "setting.mat_triplebuffered", true, true, true },
  64. { "setting.mat_grain_scale_override", true, true, true },
  65. // { "setting.mat_monitorgamma", true, true, true },
  66. { "setting.gpu_mem_level", true, true, true, true },
  67. { "setting.mem_level", true, true, true },
  68. { "setting.videoconfig_version", true, true, true },
  69. { "setting.mat_queue_mode", true, true, true },
  70. { "setting.mat_tonemapping_occlusion_use_stencil", false, false, true },
  71. { "setting.csm_quality_level", true, true, true, true },
  72. { "setting.mat_software_aa_strength", true, true, true },
  73. { "setting.mat_motion_blur_enabled", true, true, true },
  74. // Settings.
  75. { "setting.fullscreen", true, true, false },
  76. { "setting.nowindowborder", true, true, false },
  77. { "setting.aspectratiomode", true, true, false },
  78. { "setting.defaultres", true, true, false },
  79. { "setting.defaultresheight", true, true, false },
  80. { "setting.dxlevel", true, false, false },
  81. { "setting.mindxlevel", true, false, false },
  82. { "setting.maxdxlevel", true, false, false },
  83. { "setting.preferhardwaresync", true, false, false },
  84. { "setting.centroidhack", true, false, false },
  85. { "setting.preferzprepass", true, false, false },
  86. { "setting.prefertexturesinhwmemory", true, false, false },
  87. { "setting.laptop", true, false, false },
  88. { "setting.suppresspixelshadercentroidhackfixup", true, false, false },
  89. { "setting.nouserclipplanes", true, false, false },
  90. { "setting.unsupported", true, false, false },
  91. };
  92. static VideoConfigSetting_t const * VideoConfigSettingFindWhitelistEntryByName( char const *szSettingName )
  93. {
  94. for ( int k = 0; k < Q_ARRAYSIZE( s_pVideoConfigSettingsWhitelist ); ++ k )
  95. {
  96. if ( !V_stricmp( szSettingName, s_pVideoConfigSettingsWhitelist[k].m_pSettingVar ) )
  97. return &s_pVideoConfigSettingsWhitelist[k];
  98. }
  99. return NULL;
  100. }
  101. static RatioToAspectMode_t g_pRatioToAspectModes[] =
  102. {
  103. { ASPECT_RATIO_4x3, 4, 3 },
  104. { ASPECT_RATIO_16x9, 16, 9 },
  105. { ASPECT_RATIO_16x10, 16, 10 },
  106. };
  107. //--------------------------------------------------------------------------------------------------------------
  108. #if !defined( _GAMECONSOLE )
  109. static AspectRatioMode_t GetScreenAspectMode( int width, int height )
  110. {
  111. for (int i = 0; i < ARRAYSIZE(g_pRatioToAspectModes); i++)
  112. {
  113. int nFactor = width / g_pRatioToAspectModes[i].m_nWidth;
  114. if ( nFactor * g_pRatioToAspectModes[i].m_nHeight == height )
  115. return g_pRatioToAspectModes[i].m_Mode;
  116. }
  117. return ASPECT_RATIO_OTHER;
  118. }
  119. #endif
  120. //-----------------------------------------------------------------------------
  121. // Purpose:
  122. //-----------------------------------------------------------------------------
  123. #if !defined( _GAMECONSOLE )
  124. static inline int ReadHexValue( KeyValues *pVal, const char *pName )
  125. {
  126. const char *pString = pVal->GetString( pName, NULL );
  127. if (!pString)
  128. {
  129. return -1;
  130. }
  131. char *pTemp;
  132. int nVal = strtol( pString, &pTemp, 16 );
  133. return (pTemp != pString) ? nVal : -1;
  134. }
  135. #endif
  136. //-----------------------------------------------------------------------------
  137. // Purpose:
  138. //-----------------------------------------------------------------------------
  139. #if !defined( _GAMECONSOLE )
  140. void AddNewKeysUsingVideoWhitelist( KeyValues *pModKeys, KeyValues *pConfigKeys )
  141. {
  142. for( KeyValues *pSubKey = pModKeys->GetFirstSubKey(); pSubKey; pSubKey = pSubKey->GetNextKey() )
  143. {
  144. const char *pSubKeyName = pSubKey->GetName();
  145. // Find all the "setting" keys that are white-listed and add them to the
  146. // Video Config keys.
  147. int iVar;
  148. bool bWhiteListedVar = false;
  149. int nVideoConfigCount = ARRAYSIZE( s_pVideoConfigSettingsWhitelist );
  150. for ( iVar = 0; iVar < nVideoConfigCount; ++iVar )
  151. {
  152. if ( !V_stricmp( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar, pSubKeyName ) )
  153. {
  154. bWhiteListedVar = true;
  155. break;
  156. }
  157. }
  158. // This is not a valid key.
  159. if ( !bWhiteListedVar )
  160. continue;
  161. // See if the key already exists - if it doesn't add it.
  162. if ( pConfigKeys->FindKey( pSubKeyName ) )
  163. continue;
  164. const char *pValue = pSubKey->GetString();
  165. pConfigKeys->SetString( pSubKeyName, pValue );
  166. }
  167. }
  168. #endif
  169. //-----------------------------------------------------------------------------
  170. // Purpose:
  171. //-----------------------------------------------------------------------------
  172. #if !defined( _GAMECONSOLE )
  173. void CopySettingKeysUsingVideoWhitelist( KeyValues *pModKeys, KeyValues *pConfigKeys )
  174. {
  175. for( KeyValues *pSubKey = pModKeys->GetFirstSubKey(); pSubKey; pSubKey = pSubKey->GetNextKey() )
  176. {
  177. const char *pSubKeyName = pSubKey->GetName();
  178. // Find all the "setting" keys that are white-listed and add them to the
  179. // Video Config keys.
  180. int iVar;
  181. bool bWhiteListedVar = false;
  182. int nVideoConfigCount = ARRAYSIZE( s_pVideoConfigSettingsWhitelist );
  183. for ( iVar = 0; iVar < nVideoConfigCount; ++iVar )
  184. {
  185. if ( !V_stricmp( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar, pSubKeyName ) )
  186. {
  187. bWhiteListedVar = true;
  188. break;
  189. }
  190. }
  191. // This is not a valid key.
  192. if ( !bWhiteListedVar )
  193. continue;
  194. if ( pConfigKeys->FindKey( pSubKeyName ) )
  195. {
  196. float flOldValue = pConfigKeys->GetFloat( pSubKeyName );
  197. float flNewValue = pSubKey->GetFloat();
  198. if ( s_pVideoConfigSettingsWhitelist[iVar].m_bChooseLower )
  199. {
  200. if ( flNewValue >= flOldValue )
  201. continue;
  202. }
  203. else
  204. {
  205. if ( flNewValue <= flOldValue )
  206. continue;
  207. }
  208. }
  209. const char *pValue = pSubKey->GetString();
  210. pConfigKeys->SetString( pSubKeyName, pValue );
  211. }
  212. }
  213. #endif
  214. //-----------------------------------------------------------------------------
  215. // Purpose: Match the CPU data and add all the "setting" data to the Video Config Keys.
  216. //-----------------------------------------------------------------------------
  217. #if !defined( _GAMECONSOLE )
  218. void AddCPULevelKeys( KeyValues *pModKeys, KeyValues *pVideoConfigKeys )
  219. {
  220. // Get the number of physical processors in the machine.
  221. const CPUInformation &cpuInfo = GetCPUInformation();
  222. int nProcessorCount = cpuInfo.m_nPhysicalProcessors;
  223. // Test all "cpu_level_*" blocks to determine the correct block to copy data from.
  224. for( KeyValues *pModKey = pModKeys->GetFirstSubKey(); pModKey; pModKey = pModKey->GetNextKey() )
  225. {
  226. KeyValues *pMinKey = pModKey->FindKey( "min_processor_count" );
  227. KeyValues *pMaxKey = pModKey->FindKey( "max_processor_count" );
  228. if ( pMinKey && pMaxKey )
  229. {
  230. int nMin = pMinKey->GetInt();
  231. int nMax = pMaxKey->GetInt();
  232. // Is this the correct cpu_level setting.
  233. if ( nMin <= nProcessorCount && nProcessorCount <= nMax )
  234. {
  235. CopySettingKeysUsingVideoWhitelist( pModKey, pVideoConfigKeys );
  236. }
  237. }
  238. }
  239. }
  240. #endif
  241. //-----------------------------------------------------------------------------
  242. // Purpose:
  243. //-----------------------------------------------------------------------------
  244. #if !defined( _GAMECONSOLE )
  245. void AddMemoryKeys( KeyValues *pModKeys, int nMemory, KeyValues *pVideoConfigKeys )
  246. {
  247. for( KeyValues *pModKey = pModKeys->GetFirstSubKey(); pModKey; pModKey = pModKey->GetNextKey() )
  248. {
  249. KeyValues *pMinMegabytes = pModKey->FindKey( "min megabytes" );
  250. KeyValues *pMaxMegabytes = pModKey->FindKey( "max megabytes" );
  251. if ( pMinMegabytes && pMaxMegabytes )
  252. {
  253. int nMin = pMinMegabytes->GetInt();
  254. int nMax = pMaxMegabytes->GetInt();
  255. // Is this the correct cpu_level setting.
  256. if ( nMin <= nMemory && nMemory <= nMax )
  257. {
  258. CopySettingKeysUsingVideoWhitelist( pModKey, pVideoConfigKeys );
  259. }
  260. }
  261. }
  262. }
  263. #endif
  264. //-----------------------------------------------------------------------------
  265. // Purpose:
  266. //-----------------------------------------------------------------------------
  267. #if !defined( _GAMECONSOLE )
  268. void AddVideoMemoryKeys( KeyValues *pModKeys, int nVidMemory, KeyValues *pVideoConfigKeys )
  269. {
  270. for( KeyValues *pModKey = pModKeys->GetFirstSubKey(); pModKey; pModKey = pModKey->GetNextKey() )
  271. {
  272. KeyValues *pMinMegaTexels = pModKey->FindKey( "min megatexels" );
  273. KeyValues *pMaxMegaTexels = pModKey->FindKey( "max megatexels" );
  274. if ( pMinMegaTexels && pMaxMegaTexels )
  275. {
  276. int nMin = pMinMegaTexels->GetInt();
  277. int nMax = pMaxMegaTexels->GetInt();
  278. // Is this the correct cpu_level setting.
  279. if ( nMin <= nVidMemory && nVidMemory <= nMax )
  280. {
  281. CopySettingKeysUsingVideoWhitelist( pModKey, pVideoConfigKeys );
  282. }
  283. }
  284. }
  285. }
  286. #endif
  287. //-----------------------------------------------------------------------------
  288. // Purpose: Match the device and vendor id and add all the "setting" data to
  289. // the Video Config Keys.
  290. //-----------------------------------------------------------------------------
  291. #if !defined( _GAMECONSOLE )
  292. bool AddVideoCardKeys( KeyValues *pModKeys, int nVendorID, int nDeviceID, KeyValues *pVideoConfigKeys )
  293. {
  294. bool bFoundDevice = false;
  295. // Test all video card blocks to determine the correct blocks to copy data from.
  296. for( KeyValues *pModKey = pModKeys->GetFirstSubKey(); pModKey; pModKey = pModKey->GetNextKey() )
  297. {
  298. // Get and match the vendor and device id.
  299. int iVender = ReadHexValue( pModKey, "vendorid" );
  300. if ( iVender == -1 )
  301. continue;
  302. int iDeviceMin = ReadHexValue( pModKey, "mindeviceid" );
  303. int iDeviceMax = ReadHexValue( pModKey, "maxdeviceid" );
  304. if ( iDeviceMin == -1 || iDeviceMax == -1 )
  305. continue;
  306. // Only initialize with unknown data if we didn't find the actual card.
  307. bool bUnknownDevice = ( pModKey->FindKey( "makemelast" ) != NULL );
  308. // 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).
  309. if ( ( iDeviceMin <= nDeviceID ) && ( nDeviceID <= iDeviceMax ) && ( nVendorID == iVender ) )
  310. {
  311. if ( !bUnknownDevice )
  312. {
  313. CopySettingKeysUsingVideoWhitelist( pModKey, pVideoConfigKeys );
  314. bFoundDevice = true;
  315. }
  316. else
  317. {
  318. AddNewKeysUsingVideoWhitelist( pModKey, pVideoConfigKeys );
  319. }
  320. }
  321. }
  322. return bFoundDevice;
  323. }
  324. #endif
  325. //-----------------------------------------------------------------------------
  326. // Purpose: Match the device and vendor id and add all the "setting" data to
  327. // the Video Config Keys.
  328. //-----------------------------------------------------------------------------
  329. #if !defined( _GAMECONSOLE )
  330. void AddDXLevelKeys( KeyValues *pModKeys, int nDXLevel, KeyValues *pVideoConfigKeys )
  331. {
  332. // Test all video card blocks to determine the correct blocks to copy data from.
  333. for( KeyValues *pModKey = pModKeys->GetFirstSubKey(); pModKey; pModKey = pModKey->GetNextKey() )
  334. {
  335. KeyValues *pDXLevelKey = pModKey->FindKey( "setting.maxdxlevel" );
  336. if ( !pDXLevelKey )
  337. continue;
  338. if ( pDXLevelKey->GetInt() == nDXLevel )
  339. {
  340. AddNewKeysUsingVideoWhitelist( pModKey, pVideoConfigKeys );
  341. }
  342. }
  343. }
  344. #endif
  345. //-----------------------------------------------------------------------------
  346. // Purpose:
  347. //-----------------------------------------------------------------------------
  348. #if !defined( _GAMECONSOLE )
  349. bool ParseConfigKeys( VidMatConfigData_t &configData )
  350. {
  351. // Does the file exist?
  352. bool bFileExists = g_pFullFileSystem->FileExists( configData.szFileName, configData.szPathID );
  353. if ( !bFileExists )
  354. return false;
  355. // Get the key values in the file.
  356. KeyValues *pFileKeys = new KeyValues( "FileKeys" );
  357. if ( !pFileKeys )
  358. return false;
  359. if ( !pFileKeys->LoadFromFile( g_pFullFileSystem, configData.szFileName, configData.szPathID ) )
  360. {
  361. pFileKeys->deleteThis();
  362. return false;
  363. }
  364. #ifdef _DEBUG
  365. Msg( "VIDEOCFG.ParseConfigKeys: (start)\n" );
  366. KeyValuesDumpAsDevMsg( configData.pConfigKeys, 0, 0 );
  367. #endif
  368. // Add Config Keys based on cpu.
  369. AddCPULevelKeys( pFileKeys, configData.pConfigKeys );
  370. #ifdef _DEBUG
  371. Msg( "VIDEOCFG.ParseConfigKeys: (+cpu_level)\n" );
  372. KeyValuesDumpAsDevMsg( configData.pConfigKeys, 0, 0 );
  373. #endif
  374. // Add Config Keys based on memory.
  375. AddMemoryKeys( pFileKeys, configData.nSystemMemory, configData.pConfigKeys );
  376. #ifdef _DEBUG
  377. Msg( "VIDEOCFG.ParseConfigKeys: (+memory)\n" );
  378. KeyValuesDumpAsDevMsg( configData.pConfigKeys, 0, 0 );
  379. #endif
  380. // Add Config Keys based on video memory.
  381. AddVideoMemoryKeys( pFileKeys, configData.nVideoMemory, configData.pConfigKeys );
  382. #ifdef _DEBUG
  383. Msg( "VIDEOCFG.ParseConfigKeys: (+video memory)\n" );
  384. KeyValuesDumpAsDevMsg( configData.pConfigKeys, 0, 0 );
  385. #endif
  386. // Add Config Keys based on video card.
  387. bool bFoundDevice = AddVideoCardKeys( pFileKeys, configData.nVendorID, configData.nDeviceID, configData.pConfigKeys );
  388. #ifdef _DEBUG
  389. Msg( "VIDEOCFG.ParseConfigKeys: (+video card)\n" );
  390. KeyValuesDumpAsDevMsg( configData.pConfigKeys, 0, 0 );
  391. #endif
  392. // Add Config Keys based on DXLevel.
  393. if ( !bFoundDevice )
  394. {
  395. //
  396. // This actually doesn't work for CS:GO the way moddefaults.txt is setup
  397. //
  398. AddDXLevelKeys( pFileKeys, configData.nDXLevel, configData.pConfigKeys );
  399. }
  400. // Destroy the file keys.
  401. pFileKeys->deleteThis();
  402. return true;
  403. }
  404. #endif
  405. //-----------------------------------------------------------------------------
  406. //
  407. //-----------------------------------------------------------------------------
  408. #if !defined( _GAMECONSOLE )
  409. static bool GetNearestFullscreenResolution( int& nWidth, int& nHeight, VidMatConfigData_t &configData )
  410. {
  411. float flDesiredArea = nWidth * nHeight;
  412. int nBestWidth = 0;
  413. int nBestHeight = 0;
  414. float flBestDelta = FLT_MAX;
  415. AspectRatioMode_t nRequiredAspectMode = GetScreenAspectMode( configData.nPhysicalScreenWidth, configData.nPhysicalScreenHeight );
  416. // Iterate modes, looking for one that is just smaller than currentWidth and currentHeight while retaining the aspect ratio
  417. while ( true )
  418. {
  419. for ( int i = 0; i < configData.displayModes.Count(); i++ )
  420. {
  421. const ShaderDisplayMode_t &mode = configData.displayModes[i];
  422. if ( nRequiredAspectMode != ASPECT_RATIO_OTHER )
  423. {
  424. AspectRatioMode_t nAspectMode = GetScreenAspectMode( mode.m_nWidth, mode.m_nHeight );
  425. if ( nRequiredAspectMode != nAspectMode )
  426. continue;
  427. }
  428. float flArea = mode.m_nWidth * mode.m_nHeight;
  429. if ( flArea > flDesiredArea * 1.35f )
  430. continue;
  431. float flDelta = fabs( flDesiredArea - flArea );
  432. if ( flDelta >= flBestDelta )
  433. continue;
  434. flBestDelta = flDelta;
  435. nBestWidth = mode.m_nWidth;
  436. nBestHeight = mode.m_nHeight;
  437. }
  438. if ( nBestWidth != 0 )
  439. break;
  440. if ( nRequiredAspectMode == ASPECT_RATIO_OTHER )
  441. return false;
  442. nRequiredAspectMode = ASPECT_RATIO_OTHER;
  443. }
  444. nWidth = nBestWidth;
  445. nHeight = nBestHeight;
  446. return true;
  447. }
  448. #endif
  449. //-----------------------------------------------------------------------------
  450. // Purpose: Create the video config file and fill it in with default data.
  451. //-----------------------------------------------------------------------------
  452. #if !defined( _GAMECONSOLE )
  453. bool CreateDefaultVideoKeyValues( VidMatConfigData_t &configData )
  454. {
  455. // Sets the highest CSM quality level and enabled FXAA, then let the csm_quality_level settings in moddefaults override these settings with lower values.
  456. configData.pConfigKeys->SetInt( "setting.csm_quality_level", CSMQUALITY_HIGH ); //g_pHardwareConfig->GetCSMQuality() );
  457. configData.pConfigKeys->SetInt( "setting.mat_software_aa_strength", 1 );
  458. // Set the vendor and device id key values.
  459. configData.pConfigKeys->SetInt( "VendorID", configData.nVendorID );
  460. configData.pConfigKeys->SetInt( "DeviceID", configData.nDeviceID );
  461. // Initial config always assume v-sync, normal aspect ratio, and fullscreen.
  462. configData.pConfigKeys->SetInt( "setting.fullscreen", 1 );
  463. configData.pConfigKeys->SetInt( "setting.nowindowborder", 0 );
  464. configData.pConfigKeys->SetInt( "setting.aspectratiomode", GetScreenAspectMode( configData.nPhysicalScreenWidth, configData.nPhysicalScreenHeight ) );
  465. configData.pConfigKeys->SetInt( "setting.mat_vsync", IsGameConsole() ? 1 : 0 );
  466. configData.pConfigKeys->SetInt( "setting.mat_triplebuffered", 0 );
  467. configData.pConfigKeys->SetFloat( "setting.mat_monitorgamma", 2.2f );
  468. configData.pConfigKeys->SetInt( "setting.mat_queue_mode", -1 );
  469. // 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).
  470. // 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
  471. // 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
  472. // disabled.
  473. configData.pConfigKeys->SetInt( "setting.mat_motion_blur_enabled", 0 );
  474. // Not all video card DXSupport configs define GPU mem level, default it to High
  475. #if defined( DX_TO_GL_ABSTRACTION )
  476. configData.pConfigKeys->SetInt( "setting.gpu_mem_level", 3 );
  477. #else
  478. configData.pConfigKeys->SetInt( "setting.gpu_mem_level", 2 );
  479. #endif
  480. // Assume if we don't find a GPU level then it's a high level recent GPU
  481. configData.pConfigKeys->SetInt( "setting.gpu_level", 3 );
  482. // Assume if we don't find a lower mat_antialias value then we will run at the highest support MSAA setting
  483. #if defined( DX_TO_GL_ABSTRACTION )
  484. configData.pConfigKeys->SetInt( "setting.mat_antialias", 0 );
  485. #else
  486. if ( materials->SupportsMSAAMode( 8 ) )
  487. configData.pConfigKeys->SetInt( "setting.mat_antialias", 8 );
  488. else if ( materials->SupportsMSAAMode( 4 ) )
  489. configData.pConfigKeys->SetInt( "setting.mat_antialias", 4 );
  490. else if ( materials->SupportsMSAAMode( 2 ) )
  491. configData.pConfigKeys->SetInt( "setting.mat_antialias", 2 );
  492. else
  493. configData.pConfigKeys->SetInt( "setting.mat_antialias", 0 );
  494. #endif
  495. // None of our moddefaults.txt specify CSAA settings, so default quality to zero
  496. configData.pConfigKeys->SetInt( "setting.mat_aaquality", 0 );
  497. // Get the key value you data from the defined file.
  498. if ( !ParseConfigKeys( configData ) )
  499. return false;
  500. // LEGACY: mat_antialias = 1 - if such configuration is found just set it to zero (CS:GO video options interpret NONE that way)
  501. if ( configData.pConfigKeys->GetInt( "setting.mat_antialias", 0 ) == 1 )
  502. configData.pConfigKeys->SetInt( "setting.mat_antialias", 0 );
  503. // Set the default resolution based on the aspect ratio mode
  504. // int nWidth = configData.pConfigKeys->GetInt( "setting.defaultres" );
  505. // int nHeight = configData.pConfigKeys->GetInt( "setting.defaultresheight" );
  506. // Ignore moddefaults configuration that might be outdated, just default to user's desktop resolution
  507. int nWidth = configData.nPhysicalScreenWidth;
  508. int nHeight = configData.nPhysicalScreenHeight;
  509. if ( GetNearestFullscreenResolution( nWidth, nHeight, configData ) )
  510. {
  511. configData.pConfigKeys->SetInt( "setting.defaultres", nWidth );
  512. configData.pConfigKeys->SetInt( "setting.defaultresheight", nHeight );
  513. }
  514. return true;
  515. }
  516. #endif
  517. //-----------------------------------------------------------------------------
  518. // Purpose:
  519. //-----------------------------------------------------------------------------
  520. #if !defined( _GAMECONSOLE )
  521. static bool VerifyVideoConfigSettingRequired( char const *szSetting )
  522. {
  523. static char const * arrIgnoredSettings[] = { "setting.mem_level" };
  524. for ( int j = 0; j < Q_ARRAYSIZE( arrIgnoredSettings ); ++ j )
  525. {
  526. if ( !V_stricmp( arrIgnoredSettings[j], szSetting ) )
  527. return false;
  528. }
  529. return true;
  530. }
  531. bool VerifyDefaultVideoConfig( VidMatConfigData_t &configData )
  532. {
  533. // Make sure the file exists to verify.
  534. bool bFileExists = g_pFullFileSystem->FileExists( VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_PATHID );
  535. if ( !bFileExists )
  536. return false;
  537. // Open the moddefaults.cfg file and load it into key values.
  538. KeyValues *pDefaultKeys = new KeyValues( "DefaultKeys" );
  539. if ( !pDefaultKeys )
  540. return false;
  541. if ( !pDefaultKeys->LoadFromFile( g_pFullFileSystem, VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_PATHID ) )
  542. {
  543. pDefaultKeys->deleteThis();
  544. return false;
  545. }
  546. // Derive the default state from dxsupport.cfg and moddefaults.txt.
  547. if ( !CreateDefaultVideoKeyValues( configData ) )
  548. {
  549. pDefaultKeys->deleteThis();
  550. return false;
  551. }
  552. // Diagnostic buffer
  553. CUtlBuffer bufDiagnostic( 0, 0, CUtlBuffer::TEXT_BUFFER );
  554. // Start with the assumption they are the same.
  555. bool bEqual = true;
  556. for( KeyValues *pTestKey = configData.pConfigKeys->GetFirstSubKey(); pTestKey; pTestKey = pTestKey->GetNextKey() )
  557. {
  558. const char *pszTestName = pTestKey->GetName();
  559. KeyValues *pFindKey = pDefaultKeys->FindKey( pszTestName );
  560. if ( !pFindKey )
  561. {
  562. Warning( "The default video config has changed, config key '%s=%s' is no longer default.\n", pszTestName, pTestKey->GetString() );
  563. bufDiagnostic.Printf( "config key '%s=%s' is no longer default.\n", pszTestName, pTestKey->GetString() );
  564. if ( VerifyVideoConfigSettingRequired( pszTestName ) )
  565. bEqual = false;
  566. }
  567. else if ( V_stricmp( pFindKey->GetString(), pTestKey->GetString() ) )
  568. {
  569. Warning( "The default video config has changed, config key '%s=%s' is no longer default '%s'.\n", pszTestName, pTestKey->GetString(), pFindKey->GetString() );
  570. bufDiagnostic.Printf( "config key '%s=%s' is no longer default '%s'.\n", pszTestName, pTestKey->GetString(), pFindKey->GetString() );
  571. if ( VerifyVideoConfigSettingRequired( pszTestName ) )
  572. bEqual = false;
  573. }
  574. }
  575. // If we are still equal - test to see if the default file has any keys that have been removed by the default config.
  576. if ( bEqual )
  577. {
  578. for( KeyValues *pTestKey = pDefaultKeys->GetFirstSubKey(); pTestKey; pTestKey = pTestKey->GetNextKey() )
  579. {
  580. const char *pszTestName = pTestKey->GetName();
  581. KeyValues *pFindKey = configData.pConfigKeys->FindKey( pszTestName );
  582. if ( !pFindKey )
  583. {
  584. Warning( "The default video config has changed, config key '%s=%s' has been added.\n", pszTestName, pTestKey->GetString() );
  585. bufDiagnostic.Printf( "config key '%s=%s' has been added.\n", pszTestName, pTestKey->GetString() );
  586. if ( VerifyVideoConfigSettingRequired( pszTestName ) )
  587. bEqual = false;
  588. }
  589. }
  590. }
  591. // If we are not equal, put up some warning and reset the current video config file.
  592. if ( !bEqual )
  593. {
  594. Warning( "VerifyDefaultVideoConfig: The default video config for the machine has changed, updating the current config to match.\n" );
  595. bufDiagnostic.Printf( "--ConfigData--\n" );
  596. configData.pConfigKeys->RecursiveSaveToFile( bufDiagnostic, 0 );
  597. bufDiagnostic.Printf( "--Defaults--\n" );
  598. pDefaultKeys->RecursiveSaveToFile( bufDiagnostic, 0 );
  599. bufDiagnostic.Printf( "----\n" );
  600. char chBuffer[64] = {};
  601. struct tm tmNow;
  602. Plat_GetLocalTime( &tmNow );
  603. V_sprintf_safe( chBuffer, "cfg\\video.change%u.txt", Plat_timegm( &tmNow ) );
  604. WriteVideoCfgDataToFile( chBuffer, bufDiagnostic );
  605. // Create the file.
  606. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  607. configData.pConfigKeys->RecursiveSaveToFile( buf, 0 );
  608. WriteVideoCfgDataToFile( VIDEOCONFIG_DEFAULT_FILENAME, buf );
  609. //
  610. // Upgrade user's video preferences with new default autoconfig
  611. //
  612. KeyValues *kvPreviousVideoCfg = new KeyValues( "videocfg" );
  613. if ( kvPreviousVideoCfg->LoadFromFile( g_pFullFileSystem, VIDEOCONFIG_FILENAME, VIDEOCONFIG_PATHID ) )
  614. {
  615. // Preserve all settings that support auto, but user had on a custom setting
  616. for ( int k = 0; k < Q_ARRAYSIZE( s_pVideoConfigSettingsWhitelist ); ++ k )
  617. {
  618. if ( !s_pVideoConfigSettingsWhitelist[k].m_bUseAutoOption ) continue;
  619. int nUserPreferenceValue = kvPreviousVideoCfg->GetInt( s_pVideoConfigSettingsWhitelist[k].m_pSettingVar, 9999999 );
  620. if ( nUserPreferenceValue != 9999999 )
  621. {
  622. // User had explicit value, so store same explicit value in new video config
  623. configData.pConfigKeys->SetInt( s_pVideoConfigSettingsWhitelist[ k ].m_pSettingVar, nUserPreferenceValue );
  624. }
  625. else
  626. {
  627. // User had auto configured value or no value at all, if the new default config has a value then
  628. // make sure it is set on auto here
  629. if ( KeyValues *kvSubKey = configData.pConfigKeys->FindKey( s_pVideoConfigSettingsWhitelist[ k ].m_pSettingVar ) )
  630. {
  631. char chNewAutoName[ 128 ];
  632. // e.g.: "setting.cpu_level" -> "setauto.cpu_level"
  633. V_sprintf_safe( chNewAutoName, "setauto.%s", s_pVideoConfigSettingsWhitelist[ k ].m_pSettingVar + 8 );
  634. kvSubKey->SetName( chNewAutoName );
  635. }
  636. }
  637. }
  638. }
  639. else
  640. {
  641. FOR_EACH_SUBKEY( configData.pConfigKeys, kvSubKey )
  642. {
  643. if ( VideoConfigSetting_t const *pSetting = VideoConfigSettingFindWhitelistEntryByName( kvSubKey->GetName() ) )
  644. {
  645. if ( pSetting->m_bUseAutoOption )
  646. {
  647. char chNewAutoName[ 128 ];
  648. // e.g.: "setting.cpu_level" -> "setauto.cpu_level"
  649. V_sprintf_safe( chNewAutoName, "setauto.%s", pSetting->m_pSettingVar + 8 );
  650. kvSubKey->SetName( chNewAutoName );
  651. }
  652. }
  653. }
  654. }
  655. kvPreviousVideoCfg->deleteThis();
  656. buf.Purge();
  657. configData.pConfigKeys->RecursiveSaveToFile( buf, 0 );
  658. WriteVideoCfgDataToFile( VIDEOCONFIG_FILENAME, buf );
  659. }
  660. // Destroy keys.
  661. configData.pConfigKeys->Clear();
  662. pDefaultKeys->deleteThis();
  663. return true;
  664. }
  665. #endif
  666. //-----------------------------------------------------------------------------
  667. // Purpose:
  668. //-----------------------------------------------------------------------------
  669. #if !defined( _GAMECONSOLE )
  670. bool CopyDefaultVideoToCurrentVideoConfig( const char *pszDefaultFileName, const char *pszCurrentFileName )
  671. {
  672. bool bFileExists = g_pFullFileSystem->FileExists( pszDefaultFileName, VIDEOCONFIG_PATHID );
  673. if ( !bFileExists )
  674. return false;
  675. // Open the moddefaults.cfg file and load it into key values.
  676. KeyValues *pDefaultKeys = new KeyValues( "DefaultKeys" );
  677. if ( !pDefaultKeys )
  678. return false;
  679. if ( !pDefaultKeys->LoadFromFile( g_pFullFileSystem, pszDefaultFileName, VIDEOCONFIG_PATHID ) )
  680. {
  681. pDefaultKeys->deleteThis();
  682. return false;
  683. }
  684. // Create the file.
  685. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  686. pDefaultKeys->RecursiveSaveToFile( buf, 0 );
  687. WriteVideoCfgDataToFile( pszCurrentFileName, buf );
  688. // Destroy the keys.
  689. pDefaultKeys->deleteThis();
  690. return true;
  691. }
  692. #endif
  693. //-----------------------------------------------------------------------------
  694. // Purpose:
  695. //-----------------------------------------------------------------------------
  696. #if !defined( _GAMECONSOLE )
  697. bool CreateDefaultVideoConfig( VidMatConfigData_t &configData )
  698. {
  699. // Create the default video keys.
  700. if ( !CreateDefaultVideoKeyValues( configData ) )
  701. return false;
  702. // Create the file with default settings
  703. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  704. configData.pConfigKeys->RecursiveSaveToFile( buf, 0 );
  705. WriteVideoCfgDataToFile( VIDEOCONFIG_DEFAULT_FILENAME, buf );
  706. //
  707. // Now write the file with user settings skipping the settings that support "AUTO" in options
  708. //
  709. FOR_EACH_SUBKEY( configData.pConfigKeys, kvSubKey )
  710. {
  711. if ( VideoConfigSetting_t const *pSetting = VideoConfigSettingFindWhitelistEntryByName( kvSubKey->GetName() ) )
  712. {
  713. if ( pSetting->m_bUseAutoOption )
  714. {
  715. char chNewAutoName[128];
  716. // e.g.: "setting.cpu_level" -> "setauto.cpu_level"
  717. V_sprintf_safe( chNewAutoName, "setauto.%s", pSetting->m_pSettingVar + 8 );
  718. kvSubKey->SetName( chNewAutoName );
  719. }
  720. }
  721. }
  722. buf.Purge();
  723. configData.pConfigKeys->RecursiveSaveToFile( buf, 0 );
  724. WriteVideoCfgDataToFile( VIDEOCONFIG_FILENAME, buf );
  725. // Clear out the data after writing the file.
  726. configData.pConfigKeys->Clear();
  727. return true;
  728. }
  729. #endif
  730. //-----------------------------------------------------------------------------
  731. // Purpose: Look for a video config file to setup the system defaults. Create the
  732. // file if one doesn't already exist.
  733. //-----------------------------------------------------------------------------
  734. #if !defined( _GAMECONSOLE )
  735. bool BLoadUserVideoConfigFileFromDisk( KeyValues *pConfigKeys )
  736. {
  737. // Parse current video file, note that some settings will be on AUTO with setauto
  738. // their values are ensured by code above to match the default autoconfig values
  739. if ( !pConfigKeys->LoadFromFile( g_pFullFileSystem, VIDEOCONFIG_FILENAME, VIDEOCONFIG_PATHID ) )
  740. return false;
  741. // load the default config as well to expand setauto. fields
  742. KeyValues *kvDefaultSettings = new KeyValues( "default" );
  743. if ( !kvDefaultSettings->LoadFromFile( g_pFullFileSystem, VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_PATHID ) )
  744. {
  745. kvDefaultSettings->deleteThis();
  746. kvDefaultSettings = NULL;
  747. }
  748. // bloat the AUTO detected settings for compatibility as proper 'setting.' fields
  749. FOR_EACH_SUBKEY( pConfigKeys, kvSubKey )
  750. {
  751. if ( char const *szSetting = StringAfterPrefix( kvSubKey->GetName(), "setauto." ) )
  752. {
  753. char chNewAutoName[ 128 ];
  754. // e.g.: "setauto.cpu_level" -> "setting.cpu_level"
  755. V_sprintf_safe( chNewAutoName, "setting.%s", szSetting );
  756. if ( KeyValues *kvValueDefault = kvDefaultSettings->FindKey( chNewAutoName ) )
  757. {
  758. pConfigKeys->AddSubKey( kvValueDefault->MakeCopy() );
  759. }
  760. }
  761. }
  762. if ( kvDefaultSettings )
  763. {
  764. kvDefaultSettings->deleteThis();
  765. kvDefaultSettings = NULL;
  766. }
  767. return true;
  768. }
  769. bool RecommendedVideoConfig( VidMatConfigData_t &configData )
  770. {
  771. // Get the default video config file if it exists, create it otherwise.
  772. bool bFileExists = g_pFullFileSystem->FileExists( VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_PATHID );
  773. if ( !bFileExists )
  774. {
  775. if ( !CreateDefaultVideoConfig( configData ) )
  776. return false;
  777. }
  778. else
  779. {
  780. // Verify the default data is up to date.
  781. VerifyDefaultVideoConfig( configData );
  782. }
  783. return BLoadUserVideoConfigFileFromDisk( configData.pConfigKeys );
  784. }
  785. #endif
  786. //-----------------------------------------------------------------------------
  787. // Purpose:
  788. //-----------------------------------------------------------------------------
  789. #if !defined( _GAMECONSOLE )
  790. bool RecommendedConfig( VidMatConfigData_t &configData )
  791. {
  792. // Verify that the file system has been created.
  793. Assert( g_pFullFileSystem != NULL );
  794. // If we are a video - this is a special case.
  795. if ( configData.bIsVideo )
  796. {
  797. return RecommendedVideoConfig( configData );
  798. }
  799. // Parse the configuration keys.
  800. return ParseConfigKeys( configData );
  801. }
  802. #endif
  803. //-----------------------------------------------------------------------------
  804. // Purpose:
  805. //-----------------------------------------------------------------------------
  806. #if !defined( _GAMECONSOLE )
  807. bool ResetVideoConfigToDefaults( KeyValues *pConfigKeys )
  808. {
  809. // Copy the defaults settings into the current = Reset.
  810. if ( !CopyDefaultVideoToCurrentVideoConfig( VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_FILENAME ) )
  811. return false;
  812. // Copy the new key values if there the config keys exist.
  813. if ( pConfigKeys )
  814. {
  815. return pConfigKeys->LoadFromFile( g_pFullFileSystem, VIDEOCONFIG_FILENAME, VIDEOCONFIG_PATHID );
  816. }
  817. return true;
  818. }
  819. #endif
  820. //-----------------------------------------------------------------------------
  821. // Purpose:
  822. //-----------------------------------------------------------------------------
  823. #if !defined( _GAMECONSOLE )
  824. bool UpdateCurrentVideoConfig( int nWidth, int nHeight, int nAspectRatioMode, bool bFullscreen, bool bNoWindow, bool bUseRestartConvars )
  825. {
  826. // Create and Init the video config block.
  827. KeyValues *pVideoConfigKeys = new KeyValues( "VideoConfig" );
  828. if ( !pVideoConfigKeys )
  829. return false;
  830. // Go through each of the video settings and save off all necessary data.
  831. int nVideoConfigCount = ARRAYSIZE( s_pVideoConfigSettingsWhitelist );
  832. for ( int iVar = 0; iVar < nVideoConfigCount; ++iVar )
  833. {
  834. // Do we need to save this setting?
  835. if ( !s_pVideoConfigSettingsWhitelist[iVar].m_bSaved )
  836. continue;
  837. // Strip off the "setting." prefix and check for a ConVar
  838. // Strip off the "setting." prefix and check for a ConVar
  839. char szConVarName[256];
  840. int nStringLength = V_strlen( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar );
  841. nStringLength -= 8;
  842. if ( nStringLength <= 0 )
  843. continue;
  844. V_StrRight( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar, nStringLength, szConVarName, sizeof( szConVarName ) );
  845. bool bAutodetectedSetting = false;
  846. {
  847. char szConVarRestart[ 256 ];
  848. if ( s_pVideoConfigSettingsWhitelist[ iVar ].m_bUseAutoOption )
  849. {
  850. V_snprintf( szConVarRestart, sizeof( szConVarRestart ), "%s_optionsui", szConVarName );
  851. ConVarRef cvOptionsUi( szConVarRestart );
  852. if ( cvOptionsUi.IsValid() )
  853. {
  854. bAutodetectedSetting = ( cvOptionsUi.GetInt() == 9999999 );
  855. }
  856. }
  857. if ( bUseRestartConvars )
  858. {
  859. V_snprintf( szConVarRestart, sizeof( szConVarRestart ), "%s_restart", szConVarName );
  860. if ( g_pCVar->FindVar( szConVarRestart ) )
  861. {
  862. V_strncpy( szConVarName, szConVarRestart, sizeof( szConVarName ) );
  863. }
  864. }
  865. }
  866. // Is it a CVar? If so, get the value.
  867. const ConVar *pVar = g_pCVar->FindVar( szConVarName );
  868. if ( pVar )
  869. {
  870. if ( bAutodetectedSetting )
  871. {
  872. char chSettingAutoName[ 128 ];
  873. V_sprintf_safe( chSettingAutoName, "setauto.%s", s_pVideoConfigSettingsWhitelist[ iVar ].m_pSettingVar + 8 );
  874. pVideoConfigKeys->SetString( chSettingAutoName, pVar->GetString() );
  875. }
  876. else
  877. {
  878. pVideoConfigKeys->SetString( s_pVideoConfigSettingsWhitelist[ iVar ].m_pSettingVar, pVar->GetString() );
  879. }
  880. }
  881. }
  882. // Set these window settings.
  883. pVideoConfigKeys->SetInt( "setting.defaultres", nWidth );
  884. pVideoConfigKeys->SetInt( "setting.defaultresheight", nHeight );
  885. pVideoConfigKeys->SetInt( "setting.aspectratiomode", nAspectRatioMode );
  886. pVideoConfigKeys->SetInt( "setting.fullscreen", static_cast<int>( bFullscreen ) );
  887. pVideoConfigKeys->SetInt( "setting.nowindowborder", static_cast<int>( bNoWindow ) );
  888. // Write out the file.
  889. // Create the file.
  890. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  891. pVideoConfigKeys->RecursiveSaveToFile( buf, 0 );
  892. WriteVideoCfgDataToFile( VIDEOCONFIG_FILENAME, buf );
  893. // Destroy keys.
  894. pVideoConfigKeys->deleteThis();
  895. return true;
  896. }
  897. #endif
  898. //-----------------------------------------------------------------------------
  899. // Purpose:
  900. //-----------------------------------------------------------------------------
  901. #if !defined( _GAMECONSOLE )
  902. bool UpdateVideoConfigConVars( KeyValues *pConfigKeys )
  903. {
  904. bool bAllocConfig = false;
  905. if ( !pConfigKeys )
  906. {
  907. // Create and Init the video config block.
  908. pConfigKeys = new KeyValues( "VideoConfig" );
  909. if ( !pConfigKeys )
  910. return false;
  911. if ( !BLoadUserVideoConfigFileFromDisk( pConfigKeys ) )
  912. {
  913. pConfigKeys->deleteThis();
  914. return false;
  915. }
  916. bAllocConfig = true;
  917. }
  918. #ifdef _DEBUG
  919. Msg( "UpdateVideoConfigConVars:\n" );
  920. KeyValuesDumpAsDevMsg( pConfigKeys, 0, 0 );
  921. #endif
  922. ConVar *pVarOptionsUiCallback = g_pCVar->FindVar( "videooptions_optionsui_callback_disabled" );
  923. int nVideoConfigCount = ARRAYSIZE( s_pVideoConfigSettingsWhitelist );
  924. for ( int iVar = 0; iVar < nVideoConfigCount; ++iVar )
  925. {
  926. // Do we need to save this setting?
  927. if ( !s_pVideoConfigSettingsWhitelist[iVar].m_bConVar )
  928. continue;
  929. // Strip off the "setting." prefix and check for a ConVar
  930. char szConVarName[256];
  931. int nStringLength = V_strlen( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar );
  932. nStringLength -= 8;
  933. if ( nStringLength <= 0 )
  934. continue;
  935. V_StrRight( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar, nStringLength, szConVarName, sizeof( szConVarName ) );
  936. ConVar *pVar = g_pCVar->FindVar( szConVarName );
  937. if ( !pVar )
  938. continue;
  939. KeyValues *pFindKey = pConfigKeys->FindKey( s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar );
  940. if ( !pFindKey )
  941. continue;
  942. // Always allow the command line to totally override whatever convars come from the videocfg system.
  943. char szOption[256];
  944. V_snprintf( szOption, sizeof( szOption ), "+%s", szConVarName );
  945. if ( CommandLine()->CheckParm( szOption ) )
  946. {
  947. const char *pOverrideValue = CommandLine()->ParmValue( szOption, pFindKey->GetString() );
  948. pVar->SetValue( pOverrideValue );
  949. 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 );
  950. continue;
  951. }
  952. pVar->SetValue( pFindKey->GetString() );
  953. {
  954. char szConVarRestart[ 256 ];
  955. V_sprintf_safe( szConVarRestart, "%s_restart", szConVarName );
  956. if ( ConVar *pVarRestart = g_pCVar->FindVar( szConVarRestart ) )
  957. {
  958. pVarRestart->SetValue( pFindKey->GetString() );
  959. }
  960. }
  961. if ( s_pVideoConfigSettingsWhitelist[iVar].m_bUseAutoOption )
  962. {
  963. char szConVarOptionsUi[ 256 ];
  964. V_sprintf_safe( szConVarOptionsUi, "%s_optionsui", szConVarName );
  965. if ( ConVar *pVarOptionsUi = g_pCVar->FindVar( szConVarOptionsUi ) )
  966. {
  967. if ( pVarOptionsUiCallback )
  968. pVarOptionsUiCallback->SetValue( 1 );
  969. // Check if the config instructs the convar to list as "AUTO"?
  970. char chSettingAutoName[128];
  971. V_sprintf_safe( chSettingAutoName, "setauto.%s", s_pVideoConfigSettingsWhitelist[iVar].m_pSettingVar + 8 );
  972. if ( pConfigKeys->FindKey( chSettingAutoName ) )
  973. pVarOptionsUi->SetValue( 9999999 );
  974. else
  975. pVarOptionsUi->SetValue( pFindKey->GetString() );
  976. if ( pVarOptionsUiCallback )
  977. pVarOptionsUiCallback->SetValue( 0 );
  978. }
  979. }
  980. }
  981. // If we created it - destroy it!
  982. if ( bAllocConfig )
  983. {
  984. pConfigKeys->deleteThis();
  985. }
  986. return true;
  987. }
  988. #endif
  989. //-----------------------------------------------------------------------------
  990. // Purpose:
  991. //-----------------------------------------------------------------------------
  992. #if !defined( _GAMECONSOLE )
  993. bool ReadCurrentVideoConfig( KeyValues *pConfigKeys, bool bDefault )
  994. {
  995. if ( !pConfigKeys )
  996. return false;
  997. if ( !bDefault )
  998. {
  999. // Do we have a current video config file? If not, copy the defaults file.
  1000. if ( !g_pFullFileSystem->FileExists( VIDEOCONFIG_FILENAME, VIDEOCONFIG_PATHID ) )
  1001. return false;
  1002. // Parse current video file.
  1003. return BLoadUserVideoConfigFileFromDisk( pConfigKeys );
  1004. }
  1005. else
  1006. {
  1007. // Do we have a current video config file? If not, copy the defaults file.
  1008. if ( !g_pFullFileSystem->FileExists( VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_PATHID ) )
  1009. return false;
  1010. // Parse current video file.
  1011. return pConfigKeys->LoadFromFile( g_pFullFileSystem, VIDEOCONFIG_DEFAULT_FILENAME, VIDEOCONFIG_PATHID );
  1012. }
  1013. }
  1014. #endif
  1015. const unsigned char *GetModEncryptionKey( const char *pModName )
  1016. {
  1017. if ( !V_strnicmp( "left4dead", pModName, V_strlen("left4dead") ) )
  1018. return (unsigned char*)"zp14Hi(]";
  1019. else if ( !V_strnicmp( "portal2", pModName, V_strlen("portal2") ) )
  1020. return (unsigned char *)"UrE66!Ap";
  1021. else if ( !V_strnicmp( "csgo", pModName, V_strlen("csgo") ) )
  1022. return (unsigned char *)"aY7!rn[z";
  1023. else if ( !V_strnicmp( "infested", pModName, V_strlen("infested") ) )
  1024. return (unsigned char *)"sW9.JupP";
  1025. else if ( !V_strnicmp( "ep2", pModName, V_strlen("ep2") ) )
  1026. return (unsigned char *)"Xx81uBl)";
  1027. else if ( !V_strnicmp( "tf", pModName, V_strlen("tf") ) )
  1028. return (unsigned char *)"E2NcUkG2";
  1029. else if ( !V_strnicmp( "nimbus", pModName, V_strlen("nimbus") ) )
  1030. return (unsigned char *)"E2NcUkG2";
  1031. else if ( !V_strnicmp( "dota", pModName, V_strlen( "dota" ) ) )
  1032. return (unsigned char *)"dAIt1IL!";
  1033. else
  1034. return (unsigned char*)"X8bU2qll";
  1035. }
  1036. KeyValues* ReadEncryptedKVFile( const char *pRelativePath, const char *pPathID, const char *pModName )
  1037. {
  1038. // Open the keyvalues, and abort if we can't
  1039. FileHandle_t f = g_pFullFileSystem->Open( pRelativePath, "rb", pPathID );
  1040. if ( !f )
  1041. {
  1042. return NULL;
  1043. }
  1044. // load file into a null-terminated buffer
  1045. int fileSize = g_pFullFileSystem->Size( f );
  1046. char *buffer = (char*)stackalloc( fileSize + 1 );
  1047. g_pFullFileSystem->Read( buffer, fileSize, f );
  1048. buffer[fileSize] = 0;
  1049. g_pFullFileSystem->Close( f );
  1050. DecodeICE( (unsigned char*)buffer, fileSize, GetModEncryptionKey( pModName ) );
  1051. KeyValues *pKV = new KeyValues( "kv" );
  1052. bool retOK = pKV->LoadFromBuffer( pRelativePath, buffer, g_pFullFileSystem );
  1053. if ( !retOK )
  1054. {
  1055. pKV->deleteThis();
  1056. return NULL;
  1057. }
  1058. return pKV;
  1059. }
  1060. struct SystemLevelConvar_t
  1061. {
  1062. const char *m_pConVar;
  1063. bool m_bChooseLower;
  1064. bool m_bAllowed;
  1065. };
  1066. SystemLevelConvar_t s_pConVarsAllowedInSystemLevel[] =
  1067. {
  1068. { "lower_body", true, true },
  1069. { "r_shadow_half_update_rate", false, true },
  1070. { "r_rainparticledensity", true, true },
  1071. { "cl_particle_fallback_base", false, true },
  1072. { "cl_particle_fallback_multiplier",false, true },
  1073. { "r_flashlightdepthtexture", true, true },
  1074. { "r_shadowrendertotexture", true, true },
  1075. { "r_shadowfromworldlights", true, true },
  1076. { "cl_detaildist", true, true },
  1077. { "cl_detailfade", true, true },
  1078. { "r_drawmodeldecals", true, false }, // force consistency across all levels
  1079. #ifndef _PS3
  1080. { "r_decalstaticprops", true, false }, // force consistency across all levels
  1081. #endif
  1082. { "ragdoll_sleepaftertime", true, true },
  1083. { "cl_phys_maxticks", true, true },
  1084. { "r_worldlightmin", true, true },
  1085. { "props_break_max_pieces", true, true },
  1086. { "r_worldlights", true, true },
  1087. { "r_decals", true, false }, // force consistency across all levels
  1088. { "r_decal_overlap_count", true, false }, // force consistency across all levels
  1089. { "mat_bumpmap", true, true },
  1090. { "mat_detail_tex", true, true },
  1091. { "mat_specular", true, true },
  1092. { "mat_phong", true, true },
  1093. { "mat_grain_enable", true, true },
  1094. { "mat_local_contrast_enable", true, true },
  1095. { "mat_motion_blur_enabled", true, true },
  1096. { "mat_disablehwmorph", false, true },
  1097. { "r_overlayfademin", true, true },
  1098. { "r_overlayfademax", true, true },
  1099. { "z_mob_simple_shadows", false, true },
  1100. { "cl_ragdoll_maxcount", true, true },
  1101. { "cl_ragdoll_maxcount_gib", true, true },
  1102. { "cl_ragdoll_maxcount_generic", true, true },
  1103. { "cl_ragdoll_maxcount_special", true, true },
  1104. { "sv_ragdoll_maxcount", true, true },
  1105. { "sv_ragdoll_maxcount_gib", true, true },
  1106. { "sv_ragdoll_maxcount_generic", true, true },
  1107. { "sv_ragdoll_maxcount_special", true, true },
  1108. { "z_infected_decals", true, true },
  1109. { "cl_impacteffects_limit_general", true, true },
  1110. { "cl_impacteffects_limit_exit", true, true },
  1111. { "cl_impacteffects_limit_water", true, true },
  1112. { "cl_ragdoll_self_collision", true, true },
  1113. { "cl_player_max_decal_count", true, true },
  1114. { "cl_footstep_fx", true, true },
  1115. { "mp_usehwmvcds", true, true },
  1116. { "mp_usehwmmodels", true, true },
  1117. { "mat_depthfeather_enable", true, true },
  1118. { "mat_dxlevel", true, true },
  1119. { "r_flashlightinfectedfov", true, true },
  1120. { "r_flashlightinfectedfar", true, true },
  1121. { "r_flashlightinfectedlinear", true, true },
  1122. { "r_rootlod", false, true },
  1123. { "mat_picmip", false, true },
  1124. { "mat_force_vertexfog", false, true },
  1125. { "r_simpleworldmodel_waterreflections_fullscreen", false, true },
  1126. { "r_simpleworldmodel_drawforrecursionlevel_fullscreen", true, true },
  1127. { "r_simpleworldmodel_drawbeyonddistance_fullscreen", true, true },
  1128. { "r_simpleworldmodel_waterreflections_splitscreen", true, true },
  1129. { "r_simpleworldmodel_drawforrecursionlevel_splitscreen",true, true },
  1130. { "r_simpleworldmodel_drawbeyonddistance_splitscreen", true, true },
  1131. { "r_simpleworldmodel_waterreflections_pip", true, true },
  1132. { "r_simpleworldmodel_drawforrecursionlevel_pip", true, true },
  1133. { "r_simpleworldmodel_drawbeyonddistance_pip", true, true },
  1134. { "r_lod_switch_scale", true, true },
  1135. { "r_lod", false, true },
  1136. { "r_paintblob_highres_cube", false, true },
  1137. { "r_paintblob_force_single_pass", true, true },
  1138. { "r_paintblob_max_number_of_threads", true, true },
  1139. { "cl_csm_enabled", true, true },
  1140. };
  1141. void PerformSystemConfiguration( KeyValues *pResult, int nSystemLevel, const char *pConfigFile, const char *pModName, bool bUseSplitScreenCfg, bool bVGUIIsSplitscreen )
  1142. {
  1143. char pCfgFile[MAX_PATH];
  1144. if ( nSystemLevel == CONSOLE_SYSTEM_LEVEL_PS3 )
  1145. {
  1146. // PS3
  1147. Q_snprintf( pCfgFile, sizeof(pCfgFile), "cfg\\%s_ps3", pConfigFile );
  1148. }
  1149. else
  1150. {
  1151. // everything else
  1152. Q_snprintf( pCfgFile, sizeof(pCfgFile), "cfg\\%s_%d", pConfigFile, nSystemLevel );
  1153. }
  1154. if ( !IsGameConsole() )
  1155. {
  1156. Q_strncat( pCfgFile, "_pc", sizeof(pCfgFile) );
  1157. }
  1158. if ( bUseSplitScreenCfg && bVGUIIsSplitscreen )
  1159. {
  1160. Q_strncat( pCfgFile, "_ss", sizeof(pCfgFile) );
  1161. }
  1162. Q_strncat( pCfgFile, ".ekv", sizeof(pCfgFile) );
  1163. KeyValues *pKeyValues = ReadEncryptedKVFile( pCfgFile, "GAME", pModName );
  1164. if ( !pKeyValues )
  1165. {
  1166. DevWarning( "PerformSystemConfiguration: Missing %s\n", pCfgFile );
  1167. return;
  1168. }
  1169. for( KeyValues *pKey = pKeyValues->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() )
  1170. {
  1171. const char *pCVarName = pKey->GetName();
  1172. // Check if legal
  1173. int i;
  1174. bool bLegalVar = false;
  1175. for( i=0; i < ARRAYSIZE( s_pConVarsAllowedInSystemLevel ); i++ )
  1176. {
  1177. if ( !Q_stricmp( s_pConVarsAllowedInSystemLevel[i].m_pConVar, pCVarName ) )
  1178. {
  1179. bLegalVar = true;
  1180. break;
  1181. }
  1182. }
  1183. if ( !bLegalVar )
  1184. {
  1185. DevWarning("PerformSystemConfiguration: Bad convar found in %s - %s\n", pConfigFile, pCVarName );
  1186. continue;
  1187. }
  1188. if ( !s_pConVarsAllowedInSystemLevel[i].m_bAllowed )
  1189. {
  1190. #ifdef _DEBUG
  1191. DevWarning("PerformSystemConfiguration: Skipping convar found in %s - %s\n", pConfigFile, pCVarName );
  1192. #endif
  1193. continue;
  1194. }
  1195. if ( pResult->FindKey( pCVarName ) )
  1196. {
  1197. float flOldValue = pResult->GetFloat( pCVarName );
  1198. float flNewValue = pKey->GetFloat();
  1199. if ( s_pConVarsAllowedInSystemLevel[i].m_bChooseLower )
  1200. {
  1201. if ( flNewValue >= flOldValue )
  1202. continue;
  1203. }
  1204. else
  1205. {
  1206. if ( flNewValue <= flOldValue )
  1207. continue;
  1208. }
  1209. }
  1210. const char *pValue = pKey->GetString();
  1211. pResult->SetString( pCVarName, pValue );
  1212. }
  1213. pKeyValues->deleteThis();
  1214. }
  1215. void UpdateSystemLevel( int nCPULevel, int nGPULevel, int nMemLevel, int nGPUMemLevel, bool bVGUIIsSplitscreen, const char *pModName )
  1216. {
  1217. KeyValues *pKeyValues = new KeyValues( "kv" );
  1218. PerformSystemConfiguration( pKeyValues, nCPULevel, "cpu_level", pModName, true, bVGUIIsSplitscreen );
  1219. PerformSystemConfiguration( pKeyValues, nGPULevel, "gpu_level", pModName, false, bVGUIIsSplitscreen );
  1220. PerformSystemConfiguration( pKeyValues, nMemLevel, "mem_level", pModName, false, bVGUIIsSplitscreen );
  1221. PerformSystemConfiguration( pKeyValues, nGPUMemLevel, "gpu_mem_level", pModName, false, bVGUIIsSplitscreen );
  1222. for( KeyValues *pKey = pKeyValues->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() )
  1223. {
  1224. const char *pCVarName = pKey->GetName();
  1225. ConVar *pConVar = g_pCVar->FindVar( pCVarName );
  1226. if ( !pConVar )
  1227. continue;
  1228. // We want this on all platforms now - having the config system always slam convars being defined on the cmd line is just too confusing.
  1229. //if ( IsX360() )
  1230. {
  1231. bool bFound = false;
  1232. for ( int i=1; !bFound && i < CommandLine()->ParmCount(); i++ )
  1233. {
  1234. const char *szParm = CommandLine()->GetParm(i);
  1235. if ( szParm && szParm[0] == '+' )
  1236. {
  1237. bFound = ( V_stricmp( pCVarName, szParm + 1 ) == 0 );
  1238. }
  1239. }
  1240. if ( bFound )
  1241. {
  1242. // found on command line, ignore any value the script would have set
  1243. Warning( "UpdateSystemLevel: System configuration ignoring %s due to command line override\n", pCVarName );
  1244. continue;
  1245. }
  1246. }
  1247. if ( pConVar->GetFlags() & ( FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE | FCVAR_CHEAT ) )
  1248. {
  1249. Warning( "UpdateSystemLevel: ConVar %s controlled by gpu_level/cpu_level must not be marked as FCVAR_ARCHIVE or FCVAR_CHEAT!\n", pCVarName );
  1250. continue;
  1251. }
  1252. pConVar->SetValue( pKey->GetString() );
  1253. }
  1254. pKeyValues->deleteThis();
  1255. }