/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ // PerformanceConfigDialog.cpp : implementation file // #include "stdafx.h" #include "wwconfig.h" #include "performanceconfigdialog.h" #include "registry.h" #include "ww3d.h" #include "pscene.h" #include "rendobj.h" #include "phys.h" #include "videoconfigdialog.h" #include "dx8caps.h" #include "cpudetect.h" #include "formconv.h" #include "dx8wrapper.h" #include "locale_api.h" #include "wwconfig_ids.h" #include "..\..\combat\specialbuilds.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif static bool CanDoMultiPass=true; ///////////////////////////////////////////////////////////////////////////// // Structures and typedefs ///////////////////////////////////////////////////////////////////////////// typedef struct _PERFORMANCE_SETTING { int ctrl_id; int value; } PERFORMANCE_SETTING; ///////////////////////////////////////////////////////////////////////////// // Constants ///////////////////////////////////////////////////////////////////////////// const int MAX_PERFORMANCE_LEVELS = 4; const int MAX_EXPERT_OPTIONS = 8; PERFORMANCE_SETTING _PerformanceLevels[MAX_PERFORMANCE_LEVELS][MAX_EXPERT_OPTIONS] = { // // Low detail // { {IDC_CHAR_SHADOWS_SLIDER, 0}, {IDC_TEXTURE_DETAIL_SLIDER, 0}, {IDC_PARTICLE_DETAIL_SLIDER, 0}, {IDC_SURFACE_DETAIL_SLIDER, 0}, {IDC_GEOMETRY_DETAIL_SLIDER, 0}, {IDC_TEXTURE_FILTER_COMBO, TextureClass::TEXTURE_FILTER_BILINEAR}, {IDC_LIGHTING_MODE_COMBO, WW3D::PRELIT_MODE_VERTEX}, {IDC_TERRAIN_SHADOW_CHECK, 0} }, { {IDC_CHAR_SHADOWS_SLIDER, 1}, {IDC_TEXTURE_DETAIL_SLIDER, 1}, {IDC_PARTICLE_DETAIL_SLIDER, 0}, {IDC_SURFACE_DETAIL_SLIDER, 0}, {IDC_GEOMETRY_DETAIL_SLIDER, 0}, {IDC_TEXTURE_FILTER_COMBO, TextureClass::TEXTURE_FILTER_BILINEAR}, {IDC_LIGHTING_MODE_COMBO, WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE}, {IDC_TERRAIN_SHADOW_CHECK, 0} }, { {IDC_CHAR_SHADOWS_SLIDER, 2}, {IDC_TEXTURE_DETAIL_SLIDER, 2}, {IDC_PARTICLE_DETAIL_SLIDER, 1}, {IDC_SURFACE_DETAIL_SLIDER, 1}, {IDC_GEOMETRY_DETAIL_SLIDER, 1}, {IDC_TEXTURE_FILTER_COMBO, TextureClass::TEXTURE_FILTER_TRILINEAR}, {IDC_LIGHTING_MODE_COMBO, WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE}, {IDC_TERRAIN_SHADOW_CHECK, 1} }, // // High detail // { {IDC_CHAR_SHADOWS_SLIDER, 3}, {IDC_TEXTURE_DETAIL_SLIDER, 2}, {IDC_PARTICLE_DETAIL_SLIDER, 2}, {IDC_SURFACE_DETAIL_SLIDER, 2}, {IDC_GEOMETRY_DETAIL_SLIDER, 2}, {IDC_TEXTURE_FILTER_COMBO, TextureClass::TEXTURE_FILTER_TRILINEAR}, {IDC_LIGHTING_MODE_COMBO, WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE}, {IDC_TERRAIN_SHADOW_CHECK, 1} }, }; ///////////////////////////////////////////////////////////////////////////// // Registry Values ///////////////////////////////////////////////////////////////////////////// /* #ifdef MULTIPLAYERDEMO const char *KEY_NAME_SETTINGS = "Software\\Westwood\\RenegadeMPDemo\\System Settings"; const char *KEY_NAME_OPTIONS = "Software\\Westwood\\RenegadeMPDemo\\Options"; #else const char *KEY_NAME_SETTINGS = "Software\\Westwood\\Renegade\\System Settings"; const char *KEY_NAME_OPTIONS = "Software\\Westwood\\Renegade\\Options"; #endif // MULTIPLAYERDEMO */ #if defined(FREEDEDICATEDSERVER) const char *KEY_NAME_SETTINGS = "Software\\Westwood\\RenegadeFDS\\System Settings"; const char *KEY_NAME_OPTIONS = "Software\\Westwood\\RenegadeFDS\\Options"; #elif defined(MULTIPLAYERDEMO) const char *KEY_NAME_SETTINGS = "Software\\Westwood\\RenegadeMPDemo\\System Settings"; const char *KEY_NAME_OPTIONS = "Software\\Westwood\\RenegadeMPDemo\\Options"; #elif defined(BETACLIENT) const char *KEY_NAME_SETTINGS = "Software\\Westwood\\RenegadeBeta\\System Settings"; const char *KEY_NAME_OPTIONS = "Software\\Westwood\\RenegadeBeta\\Options"; #else const char *KEY_NAME_SETTINGS = "Software\\Westwood\\Renegade\\System Settings"; const char *KEY_NAME_OPTIONS = "Software\\Westwood\\Renegade\\Options"; #endif const char *VALUE_NAME_DYN_LOD = "Dynamic_LOD_Budget"; const char *VALUE_NAME_STATIC_LOD = "Static_LOD_Budget"; const char *VALUE_NAME_DYN_SHADOWS = "Dynamic_Projectors"; const char *VALUE_NAME_TEXTURE_FILTER = "Texture_Filter_Mode"; const char *VALUE_NAME_PRELIT_MODE = "Prelit_Mode"; const char *VALUE_NAME_SHADOW_MODE = "Shadow_Mode"; const char *VALUE_NAME_STATIC_SHADOWS = "Static_Projectors"; const char *VALUE_NAME_TEXTURE_RES = "Texture_Resolution"; const char *VALUE_NAME_SURFACE_EFFECT = "Surface_Effect_Detail"; const char *VALUE_NAME_PARTICLE_DETAIL = "Particle_Detail"; ///////////////////////////////////////////////////////////////////////////// // // PerformanceConfigDialogClass // ///////////////////////////////////////////////////////////////////////////// PerformanceConfigDialogClass::PerformanceConfigDialogClass(CWnd* pParent /*=NULL*/) : CDialog (PerformanceConfigDialogClass::IDD, pParent) { //{{AFX_DATA_INIT(PerformanceConfigDialogClass) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT CDialog::Create (PerformanceConfigDialogClass::IDD, pParent); return ; } ///////////////////////////////////////////////////////////////////////////// // // DoDataExchange // ///////////////////////////////////////////////////////////////////////////// void PerformanceConfigDialogClass::DoDataExchange (CDataExchange *pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(PerformanceConfigDialogClass) DDX_Control(pDX, IDC_GEOMETRY_DETAIL_SLIDER, m_GeometrySlider); DDX_Control(pDX, IDC_CHAR_SHADOWS_SLIDER, m_CharShadowsSlider); DDX_Control(pDX, IDC_TEXTURE_DETAIL_SLIDER, m_TextureDetailSlider); DDX_Control(pDX, IDC_SURFACE_DETAIL_SLIDER, m_SurfaceEffectsSlider); DDX_Control(pDX, IDC_PERFORMANCE_SLIDER, m_PerformanceSlider); DDX_Control(pDX, IDC_PARTICLE_DETAIL_SLIDER, m_ParticleSlider); //}}AFX_DATA_MAP return ; } BEGIN_MESSAGE_MAP(PerformanceConfigDialogClass, CDialog) //{{AFX_MSG_MAP(PerformanceConfigDialogClass) ON_BN_CLICKED(IDC_EXPERT_CHECK, OnExpertCheck) ON_WM_HSCROLL() ON_BN_CLICKED(IDC_AUTO_CONFIG_BUTTON, OnGraphicsAutoSetup) ON_WM_SHOWWINDOW() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // // OnInitDialog // // Modified: 12/06/2001 by MML - Retrieving strings from Locomoto file. // ///////////////////////////////////////////////////////////////////////////// BOOL PerformanceConfigDialogClass::OnInitDialog (void) { char string [_MAX_PATH]; CDialog::OnInitDialog (); // // Set all the static strings for this dialog. // SetDlgItemText( IDC_DETAIL, Locale_GetString( IDS_DETAIL, string )); SetDlgItemText( IDC_LOW_DESC, Locale_GetString( IDS_LOW_DESC, string )); SetDlgItemText( IDC_HIGH_DESC, Locale_GetString( IDS_HIGH_DESC, string )); SetDlgItemText( IDC_EXPERT_CHECK, Locale_GetString( IDS_EXPERT_MODE, string )); SetDlgItemText( IDC_EXPERT_SETTINGS, Locale_GetString( IDS_EXPERT_SETTINGS, string )); SetDlgItemText( IDC_AUTO_CONFIG_BUTTON, Locale_GetString( IDS_AUTOCONFIG, string )); SetDlgItemText( IDC_GEOMETRY_DETAIL, Locale_GetString( IDS_GEOMETRY_DETAIL, string )); SetDlgItemText( IDC_CHARACTER_SHADOWS, Locale_GetString( IDS_CHARACTER_SHADOWS, string )); SetDlgItemText( IDC_TEXTURE_DETAIL, Locale_GetString( IDS_TEXTURE_DETAIL, string )); SetDlgItemText( IDC_PARTICLE_DETAIL, Locale_GetString( IDS_PARTICLE_DETAIL, string )); SetDlgItemText( IDC_SURFACE_EFFECT_DETAIL, Locale_GetString( IDS_SURFACE_EFFECT_DETAIL, string )); Locale_GetString( IDS_LOW, string ); SetDlgItemText( IDC_LOW1, string ); SetDlgItemText( IDC_LOW2, string ); SetDlgItemText( IDC_LOW3, string ); SetDlgItemText( IDC_LOW4, string ); SetDlgItemText( IDC_LOW5, string ); Locale_GetString( IDS_HIGH, string ); SetDlgItemText( IDC_HIGH1, string ); SetDlgItemText( IDC_HIGH2, string ); SetDlgItemText( IDC_HIGH3, string ); SetDlgItemText( IDC_HIGH4, string ); SetDlgItemText( IDC_HIGH5, string ); SetDlgItemText( IDC_LIGHTING_MODE, Locale_GetString( IDS_LIGHTING_MODE, string )); SetDlgItemText( IDC_TEXTURE_FILTER, Locale_GetString( IDS_TEXTURE_FILTER, string )); SetDlgItemText( IDC_TERRAIN_SHADOW_CHECK, Locale_GetString( IDS_TERRAIN_SHADOWS, string )); // // Configure the dialog controls // Setup_Controls (); Load_Values (); // Determine_Performance_Setting (); // // Set the visibility of the expert windows controls // Build_Expert_Window_List (); Display_Expert_Settings (false); return TRUE; } ///////////////////////////////////////////////////////////////////////////// // // Build_Expert_Window_List // ///////////////////////////////////////////////////////////////////////////// void PerformanceConfigDialogClass::Build_Expert_Window_List (void) { ExpertWindowList.Delete_All (); // // Find the y-position of the expert mode checkbox // CRect rect; ::GetWindowRect (::GetDlgItem (m_hWnd, IDC_EXPERT_CHECK), &rect); float y_pos = rect.top; // // Loop over all the child windows of the dialog // for ( HWND child_wnd = ::GetWindow (m_hWnd, GW_CHILD); child_wnd != NULL; child_wnd = ::GetWindow (child_wnd, GW_HWNDNEXT)) { // // If this child window is below the expert checkbox then its // part of the expert settings // ::GetWindowRect (child_wnd, &rect); if (rect.top > y_pos) { ExpertWindowList.Add (child_wnd); } } return ; } ///////////////////////////////////////////////////////////////////////////// // // Display_Expert_Settings // ///////////////////////////////////////////////////////////////////////////// void PerformanceConfigDialogClass::Display_Expert_Settings (bool onoff) { // // Loop over all the expert settings windows and either // show or hide them... // for (int index = 0; index < ExpertWindowList.Count (); index ++) { ::ShowWindow (ExpertWindowList[index], onoff ? SW_SHOW : SW_HIDE); } return ; } ///////////////////////////////////////////////////////////////////////////// // // OnExpertCheck // ///////////////////////////////////////////////////////////////////////////// void PerformanceConfigDialogClass::OnExpertCheck (void) { bool enabled = bool(SendDlgItemMessage (IDC_EXPERT_CHECK, BM_GETCHECK) == 1); Display_Expert_Settings (enabled); return ; } ///////////////////////////////////////////////////////////////////////////// // // Setup_Controls // ///////////////////////////////////////////////////////////////////////////// void PerformanceConfigDialogClass::Setup_Controls (void) { // // Configure the main performance slider // m_PerformanceSlider.SetRange (0, MAX_PERFORMANCE_LEVELS - 1); // // Configure the individual detail-setting sliders // m_CharShadowsSlider.SetRange (0, 3); m_GeometrySlider.SetRange (0, 2); m_TextureDetailSlider.SetRange (0, 2); m_SurfaceEffectsSlider.SetRange (0, 2); m_ParticleSlider.SetRange (0, 2); return ; } ///////////////////////////////////////////////////////////////////////////// // // Load_Values // ///////////////////////////////////////////////////////////////////////////// void PerformanceConfigDialogClass::Load_Values (void) { // // Attempt to open the registry key // RegistryClass registry (KEY_NAME_SETTINGS); if (registry.Is_Valid ()) { // // Read the values from the registry // int dynamic_lod = registry.Get_Int (VALUE_NAME_DYN_LOD, 3000); int static_lod = registry.Get_Int (VALUE_NAME_STATIC_LOD, 3000); int dynamic_shadows = registry.Get_Int (VALUE_NAME_DYN_SHADOWS, 1); int static_shadows = registry.Get_Int (VALUE_NAME_STATIC_SHADOWS, 1); int prelit_mode = registry.Get_Int (VALUE_NAME_PRELIT_MODE, WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE); int texture_filter = registry.Get_Int (VALUE_NAME_TEXTURE_FILTER, TextureClass::TEXTURE_FILTER_BILINEAR); int shadow_mode = registry.Get_Int (VALUE_NAME_SHADOW_MODE, PhysicsSceneClass::SHADOW_MODE_BLOBS_PLUS); int texture_red = registry.Get_Int (VALUE_NAME_TEXTURE_RES, 0); int surface_effect = registry.Get_Int (VALUE_NAME_SURFACE_EFFECT, 1); int particle_detail = registry.Get_Int (VALUE_NAME_PARTICLE_DETAIL, 1); // // Set the slider's positions to reflect the loaded values // m_CharShadowsSlider.SetPos (min (shadow_mode, 3)); m_TextureDetailSlider.SetPos (max (2 - texture_red, 0)); m_SurfaceEffectsSlider.SetPos (surface_effect); m_ParticleSlider.SetPos (particle_detail); // // Choose a setting for the geometry slider based on // the dynamic and static LOD budgets // if (dynamic_lod < 1000 && static_lod < 1000) { m_GeometrySlider.SetPos (0); } else if (dynamic_lod <= 5000 && static_lod <= 5000) { m_GeometrySlider.SetPos (1); } else { m_GeometrySlider.SetPos (2); } // // Check the checkbox controls (if necessary) // SendDlgItemMessage (IDC_TERRAIN_SHADOW_CHECK, BM_SETCHECK, (WPARAM)(static_shadows != 0)); // // Select the correct setting from the lighting mode combo box // SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_SETCURSEL, prelit_mode); // // Select the correct setting from the texture filtering mode combo box // SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_SETCURSEL, texture_filter); } return ; } ///////////////////////////////////////////////////////////////////////////// // // Determine_Performance_Setting // ///////////////////////////////////////////////////////////////////////////// void PerformanceConfigDialogClass::Determine_Performance_Setting (void) { float option_levels[MAX_EXPERT_OPTIONS] = { 0 }; int count_per_option[MAX_EXPERT_OPTIONS] = { 0 }; // // Get the current values of each setting // DynamicVectorClass option_values; Get_Settings (option_values); // // Find out which level each option is currently set at // for (int level = MAX_PERFORMANCE_LEVELS - 1; level >= 0; level --) { for (int index = 0; index < MAX_EXPERT_OPTIONS; index ++) { // // If the values match, then record the current level for this option // if (option_values[index] == _PerformanceLevels[level][index].value) { option_levels[index] += level; count_per_option[index] ++; } } } // // Add up all the levels // float level_sum = 0; for (int index = 0; index < MAX_EXPERT_OPTIONS; index ++) { level_sum += (option_levels[index] / count_per_option[index]); } // // Take the average rating // float level_rating = level_sum / MAX_EXPERT_OPTIONS; // // Set the slider's position // m_PerformanceSlider.SetPos (min (int(level_rating + 0.5F), MAX_EXPERT_OPTIONS - 1)); return ; } ///////////////////////////////////////////////////////////////////////////// // // Get_Settings // ///////////////////////////////////////////////////////////////////////////// void PerformanceConfigDialogClass::Get_Settings (DynamicVectorClass &settings) { // // Determine what the value of each control is // for (int index = 0; index < MAX_EXPERT_OPTIONS; index ++) { // // Determine what the value of this control is // int curr_value = 0; int ctrl_id = _PerformanceLevels[0][index].ctrl_id; switch (ctrl_id) { // // Read any of the slider positions // case IDC_GEOMETRY_DETAIL_SLIDER: case IDC_CHAR_SHADOWS_SLIDER: case IDC_TEXTURE_DETAIL_SLIDER: case IDC_PARTICLE_DETAIL_SLIDER: case IDC_SURFACE_DETAIL_SLIDER: curr_value = SendDlgItemMessage (ctrl_id, TBM_GETPOS); break; // // Read the values from the checkbox // case IDC_TERRAIN_SHADOW_CHECK: curr_value = SendDlgItemMessage (ctrl_id, BM_GETCHECK); break; // // Read a value from a combo box. // case IDC_LIGHTING_MODE_COMBO: case IDC_TEXTURE_FILTER_COMBO: curr_value = SendDlgItemMessage (ctrl_id, CB_GETCURSEL); break; } // // Add this value to the list // settings.Add (curr_value); } return ; } ///////////////////////////////////////////////////////////////////////////// // // Update_Expert_Controls // ///////////////////////////////////////////////////////////////////////////// void PerformanceConfigDialogClass::Update_Expert_Controls (int level) { for (int index = 0; index < MAX_EXPERT_OPTIONS; index ++) { // // Determine which control we are updating // int ctrl_id = _PerformanceLevels[level][index].ctrl_id; switch (ctrl_id) { // // Update any of the sliders via the same mechanism // case IDC_GEOMETRY_DETAIL_SLIDER: case IDC_CHAR_SHADOWS_SLIDER: case IDC_TEXTURE_DETAIL_SLIDER: case IDC_PARTICLE_DETAIL_SLIDER: case IDC_SURFACE_DETAIL_SLIDER: SendDlgItemMessage (ctrl_id, TBM_SETPOS, TRUE, _PerformanceLevels[level][index].value); break; // // Update any of the check boxes via the same mechanism // case IDC_TERRAIN_SHADOW_CHECK: SendDlgItemMessage (ctrl_id, BM_SETCHECK, _PerformanceLevels[level][index].value); break; // // Update any of the combo boxes. // case IDC_LIGHTING_MODE_COMBO: case IDC_TEXTURE_FILTER_COMBO: SendDlgItemMessage (ctrl_id, CB_SETCURSEL, _PerformanceLevels[level][index].value); break; } } return ; } ///////////////////////////////////////////////////////////////////////////// // // OnHScroll // ///////////////////////////////////////////////////////////////////////////// void PerformanceConfigDialogClass::OnHScroll ( UINT nSBCode, UINT nPos, CScrollBar * pScrollBar ) { int ctrl_id = ::GetWindowLong (pScrollBar->m_hWnd, GWL_ID); // // If this is the overall performance slider, then // update the expert controls to reflect the new setting // if (ctrl_id == IDC_PERFORMANCE_SLIDER) { int new_level = m_PerformanceSlider.GetPos (); Update_Expert_Controls (new_level); } CDialog::OnHScroll (nSBCode, nPos, pScrollBar); return ; } ///////////////////////////////////////////////////////////////////////////// // // Apply_Changes // ///////////////////////////////////////////////////////////////////////////// void PerformanceConfigDialogClass::Apply_Changes (void) { // // Attempt to open the registry key // RegistryClass registry (KEY_NAME_SETTINGS); if (registry.Is_Valid ()) { // // Get the current settings from the dialog // int geometry_detail = m_GeometrySlider.GetPos (); int shadow_mode = m_CharShadowsSlider.GetPos (); int texture_red = m_TextureDetailSlider.GetPos (); int surface_effect = m_SurfaceEffectsSlider.GetPos (); int particle_detail = m_ParticleSlider.GetPos (); int static_shadows = SendDlgItemMessage (IDC_TERRAIN_SHADOW_CHECK, BM_GETCHECK); int prelit_mode = SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_GETCURSEL); // If card can't do multi-pass, value 1 means multi-texture (multi-pass selection is missing from the combo box) if (!CanDoMultiPass) { if (prelit_mode==1) prelit_mode=WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE; } int texture_filter = SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_GETCURSEL); // // Determine a good LOD budget to use // int lod_budget = 0; if (geometry_detail == 0) { lod_budget = 0; } else if (geometry_detail == 1) { lod_budget = 5000; } else if (geometry_detail == 2) { lod_budget = 10000; } // // Store the values in the registry // registry.Set_Int (VALUE_NAME_DYN_LOD, lod_budget); registry.Set_Int (VALUE_NAME_STATIC_LOD, lod_budget); registry.Set_Int (VALUE_NAME_DYN_SHADOWS, (shadow_mode != PhysicsSceneClass::SHADOW_MODE_NONE)); registry.Set_Int (VALUE_NAME_STATIC_SHADOWS, static_shadows); registry.Set_Int (VALUE_NAME_PRELIT_MODE, prelit_mode); registry.Set_Int (VALUE_NAME_TEXTURE_FILTER, texture_filter); registry.Set_Int (VALUE_NAME_SHADOW_MODE, shadow_mode); registry.Set_Int (VALUE_NAME_TEXTURE_RES, max (2 - texture_red, 0)); registry.Set_Int (VALUE_NAME_SURFACE_EFFECT, surface_effect); registry.Set_Int (VALUE_NAME_PARTICLE_DETAIL, particle_detail); } return ; } ///////////////////////////////////////////////////////////////////////////// // // WindowProc // ///////////////////////////////////////////////////////////////////////////// LRESULT PerformanceConfigDialogClass::WindowProc ( UINT message, WPARAM wParam, LPARAM lParam ) { if (message == (WM_USER + 101)) { Apply_Changes (); } return CDialog::WindowProc(message, wParam, lParam); } /* //If really low texture memory such as 4 Mb (if possible to detect) set level 2 - If multtexturing available, default to multitextured lighting, otherwise multi pass - If a low end card, default to vertex solve - Default to 640x480, 800x600 or 1024x768 depending on video card - Default to 32 bit display on HW T&L cards, 16 bit otherwise - Default to fullscreen (do we even support windowed mode in the release?) - The same for particle detail */ void AutoConfigSettings(); void PerformanceConfigDialogClass::OnGraphicsAutoSetup() { // TODO: Add your control notification handler code here AutoConfigSettings(); Load_Values(); // Apply_Changes(); }; /* registry.Set_Int (VALUE_NAME_DYN_LOD, lod_budget); registry.Set_Int (VALUE_NAME_STATIC_LOD, lod_budget); registry.Set_Int (VALUE_NAME_DYN_SHADOWS, (shadow_mode != PhysicsSceneClass::SHADOW_MODE_NONE)); registry.Set_Int (VALUE_NAME_STATIC_SHADOWS, static_shadows); registry.Set_Int (VALUE_NAME_PRELIT_MODE, prelit_mode); registry.Set_Int (VALUE_NAME_SHADOW_MODE, shadow_mode); registry.Set_Int (VALUE_NAME_TEXTURE_RES, max (2 - texture_red, 0)); registry.Set_Int (VALUE_NAME_SURFACE_EFFECT, surface_effect); registry.Set_Int (VALUE_NAME_PARTICLE_DETAIL, particle_detail); */ void AutoConfigSettings() { // // Attempt to open the registry key // RegistryClass registry (KEY_NAME_SETTINGS); if (!registry.Is_Valid()) return; // Access registry key "Render" RegistryClass render_registry(RENEGADE_SUB_KEY_NAME_RENDER); if ( !render_registry.Is_Valid() ) { return; } IDirect3D8* d3d=NULL; D3DCAPS8 tmp_caps; const D3DCAPS8* d3dcaps=NULL; D3DADAPTER_IDENTIFIER8 adapter_id; D3DFORMAT display_format; VideoConfigDialogClass* video=VideoConfigDialogClass::Get_Instance(); if (video) { WW3D::Set_Texture_Bitdepth(16); render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_TEXTURE_DEPTH, 16 ); d3d=DX8Wrapper::_Get_D3D8(); d3d->AddRef(); d3dcaps=&video->Get_Current_Caps(); adapter_id=video->Get_Current_Adapter_Identifier(); if (video->Get_Current_Bit_Depth()==32) { display_format=D3DFMT_X8R8G8B8; } else { display_format=D3DFMT_R5G6B5; } } else { // Init D3D Init_D3D_To_WW3_Conversion(); d3d=Direct3DCreate8(D3D_SDK_VERSION); // TODO: handle failure cases... if (!d3d) { return; } // Select device. If there is already a device selected in the registry, use it. int current_adapter_index=D3DADAPTER_DEFAULT; // // Load the render device settings from the registry // char device_name[256] = { 0 }; render_registry.Get_String( VALUE_NAME_RENDER_DEVICE_NAME, device_name, sizeof(device_name)); int adapter_count = d3d->GetAdapterCount(); for (int adapter_index=0; adapter_indexGetAdapterIdentifier(adapter_index,D3DENUM_NO_WHQL_LEVEL,&id); // If device ok, check if it matches the currently set adapter name if (res == D3D_OK) { StringClass name(id.Description,true); if (name==device_name) { current_adapter_index=adapter_index; break; } } } if (FAILED(d3d->GetDeviceCaps( current_adapter_index, D3DDEVTYPE_HAL, &tmp_caps))) { d3d->Release(); return; } ::ZeroMemory(&adapter_id, sizeof(D3DADAPTER_IDENTIFIER8)); if (FAILED( d3d->GetAdapterIdentifier( current_adapter_index, D3DENUM_NO_WHQL_LEVEL, &adapter_id))) { d3d->Release(); return; } // Store device name in registry render_registry.Set_String( VALUE_NAME_RENDER_DEVICE_NAME, adapter_id.Description); // Set resolution to 800 x 600 x 16 render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_WIDTH, 800 ); render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_HEIGHT, 600 ); render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_DEPTH, 16 ); render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_WINDOWED, 0 ); render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_TEXTURE_DEPTH, 16 ); d3dcaps=&tmp_caps; display_format=D3DFMT_R5G6B5; // Test if the card if new enough to do 32 bit... DX8Caps tmp_caps(d3d,*d3dcaps,WW3D_FORMAT_UNKNOWN,adapter_id); switch (tmp_caps.Get_Vendor()) { default: break; case DX8Caps::VENDOR_NVIDIA: switch (tmp_caps.Get_Device()) { default: display_format=D3DFMT_X8R8G8B8; render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_DEPTH, 32 ); break; case DX8Caps::DEVICE_NVIDIA_TNT2_ALADDIN: case DX8Caps::DEVICE_NVIDIA_TNT2: case DX8Caps::DEVICE_NVIDIA_TNT2_ULTRA: case DX8Caps::DEVICE_NVIDIA_TNT2_VANTA: case DX8Caps::DEVICE_NVIDIA_TNT2_M64: case DX8Caps::DEVICE_NVIDIA_TNT: case DX8Caps::DEVICE_NVIDIA_RIVA_128: case DX8Caps::DEVICE_NVIDIA_TNT_VANTA: case DX8Caps::DEVICE_NVIDIA_NV1: break; } break; case DX8Caps::VENDOR_ATI: switch (tmp_caps.Get_Device()) { case DX8Caps::DEVICE_ATI_RAGE_II: case DX8Caps::DEVICE_ATI_RAGE_II_PLUS: case DX8Caps::DEVICE_ATI_RAGE_IIC_PCI: case DX8Caps::DEVICE_ATI_RAGE_IIC_AGP: case DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY: case DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY_M3: case DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY_M4: case DX8Caps::DEVICE_ATI_RAGE_128_PRO_ULTRA: case DX8Caps::DEVICE_ATI_RAGE_128_4X: case DX8Caps::DEVICE_ATI_RAGE_128_PRO_GL: case DX8Caps::DEVICE_ATI_RAGE_128_PRO_VR: case DX8Caps::DEVICE_ATI_RAGE_128_GL: case DX8Caps::DEVICE_ATI_RAGE_128_VR: case DX8Caps::DEVICE_ATI_RAGE_PRO: case DX8Caps::DEVICE_ATI_RAGE_PRO_MOBILITY: break; default: display_format=D3DFMT_X8R8G8B8; render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_DEPTH, 32 ); break; } break; } } DX8Caps caps(d3d,*d3dcaps,D3DFormat_To_WW3DFormat(display_format),adapter_id); CanDoMultiPass=caps.Can_Do_Multi_Pass(); bool high_end_processor=CPUDetectClass::Has_SSE_Instruction_Set(); if (CPUDetectClass::Get_Processor_Manufacturer()==CPUDetectClass::MANUFACTURER_AMD && CPUDetectClass::Get_AMD_Processor()>=CPUDetectClass::AMD_PROCESSOR_ATHLON_025) { high_end_processor=true; } // If no texture compression, default to texture resolution 1 if (caps.Support_DXTC()) { registry.Set_Int (VALUE_NAME_TEXTURE_RES, 0); } else { registry.Set_Int (VALUE_NAME_TEXTURE_RES, 1); } // High geometry detail on T&L cards, medium on fast processors and low on slow ones if (caps.Support_TnL()) { registry.Set_Int (VALUE_NAME_DYN_LOD, 10000); registry.Set_Int (VALUE_NAME_STATIC_LOD, 10000); } else { // If T&L hardware present, set to medium or low. Set to medium if high end cpu. // TODO: Set to medium if Athlon detected. if (high_end_processor) { registry.Set_Int (VALUE_NAME_DYN_LOD, 5000); registry.Set_Int (VALUE_NAME_STATIC_LOD, 5000); } else { registry.Set_Int (VALUE_NAME_DYN_LOD, 0); registry.Set_Int (VALUE_NAME_STATIC_LOD, 0); } } // Set high shadow detail if render to texture is supported AND HWTL available // Set medium shadow detail if render to texture is supported but no HWTL // Set low shadow detail if no render to texture is available if (caps.Support_Render_To_Texture_Format(D3DFormat_To_WW3DFormat(display_format))) { if (caps.Support_TnL()) { registry.Set_Int (VALUE_NAME_SHADOW_MODE, 3); registry.Set_Int (VALUE_NAME_STATIC_SHADOWS, 1); } else { registry.Set_Int (VALUE_NAME_SHADOW_MODE, 2); registry.Set_Int (VALUE_NAME_STATIC_SHADOWS, 0); } } else { registry.Set_Int (VALUE_NAME_STATIC_SHADOWS, 0); // Set to medium if high end cpu detected. // TODO: Set to medium if Athlon detected. if (high_end_processor) { registry.Set_Int (VALUE_NAME_SHADOW_MODE, 1); } else { registry.Set_Int (VALUE_NAME_SHADOW_MODE, 0); } } // If a low end system turn surface effects off if (caps.Support_TnL()) { registry.Set_Int (VALUE_NAME_SURFACE_EFFECT, 2); } else { // Set to medium if high end cpu detected. // TODO: Set to medium if Athlon detected. if (high_end_processor) { registry.Set_Int (VALUE_NAME_SURFACE_EFFECT, 1); } else { registry.Set_Int (VALUE_NAME_SURFACE_EFFECT, 0); } } // If HWTL and high end cpu, use highest particle detail if (caps.Support_TnL() && high_end_processor) { registry.Set_Int (VALUE_NAME_PARTICLE_DETAIL, 2); } // If one or the other, use medium particle detail else if (caps.Support_TnL() || high_end_processor) { registry.Set_Int (VALUE_NAME_PARTICLE_DETAIL, 1); } else { registry.Set_Int (VALUE_NAME_PARTICLE_DETAIL, 0); } // If the system has less than 100 Megs (64 or 96 most likely) of RAM, select vertex solve to // save memory. // If card can't do multi pass (which is the case if we've seen z-fighting problems when multi-passing) // select vertex solve. if (!caps.Can_Do_Multi_Pass() || CPUDetectClass::Get_Total_Physical_Memory()<100*1024*1024) { registry.Set_Int (VALUE_NAME_PRELIT_MODE, 0); } // Otherwise select multitexturing if card can do it, or multipass... else { if (caps.Get_Max_Textures_Per_Pass()>=2) { registry.Set_Int (VALUE_NAME_PRELIT_MODE, 2); } else { registry.Set_Int (VALUE_NAME_PRELIT_MODE, 1); } } RegistryClass registry_options (KEY_NAME_OPTIONS); if (!registry_options.Is_Valid()) return; // The uv bias setting for most of the cards // (PowerVR Kyro and Kyro II and ATI Rage Pro need different UV bias and the rest of the cards.) registry_options.Set_Int( "ScreenUVBias", 1 ); switch (caps.Get_Vendor()) { default: registry.Set_Int(VALUE_NAME_TEXTURE_FILTER,0); // Most cards default to bilinear filtering break; case DX8Caps::VENDOR_NVIDIA: switch (caps.Get_Device()) { case DX8Caps::DEVICE_NVIDIA_TNT2_ALADDIN: case DX8Caps::DEVICE_NVIDIA_TNT2: case DX8Caps::DEVICE_NVIDIA_TNT2_ULTRA: case DX8Caps::DEVICE_NVIDIA_TNT2_VANTA: case DX8Caps::DEVICE_NVIDIA_TNT2_M64: case DX8Caps::DEVICE_NVIDIA_TNT: case DX8Caps::DEVICE_NVIDIA_RIVA_128: case DX8Caps::DEVICE_NVIDIA_TNT_VANTA: case DX8Caps::DEVICE_NVIDIA_NV1: registry.Set_Int(VALUE_NAME_TEXTURE_FILTER,0); break; default: registry.Set_Int(VALUE_NAME_TEXTURE_FILTER,1); // New NVidia cards default to trilinear } break; case DX8Caps::VENDOR_ATI: switch (caps.Get_Device()) { case DX8Caps::DEVICE_ATI_RAGE_II: case DX8Caps::DEVICE_ATI_RAGE_II_PLUS: case DX8Caps::DEVICE_ATI_RAGE_IIC_PCI: case DX8Caps::DEVICE_ATI_RAGE_IIC_AGP: case DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY: case DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY_M3: case DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY_M4: case DX8Caps::DEVICE_ATI_RAGE_128_PRO_ULTRA: case DX8Caps::DEVICE_ATI_RAGE_128_4X: case DX8Caps::DEVICE_ATI_RAGE_128_PRO_GL: case DX8Caps::DEVICE_ATI_RAGE_128_PRO_VR: case DX8Caps::DEVICE_ATI_RAGE_128_GL: case DX8Caps::DEVICE_ATI_RAGE_128_VR: case DX8Caps::DEVICE_ATI_RAGE_PRO: case DX8Caps::DEVICE_ATI_RAGE_PRO_MOBILITY: registry.Set_Int(VALUE_NAME_TEXTURE_FILTER,0); // It seems the bias needs to be adjusted on Rage128 as well... if (caps.Get_Device()==DX8Caps::DEVICE_ATI_RAGE_PRO || caps.Get_Device()==DX8Caps::DEVICE_ATI_RAGE_PRO_MOBILITY || caps.Get_Device()==DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY || caps.Get_Device()==DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY_M3 || caps.Get_Device()==DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY_M4 || caps.Get_Device()==DX8Caps::DEVICE_ATI_RAGE_128_PRO_ULTRA) { registry_options.Set_Int( "ScreenUVBias", 0 ); } break; default: registry.Set_Int(VALUE_NAME_TEXTURE_FILTER,1); // New ATI cards default to trilinear break; } break; case DX8Caps::VENDOR_POWERVR: // not sure how this goes. Kyro at the office requires 1, but some other powervr // card seems to require 0... registry_options.Set_Int( "ScreenUVBias", 0 ); switch (caps.Get_Device()) { case DX8Caps::DEVICE_POWERVR_KYRO: registry_options.Set_Int( "ScreenUVBias", 1 ); break; } break; } d3d->Release(); } ///////////////////////////////////////////////////////////////////////////// // // OnShowWindow // // Modified: 12/06/2001 by MML - Retrieving strings from Locomoto file. // ///////////////////////////////////////////////////////////////////////////// void PerformanceConfigDialogClass::OnShowWindow(BOOL bShow, UINT nStatus) { char string[ _MAX_PATH ]; CDialog::OnShowWindow(bShow, nStatus); if (bShow) { // // Insert code here // RegistryClass registry (KEY_NAME_SETTINGS); if (!registry.Is_Valid ()) return; VideoConfigDialogClass* video=VideoConfigDialogClass::Get_Instance(); if (video) { IDirect3D8* d3d=DX8Wrapper::_Get_D3D8(); d3d->AddRef(); D3DADAPTER_IDENTIFIER8 adapter_id=video->Get_Current_Adapter_Identifier(); D3DFORMAT display_format; if (video->Get_Current_Bit_Depth()==32) { display_format=D3DFMT_X8R8G8B8; } else { display_format=D3DFMT_R5G6B5; } DX8Caps caps(d3d,video->Get_Current_Caps(),D3DFormat_To_WW3DFormat(display_format),adapter_id); CanDoMultiPass=caps.Can_Do_Multi_Pass(); // // Populate the lighting combobox // // Get the current selection char cur_sel_string[256]; unsigned sel=SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_GETCURSEL, 0, 0); if (sel!=CB_ERR) { SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_GETLBTEXT, sel, (LPARAM)cur_sel_string); } else { cur_sel_string[0]=0; sel=registry.Get_Int (VALUE_NAME_PRELIT_MODE, WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE); } // Reset content and add available modes SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_RESETCONTENT, 0, 0); SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)Locale_GetString( IDS_VERTEX, string )); if (caps.Can_Do_Multi_Pass()) { SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)Locale_GetString( IDS_MULTI_PASS, string )); } if (caps.Get_Max_Textures_Per_Pass()>1) { SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)Locale_GetString( IDS_MULTI_TEXTURE, string )); } // Try to set the previous selection unsigned res=SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_FINDSTRINGEXACT, -1, (LPARAM)cur_sel_string); if (res==CB_ERR) { if (sel==0) res=0; else { res=SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_GETCOUNT, 0, 0)-1; if (selRelease(); Determine_Performance_Setting (); } } return ; }