private static void BuildWeirdSettingsSection(DiscordEmbedBuilder builder, NameValueCollection items) { var notes = new List <string>(); var serial = items["serial"] ?? ""; if (!string.IsNullOrWhiteSpace(items["log_disabled_channels"]) || !string.IsNullOrWhiteSpace(items["log_disabled_channels_multiline"])) { notes.Add("❗ Some logging priorities were modified, please reset and upload a new log"); } var hasTsx = items["cpu_extensions"]?.Contains("TSX") ?? false; var hasTsxFa = items["cpu_extensions"]?.Contains("TSX-FA") ?? false; items["has_tsx"] = hasTsx ? EnabledMark : DisabledMark; items["has_tsx_fa"] = hasTsxFa ? EnabledMark : DisabledMark; if (items["enable_tsx"] == "Disabled" && hasTsx && !hasTsxFa) { notes.Add("⚠ TSX support is disabled; performance may suffer"); } else if (items["enable_tsx"] == "Enabled" && hasTsxFa) { notes.Add("⚠ Disable TSX support if you experience performance issues"); } if (items["spu_lower_thread_priority"] == EnabledMark && int.TryParse(items["thread_count"], out var threadCount) && threadCount > 4) { notes.Add("❔ `Lower SPU thread priority` is enabled on a CPU with enough threads"); } if (items["llvm_arch"] is string llvmArch) { notes.Add($"❔ LLVM target CPU architecture override is set to `{llvmArch.Sanitize(replaceBackTicks: true)}`"); } if (items["renderer"] == "D3D12") { notes.Add("💢 Do **not** use DX12 renderer"); } if (!string.IsNullOrEmpty(items["resolution"]) && items["resolution"] != "1280x720") { if (items["resolution"] != "1920x1080" || !Known1080pIds.Contains(serial)) { notes.Add("⚠ `Resolution` was changed from the recommended `1280x720`"); } var dimensions = items["resolution"].Split("x"); if (dimensions.Length > 1 && int.TryParse(dimensions[1], out var height) && height < 720) { notes.Add("⚠ `Resolution` below 720p will not improve performance"); } } if (items["stretch_to_display"] == EnabledMark) { notes.Add("🤮 `Stretch to Display Area` is enabled"); } if (KnownDisableVertexCacheIds.Contains(serial)) { if (items["vertex_cache"] == DisabledMark) { notes.Add("⚠ This game requires disabling `Vertex Cache` in the GPU tab of the Settings"); } } if (items["ppu_decoder"] is string ppuDecoder) { if (KnownGamesThatRequireInterpreter.Contains(serial)) { if (ppuDecoder.Contains("Recompiler", StringComparison.InvariantCultureIgnoreCase)) { notes.Add("⚠ This game requires `PPU Decoder` to use `Interpreter (fast)`"); } } else { if (ppuDecoder.Contains("Interpreter", StringComparison.InvariantCultureIgnoreCase)) { notes.Add("⚠ Please set `PPU Decoder` to use recompiler for better performance"); } } } if (items["spu_decoder"] is string spuDecoder && spuDecoder.Contains("Interpreter", StringComparison.InvariantCultureIgnoreCase)) { notes.Add("⚠ Please set `SPU Decoder` to use recompiler for better performance"); } if (items["approximate_xfloat"] is string approximateXfloat && approximateXfloat == DisabledMark) { if (KnownNoApproximateXFloatIds.Contains(serial)) { notes.Add("ℹ `Approximate xfloat` is disabled"); } else { notes.Add("⚠ `Approximate xfloat` is disabled, please enable"); } } var ppuPatches = GetPatches(items["ppu_hash"], items["ppu_hash_patch"]); if (!string.IsNullOrEmpty(serial)) { CheckP5Settings(serial, items, notes); CheckAsurasWrathSettings(serial, items, notes); CheckJojoSettings(serial, items, notes); CheckSimpsonsSettings(serial, notes); CheckNierSettings(serial, items, notes, ppuPatches); CheckScottPilgrimSettings(serial, items, notes); CheckGoWSettings(serial, items, notes); CheckDesSettings(serial, items, notes, ppuPatches); CheckTlouSettings(serial, items, notes); CheckMgs4Settings(serial, items, notes); } else if (items["game_title"] == "vsh.self") { CheckVshSettings(items, notes); } if (items["game_category"] == "1P") { CheckPs1ClassicsSettings(items, notes); } if (items["hook_static_functions"] is string hookStaticFunctions && hookStaticFunctions == EnabledMark) { notes.Add("⚠ `Hook Static Functions` is enabled, please disable"); } if (items["host_root"] is string hostRoot && hostRoot == EnabledMark) { notes.Add("❔ `/host_root/` is enabled"); } if (items["spurs_threads"] is string spursSetting && int.TryParse(spursSetting, out var spursThreads) && spursThreads != 6) { if (spursThreads > 6 || spursThreads < 1) { notes.Add($"⚠ `Max SPURS Threads` is set to `{spursThreads}`; please change it back to `6`"); } else { notes.Add($"ℹ `Max SPURS Threads` is set to `{spursThreads}`; may result in game crash"); } } if (items["gpu_texture_scaling"] is string gpuTextureScaling && gpuTextureScaling == EnabledMark) { notes.Add("⚠ `GPU Texture Scaling` is enabled, please disable"); } if (items["af_override"] is string af) { if (af == "Disabled") { notes.Add("❌ `Anisotropic Filter` is `Disabled`, please use `Auto` instead"); } else if (af.ToLowerInvariant() != "auto" && af != "16") { notes.Add($"❔ `Anisotropic Filter` is set to `{af}x`, which makes little sense over `16x` or `Auto`"); } } if (items["resolution_scale"] is string resScale && int.TryParse(resScale, out var resScaleFactor) && resScaleFactor < 100) { notes.Add($"❔ `Resolution Scale` is `{resScale}%`; this will not increase performance"); } if (items["async_shaders"] == EnabledMark) { notes.Add("❔ `Async Shader Compiler` is disabled"); } if (items["write_color_buffers"] == DisabledMark && !string.IsNullOrEmpty(serial) && KnownWriteColorBuffersIds.Contains(serial)) { if (DesIds.Contains(serial) && ppuPatches.Any()) { notes.Add("ℹ `Write Color Buffers` is disabled"); } else { notes.Add("⚠ `Write Color Buffers` is disabled, please enable"); } } if (items["vertex_cache"] == EnabledMark && !string.IsNullOrEmpty(serial) && !KnownDisableVertexCacheIds.Contains(serial)) { notes.Add("⚠ `Vertex Cache` is disabled, please re-enable"); } if (items["frame_skip"] == EnabledMark) { notes.Add("⚠ `Frame Skip` is enabled, please disable"); } if (items["cpu_blit"] is string cpuBlit && cpuBlit == EnabledMark && items["write_color_buffers"] is string wcb && wcb == DisabledMark) { notes.Add("❔ `Force CPU Blit` is enabled, but `Write Color Buffers` is disabled"); } if (items["zcull"] is string zcull && zcull == EnabledMark) { notes.Add("⚠ `ZCull Occlusion Queries` are disabled, can result in visual artifacts"); } if (items["driver_recovery_timeout"] is string driverRecoveryTimeout && int.TryParse(driverRecoveryTimeout, out var drtValue) && drtValue != 1000000) { if (drtValue == 0) { notes.Add("⚠ `Driver Recovery Timeout` is set to 0 (infinite), please use default value of 1000000"); } else if (drtValue < 10_000) { notes.Add($"⚠ `Driver Recovery Timeout` is set too low: {GetTimeFormat(drtValue)} (1 frame @ {(1_000_000.0 / drtValue):0.##} fps)"); } else if (drtValue > 10_000_000) { notes.Add($"⚠ `Driver Recovery Timeout` is set too high: {GetTimeFormat(drtValue)}"); } } if (!KnownFpsUnlockPatchIds.Contains(serial) || !ppuPatches.Any()) { if (items["vblank_rate"] is string vblank && int.TryParse(vblank, out var vblankRate) && vblankRate != 60) { notes.Add($"ℹ `VBlank Rate` is set to {vblankRate} Hz"); } if (items["clock_scale"] is string clockScaleStr && int.TryParse(clockScaleStr, out var clockScale) && clockScale != 100) { notes.Add($"ℹ `Clock Scale` is set to {clockScale}%"); } } if (items["mtrsx"] is string mtrsx && mtrsx == EnabledMark) { notes.Add("ℹ `Multithreaded RSX` is enabled"); } if (!string.IsNullOrEmpty(serial) && KnownMotionControlsIds.Contains(serial) && items["pad_handler"] is string padHandler && !padHandler.StartsWith("DualShock")) { notes.Add("❗ This game requires motion controls, please use DS3 or DS4 gamepad"); } if (items["audio_backend"] is string audioBackend && !string.IsNullOrEmpty(audioBackend)) { if (items["os_type"] == "Windows" && !audioBackend.Equals("XAudio2", StringComparison.InvariantCultureIgnoreCase)) { notes.Add("⚠ Please use `XAudio2` as the audio backend on Windows"); } else if (items["os_type"] == "Linux" && !audioBackend.Equals("OpenAL", StringComparison.InvariantCultureIgnoreCase)) { notes.Add("ℹ `OpenAL` is the recommended audio backend on Linux"); } if (audioBackend.Equals("null", StringComparison.InvariantCultureIgnoreCase)) { notes.Add("⚠ `Audio backend` is set to `null`"); } } if (int.TryParse(items["audio_volume"], out var audioVolume)) { if (audioVolume < 10) { notes.Add($"⚠ Audio volume is set to {audioVolume}%"); } else if (audioVolume > 100) { notes.Add($"⚠ Audio volume is set to {audioVolume}%; audio clipping is to be expected"); } } if (items["hle_lwmutex"] is string hleLwmutex && hleLwmutex == EnabledMark) { notes.Add("⚠ `HLE lwmutex` is enabled, might affect compatibility"); } if (items["spu_block_size"] is string spuBlockSize) { if (spuBlockSize == "Giga") { notes.Add($"⚠ Please change `SPU Block Size`, `{spuBlockSize}` is currently unstable."); } } if (items["lib_loader"] is string libLoader && (libLoader == "Auto" || (libLoader.Contains("manual", StringComparison.InvariantCultureIgnoreCase) && (string.IsNullOrEmpty(items["library_list"]) || items["library_list"] == "None")))) { if (items["game_title"] != "vsh.self") { notes.Add("⚠ Please use `Load liblv2.sprx only` as a `Library loader`"); } } if (notes.Any()) { items["weird_settings_notes"] = "true"; } var notesContent = new StringBuilder(); foreach (var line in SortLines(notes)) { notesContent.AppendLine(line); } PageSection(builder, notesContent.ToString().Trim(), "Important Settings to Review"); }
private static void BuildWeirdSettingsSection(DiscordEmbedBuilder builder, NameValueCollection items, List <string> generalNotes) { var notes = new List <string>(); var serial = items["serial"] ?? ""; if (!string.IsNullOrWhiteSpace(items["log_disabled_channels"]) || !string.IsNullOrWhiteSpace(items["log_disabled_channels_multiline"])) { notes.Add("❗ Some logging priorities were modified, please reset and upload a new log"); } var hasTsx = items["cpu_extensions"]?.Contains("TSX") ?? false; var hasTsxFa = items["cpu_extensions"]?.Contains("TSX-FA") ?? false; items["has_tsx"] = hasTsx ? EnabledMark : DisabledMark; items["has_tsx_fa"] = hasTsxFa ? EnabledMark : DisabledMark; if (items["enable_tsx"] == "Disabled" && hasTsx && !hasTsxFa) { notes.Add("⚠ TSX support is disabled; performance may suffer"); } else if (items["enable_tsx"] == "Enabled" && hasTsxFa) { notes.Add("⚠ Disable TSX support if you experience performance issues"); } if (items["spu_lower_thread_priority"] == EnabledMark && int.TryParse(items["thread_count"], out var threadCount) && threadCount > 4) { notes.Add("❔ `Lower SPU thread priority` is enabled on a CPU with enough threads"); } if (items["llvm_arch"] is string llvmArch) { notes.Add($"❔ LLVM target CPU architecture override is set to `{llvmArch.Sanitize(replaceBackTicks: true)}`"); } if (items["renderer"] == "D3D12") { notes.Add("💢 Do **not** use DX12 renderer"); } if (!string.IsNullOrEmpty(items["resolution"]) && items["resolution"] != "1280x720") { if (items["resolution"] != "1920x1080" || !Known1080pIds.Contains(serial)) { notes.Add("⚠ `Resolution` was changed from the recommended `1280x720`"); } var dimensions = items["resolution"].Split("x"); if (dimensions.Length > 1 && int.TryParse(dimensions[1], out var height) && height < 720) { notes.Add("⚠ `Resolution` below 720p will not improve performance"); } } if (items["stretch_to_display"] == EnabledMark) { notes.Add("🤢 `Stretch to Display Area` is enabled"); } if (KnownDisableVertexCacheIds.Contains(serial)) { if (items["vertex_cache"] == DisabledMark) { notes.Add("⚠ This game requires disabling `Vertex Cache` in the GPU tab of the Settings"); } } if (items["rsx_not_supported"] is string notSupported) { var rsxCaveats = notSupported.Split(Environment.NewLine).Distinct().ToArray(); if (rsxCaveats.Contains("alpha-to-one for multisampling")) { if (items["msaa"] is string msaa && msaa != "Disabled") { generalNotes.Add("⚠ This GPU doesn't support required features for proper MSAA implementation"); } } } if (items["msaa"] == DisabledMark) { notes.Add("⚠ `Anti-aliasing` is disabled, may result in visual artifacts"); } var vsync = items["vsync"] == EnabledMark; string vkPm; if (items["rsx_present_mode"] is string pm) { RsxPresentModeMap.TryGetValue(pm, out vkPm); } else { vkPm = null; } if (items["force_fifo_present"] == EnabledMark) { notes.Add("⚠ Double-buffered VSync is forced"); vsync = true; } if (items["rsx_swapchain_mode"] is string swapchainMode && swapchainMode == "2") { vsync = true; } if (vsync && items["frame_limit"] is string frameLimitStr) { if (frameLimitStr == "Auto") { notes.Add("ℹ Frame rate might be limited to 30 fps"); } else if (double.TryParse(frameLimitStr, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out var frameLimit)) { if (frameLimit > 30 && frameLimit < 60) { notes.Add("⚠ Frame rate might be limited to 30 fps"); } else if (frameLimit < 30) { notes.Add("⚠ Frame rate might be limited to 15 fps"); } else { notes.Add("ℹ Frame pacing might be affected due to VSync and Frame Limiter enabled at the same time"); } } } if (!vsync && vkPm != "VK_PRESENT_MODE_IMMEDIATE_KHR") { var pmDesc = vkPm switch { "VK_PRESENT_MODE_MAILBOX_KHR" => "Fast Sync", "VK_PRESENT_MODE_FIFO_KHR" => "Double-buffered VSync", "VK_PRESENT_MODE_FIFO_RELAXED_KHR" => "Adaptive VSync", _ => null, }; if (pmDesc != null) { notes.Add($"ℹ `VSync` is disabled, but the drivers provided `{pmDesc}`"); } } if (items["ppu_decoder"] is string ppuDecoder) { if (KnownGamesThatRequireInterpreter.Contains(serial)) { if (ppuDecoder.Contains("Recompiler", StringComparison.InvariantCultureIgnoreCase)) { notes.Add("⚠ This game requires `PPU Decoder` to use `Interpreter (fast)`"); } } else { if (ppuDecoder.Contains("Interpreter", StringComparison.InvariantCultureIgnoreCase)) { notes.Add("⚠ Please set `PPU Decoder` to use recompiler for better performance"); } } } if (items["spu_decoder"] is string spuDecoder && spuDecoder.Contains("Interpreter", StringComparison.InvariantCultureIgnoreCase)) { notes.Add("⚠ Please set `SPU Decoder` to use recompiler for better performance"); } if (items["approximate_xfloat"] is string approximateXfloat && approximateXfloat == DisabledMark) { if (KnownNoApproximateXFloatIds.Contains(serial)) { notes.Add("ℹ `Approximate xfloat` is disabled"); } else { notes.Add("⚠ `Approximate xfloat` is disabled, please enable"); } } if (items["resolution_scale"] is string resScale && int.TryParse(resScale, out var resScaleFactor) && resScaleFactor < 100) { notes.Add($"❔ `Resolution Scale` is `{resScale}%`; this will not increase performance"); } var ppuPatches = GetPatches(items["ppu_hash"], items["ppu_hash_patch"]); var ppuHashes = GetHashes(items["ppu_hash"]); if (items["write_color_buffers"] == DisabledMark && !string.IsNullOrEmpty(serial) && KnownWriteColorBuffersIds.Contains(serial)) { if (DesIds.Contains(serial) && ppuPatches.Any()) { notes.Add("ℹ `Write Color Buffers` is disabled"); } else { notes.Add("⚠ `Write Color Buffers` is disabled, please enable"); } } if (items["vertex_cache"] == EnabledMark && !string.IsNullOrEmpty(serial) && !KnownDisableVertexCacheIds.Contains(serial)) { notes.Add("⚠ `Vertex Cache` is disabled, please re-enable"); } if (items["frame_skip"] == EnabledMark) { notes.Add("⚠ `Frame Skip` is enabled, please disable"); } if (items["cpu_blit"] is string cpuBlit && cpuBlit == EnabledMark && items["write_color_buffers"] is string wcb && wcb == DisabledMark) { notes.Add("❔ `Force CPU Blit` is enabled, but `Write Color Buffers` is disabled"); } if (items["zcull"] is string zcull && zcull == EnabledMark) { notes.Add("⚠ `ZCull Occlusion Queries` are disabled, can result in visual artifacts"); } if (!KnownFpsUnlockPatchIds.Contains(serial) || !ppuPatches.Any()) { if (items["vblank_rate"] is string vblank && int.TryParse(vblank, out var vblankRate) && vblankRate != 60) { notes.Add($"ℹ `VBlank Rate` is set to {vblankRate} Hz ({vblankRate / 60.0 * 100:0}%)"); } if (items["clock_scale"] is string clockScaleStr && int.TryParse(clockScaleStr, out var clockScale) && clockScale != 100) { notes.Add($"ℹ `Clock Scale` is set to {clockScale}%"); } } if (items["lib_loader"] is string libLoader && (libLoader == "Auto" || ((libLoader.Contains("manual", StringComparison.InvariantCultureIgnoreCase) || libLoader.Contains("strict", StringComparison.InvariantCultureIgnoreCase)) && (string.IsNullOrEmpty(items["library_list"]) || items["library_list"] == "None")))) { if (items["game_title"] != "vsh.self") { notes.Add("⚠ Please use `Load liblv2.sprx only` as a `Library loader`"); } } if (!string.IsNullOrEmpty(serial)) { CheckP5Settings(serial, items, notes); CheckAsurasWrathSettings(serial, items, notes); CheckJojoSettings(serial, items, notes, ppuPatches, ppuHashes, generalNotes); CheckSimpsonsSettings(serial, generalNotes); CheckNierSettings(serial, items, notes, ppuPatches, ppuHashes, generalNotes); CheckDod3Settings(serial, items, notes, ppuPatches, ppuHashes, generalNotes); CheckScottPilgrimSettings(serial, items, notes, generalNotes); CheckGoWSettings(serial, items, notes, generalNotes); CheckDesSettings(serial, items, notes, ppuPatches, ppuHashes, generalNotes); CheckTlouSettings(serial, items, notes); CheckMgs4Settings(serial, items, notes, generalNotes); CheckProjectDivaSettings(serial, items, notes, ppuPatches, ppuHashes, generalNotes); CheckGt5Settings(serial, items, notes, generalNotes); CheckGt6Settings(serial, items, notes, generalNotes); } else if (items["game_title"] == "vsh.self") { CheckVshSettings(items, notes, generalNotes); } if (items["game_category"] == "1P") { CheckPs1ClassicsSettings(items, notes); } if (items["hook_static_functions"] is string hookStaticFunctions && hookStaticFunctions == EnabledMark) { notes.Add("⚠ `Hook Static Functions` is enabled, please disable"); } if (items["host_root"] is string hostRoot && hostRoot == EnabledMark) { notes.Add("❔ `/host_root/` is enabled"); } if (items["ppu_threads"] is string ppuThreads && ppuThreads != "2") { notes.Add($"⚠ `PPU Threads` is set to `{ppuThreads.Sanitize()}`; please change it back to `2`"); } if (items["spurs_threads"] is string spursSetting && int.TryParse(spursSetting, out var spursThreads) && spursThreads != 6) { if (spursThreads > 6 || spursThreads < 1) { notes.Add($"⚠ `Max SPURS Threads` is set to `{spursThreads}`; please change it back to `6`"); } else { notes.Add($"ℹ `Max SPURS Threads` is set to `{spursThreads}`; may result in game crash"); } } if (items["gpu_texture_scaling"] is string gpuTextureScaling && gpuTextureScaling == EnabledMark) { notes.Add("⚠ `GPU Texture Scaling` is enabled, please disable"); } if (items["af_override"] is string af) { if (af == "Disabled") { notes.Add("❌ `Anisotropic Filter` is `Disabled`, please use `Auto` instead"); } else if (af.ToLowerInvariant() != "auto" && af != "16") { notes.Add($"❔ `Anisotropic Filter` is set to `{af}x`, which makes little sense over `16x` or `Auto`"); } } if (items["async_shaders"] == EnabledMark) { notes.Add("❔ `Async Shader Compiler` is disabled"); } if (items["driver_recovery_timeout"] is string driverRecoveryTimeout && int.TryParse(driverRecoveryTimeout, out var drtValue) && drtValue != 1000000) { if (drtValue == 0) { notes.Add("⚠ `Driver Recovery Timeout` is set to 0 (infinite), please use default value of 1000000"); } else if (drtValue < 10_000) { notes.Add($"⚠ `Driver Recovery Timeout` is set too low: {GetTimeFormat(drtValue)} (1 frame @ {(1_000_000.0 / drtValue):0.##} fps)"); } else if (drtValue > 10_000_000) { notes.Add($"⚠ `Driver Recovery Timeout` is set too high: {GetTimeFormat(drtValue)}"); } } if (items["mtrsx"] is string mtrsx && mtrsx == EnabledMark) { notes.Add("ℹ `Multithreaded RSX` is enabled"); } if (!string.IsNullOrEmpty(serial) && KnownMotionControlsIds.Contains(serial) && items["pad_handler"] is string padHandler && !padHandler.StartsWith("DualShock")) { notes.Add("❗ This game requires motion controls, please use native handler for DualShock 3 or DualShock 4 controller"); } if (items["audio_backend"] is string audioBackend && !string.IsNullOrEmpty(audioBackend)) { if (items["os_type"] == "Windows" && !audioBackend.Equals("XAudio2", StringComparison.InvariantCultureIgnoreCase)) { notes.Add("⚠ Please use `XAudio2` as the audio backend on Windows"); } else if (items["os_type"] == "Linux" && !audioBackend.Equals("OpenAL", StringComparison.InvariantCultureIgnoreCase)) { notes.Add("ℹ `OpenAL` is the recommended audio backend on Linux"); } if (audioBackend.Equals("null", StringComparison.InvariantCultureIgnoreCase)) { notes.Add("⚠ `Audio backend` is set to `null`"); } } if (int.TryParse(items["audio_volume"], out var audioVolume)) { if (audioVolume < 10) { notes.Add($"⚠ Audio volume is set to {audioVolume}%"); } else if (audioVolume > 100) { notes.Add($"⚠ Audio volume is set to {audioVolume}%; audio clipping is to be expected"); } } if (items["hle_lwmutex"] is string hleLwmutex && hleLwmutex == EnabledMark) { notes.Add("⚠ `HLE lwmutex` is enabled, might affect compatibility"); } if (items["spu_block_size"] is string spuBlockSize) { if (spuBlockSize == "Giga") { notes.Add($"⚠ Please change `SPU Block Size`, `{spuBlockSize}` is currently unstable."); } } if (items["auto_start_on_boot"] == DisabledMark) { notes.Add("❔ `Automatically start games after boot` is disabled"); } else if (items["always_start_on_boot"] == DisabledMark) { notes.Add("❔ `Always start after boot` is disabled"); } if (items["custom_config"] != null && notes.Any()) { generalNotes.Add("⚠ To change custom configuration, **Right-click on the game**, then `Configure`"); } var notesContent = new StringBuilder(); foreach (var line in SortLines(notes)) { notesContent.AppendLine(line); } PageSection(builder, notesContent.ToString().Trim(), "Important Settings to Review"); }