diff --git a/portprotonqt/dialogs.py b/portprotonqt/dialogs.py index 42a0fd5..84e8365 100644 --- a/portprotonqt/dialogs.py +++ b/portprotonqt/dialogs.py @@ -18,6 +18,7 @@ from portprotonqt.custom_widgets import AutoSizeButton from portprotonqt.downloader import Downloader from portprotonqt.virtual_keyboard import VirtualKeyboard from portprotonqt.preloader import Preloader +from portprotonqt.settings_manager import get_toggle_settings, get_advanced_settings, ADVANCED_SETTING_KEYS import psutil if TYPE_CHECKING: @@ -1712,7 +1713,9 @@ class ExeSettingsDialog(QDialog): self.resize(1100, 720) self.setStyleSheet(self.theme.MAIN_WINDOW_STYLE + self.theme.MESSAGE_BOX_STYLE) - self.init_toggle_settings() + # Load toggle settings from config module + self.toggle_settings = get_toggle_settings() + self.setup_ui() # Find input_manager and main_window @@ -1737,50 +1740,6 @@ class ExeSettingsDialog(QDialog): else: return self.start_sh + subcommand_args - def init_toggle_settings(self): - """Initialize predefined toggle settings with descriptions.""" - self.toggle_settings = { - 'PW_MANGOHUD': _("Using FPS and system load monitoring (Turns on and off by the key combination - right Shift + F12)"), - 'PW_MANGOHUD_USER_CONF': _("Forced use of MANGOHUD system settings (GOverlay, etc.)"), - 'PW_VKBASALT': _("Enable vkBasalt by default to improve graphics in games running on Vulkan. (The HOME hotkey disables vkbasalt)"), - 'PW_VKBASALT_USER_CONF': _("Forced use of VKBASALT system settings (GOverlay, etc.)"), - 'PW_DGVOODOO2': _("Enable dgVoodoo2. Forced use all dgVoodoo2 libs (Glide 2.11-3.1, DirectDraw 1-7, Direct3D 2-9) on all 3D API."), - 'PW_GAMESCOPE': _("Super + F : Toggle fullscreen\nSuper + N : Toggle nearest neighbour filtering\nSuper + U : Toggle FSR upscaling\nSuper + Y : Toggle NIS upscaling\nSuper + I : Increase FSR sharpness by 1\nSuper + O : Decrease FSR sharpness by 1\nSuper + S : Take screenshot (currently goes to /tmp/gamescope_DATE.png)\nSuper + G : Toggle keyboard grab\nSuper + C : Update clipboard"), - 'PW_USE_ESYNC': _("Enable in-process synchronization primitives based on eventfd."), - 'PW_USE_FSYNC': _("Enable futex-based in-process synchronization primitives."), - 'PW_USE_NTSYNC': _("Enable in-process synchronization via the Linux ntsync driver."), - 'PW_USE_RAY_TRACING': _("Enable vkd3d support - Ray Tracing"), - 'PW_USE_NVAPI_AND_DLSS': _("Enable DLSS on supported NVIDIA graphics cards"), - 'PW_USE_OPTISCALER': _("Enable OptiScaler (replacement upscaler / frame generator)"), - 'PW_USE_LS_FRAME_GEN': _("Enable Lossless Scaling frame generation (experimental)"), - 'PW_WINE_FULLSCREEN_FSR': _("FSR upscaling in fullscreen with ProtonGE below native resolution"), - 'PW_HIDE_NVIDIA_GPU': _("Disguise all NVIDIA GPU features"), - 'PW_VIRTUAL_DESKTOP': _("Run the application in WINE virtual desktop"), - 'PW_USE_TERMINAL': _("Run the application in a terminal"), - 'PW_GUI_DISABLED_CS': _("Disable startup mode and WINE version selector window"), - 'PW_USE_GAMEMODE': _("Use system GameMode for performance optimization"), - 'PW_USE_D3D_EXTRAS': _("Enable forced use of third-party DirectX libraries"), - 'PW_FIX_VIDEO_IN_GAME': _("Fix pink-tinted video playback in some games"), - 'PW_REDUCE_PULSE_LATENCY': _("Reduce PulseAudio latency to fix intermittent sound"), - 'PW_USE_US_LAYOUT': _("Force US keyboard layout"), - 'PW_USE_GSTREAMER': _("Use GStreamer for in-game clips (WMF support)"), - 'PW_USE_SHADER_CACHE': _("Use WINE shader caching"), - 'PW_USE_WINE_DXGI': _("Force use of built-in DXGI library"), - 'PW_USE_EAC_AND_BE': _("Enable Easy Anti-Cheat and BattlEye runtimes"), - 'PW_USE_SYSTEM_VK_LAYERS': _("Use system Vulkan layers (MangoHud, vkBasalt, OBS, etc.)"), - 'PW_USE_OBS_VKCAPTURE': _("Enable OBS Studio capture via obs-vkcapture"), - 'PW_DISABLE_COMPOSITING': _("Disable desktop compositing for performance"), - 'PW_USE_RUNTIME': _("Use container launch mode (recommended default)"), - 'PW_DINPUT_PROTOCOL': _("Force DirectInput protocol instead of XInput"), - 'PW_USE_NATIVE_WAYLAND': _("Enable experimental native Wayland support"), - 'PW_USE_DXVK_HDR': _("Enable HDR settings under native Wayland"), - 'PW_USE_GALLIUM_ZINK': _("Use Gallium Zink (OpenGL via Vulkan)"), - 'PW_USE_GALLIUM_NINE': _("Use Gallium Nine (native DirectX 9 for Mesa)"), - 'PW_USE_WINED3D_VULKAN': _("Use WineD3D Vulkan backend (Damavand)"), - 'PW_USE_SUPPLIED_DXVK_VKD3D': _("Use bundled dxvk/vkd3d from Wine/Proton"), - 'PW_USE_SAREK_ASYNC': _("Use async dxvk-sarek (experimental)") - } - def setup_ui(self): """Set up the user interface.""" self.main_layout = QVBoxLayout(self) @@ -1798,7 +1757,7 @@ class ExeSettingsDialog(QDialog): self.tab_widget.addTab(self.main_tab, _("Main")) self.tab_widget.addTab(self.advanced_tab, _("Advanced")) - # Таблица настроек + # Main settings table self.settings_table = QTableWidget() self.settings_table.setAlternatingRowColors(True) self.settings_table.setFocusPolicy(Qt.FocusPolicy.StrongFocus) @@ -1817,7 +1776,7 @@ class ExeSettingsDialog(QDialog): self.settings_table.setStyleSheet(self.theme.WINETRICKS_TABBLE_STYLE) self.main_tab_layout.addWidget(self.settings_table) - # Таблица Advanced + # Advanced settings table self.advanced_table = QTableWidget() self.advanced_table.setAlternatingRowColors(True) self.advanced_table.setFocusPolicy(Qt.FocusPolicy.StrongFocus) @@ -1838,7 +1797,7 @@ class ExeSettingsDialog(QDialog): self.main_layout.addWidget(self.tab_widget) - # Кнопки + # Buttons button_layout = QHBoxLayout() self.apply_button = AutoSizeButton(_("Apply"), icon=ThemeManager().get_icon("apply")) self.cancel_button = AutoSizeButton(_("Cancel"), icon=ThemeManager().get_icon("cancel")) @@ -1851,14 +1810,12 @@ class ExeSettingsDialog(QDialog): self.apply_button.clicked.connect(self.apply_changes) self.cancel_button.clicked.connect(self.reject) - def load_current_settings(self): """Load available toggles first, then current settings.""" process = QProcess(self) process.finished.connect(self.on_list_db_finished) process.start(self.start_sh[0], ["cli", "--list-db"]) - def on_list_db_finished(self, exit_code, exit_status): """Handle --list-db output and extract available keys and system info.""" process = cast(QProcess, self.sender()) @@ -1898,10 +1855,10 @@ class ExeSettingsDialog(QDialog): if len(parts) > 1 and 'blocked' in parts[1]: self.blocked_keys.add(key) - # Показываем только пересечение + # Show only intersection self.available_keys &= set(self.toggle_settings.keys()) - # Загружаем текущие настройки + # Load current settings process = QProcess(self) process.finished.connect(self.on_show_ppdb_finished) process.start(self.start_sh[0], ["cli", "--show-ppdb", f"{self.exe_path}.ppdb"]) @@ -1913,11 +1870,7 @@ class ExeSettingsDialog(QDialog): # Fallback to defaults if load fails for key in self.toggle_settings: self.current_settings[key] = '0' - for adv_key in ['PW_WINDOWS_VER', 'WINEDLLOVERRIDES', 'LAUNCH_PARAMETERS', - 'PW_WINE_CPU_TOPOLOGY', 'PW_MESA_GL_VERSION_OVERRIDE', - 'PW_VKD3D_FEATURE_LEVEL', 'PW_LOCALE_SELECT', - 'PW_MESA_VK_WSI_PRESENT_MODE', 'PW_AMD_VULKAN_USE', - 'PW_CPU_NUMA_NODE_INDEX']: + for adv_key in ADVANCED_SETTING_KEYS: self.current_settings[adv_key] = 'disabled' if 'TOPOLOGY' in adv_key or 'SELECT' in adv_key or 'MODE' in adv_key or 'LEVEL' in adv_key or 'GL_VERSION' in adv_key or 'NUMA' in adv_key else '' else: output = bytes(process.readAllStandardOutput().data()).decode('utf-8', 'ignore').strip() @@ -1925,14 +1878,9 @@ class ExeSettingsDialog(QDialog): for line in output.split('\n'): line_stripped = line.strip() if '=' in line_stripped: - # Parse all KEY=VALUE lines, not just specific prefixes, to catch more try: key, val = line_stripped.split('=', 1) - if key in self.toggle_settings or key in ['PW_WINDOWS_VER', 'WINEDLLOVERRIDES', 'LAUNCH_PARAMETERS', - 'PW_WINE_CPU_TOPOLOGY', 'PW_MESA_GL_VERSION_OVERRIDE', - 'PW_VKD3D_FEATURE_LEVEL', 'PW_LOCALE_SELECT', - 'PW_MESA_VK_WSI_PRESENT_MODE', 'PW_AMD_VULKAN_USE', - 'PW_CPU_NUMA_NODE_INDEX', 'PW_TASKSET_SLR']: + if key in self.toggle_settings or key in ADVANCED_SETTING_KEYS: self.current_settings[key] = val except ValueError: continue @@ -2006,109 +1954,15 @@ class ExeSettingsDialog(QDialog): current = self.current_settings disabled_text = _('disabled') - # Define advanced settings configuration - advanced_settings = [] - - # 1. Windows version - advanced_settings.append({ - 'key': 'PW_WINDOWS_VER', - 'name': _("Windows version"), - 'description': _("Changing the WINDOWS emulation version may be required to run older games. WINDOWS versions below 10 do not support new games with DirectX 12"), - 'type': 'combo', - 'options': ['11', '10', '7', 'XP'], - 'default': '10' - }) - - # 2. Forced to use/disable libraries - advanced_settings.append({ - 'key': 'WINEDLLOVERRIDES', - 'name': _("DLL Overrides"), - 'description': _("Forced to use/disable the library only for the given application.\n\nA brief instruction:\n* libraries are written WITHOUT the .dll file extension\n* libraries are separated by semicolons - ;\n* library=n - use the WINDOWS (third-party) library\n* library=b - use WINE (built-in) library\n* library=n,b - use WINDOWS library and then WINE\n* library=b,n - use WINE library and then WINDOWS\n* library= - disable the use of this library\n\nExample: libglesv2=;d3dx9_36,d3dx9_42=n,b;mfc120=b,n"), - 'type': 'text', - 'default': '' - }) - - # 3. Launch arguments - advanced_settings.append({ - 'key': 'LAUNCH_PARAMETERS', - 'name': _("Launch Arguments"), - 'description': _("Adding an argument after the .exe file, just like you would add an argument in a shortcut on a WINDOWS system.\n\nExample: -dx11 -skipintro 1"), - 'type': 'text', - 'default': '' - }) - - # 4. CPU cores limit - advanced_settings.append({ - 'key': 'PW_WINE_CPU_TOPOLOGY', - 'name': _("CPU Cores Limit"), - 'description': _("Limiting the number of CPU cores is useful for Unity games (It is recommended to set the value equal to 8)"), - 'type': 'combo', - 'options': [disabled_text] + self.logical_core_options, - 'default': disabled_text - }) - - # 5. OpenGL version - advanced_settings.append({ - 'key': 'PW_MESA_GL_VERSION_OVERRIDE', - 'name': _("OpenGL Version"), - 'description': _("You can select the required OpenGL version, some games require a forced Compatibility Profile (COMP)."), - 'type': 'combo', - 'options': [disabled_text, '4.6COMPAT', '4.5COMPAT', '4.3COMPAT', '4.1COMPAT', '3.3COMPAT', '3.2COMPAT'], - 'default': disabled_text - }) - - # 6. VKD3D feature level - advanced_settings.append({ - 'key': 'PW_VKD3D_FEATURE_LEVEL', - 'name': _("VKD3D Feature Level"), - 'description': _("You can set a forced feature level VKD3D for games on DirectX12"), - 'type': 'combo', - 'options': [disabled_text, '12_2', '12_1', '12_0', '11_1', '11_0'], - 'default': disabled_text - }) - - # 7. Locale - advanced_settings.append({ - 'key': 'PW_LOCALE_SELECT', - 'name': _("Locale"), - 'description': _("Force certain locale for an app. Fixes encoding issues in legacy software"), - 'type': 'combo', - 'options': [disabled_text] + self.locale_options, - 'default': disabled_text - }) - - # 8. Present mode - advanced_settings.append({ - 'key': 'PW_MESA_VK_WSI_PRESENT_MODE', - 'name': _("Window Mode"), - 'description': _("Window mode (for Vulkan and OpenGL):\nfifo - First in, first out. Limits the frame rate + no tearing. (VSync)\nimmediate - Unlimited frame rate + tearing.\nmailbox - Triple buffering. Unlimited frame rate + no tearing.\nrelaxed - Same as fifo but allows tearing when below the monitors refresh rate."), - 'type': 'combo', - 'options': [disabled_text, 'fifo', 'immediate', 'mailbox', 'relaxed'], - 'default': disabled_text - }) - - # 9. AMD Vulkan (always show, block if not applicable) - amd_options = [disabled_text] + self.amd_vulkan_drivers if self.is_amd and self.amd_vulkan_drivers else [disabled_text] - advanced_settings.append({ - 'key': 'PW_AMD_VULKAN_USE', - 'name': _("AMD Vulkan Driver"), - 'description': _("Select needed AMD vulkan implementation. Choosing which implementation of vulkan will be used to run the game"), - 'type': 'combo', - 'options': amd_options, - 'default': disabled_text - }) - - # 10. NUMA node (always show if numa_nodes exist, block if <=1) - numa_ids = sorted(self.numa_nodes.keys()) - numa_options = [disabled_text] + numa_ids if len(numa_ids) > 1 else [disabled_text] - advanced_settings.append({ - 'key': 'PW_CPU_NUMA_NODE_INDEX', - 'name': _("NUMA Node"), - 'description': _("NUMA node for CPU affinity. In multi-core systems, CPUs are split into NUMA nodes, each with its own local memory and cores. Binding a game to a single node reduces memory-access latency and limits costly core-to-core switches."), - 'type': 'combo', - 'options': numa_options, - 'default': disabled_text - }) + # Get advanced settings from config module + advanced_settings = get_advanced_settings( + disabled_text=disabled_text, + logical_core_options=self.logical_core_options, + locale_options=self.locale_options, + amd_vulkan_drivers=self.amd_vulkan_drivers, + is_amd=self.is_amd, + numa_nodes=self.numa_nodes + ) # Populate table for setting in advanced_settings: @@ -2161,23 +2015,22 @@ class ExeSettingsDialog(QDialog): desc_item.setToolTip(setting['description']) desc_item.setTextAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter) self.advanced_table.setItem(row, 2, desc_item) - - # Make sure QLineEdit and QComboBox look consistent - # self.advanced_table.setStyleSheet(""" - # QComboBox, QLineEdit { - # padding: 3px 6px; - # min-height: 26px; - # } - # QComboBox::drop-down { - # subcontrol-origin: padding; - # subcontrol-position: top right; - # width: 18px; - # } - # QTextEdit { - # border-radius: 4px; - # padding: 4px; - # } - # """) + # Style for consistency + self.advanced_table.setStyleSheet(""" + QComboBox, QLineEdit { + padding: 3px 6px; + min-height: 26px; + } + QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 18px; + } + QTextEdit { + border-radius: 4px; + padding: 4px; + } + """) def apply_changes(self): """Apply changes by collecting diffs from both main and advanced tabs.""" diff --git a/portprotonqt/settings_manager.py b/portprotonqt/settings_manager.py new file mode 100644 index 0000000..e219730 --- /dev/null +++ b/portprotonqt/settings_manager.py @@ -0,0 +1,174 @@ +"""Configuration module for exe settings dialog.""" + +def get_toggle_settings(): + """Get predefined toggle settings with descriptions.""" + from portprotonqt.localization import _ + + return { + 'PW_MANGOHUD': _("Using FPS and system load monitoring (Turns on and off by the key combination - right Shift + F12)"), + 'PW_MANGOHUD_USER_CONF': _("Forced use of MANGOHUD system settings (GOverlay, etc.)"), + 'PW_VKBASALT': _("Enable vkBasalt by default to improve graphics in games running on Vulkan. (The HOME hotkey disables vkbasalt)"), + 'PW_VKBASALT_USER_CONF': _("Forced use of VKBASALT system settings (GOverlay, etc.)"), + 'PW_DGVOODOO2': _("Enable dgVoodoo2. Forced use all dgVoodoo2 libs (Glide 2.11-3.1, DirectDraw 1-7, Direct3D 2-9) on all 3D API."), + 'PW_GAMESCOPE': _("Super + F : Toggle fullscreen\nSuper + N : Toggle nearest neighbour filtering\nSuper + U : Toggle FSR upscaling\nSuper + Y : Toggle NIS upscaling\nSuper + I : Increase FSR sharpness by 1\nSuper + O : Decrease FSR sharpness by 1\nSuper + S : Take screenshot (currently goes to /tmp/gamescope_DATE.png)\nSuper + G : Toggle keyboard grab\nSuper + C : Update clipboard"), + 'PW_USE_ESYNC': _("Enable in-process synchronization primitives based on eventfd."), + 'PW_USE_FSYNC': _("Enable futex-based in-process synchronization primitives."), + 'PW_USE_NTSYNC': _("Enable in-process synchronization via the Linux ntsync driver."), + 'PW_USE_RAY_TRACING': _("Enable vkd3d support - Ray Tracing"), + 'PW_USE_NVAPI_AND_DLSS': _("Enable DLSS on supported NVIDIA graphics cards"), + 'PW_USE_OPTISCALER': _("Enable OptiScaler (replacement upscaler / frame generator)"), + 'PW_USE_LS_FRAME_GEN': _("Enable Lossless Scaling frame generation (experimental)"), + 'PW_WINE_FULLSCREEN_FSR': _("FSR upscaling in fullscreen with ProtonGE below native resolution"), + 'PW_HIDE_NVIDIA_GPU': _("Disguise all NVIDIA GPU features"), + 'PW_VIRTUAL_DESKTOP': _("Run the application in WINE virtual desktop"), + 'PW_USE_TERMINAL': _("Run the application in a terminal"), + 'PW_GUI_DISABLED_CS': _("Disable startup mode and WINE version selector window"), + 'PW_USE_GAMEMODE': _("Use system GameMode for performance optimization"), + 'PW_USE_D3D_EXTRAS': _("Enable forced use of third-party DirectX libraries"), + 'PW_FIX_VIDEO_IN_GAME': _("Fix pink-tinted video playback in some games"), + 'PW_REDUCE_PULSE_LATENCY': _("Reduce PulseAudio latency to fix intermittent sound"), + 'PW_USE_US_LAYOUT': _("Force US keyboard layout"), + 'PW_USE_GSTREAMER': _("Use GStreamer for in-game clips (WMF support)"), + 'PW_USE_SHADER_CACHE': _("Use WINE shader caching"), + 'PW_USE_WINE_DXGI': _("Force use of built-in DXGI library"), + 'PW_USE_EAC_AND_BE': _("Enable Easy Anti-Cheat and BattlEye runtimes"), + 'PW_USE_SYSTEM_VK_LAYERS': _("Use system Vulkan layers (MangoHud, vkBasalt, OBS, etc.)"), + 'PW_USE_OBS_VKCAPTURE': _("Enable OBS Studio capture via obs-vkcapture"), + 'PW_DISABLE_COMPOSITING': _("Disable desktop compositing for performance"), + 'PW_USE_RUNTIME': _("Use container launch mode (recommended default)"), + 'PW_DINPUT_PROTOCOL': _("Force DirectInput protocol instead of XInput"), + 'PW_USE_NATIVE_WAYLAND': _("Enable experimental native Wayland support"), + 'PW_USE_DXVK_HDR': _("Enable HDR settings under native Wayland"), + 'PW_USE_GALLIUM_ZINK': _("Use Gallium Zink (OpenGL via Vulkan)"), + 'PW_USE_GALLIUM_NINE': _("Use Gallium Nine (native DirectX 9 for Mesa)"), + 'PW_USE_WINED3D_VULKAN': _("Use WineD3D Vulkan backend (Damavand)"), + 'PW_USE_SUPPLIED_DXVK_VKD3D': _("Use bundled dxvk/vkd3d from Wine/Proton"), + 'PW_USE_SAREK_ASYNC': _("Use async dxvk-sarek (experimental)") + } + + +def get_advanced_settings(disabled_text, logical_core_options, locale_options, + amd_vulkan_drivers, is_amd, numa_nodes): + """Get advanced settings configuration.""" + from portprotonqt.localization import _ + + + advanced_settings = [] + + # 1. Windows version + advanced_settings.append({ + 'key': 'PW_WINDOWS_VER', + 'name': _("Windows version"), + 'description': _("Changing the WINDOWS emulation version may be required to run older games. WINDOWS versions below 10 do not support new games with DirectX 12"), + 'type': 'combo', + 'options': ['11', '10', '7', 'XP'], + 'default': '10' + }) + + # 2. DLL Overrides + advanced_settings.append({ + 'key': 'WINEDLLOVERRIDES', + 'name': _("DLL Overrides"), + 'description': _("Forced to use/disable the library only for the given application.\n\nA brief instruction:\n* libraries are written WITHOUT the .dll file extension\n* libraries are separated by semicolons - ;\n* library=n - use the WINDOWS (third-party) library\n* library=b - use WINE (built-in) library\n* library=n,b - use WINDOWS library and then WINE\n* library=b,n - use WINE library and then WINDOWS\n* library= - disable the use of this library\n\nExample: libglesv2=;d3dx9_36,d3dx9_42=n,b;mfc120=b,n"), + 'type': 'text', + 'default': '' + }) + + # 3. Launch arguments + advanced_settings.append({ + 'key': 'LAUNCH_PARAMETERS', + 'name': _("Launch Arguments"), + 'description': _("Adding an argument after the .exe file, just like you would add an argument in a shortcut on a WINDOWS system.\n\nExample: -dx11 -skipintro 1"), + 'type': 'text', + 'default': '' + }) + + # 4. CPU cores limit + advanced_settings.append({ + 'key': 'PW_WINE_CPU_TOPOLOGY', + 'name': _("CPU Cores Limit"), + 'description': _("Limiting the number of CPU cores is useful for Unity games (It is recommended to set the value equal to 8)"), + 'type': 'combo', + 'options': [disabled_text] + logical_core_options, + 'default': disabled_text + }) + + # 5. OpenGL version + advanced_settings.append({ + 'key': 'PW_MESA_GL_VERSION_OVERRIDE', + 'name': _("OpenGL Version"), + 'description': _("You can select the required OpenGL version, some games require a forced Compatibility Profile (COMP)."), + 'type': 'combo', + 'options': [disabled_text, '4.6COMPAT', '4.5COMPAT', '4.3COMPAT', '4.1COMPAT', '3.3COMPAT', '3.2COMPAT'], + 'default': disabled_text + }) + + # 6. VKD3D feature level + advanced_settings.append({ + 'key': 'PW_VKD3D_FEATURE_LEVEL', + 'name': _("VKD3D Feature Level"), + 'description': _("You can set a forced feature level VKD3D for games on DirectX12"), + 'type': 'combo', + 'options': [disabled_text, '12_2', '12_1', '12_0', '11_1', '11_0'], + 'default': disabled_text + }) + + # 7. Locale + advanced_settings.append({ + 'key': 'PW_LOCALE_SELECT', + 'name': _("Locale"), + 'description': _("Force certain locale for an app. Fixes encoding issues in legacy software"), + 'type': 'combo', + 'options': [disabled_text] + locale_options, + 'default': disabled_text + }) + + # 8. Present mode + advanced_settings.append({ + 'key': 'PW_MESA_VK_WSI_PRESENT_MODE', + 'name': _("Window Mode"), + 'description': _("Window mode (for Vulkan and OpenGL):\nfifo - First in, first out. Limits the frame rate + no tearing. (VSync)\nimmediate - Unlimited frame rate + tearing.\nmailbox - Triple buffering. Unlimited frame rate + no tearing.\nrelaxed - Same as fifo but allows tearing when below the monitors refresh rate."), + 'type': 'combo', + 'options': [disabled_text, 'fifo', 'immediate', 'mailbox', 'relaxed'], + 'default': disabled_text + }) + + # 9. AMD Vulkan driver + amd_options = [disabled_text] + amd_vulkan_drivers if is_amd and amd_vulkan_drivers else [disabled_text] + advanced_settings.append({ + 'key': 'PW_AMD_VULKAN_USE', + 'name': _("AMD Vulkan Driver"), + 'description': _("Select needed AMD vulkan implementation. Choosing which implementation of vulkan will be used to run the game"), + 'type': 'combo', + 'options': amd_options, + 'default': disabled_text + }) + + # 10. NUMA node + numa_ids = sorted(numa_nodes.keys()) + numa_options = [disabled_text] + numa_ids if len(numa_ids) > 1 else [disabled_text] + advanced_settings.append({ + 'key': 'PW_CPU_NUMA_NODE_INDEX', + 'name': _("NUMA Node"), + 'description': _("NUMA node for CPU affinity. In multi-core systems, CPUs are split into NUMA nodes, each with its own local memory and cores. Binding a game to a single node reduces memory-access latency and limits costly core-to-core switches."), + 'type': 'combo', + 'options': numa_options, + 'default': disabled_text + }) + + return advanced_settings + + +# Keys that should be recognized as advanced settings +ADVANCED_SETTING_KEYS = [ + 'PW_WINDOWS_VER', + 'WINEDLLOVERRIDES', + 'LAUNCH_PARAMETERS', + 'PW_WINE_CPU_TOPOLOGY', + 'PW_MESA_GL_VERSION_OVERRIDE', + 'PW_VKD3D_FEATURE_LEVEL', + 'PW_LOCALE_SELECT', + 'PW_MESA_VK_WSI_PRESENT_MODE', + 'PW_AMD_VULKAN_USE', + 'PW_CPU_NUMA_NODE_INDEX', +]