diff --git a/src/common/emulatorConfig.cpp b/src/common/emulatorConfig.cpp index 5f88cd587..4ef94bbc0 100644 --- a/src/common/emulatorConfig.cpp +++ b/src/common/emulatorConfig.cpp @@ -63,6 +63,10 @@ bool VrEnabled() { return g_config->vr_enabled; } +bool AmdCpuEnabled() { + return g_config->amd_cpu_enabled; +} + uint32_t GetVblankFrequency() { return std::clamp(g_config->vblank_frequency, 30u, 360u); } diff --git a/src/common/emulatorConfig.h b/src/common/emulatorConfig.h index 924733fbe..9b5e66cf6 100644 --- a/src/common/emulatorConfig.h +++ b/src/common/emulatorConfig.h @@ -48,6 +48,7 @@ struct ConfigOptions { int32_t gpu_index = -1; bool fullscreen_enabled = false; bool vr_enabled = false; + bool amd_cpu_enabled = false; uint32_t vblank_frequency = 60; uint32_t console_language = DEFAULT_CONSOLE_LANGUAGE; bool vulkan_validation_enabled = false; @@ -83,6 +84,7 @@ PresentMode GetPresentMode(); int32_t GetGpuIndex(); bool FullscreenEnabled(); bool VrEnabled(); +bool AmdCpuEnabled(); uint32_t GetVblankFrequency(); uint32_t GetConsoleLanguage(); bool VulkanValidationEnabled(); diff --git a/src/launcher/forms/configuration_edit_dialog.ui b/src/launcher/forms/configuration_edit_dialog.ui index bfd2109fe..e3f3ecb46 100644 --- a/src/launcher/forms/configuration_edit_dialog.ui +++ b/src/launcher/forms/configuration_edit_dialog.ui @@ -271,21 +271,19 @@ Compatibility - + + + + Patch CPU instructions that differ between AMD and the host CPU. + AMD CPU patch (EXPERIMENTAL) + + Helps prevent crashes in some games on Windows Windows SysV red zone crash protection (Experimental) - - - Qt::Horizontal - - 4020 - - - diff --git a/src/launcher/include/configuration.h b/src/launcher/include/configuration.h index 36111bcb0..bbeb79244 100644 --- a/src/launcher/include/configuration.h +++ b/src/launcher/include/configuration.h @@ -105,6 +105,7 @@ public: QString printf_output_file = "_kyty.txt"; bool profiler_enabled = false; bool renderdoc_enabled = false; + bool amd_cpu_enabled = false; #if defined(_WIN32) bool red_zone_protection_enabled = false; #endif @@ -134,6 +135,7 @@ public: printf_output_file = other.printf_output_file; profiler_enabled = other.profiler_enabled; renderdoc_enabled = other.renderdoc_enabled; + amd_cpu_enabled = other.amd_cpu_enabled; #if defined(_WIN32) red_zone_protection_enabled = other.red_zone_protection_enabled; #endif @@ -180,6 +182,7 @@ public: KYTY_CFG_SET(printf_output_file); KYTY_CFG_SET(profiler_enabled); KYTY_CFG_SET(renderdoc_enabled); + KYTY_CFG_SET(amd_cpu_enabled); #if defined(_WIN32) KYTY_CFG_SET(red_zone_protection_enabled); #endif @@ -223,6 +226,7 @@ public: KYTY_CFG_GET(printf_output_file); KYTY_CFG_GET(profiler_enabled); KYTY_CFG_GET(renderdoc_enabled); + amd_cpu_enabled = s->value("amd_cpu_enabled", false).toBool(); #if defined(_WIN32) red_zone_protection_enabled = s->value("red_zone_protection_enabled", red_zone_protection_enabled).toBool(); diff --git a/src/launcher/src/configurationEditDialog.cpp b/src/launcher/src/configurationEditDialog.cpp index a0250aa34..3e63778e0 100644 --- a/src/launcher/src/configurationEditDialog.cpp +++ b/src/launcher/src/configurationEditDialog.cpp @@ -239,6 +239,10 @@ void ConfigurationEditDialog::Init(const Configuration& info) { m_ui->checkBox_shader_validation->setChecked(info.shader_validation_enabled); m_ui->checkBox_vulkan_validation->setChecked(info.vulkan_validation_enabled); m_ui->checkBox_renderdoc_capture->setChecked(info.renderdoc_enabled); + m_ui->checkBox_amd_cpu->setChecked(info.amd_cpu_enabled); +#if !defined(__linux__) + m_ui->checkBox_amd_cpu->setVisible(false); +#endif #if defined(_WIN32) m_ui->checkBox_red_zone_protection->setChecked(info.red_zone_protection_enabled); #else @@ -379,6 +383,7 @@ static void UpdateInfo(Configuration& info, Ui::ConfigurationEditDialog& ui) { info.vulkan_validation_enabled = ui.checkBox_vulkan_validation->isChecked(); info.shader_validation_enabled = ui.checkBox_shader_validation->isChecked(); info.renderdoc_enabled = ui.checkBox_renderdoc_capture->isChecked(); + info.amd_cpu_enabled = ui.checkBox_amd_cpu->isChecked(); #if defined(_WIN32) info.red_zone_protection_enabled = ui.checkBox_red_zone_protection->isChecked(); #endif diff --git a/src/launcher/src/mainDialog.cpp b/src/launcher/src/mainDialog.cpp index 7a4cee5d5..8896ad033 100644 --- a/src/launcher/src/mainDialog.cpp +++ b/src/launcher/src/mainDialog.cpp @@ -254,6 +254,9 @@ static QStringList CreateEmulatorArgs(const Configuration& info) { args << "--profile"; } args << "--spirv-debug-printf" << "false"; + if (info.amd_cpu_enabled) { + args << "--amd-cpu"; + } #if defined(_WIN32) if (info.red_zone_protection_enabled) { args << "--redzone"; diff --git a/src/loader/runtimeLinker.cpp b/src/loader/runtimeLinker.cpp index 85433363f..621e4a003 100644 --- a/src/loader/runtimeLinker.cpp +++ b/src/loader/runtimeLinker.cpp @@ -2089,13 +2089,15 @@ void RuntimeLinker::LoadProgramToMemory(Program* program) { mode == Common::VirtualMemory::Mode::NoAccess); if (Common::VirtualMemory::IsExecute(mode)) { - const auto reciprocal_sqrt_count = - X64InstructionEmulator::PatchReciprocalSquareRoots(segment_addr, - segment_file_size); - if (reciprocal_sqrt_count != 0) { - LOGF("Guest VRSQRTPS emulation: %s, instructions=%" PRIu64 "\n", - Common::PathToString(program->file_name.filename()).c_str(), - reciprocal_sqrt_count); + if (Config::AmdCpuEnabled()) { + const auto reciprocal_sqrt_count = + X64InstructionEmulator::PatchReciprocalSquareRoots(segment_addr, + segment_file_size); + if (reciprocal_sqrt_count != 0) { + LOGF("Guest VRSQRTPS emulation: %s, instructions=%" PRIu64 "\n", + Common::PathToString(program->file_name.filename()).c_str(), + reciprocal_sqrt_count); + } } PatchProgram(program, segment_addr, segment_memory_size); #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS diff --git a/src/main.cpp b/src/main.cpp index 1c35cd237..c5ddc5256 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -56,6 +56,7 @@ static void PrintUsage() { " --gpu Vulkan physical device index. Default: auto.\n"); ::printf(" --fullscreen Run in borderless desktop fullscreen.\n"); ::printf(" --vr Enable the virtual VR headset.\n"); + ::printf(" --amd-cpu Apply AMD CPU instruction patches (Linux).\n"); ::printf(" --vblank-frequency Virtual vblank frequency. Default: 60.\n"); ::printf(" --console-language <0-29> Console language. Default: 1 (English US).\n"); ::printf(" --vulkan-validation Enable Vulkan validation.\n"); @@ -168,6 +169,11 @@ static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_he continue; } + if (arg == "--amd-cpu") { + options.config.amd_cpu_enabled = true; + continue; + } + if (arg == "--playgo-hack") { options.config.playgo_hack_enabled = true; continue;