From 78c6819f5e61a77321479f6db8b4d5b7dfcff85d Mon Sep 17 00:00:00 2001 From: dreamsyntax Date: Sun, 17 Apr 2022 00:15:12 -0700 Subject: [PATCH] Core: pause on panic handler option --- Source/Core/Core/Config/MainSettings.cpp | 1 + Source/Core/Core/Config/MainSettings.h | 1 + .../Core/Core/ConfigLoaders/IsSettingSaveable.cpp | 1 + .../Core/Core/PowerPC/Interpreter/Interpreter.cpp | 3 +++ Source/Core/Core/PowerPC/JitCommon/JitBase.cpp | 4 +++- Source/Core/Core/PowerPC/JitCommon/JitBase.h | 1 + Source/Core/Core/PowerPC/MMU.cpp | 15 +++++++++++++++ Source/Core/Core/System.cpp | 1 + Source/Core/Core/System.h | 2 ++ Source/Core/DolphinQt/Settings/AdvancedPane.cpp | 12 ++++++++++++ Source/Core/DolphinQt/Settings/AdvancedPane.h | 1 + 11 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp index 01fd799846..03214152ba 100644 --- a/Source/Core/Core/Config/MainSettings.cpp +++ b/Source/Core/Core/Config/MainSettings.cpp @@ -168,6 +168,7 @@ const Info MAIN_WIIMOTE_ENABLE_SPEAKER{{System::Main, "Core", "WiimoteEnab const Info MAIN_CONNECT_WIIMOTES_FOR_CONTROLLER_INTERFACE{ {System::Main, "Core", "WiimoteControllerInterface"}, false}; const Info MAIN_MMU{{System::Main, "Core", "MMU"}, false}; +const Info MAIN_PAUSE_ON_PANIC{{System::Main, "Core", "PauseOnPanic"}, false}; const Info MAIN_BB_DUMP_PORT{{System::Main, "Core", "BBDumpPort"}, -1}; const Info MAIN_SYNC_GPU{{System::Main, "Core", "SyncGPU"}, false}; const Info MAIN_SYNC_GPU_MAX_DISTANCE{{System::Main, "Core", "SyncGpuMaxDistance"}, 200000}; diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h index e731e891b7..e27a6eef0b 100644 --- a/Source/Core/Core/Config/MainSettings.h +++ b/Source/Core/Core/Config/MainSettings.h @@ -98,6 +98,7 @@ extern const Info MAIN_WIIMOTE_CONTINUOUS_SCANNING; extern const Info MAIN_WIIMOTE_ENABLE_SPEAKER; extern const Info MAIN_CONNECT_WIIMOTES_FOR_CONTROLLER_INTERFACE; extern const Info MAIN_MMU; +extern const Info MAIN_PAUSE_ON_PANIC; extern const Info MAIN_BB_DUMP_PORT; extern const Info MAIN_SYNC_GPU; extern const Info MAIN_SYNC_GPU_MAX_DISTANCE; diff --git a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp index 92411968b4..048719d2c3 100644 --- a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp +++ b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp @@ -124,6 +124,7 @@ bool IsSettingSaveable(const Config::Location& config_location) &Config::GetInfoForSIDevice(3).GetLocation(), &Config::MAIN_CPU_THREAD.GetLocation(), &Config::MAIN_MMU.GetLocation(), + &Config::MAIN_PAUSE_ON_PANIC.GetLocation(), &Config::MAIN_BB_DUMP_PORT.GetLocation(), &Config::MAIN_SYNC_GPU.GetLocation(), &Config::MAIN_SYNC_GPU_MAX_DISTANCE.GetLocation(), diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index 0207779e9f..597a07c9c0 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -24,6 +24,7 @@ #include "Core/PowerPC/MMU.h" #include "Core/PowerPC/PPCTables.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/System.h" namespace { @@ -341,6 +342,8 @@ void Interpreter::unknown_instruction(UGeckoInstruction inst) ASSERT_MSG(POWERPC, 0, "\nIntCPU: Unknown instruction {:08x} at PC = {:08x} last_PC = {:08x} LR = {:08x}\n", inst.hex, PC, last_pc, LR); + if (Core::System::GetInstance().IsPauseOnPanicMode()) + CPU::Break(); } void Interpreter::ClearCache() diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp index 392aca5f0d..679fdea0a8 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp @@ -57,6 +57,8 @@ void JitBase::RefreshConfig() m_accurate_nans = Config::Get(Config::MAIN_ACCURATE_NANS); m_fastmem_enabled = Config::Get(Config::MAIN_FASTMEM); m_mmu_enabled = Core::System::GetInstance().IsMMUMode(); + m_pause_on_panic_enabled = Core::System::GetInstance().IsPauseOnPanicMode(); + analyzer.SetDebuggingEnabled(m_enable_debugging); analyzer.SetBranchFollowingEnabled(Config::Get(Config::MAIN_JIT_FOLLOW_BRANCH)); analyzer.SetFloatExceptionsEnabled(m_enable_float_exceptions); @@ -82,7 +84,7 @@ void JitBase::UpdateMemoryAndExceptionOptions() { bool any_watchpoints = PowerPC::memchecks.HasAny(); jo.fastmem = m_fastmem_enabled && jo.fastmem_arena && (MSR.DR || !any_watchpoints); - jo.memcheck = m_mmu_enabled || any_watchpoints; + jo.memcheck = m_mmu_enabled || m_pause_on_panic_enabled || any_watchpoints; jo.fp_exceptions = m_enable_float_exceptions; jo.div_by_zero_exceptions = m_enable_div_by_zero_exceptions; } diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.h b/Source/Core/Core/PowerPC/JitCommon/JitBase.h index a4b895739c..4abbb4dad7 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.h @@ -134,6 +134,7 @@ protected: bool m_accurate_nans = false; bool m_fastmem_enabled = false; bool m_mmu_enabled = false; + bool m_pause_on_panic_enabled = false; void RefreshConfig(); diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index 301ff55a6b..f63c023622 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -244,6 +244,11 @@ static T ReadFromHardware(u32 em_address) } PanicAlertFmt("Unable to resolve read address {:x} PC {:x}", em_address, PC); + if (Core::System::GetInstance().IsPauseOnPanicMode()) + { + CPU::Break(); + ppcState.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; + } return 0; } @@ -406,6 +411,11 @@ static void WriteToHardware(u32 em_address, const u32 data, const u32 size) } PanicAlertFmt("Unable to resolve write address {:x} PC {:x}", em_address, PC); + if (Core::System::GetInstance().IsPauseOnPanicMode()) + { + CPU::Break(); + ppcState.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; + } } // ===================== @@ -1148,6 +1158,11 @@ static void GenerateDSIException(u32 effective_address, bool write) { PanicAlertFmt("Invalid {} {:#010x}, PC = {:#010x}", write ? "write to" : "read from", effective_address, PC); + if (Core::System::GetInstance().IsPauseOnPanicMode()) + { + CPU::Break(); + ppcState.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; + } return; } diff --git a/Source/Core/Core/System.cpp b/Source/Core/Core/System.cpp index 4320bded39..9cda1cf203 100644 --- a/Source/Core/Core/System.cpp +++ b/Source/Core/Core/System.cpp @@ -27,6 +27,7 @@ void System::Initialize() { m_separate_cpu_and_gpu_threads = Config::Get(Config::MAIN_CPU_THREAD); m_mmu_enabled = Config::Get(Config::MAIN_MMU); + m_pause_on_panic_enabled = Config::Get(Config::MAIN_PAUSE_ON_PANIC); } SoundStream* System::GetSoundStream() const diff --git a/Source/Core/Core/System.h b/Source/Core/Core/System.h index 85b7087095..f72bf81e16 100644 --- a/Source/Core/Core/System.h +++ b/Source/Core/Core/System.h @@ -32,6 +32,7 @@ public: bool IsDualCoreMode() const { return m_separate_cpu_and_gpu_threads; } bool IsMMUMode() const { return m_mmu_enabled; } + bool IsPauseOnPanicMode() const { return m_pause_on_panic_enabled; } SoundStream* GetSoundStream() const; void SetSoundStream(std::unique_ptr sound_stream); @@ -48,5 +49,6 @@ private: bool m_separate_cpu_and_gpu_threads = false; bool m_mmu_enabled = false; + bool m_pause_on_panic_enabled = false; }; } // namespace Core diff --git a/Source/Core/DolphinQt/Settings/AdvancedPane.cpp b/Source/Core/DolphinQt/Settings/AdvancedPane.cpp index bdea2ed2ba..f08f9d1570 100644 --- a/Source/Core/DolphinQt/Settings/AdvancedPane.cpp +++ b/Source/Core/DolphinQt/Settings/AdvancedPane.cpp @@ -68,6 +68,12 @@ void AdvancedPane::CreateLayout() "Enables the Memory Management Unit, needed for some games. (ON = Compatible, OFF = Fast)")); cpu_options_group_layout->addWidget(m_enable_mmu_checkbox); + m_pause_on_panic_checkbox = new QCheckBox(tr("Pause on Panic")); + m_pause_on_panic_checkbox->setToolTip( + tr("Pauses the emulation if a Read/Write or Unknown Instruction panic occurs.\nEnabling will " + "affect performance.\nThe performance impact is the same as having Enable MMU on.")); + cpu_options_group_layout->addWidget(m_pause_on_panic_checkbox); + auto* clock_override = new QGroupBox(tr("Clock Override")); auto* clock_override_layout = new QVBoxLayout(); clock_override->setLayout(clock_override_layout); @@ -180,6 +186,9 @@ void AdvancedPane::ConnectLayout() connect(m_enable_mmu_checkbox, &QCheckBox::toggled, this, [](bool checked) { Config::SetBaseOrCurrent(Config::MAIN_MMU, checked); }); + connect(m_pause_on_panic_checkbox, &QCheckBox::toggled, this, + [](bool checked) { Config::SetBaseOrCurrent(Config::MAIN_PAUSE_ON_PANIC, checked); }); + m_cpu_clock_override_checkbox->setChecked(Config::Get(Config::MAIN_OVERCLOCK_ENABLE)); connect(m_cpu_clock_override_checkbox, &QCheckBox::toggled, [this](bool enable_clock_override) { Config::SetBaseOrCurrent(Config::MAIN_OVERCLOCK_ENABLE, enable_clock_override); @@ -246,6 +255,9 @@ void AdvancedPane::Update() m_enable_mmu_checkbox->setChecked(Config::Get(Config::MAIN_MMU)); m_enable_mmu_checkbox->setEnabled(!running); + m_pause_on_panic_checkbox->setChecked(Config::Get(Config::MAIN_PAUSE_ON_PANIC)); + m_pause_on_panic_checkbox->setEnabled(!running); + QFont bf = font(); bf.setBold(Config::GetActiveLayerForConfig(Config::MAIN_OVERCLOCK_ENABLE) != Config::LayerType::Base); diff --git a/Source/Core/DolphinQt/Settings/AdvancedPane.h b/Source/Core/DolphinQt/Settings/AdvancedPane.h index 726ce93bc1..c74aeacf09 100644 --- a/Source/Core/DolphinQt/Settings/AdvancedPane.h +++ b/Source/Core/DolphinQt/Settings/AdvancedPane.h @@ -32,6 +32,7 @@ private: QComboBox* m_cpu_emulation_engine_combobox; QCheckBox* m_enable_mmu_checkbox; + QCheckBox* m_pause_on_panic_checkbox; QCheckBox* m_cpu_clock_override_checkbox; QSlider* m_cpu_clock_override_slider; QLabel* m_cpu_clock_override_slider_label;