From 219a5078e86ad05cdc90a91a41a337be2eb8e679 Mon Sep 17 00:00:00 2001 From: skidau Date: Wed, 15 Oct 2014 20:04:23 +1100 Subject: [PATCH 01/14] Added a "Step Out" (aka "Step return") function to the debugger. Conflicts: Source/Core/DolphinWX/Debugger/CodeWindow.h --- Source/Core/DolphinWX/Debugger/CodeWindow.cpp | 25 +++++++++++++++++++ Source/Core/DolphinWX/Debugger/CodeWindow.h | 1 + Source/Core/DolphinWX/Globals.h | 2 ++ 3 files changed, 28 insertions(+) diff --git a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp index 94ca897a7b..f10421e860 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp @@ -180,6 +180,10 @@ void CCodeWindow::OnCodeStep(wxCommandEvent& event) StepOver(); break; + case IDM_STEPOUT: + StepOut(); + break; + case IDM_TOGGLE_BREAKPOINT: ToggleBreakpoint(); break; @@ -320,6 +324,21 @@ void CCodeWindow::StepOver() } } +void CCodeWindow::StepOut() +{ + if (CCPU::IsStepping()) + { + PowerPC::breakpoints.Add(LR, true); + CCPU::EnableStepping(false); + JumpToAddress(PC); + Update(); + + UpdateButtonStates(); + // Update all toolbars in the aui manager + Parent->UpdateGUI(); + } +} + void CCodeWindow::ToggleBreakpoint() { if (CCPU::IsStepping()) @@ -443,6 +462,7 @@ void CCodeWindow::CreateMenu(const SCoreStartupParameter& core_startup_parameter pDebugMenu->Append(IDM_STEP, _("Step &Into\tF11")); pDebugMenu->Append(IDM_STEPOVER, _("Step &Over\tF10")); + pDebugMenu->Append(IDM_STEPOUT, _("Step O&ut\tSHIFT+F11")); pDebugMenu->Append(IDM_TOGGLE_BREAKPOINT, _("Toggle &Breakpoint\tF9")); pDebugMenu->AppendSeparator(); @@ -607,6 +627,7 @@ void CCodeWindow::InitBitmaps() // load original size 48x48 m_Bitmaps[Toolbar_Step] = wxGetBitmapFromMemory(toolbar_add_breakpoint_png); m_Bitmaps[Toolbar_StepOver] = wxGetBitmapFromMemory(toolbar_add_memcheck_png); + m_Bitmaps[Toolbar_StepOut] = wxGetBitmapFromMemory(toolbar_add_memcheck_png); m_Bitmaps[Toolbar_Skip] = wxGetBitmapFromMemory(toolbar_add_memcheck_png); m_Bitmaps[Toolbar_GotoPC] = wxGetBitmapFromMemory(toolbar_add_memcheck_png); m_Bitmaps[Toolbar_SetPC] = wxGetBitmapFromMemory(toolbar_add_memcheck_png); @@ -624,6 +645,7 @@ void CCodeWindow::PopulateToolbar(wxToolBar* toolBar) toolBar->SetToolBitmapSize(wxSize(w, h)); WxUtils::AddToolbarButton(toolBar, IDM_STEP, _("Step"), m_Bitmaps[Toolbar_Step], _("Step into the next instruction")); WxUtils::AddToolbarButton(toolBar, IDM_STEPOVER, _("Step Over"), m_Bitmaps[Toolbar_StepOver], _("Step over the next instruction")); + WxUtils::AddToolbarButton(toolBar, IDM_STEPOUT, _("Step Out"), m_Bitmaps[Toolbar_StepOut], _("Step out of the current function")); WxUtils::AddToolbarButton(toolBar, IDM_SKIP, _("Skip"), m_Bitmaps[Toolbar_Skip], _("Skips the next instruction completely")); toolBar->AddSeparator(); WxUtils::AddToolbarButton(toolBar, IDM_GOTOPC, _("Show PC"), m_Bitmaps[Toolbar_GotoPC], _("Go to the current instruction")); @@ -660,6 +682,7 @@ void CCodeWindow::UpdateButtonStates() if (!Initialized) { ToolBar->EnableTool(IDM_STEPOVER, false); + ToolBar->EnableTool(IDM_STEPOUT, false); ToolBar->EnableTool(IDM_SKIP, false); } else @@ -667,11 +690,13 @@ void CCodeWindow::UpdateButtonStates() if (!Stepping) { ToolBar->EnableTool(IDM_STEPOVER, false); + ToolBar->EnableTool(IDM_STEPOUT, false); ToolBar->EnableTool(IDM_SKIP, false); } else { ToolBar->EnableTool(IDM_STEPOVER, true); + ToolBar->EnableTool(IDM_STEPOUT, true); ToolBar->EnableTool(IDM_SKIP, true); } } diff --git a/Source/Core/DolphinWX/Debugger/CodeWindow.h b/Source/Core/DolphinWX/Debugger/CodeWindow.h index 1953c85493..dfe2ed0188 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindow.h +++ b/Source/Core/DolphinWX/Debugger/CodeWindow.h @@ -126,6 +126,7 @@ private: // Debugger functions void SingleStep(); void StepOver(); + void StepOut(); void ToggleBreakpoint(); void UpdateLists(); diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h index 51428100ff..84b046f9ef 100644 --- a/Source/Core/DolphinWX/Globals.h +++ b/Source/Core/DolphinWX/Globals.h @@ -14,6 +14,7 @@ enum { Toolbar_Step, Toolbar_StepOver, + Toolbar_StepOut, Toolbar_Skip, Toolbar_GotoPC, Toolbar_SetPC, @@ -230,6 +231,7 @@ enum ID_TOOLBAR_DEBUG, IDM_STEP, IDM_STEPOVER, + IDM_STEPOUT, IDM_TOGGLE_BREAKPOINT, IDM_SKIP, IDM_SETPC, From b331ec96a36a0c8bc70c45aa4b3c610342a734b4 Mon Sep 17 00:00:00 2001 From: skidau Date: Thu, 16 Oct 2014 01:29:05 +1100 Subject: [PATCH 02/14] Made the "continue", "stepover" and "stepout" functions work when the PC is at a breakpoint --- Source/Core/Core/HW/CPU.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Source/Core/Core/HW/CPU.cpp b/Source/Core/Core/HW/CPU.cpp index 12787dbde1..6164817194 100644 --- a/Source/Core/Core/HW/CPU.cpp +++ b/Source/Core/Core/HW/CPU.cpp @@ -117,6 +117,15 @@ void CCPU::EnableStepping(const bool _bStepping) } else { + // SingleStep so that the "continue", "step over" and "step out" debugger functions + // work when the PC is at a breakpoint at the beginning of the block + if (PowerPC::breakpoints.IsAddressBreakPoint(PC) && PowerPC::GetMode() != PowerPC::MODE_INTERPRETER) + { + PowerPC::CoreMode oldMode = PowerPC::GetMode(); + PowerPC::SetMode(PowerPC::MODE_INTERPRETER); + PowerPC::SingleStep(); + PowerPC::SetMode(oldMode); + } PowerPC::Start(); m_StepEvent.Set(); g_video_backend->EmuStateChange(EMUSTATE_CHANGE_PLAY); From df37649b9f8499ec732b7511e7fed2b075ef7781 Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 18 Oct 2014 11:02:26 +1100 Subject: [PATCH 03/14] Changed the step over routine to a single stepping version that steps until a blr is encountered. Cleared out all temporary breakpoints on each step to prevent phantom breakpoints from stopping the debugger. --- Source/Core/Common/BreakPoints.cpp | 13 +++++++ Source/Core/Common/BreakPoints.h | 1 + Source/Core/Core/PowerPC/PowerPC.cpp | 3 ++ Source/Core/DolphinWX/Debugger/CodeWindow.cpp | 38 ++++++++++++++++++- 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/Source/Core/Common/BreakPoints.cpp b/Source/Core/Common/BreakPoints.cpp index db0cedf0bb..6014eae776 100644 --- a/Source/Core/Common/BreakPoints.cpp +++ b/Source/Core/Common/BreakPoints.cpp @@ -113,6 +113,19 @@ void BreakPoints::Clear() m_BreakPoints.clear(); } +void BreakPoints::ClearAllTemporary() +{ + for (const TBreakPoint& bp : m_BreakPoints) + { + if (bp.bTemporary) + { + if (jit) + jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4, true); + Remove(bp.iAddress); + } + } +} + MemChecks::TMemChecksStr MemChecks::GetStrings() const { TMemChecksStr mcs; diff --git a/Source/Core/Common/BreakPoints.h b/Source/Core/Common/BreakPoints.h index 99ea0809ca..3d656b12e8 100644 --- a/Source/Core/Common/BreakPoints.h +++ b/Source/Core/Common/BreakPoints.h @@ -67,6 +67,7 @@ public: // Remove Breakpoint void Remove(u32 _iAddress); void Clear(); + void ClearAllTemporary(); void DeleteByAddress(u32 _Address); diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index 0480677831..ebd5a7d7db 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -161,6 +161,9 @@ void Init(int cpu_core) state = CPU_STEPPING; ppcState.iCache.Init(); + + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) + breakpoints.ClearAllTemporary(); } void Shutdown() diff --git a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp index f10421e860..c6ad04e8b7 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp @@ -37,6 +37,7 @@ #include "Core/Debugger/PPCDebugInterface.h" #include "Core/HW/CPU.h" #include "Core/HW/Memmap.h" +#include "Core/HW/SystemTimers.h" #include "Core/PowerPC/Gekko.h" #include "Core/PowerPC/JitInterface.h" #include "Core/PowerPC/PowerPC.h" @@ -292,6 +293,7 @@ void CCodeWindow::SingleStep() { if (CCPU::IsStepping()) { + PowerPC::breakpoints.ClearAllTemporary(); JitInterface::InvalidateICache(PC, 4, true); CCPU::StepOpcode(&sync_event); wxThread::Sleep(20); @@ -305,6 +307,7 @@ void CCodeWindow::StepOver() { if (CCPU::IsStepping()) { + PowerPC::breakpoints.ClearAllTemporary(); UGeckoInstruction inst = Memory::Read_Instruction(PC); if (inst.LK) { @@ -328,8 +331,39 @@ void CCodeWindow::StepOut() { if (CCPU::IsStepping()) { - PowerPC::breakpoints.Add(LR, true); - CCPU::EnableStepping(false); + PowerPC::breakpoints.ClearAllTemporary(); + + // Keep stepping until the next blr or timeout after one second + u64 timeout = SystemTimers::GetTicksPerSecond(); + u64 steps = 0; + PowerPC::CoreMode oldMode = PowerPC::GetMode(); + PowerPC::SetMode(PowerPC::MODE_INTERPRETER); + UGeckoInstruction inst = Memory::Read_Instruction(PC); + GekkoOPInfo *opinfo = GetOpInfo(inst); + while (inst.hex != 0x4e800020 && steps < timeout) // check for blr + { + if (inst.LK) + { + // Step over branches + u32 next_pc = PC + 4; + while (PC != next_pc && steps < timeout) + { + PowerPC::SingleStep(); + ++steps; + } + } + else + { + PowerPC::SingleStep(); + ++steps; + } + inst = Memory::Read_Instruction(PC); + opinfo = GetOpInfo(inst); + } + + PowerPC::SingleStep(); + PowerPC::SetMode(oldMode); + JumpToAddress(PC); Update(); From 613cae613a8c2ac34dd823f875ac4a6a0059db38 Mon Sep 17 00:00:00 2001 From: skidau Date: Sun, 19 Oct 2014 21:45:40 +1100 Subject: [PATCH 04/14] Added a RAM Watch window to the debugger Conflicts: Source/Core/Core/HW/Memmap.cpp Source/Core/Core/HW/Memmap.h Source/Core/DolphinWX/Debugger/CodeWindow.h --- Source/Core/Common/BreakPoints.cpp | 83 +++++++ Source/Core/Common/BreakPoints.h | 37 +++ Source/Core/Common/DebugInterface.h | 1 + .../Core/Core/Debugger/PPCDebugInterface.cpp | 5 + Source/Core/Core/Debugger/PPCDebugInterface.h | 1 + Source/Core/Core/PowerPC/PowerPC.cpp | 1 + Source/Core/Core/PowerPC/PowerPC.h | 1 + Source/Core/DolphinWX/CMakeLists.txt | 2 + Source/Core/DolphinWX/Debugger/CodeWindow.cpp | 3 + Source/Core/DolphinWX/Debugger/CodeWindow.h | 179 +++++++-------- .../Debugger/CodeWindowFunctions.cpp | 21 ++ Source/Core/DolphinWX/Debugger/MemoryView.cpp | 7 + Source/Core/DolphinWX/Debugger/WatchView.cpp | 212 ++++++++++++++++++ Source/Core/DolphinWX/Debugger/WatchView.h | 50 +++++ .../Core/DolphinWX/Debugger/WatchWindow.cpp | 46 ++++ Source/Core/DolphinWX/Debugger/WatchWindow.h | 42 ++++ Source/Core/DolphinWX/DolphinWX.vcxproj | 4 + .../Core/DolphinWX/DolphinWX.vcxproj.filters | 14 +- Source/Core/DolphinWX/FrameAui.cpp | 6 + Source/Core/DolphinWX/FrameTools.cpp | 1 + Source/Core/DolphinWX/Globals.h | 1 + 21 files changed, 628 insertions(+), 89 deletions(-) create mode 100644 Source/Core/DolphinWX/Debugger/WatchView.cpp create mode 100644 Source/Core/DolphinWX/Debugger/WatchView.h create mode 100644 Source/Core/DolphinWX/Debugger/WatchWindow.cpp create mode 100644 Source/Core/DolphinWX/Debugger/WatchWindow.h diff --git a/Source/Core/Common/BreakPoints.cpp b/Source/Core/Common/BreakPoints.cpp index 6014eae776..50b4d56be5 100644 --- a/Source/Core/Common/BreakPoints.cpp +++ b/Source/Core/Common/BreakPoints.cpp @@ -217,3 +217,86 @@ void TMemCheck::Action(DebugInterface *debug_interface, u32 iValue, u32 addr, bo debug_interface->BreakNow(); } } + + +bool Watches::IsAddressWatch(u32 _iAddress) +{ + for (const TWatch& bp : m_Watches) + if (bp.iAddress == _iAddress) + return true; + + return false; +} + +Watches::TWatchesStr Watches::GetStrings() const +{ + TWatchesStr bps; + for (const TWatch& bp : m_Watches) + { + std::stringstream ss; + ss << std::hex << bp.iAddress << " " << (bp.bOn ? "n" : ""); + bps.push_back(ss.str()); + } + + return bps; +} + +void Watches::AddFromStrings(const TWatchesStr& bpstrs) +{ + for (const std::string& bpstr : bpstrs) + { + TWatch bp; + std::stringstream ss; + ss << std::hex << bpstr; + ss >> bp.iAddress; + bp.bOn = bpstr.find("n") != bpstr.npos; + Add(bp); + } +} + +void Watches::Add(const TWatch& bp) +{ + if (!IsAddressWatch(bp.iAddress)) + { + m_Watches.push_back(bp); + } +} + +void Watches::Add(u32 em_address) +{ + if (!IsAddressWatch(em_address)) // only add new addresses + { + TWatch pt; // breakpoint settings + pt.bOn = true; + pt.iAddress = em_address; + + m_Watches.push_back(pt); + } +} + +void Watches::Update(int count, u32 em_address) +{ + m_Watches.at(count).iAddress = em_address; +} + +void Watches::UpdateName(int count, std::string name) +{ + m_Watches.at(count).name = name; +} + +void Watches::Remove(u32 em_address) +{ + for (auto i = m_Watches.begin(); i != m_Watches.end(); ++i) + { + if (i->iAddress == em_address) + { + m_Watches.erase(i); + return; + } + } +} + +void Watches::Clear() +{ + m_Watches.clear(); +} diff --git a/Source/Core/Common/BreakPoints.h b/Source/Core/Common/BreakPoints.h index 3d656b12e8..cd18eedd60 100644 --- a/Source/Core/Common/BreakPoints.h +++ b/Source/Core/Common/BreakPoints.h @@ -44,6 +44,13 @@ struct TMemCheck bool write, int size, u32 pc); }; +struct TWatch +{ + std::string name = ""; + u32 iAddress; + bool bOn; +}; + // Code breakpoints. class BreakPoints { @@ -99,3 +106,33 @@ public: void Clear() { m_MemChecks.clear(); } }; + +class Watches +{ +public: + typedef std::vector TWatches; + typedef std::vector TWatchesStr; + + const TWatches& GetWatches() { return m_Watches; } + + TWatchesStr GetStrings() const; + void AddFromStrings(const TWatchesStr& bps); + + bool IsAddressWatch(u32 _iAddress); + + // Add BreakPoint + void Add(u32 em_address); + void Add(const TWatch& bp); + + void Update(int count, u32 em_address); + void UpdateName(int count, std::string name); + + // Remove Breakpoint + void Remove(u32 _iAddress); + void Clear(); + + void DeleteByAddress(u32 _Address); + +private: + TWatches m_Watches; +}; \ No newline at end of file diff --git a/Source/Core/Common/DebugInterface.h b/Source/Core/Common/DebugInterface.h index 5bee2f7951..a21921d496 100644 --- a/Source/Core/Common/DebugInterface.h +++ b/Source/Core/Common/DebugInterface.h @@ -18,6 +18,7 @@ public: virtual void ClearBreakpoint(unsigned int /*address*/){} virtual void ClearAllBreakpoints() {} virtual void ToggleBreakpoint(unsigned int /*address*/){} + virtual void AddWatch(unsigned int /*address*/){} virtual void ClearAllMemChecks() {} virtual bool IsMemCheck(unsigned int /*address*/) {return false;} virtual void ToggleMemCheck(unsigned int /*address*/){} diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.cpp b/Source/Core/Core/Debugger/PPCDebugInterface.cpp index 84e2cb6879..988d0de20d 100644 --- a/Source/Core/Core/Debugger/PPCDebugInterface.cpp +++ b/Source/Core/Core/Debugger/PPCDebugInterface.cpp @@ -131,6 +131,11 @@ void PPCDebugInterface::ToggleBreakpoint(unsigned int address) PowerPC::breakpoints.Add(address); } +void PPCDebugInterface::AddWatch(unsigned int address) +{ + PowerPC::watches.Add(address); +} + void PPCDebugInterface::ClearAllMemChecks() { PowerPC::memchecks.Clear(); diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.h b/Source/Core/Core/Debugger/PPCDebugInterface.h index 3675c9f9cf..0cecef0ea6 100644 --- a/Source/Core/Core/Debugger/PPCDebugInterface.h +++ b/Source/Core/Core/Debugger/PPCDebugInterface.h @@ -22,6 +22,7 @@ public: virtual void SetBreakpoint(unsigned int address) override; virtual void ClearBreakpoint(unsigned int address) override; virtual void ClearAllBreakpoints() override; + virtual void AddWatch(unsigned int address) override; virtual void ToggleBreakpoint(unsigned int address) override; virtual void ClearAllMemChecks() override; virtual bool IsMemCheck(unsigned int address) override; diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index ebd5a7d7db..7e3a4f38ac 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -35,6 +35,7 @@ static volatile CPUState state = CPU_POWERDOWN; Interpreter * const interpreter = Interpreter::getInstance(); static CoreMode mode; +Watches watches; BreakPoints breakpoints; MemChecks memchecks; PPCDebugInterface debug_interface; diff --git a/Source/Core/Core/PowerPC/PowerPC.h b/Source/Core/Core/PowerPC/PowerPC.h index a4c2fc4af1..e9f3aee367 100644 --- a/Source/Core/Core/PowerPC/PowerPC.h +++ b/Source/Core/Core/PowerPC/PowerPC.h @@ -114,6 +114,7 @@ enum CPUState extern PowerPCState ppcState; +extern Watches watches; extern BreakPoints breakpoints; extern MemChecks memchecks; extern PPCDebugInterface debug_interface; diff --git a/Source/Core/DolphinWX/CMakeLists.txt b/Source/Core/DolphinWX/CMakeLists.txt index f00fa4ca05..0cf9153142 100644 --- a/Source/Core/DolphinWX/CMakeLists.txt +++ b/Source/Core/DolphinWX/CMakeLists.txt @@ -45,6 +45,8 @@ set(GUI_SRCS Debugger/MemoryWindow.cpp Debugger/RegisterView.cpp Debugger/RegisterWindow.cpp + Debugger/WatchView.cpp + Debugger/WatchWindow.cpp FifoPlayerDlg.cpp Frame.cpp FrameAui.cpp diff --git a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp index c6ad04e8b7..b34dfa29b5 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp @@ -52,6 +52,7 @@ #include "DolphinWX/Debugger/DebuggerUIUtil.h" #include "DolphinWX/Debugger/JitWindow.h" #include "DolphinWX/Debugger/RegisterWindow.h" +#include "DolphinWX/Debugger/WatchWindow.h" extern "C" // Bitmaps { @@ -93,6 +94,7 @@ CCodeWindow::CCodeWindow(const SCoreStartupParameter& _LocalCoreStartupParameter : wxPanel(parent, id, position, size, style, name) , Parent(parent) , m_RegisterWindow(nullptr) + , m_WatchWindow(nullptr) , m_BreakpointWindow(nullptr) , m_MemoryWindow(nullptr) , m_JitWindow(nullptr) @@ -152,6 +154,7 @@ void CCodeWindow::OnHostMessage(wxCommandEvent& event) Update(); if (codeview) codeview->Center(PC); if (m_RegisterWindow) m_RegisterWindow->NotifyUpdate(); + if (m_WatchWindow) m_WatchWindow->NotifyUpdate(); break; case IDM_UPDATEBREAKPOINTS: diff --git a/Source/Core/DolphinWX/Debugger/CodeWindow.h b/Source/Core/DolphinWX/Debugger/CodeWindow.h index dfe2ed0188..26322b1b90 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindow.h +++ b/Source/Core/DolphinWX/Debugger/CodeWindow.h @@ -19,6 +19,7 @@ class CFrame; class CRegisterWindow; +class CWatchWindow; class CBreakPointWindow; class CMemoryWindow; class CJitWindow; @@ -35,111 +36,113 @@ class wxMenuBar; class CCodeWindow : public wxPanel { public: - CCodeWindow(const SCoreStartupParameter& _LocalCoreStartupParameter, - CFrame * parent, - wxWindowID id = wxID_ANY, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxTAB_TRAVERSAL | wxBORDER_NONE, + CCodeWindow(const SCoreStartupParameter& _LocalCoreStartupParameter, + CFrame * parent, + wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTAB_TRAVERSAL | wxBORDER_NONE, const wxString& name = _("Code")); - void Load(); - void Save(); + void Load(); + void Save(); - // Parent interaction - CFrame *Parent; - wxMenuBar * GetMenuBar(); - wxToolBar * GetToolBar(); - wxBitmap m_Bitmaps[ToolbarDebugBitmapMax]; + // Parent interaction + CFrame *Parent; + wxMenuBar * GetMenuBar(); + wxToolBar * GetToolBar(); + wxBitmap m_Bitmaps[ToolbarDebugBitmapMax]; - bool UseInterpreter(); - bool BootToPause(); - bool AutomaticStart(); - bool JITNoBlockCache(); - bool JITNoBlockLinking(); - bool JumpToAddress(u32 address); + bool UseInterpreter(); + bool BootToPause(); + bool AutomaticStart(); + bool JITNoBlockCache(); + bool JITNoBlockLinking(); + bool JumpToAddress(u32 address); - void Update() override; - void NotifyMapLoaded(); - void CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParameter, wxMenuBar *pMenuBar); - void CreateMenuOptions(wxMenu *pMenu); - void CreateMenuSymbols(wxMenuBar *pMenuBar); - void RecreateToolbar(wxToolBar*); - void PopulateToolbar(wxToolBar* toolBar); - void UpdateButtonStates(); - void OpenPages(); - void UpdateManager(); + void Update() override; + void NotifyMapLoaded(); + void CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParameter, wxMenuBar *pMenuBar); + void CreateMenuOptions(wxMenu *pMenu); + void CreateMenuSymbols(wxMenuBar *pMenuBar); + void RecreateToolbar(wxToolBar*); + void PopulateToolbar(wxToolBar* toolBar); + void UpdateButtonStates(); + void OpenPages(); + void UpdateManager(); - // Menu bar - // ------------------- - void OnCPUMode(wxCommandEvent& event); // CPU Mode menu - void OnJITOff(wxCommandEvent& event); + // Menu bar + // ------------------- + void OnCPUMode(wxCommandEvent& event); // CPU Mode menu + void OnJITOff(wxCommandEvent& event); - void ToggleCodeWindow(bool bShow); - void ToggleRegisterWindow(bool bShow); - void ToggleBreakPointWindow(bool bShow); - void ToggleMemoryWindow(bool bShow); - void ToggleJitWindow(bool bShow); - void ToggleSoundWindow(bool bShow); - void ToggleVideoWindow(bool bShow); + void ToggleCodeWindow(bool bShow); + void ToggleRegisterWindow(bool bShow); + void ToggleWatchWindow(bool bShow); + void ToggleBreakPointWindow(bool bShow); + void ToggleMemoryWindow(bool bShow); + void ToggleJitWindow(bool bShow); + void ToggleSoundWindow(bool bShow); + void ToggleVideoWindow(bool bShow); - void OnChangeFont(wxCommandEvent& event); + void OnChangeFont(wxCommandEvent& event); - void OnCodeStep(wxCommandEvent& event); - void OnAddrBoxChange(wxCommandEvent& event); - void OnSymbolsMenu(wxCommandEvent& event); - void OnJitMenu(wxCommandEvent& event); - void OnProfilerMenu(wxCommandEvent& event); + void OnCodeStep(wxCommandEvent& event); + void OnAddrBoxChange(wxCommandEvent& event); + void OnSymbolsMenu(wxCommandEvent& event); + void OnJitMenu(wxCommandEvent& event); + void OnProfilerMenu(wxCommandEvent& event); - // Sub dialogs - CRegisterWindow* m_RegisterWindow; - CBreakPointWindow* m_BreakpointWindow; - CMemoryWindow* m_MemoryWindow; - CJitWindow* m_JitWindow; - DSPDebuggerLLE* m_SoundWindow; - GFXDebuggerPanel* m_VideoWindow; + // Sub dialogs + CRegisterWindow* m_RegisterWindow; + CWatchWindow* m_WatchWindow; + CBreakPointWindow* m_BreakpointWindow; + CMemoryWindow* m_MemoryWindow; + CJitWindow* m_JitWindow; + DSPDebuggerLLE* m_SoundWindow; + GFXDebuggerPanel* m_VideoWindow; - // Settings - bool bAutomaticStart; bool bBootToPause; - bool bShowOnStart[IDM_VIDEOWINDOW - IDM_LOGWINDOW + 1]; - int iNbAffiliation[IDM_CODEWINDOW - IDM_LOGWINDOW + 1]; + // Settings + bool bAutomaticStart; bool bBootToPause; + bool bShowOnStart[IDM_VIDEOWINDOW - IDM_LOGWINDOW + 1]; + int iNbAffiliation[IDM_CODEWINDOW - IDM_LOGWINDOW + 1]; private: - enum - { - // Debugger GUI Objects - ID_CODEVIEW, - ID_CALLSTACKLIST, - ID_CALLERSLIST, - ID_CALLSLIST, - ID_SYMBOLLIST - }; + enum + { + // Debugger GUI Objects + ID_CODEVIEW, + ID_CALLSTACKLIST, + ID_CALLERSLIST, + ID_CALLSLIST, + ID_SYMBOLLIST + }; - void OnSymbolListChange(wxCommandEvent& event); - void OnSymbolListContextMenu(wxContextMenuEvent& event); - void OnCallstackListChange(wxCommandEvent& event); - void OnCallersListChange(wxCommandEvent& event); - void OnCallsListChange(wxCommandEvent& event); - void OnCodeViewChange(wxCommandEvent &event); - void OnHostMessage(wxCommandEvent& event); + void OnSymbolListChange(wxCommandEvent& event); + void OnSymbolListContextMenu(wxContextMenuEvent& event); + void OnCallstackListChange(wxCommandEvent& event); + void OnCallersListChange(wxCommandEvent& event); + void OnCallsListChange(wxCommandEvent& event); + void OnCodeViewChange(wxCommandEvent &event); + void OnHostMessage(wxCommandEvent& event); - // Debugger functions - void SingleStep(); - void StepOver(); - void StepOut(); - void ToggleBreakpoint(); + // Debugger functions + void SingleStep(); + void StepOver(); + void StepOut(); + void ToggleBreakpoint(); - void UpdateLists(); - void UpdateCallstack(); + void UpdateLists(); + void UpdateCallstack(); - void InitBitmaps(); + void InitBitmaps(); - CCodeView* codeview; - wxListBox* callstack; - wxListBox* symbols; - wxListBox* callers; - wxListBox* calls; - Common::Event sync_event; + CCodeView* codeview; + wxListBox* callstack; + wxListBox* symbols; + wxListBox* callers; + wxListBox* calls; + Common::Event sync_event; - DECLARE_EVENT_TABLE() + DECLARE_EVENT_TABLE() }; diff --git a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp index fbf5820c0a..099d184bee 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp @@ -51,6 +51,7 @@ #include "DolphinWX/Debugger/JitWindow.h" #include "DolphinWX/Debugger/MemoryWindow.h" #include "DolphinWX/Debugger/RegisterWindow.h" +#include "DolphinWX/Debugger/WatchWindow.h" // Save and load settings @@ -421,6 +422,8 @@ void CCodeWindow::OpenPages() Parent->ToggleLogConfigWindow(true); if (bShowOnStart[IDM_REGISTERWINDOW - IDM_LOGWINDOW]) ToggleRegisterWindow(true); + if (bShowOnStart[IDM_WATCHWINDOW - IDM_LOGWINDOW]) + ToggleWatchWindow(true); if (bShowOnStart[IDM_BREAKPOINTWINDOW - IDM_LOGWINDOW]) ToggleBreakPointWindow(true); if (bShowOnStart[IDM_MEMORYWINDOW - IDM_LOGWINDOW]) @@ -461,6 +464,24 @@ void CCodeWindow::ToggleRegisterWindow(bool bShow) } } +void CCodeWindow::ToggleWatchWindow(bool bShow) +{ + GetMenuBar()->FindItem(IDM_WATCHWINDOW)->Check(bShow); + if (bShow) + { + if (!m_WatchWindow) + m_WatchWindow = new CWatchWindow(Parent, IDM_WATCHWINDOW); + Parent->DoAddPage(m_WatchWindow, + iNbAffiliation[IDM_WATCHWINDOW - IDM_LOGWINDOW], + Parent->bFloatWindow[IDM_WATCHWINDOW - IDM_LOGWINDOW]); + } + else // Close + { + Parent->DoRemovePage(m_WatchWindow, false); + m_WatchWindow = nullptr; + } +} + void CCodeWindow::ToggleBreakPointWindow(bool bShow) { GetMenuBar()->FindItem(IDM_BREAKPOINTWINDOW)->Check(bShow); diff --git a/Source/Core/DolphinWX/Debugger/MemoryView.cpp b/Source/Core/DolphinWX/Debugger/MemoryView.cpp index 0fd8f48746..f05c1b96fa 100644 --- a/Source/Core/DolphinWX/Debugger/MemoryView.cpp +++ b/Source/Core/DolphinWX/Debugger/MemoryView.cpp @@ -38,6 +38,7 @@ enum IDM_COPYCODE, IDM_RUNTOHERE, IDM_DYNARECRESULTS, + IDM_WATCHADDRESS, IDM_TOGGLEMEMORY, IDM_VIEWASFP, IDM_VIEWASASCII, @@ -180,6 +181,11 @@ void CMemoryView::OnPopupMenu(wxCommandEvent& event) break; #endif + case IDM_WATCHADDRESS: + debugger->AddWatch(selection); + Refresh(); + break; + case IDM_TOGGLEMEMORY: memory ^= 1; Refresh(); @@ -215,6 +221,7 @@ void CMemoryView::OnMouseDownR(wxMouseEvent& event) menu->Append(IDM_COPYADDRESS, _("Copy &address")); menu->Append(IDM_COPYHEX, _("Copy &hex")); #endif + menu->Append(IDM_WATCHADDRESS, _("Add to &watch")); menu->Append(IDM_TOGGLEMEMORY, _("Toggle &memory")); wxMenu* viewAsSubMenu = new wxMenu; diff --git a/Source/Core/DolphinWX/Debugger/WatchView.cpp b/Source/Core/DolphinWX/Debugger/WatchView.cpp new file mode 100644 index 0000000000..6982dd8816 --- /dev/null +++ b/Source/Core/DolphinWX/Debugger/WatchView.cpp @@ -0,0 +1,212 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include + +#include "Common/GekkoDisassembler.h" +#include "Core/HW/Memmap.h" +#include "Core/PowerPC/PowerPC.h" +#include "DolphinWX/WxUtils.h" +#include "DolphinWX/Debugger/DebuggerUIUtil.h" +#include "DolphinWX/Debugger/WatchView.h" + +class wxWindow; + +static std::string GetWatchName(int count) +{ + return PowerPC::watches.GetWatches().at(count - 1).name; +} + +static u32 GetWatchAddr(int count) +{ + return PowerPC::watches.GetWatches().at(count - 1).iAddress; +} + +static u32 GetWatchValue(int count) +{ + return Memory::ReadUnchecked_U32(GetWatchAddr(count)); +} + +static void AddWatchAddr(int count, u32 value) +{ + PowerPC::watches.Add(value); +} + +static void UpdateWatchAddr(int count, u32 value) +{ + PowerPC::watches.Update(count - 1, value); +} + +static void SetWatchName(int count, std::string value) +{ + PowerPC::watches.UpdateName(count - 1, value); +} + +static void SetWatchValue(int count, u32 value) +{ + Memory::WriteUnchecked_U32(value, GetWatchAddr(count)); +} + +wxString CWatchTable::GetValue(int row, int col) +{ + if (row == 0) + { + // Column Labels + switch (col) + { + case 0: return wxString::Format("Label"); + case 1: return wxString::Format("Addr"); + case 2: return wxString::Format("Hex"); + case 3: return wxString::Format("Dec"); + case 4: return wxString::Format("Str"); + default: return wxEmptyString; + } + } + else if (row <= PowerPC::watches.GetWatches().size()) + { + if (PowerPC::GetState() != PowerPC::CPU_POWERDOWN) + { + switch (col) + { + case 0: return wxString::Format("%s", GetWatchName(row)); + case 1: return wxString::Format("%08x", GetWatchAddr(row)); + case 2: return wxString::Format("%08x", GetWatchValue(row)); + case 3: return wxString::Format("%lu", GetWatchValue(row)); + case 4: + { + u32 addr = GetWatchAddr(row); + if (Memory::IsRAMAddress(addr)) + return Memory::GetString(addr, 32).c_str(); + else + return wxEmptyString; + } + default: return wxEmptyString; + } + } + } + return wxEmptyString; +} + +void CWatchTable::SetValue(int row, int col, const wxString& strNewVal) +{ + u32 newVal = 0; + if (col == 0 || TryParse("0x" + WxStrToStr(strNewVal), &newVal)) + { + if (row > 0) + { + switch (col) + { + case 0: + { + SetWatchName(row, std::string(WxStrToStr(strNewVal))); + break; + } + case 1: + { + if (row > (int)PowerPC::watches.GetWatches().size()) + { + AddWatchAddr(row, newVal); + row = (int)PowerPC::watches.GetWatches().size(); + } + else + { + UpdateWatchAddr(row, newVal); + } + break; + } + case 2: + { + SetWatchValue(row, newVal); + break; + } + default: + break; + } + } + } +} + +void CWatchTable::UpdateWatch() +{ + for (int i = 0; i < (int)PowerPC::watches.GetWatches().size(); ++i) + { + m_CachedWatchHasChanged[i] = (m_CachedWatch[i] != GetWatchValue(i + 1)); + m_CachedWatch[i] = GetWatchValue(i + 1); + } +} + +wxGridCellAttr *CWatchTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKind) +{ + wxGridCellAttr *attr = new wxGridCellAttr(); + + attr->SetBackgroundColour(*wxWHITE); + attr->SetFont(DebuggerFont); + + switch (col) + { + case 1: + attr->SetAlignment(wxALIGN_LEFT, wxALIGN_CENTER); + break; + case 3: + case 4: + attr->SetAlignment(wxALIGN_LEFT, wxALIGN_CENTER); + break; + default: + attr->SetAlignment(wxALIGN_LEFT, wxALIGN_CENTER); + break; + } + + if (row == 0) + { + attr->SetReadOnly(true); + attr->SetBackgroundColour(*wxBLACK); + attr->SetTextColour(*wxWHITE); + } + else + { + bool red = false; + switch (col) + { + case 1: red = m_CachedWatchHasChanged[row]; break; + } + + attr->SetTextColour(red ? *wxRED : *wxBLACK); + + if (row > (int)(PowerPC::watches.GetWatches().size() + 1)) + { + attr->SetReadOnly(true); + attr->SetBackgroundColour(*wxLIGHT_GREY); + } + } + attr->IncRef(); + return attr; +} + +CWatchView::CWatchView(wxWindow *parent, wxWindowID id) + : wxGrid(parent, id) +{ + SetTable(new CWatchTable(), false); + SetRowLabelSize(0); + SetColLabelSize(0); + DisableDragRowSize(); + + if (PowerPC::GetState() != PowerPC::CPU_POWERDOWN) + { + AutoSizeColumns(); + } +} + +void CWatchView::Update() +{ + if (PowerPC::GetState() != PowerPC::CPU_POWERDOWN) + { + ForceRefresh(); + ((CWatchTable *)GetTable())->UpdateWatch(); + } +} diff --git a/Source/Core/DolphinWX/Debugger/WatchView.h b/Source/Core/DolphinWX/Debugger/WatchView.h new file mode 100644 index 0000000000..4f093624a0 --- /dev/null +++ b/Source/Core/DolphinWX/Debugger/WatchView.h @@ -0,0 +1,50 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "Common/CommonTypes.h" + +class wxWindow; + +class CWatchTable : public wxGridTableBase +{ + enum + { + NUM_SPECIALS = 1, + MAX_SPECIALS = 256, + }; + +public: + CWatchTable() + { + } + + int GetNumberCols() override { return 5; } + int GetNumberRows() override { return MAX_SPECIALS; } + wxString GetValue(int row, int col) override; + void SetValue(int row, int col, const wxString &) override; + wxGridCellAttr *GetAttr(int, int, wxGridCellAttr::wxAttrKind) override; + void UpdateWatch(); + +private: + std::array m_CachedWatch; + std::array m_CachedWatchHasChanged; + + DECLARE_NO_COPY_CLASS(CWatchTable); +}; + +class CWatchView : public wxGrid +{ +public: + CWatchView(wxWindow* parent, wxWindowID id); + void Update() override; +}; diff --git a/Source/Core/DolphinWX/Debugger/WatchWindow.cpp b/Source/Core/DolphinWX/Debugger/WatchWindow.cpp new file mode 100644 index 0000000000..8f6f578b01 --- /dev/null +++ b/Source/Core/DolphinWX/Debugger/WatchWindow.cpp @@ -0,0 +1,46 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DolphinWX/Debugger/WatchView.h" +#include "DolphinWX/Debugger/WatchWindow.h" + +class wxWindow; + +BEGIN_EVENT_TABLE(CWatchWindow, wxPanel) +END_EVENT_TABLE() + + +CWatchWindow::CWatchWindow(wxWindow* parent, wxWindowID id, + const wxPoint& position, const wxSize& size, + long style, const wxString& name) + : wxPanel(parent, id, position, size, style, name) + , m_GPRGridView(nullptr) +{ + CreateGUIControls(); +} + +void CWatchWindow::CreateGUIControls() +{ + wxBoxSizer *sGrid = new wxBoxSizer(wxVERTICAL); + m_GPRGridView = new CWatchView(this, ID_GPR); + sGrid->Add(m_GPRGridView, 1, wxGROW); + SetSizer(sGrid); + + NotifyUpdate(); +} + +void CWatchWindow::NotifyUpdate() +{ + if (m_GPRGridView != nullptr) + m_GPRGridView->Update(); +} diff --git a/Source/Core/DolphinWX/Debugger/WatchWindow.h b/Source/Core/DolphinWX/Debugger/WatchWindow.h new file mode 100644 index 0000000000..9a3b9c4d67 --- /dev/null +++ b/Source/Core/DolphinWX/Debugger/WatchWindow.h @@ -0,0 +1,42 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +class CWatchView; +class wxWindow; + +class CWatchWindow + : public wxPanel +{ +public: + CWatchWindow(wxWindow* parent, + wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTAB_TRAVERSAL | wxNO_BORDER, + const wxString& name = _("Watch")); + + void NotifyUpdate(); + + +private: + DECLARE_EVENT_TABLE(); + + enum + { + ID_GPR = 1002 + }; + + CWatchView* m_GPRGridView; + void CreateGUIControls(); +}; diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj b/Source/Core/DolphinWX/DolphinWX.vcxproj index 124315d863..51026da88e 100644 --- a/Source/Core/DolphinWX/DolphinWX.vcxproj +++ b/Source/Core/DolphinWX/DolphinWX.vcxproj @@ -71,6 +71,8 @@ + + @@ -124,6 +126,8 @@ + + diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj.filters b/Source/Core/DolphinWX/DolphinWX.vcxproj.filters index b01a58d3f3..8e46985a83 100644 --- a/Source/Core/DolphinWX/DolphinWX.vcxproj.filters +++ b/Source/Core/DolphinWX/DolphinWX.vcxproj.filters @@ -90,6 +90,12 @@ GUI\Debugger + + GUI\Debugger + + + GUI\Debugger + GUI\InputConfig @@ -222,6 +228,12 @@ GUI\Debugger + + GUI\Debugger + + + GUI\Debugger + GUI\InputConfig @@ -303,4 +315,4 @@ - \ No newline at end of file + diff --git a/Source/Core/DolphinWX/FrameAui.cpp b/Source/Core/DolphinWX/FrameAui.cpp index 34d52068c1..3c44ab5920 100644 --- a/Source/Core/DolphinWX/FrameAui.cpp +++ b/Source/Core/DolphinWX/FrameAui.cpp @@ -179,6 +179,9 @@ void CFrame::OnToggleWindow(wxCommandEvent& event) case IDM_REGISTERWINDOW: g_pCodeWindow->ToggleRegisterWindow(bShow); break; + case IDM_WATCHWINDOW: + g_pCodeWindow->ToggleWatchWindow(bShow); + break; case IDM_BREAKPOINTWINDOW: g_pCodeWindow->ToggleBreakPointWindow(bShow); break; @@ -208,6 +211,7 @@ void CFrame::ClosePages() { g_pCodeWindow->ToggleCodeWindow(false); g_pCodeWindow->ToggleRegisterWindow(false); + g_pCodeWindow->ToggleWatchWindow(false); g_pCodeWindow->ToggleBreakPointWindow(false); g_pCodeWindow->ToggleMemoryWindow(false); g_pCodeWindow->ToggleJitWindow(false); @@ -247,6 +251,8 @@ void CFrame::OnNotebookPageClose(wxAuiNotebookEvent& event) ToggleLogConfigWindow(false); if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_REGISTERWINDOW) g_pCodeWindow->ToggleRegisterWindow(false); + if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_WATCHWINDOW) + g_pCodeWindow->ToggleWatchWindow(false); if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_BREAKPOINTWINDOW) g_pCodeWindow->ToggleBreakPointWindow(false); if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_JITWINDOW) diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index de080a8587..eb9c6632a7 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -285,6 +285,7 @@ wxMenuBar* CFrame::CreateMenu() const wxString MenuText[] = { wxTRANSLATE("&Registers"), + wxTRANSLATE("&Watch"), wxTRANSLATE("&Breakpoints"), wxTRANSLATE("&Memory"), wxTRANSLATE("&JIT"), diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h index 84b046f9ef..d8b83bd400 100644 --- a/Source/Core/DolphinWX/Globals.h +++ b/Source/Core/DolphinWX/Globals.h @@ -150,6 +150,7 @@ enum IDM_LOGWINDOW, IDM_LOGCONFIGWINDOW, IDM_REGISTERWINDOW, + IDM_WATCHWINDOW, IDM_BREAKPOINTWINDOW, IDM_MEMORYWINDOW, IDM_JITWINDOW, From d0a3bb765088b8d6f923ef62aac4761de332a12f Mon Sep 17 00:00:00 2001 From: skidau Date: Fri, 24 Oct 2014 00:47:00 +1100 Subject: [PATCH 05/14] Added "Add to watch" context menu items to the Memory and Register windows. Added "View memory" context menu item to the Register window. --- Source/Core/DolphinWX/Debugger/MemoryView.cpp | 9 +++ .../Core/DolphinWX/Debugger/RegisterView.cpp | 58 ++++++++++++++++++- Source/Core/DolphinWX/Debugger/RegisterView.h | 12 ++-- .../DolphinWX/Debugger/RegisterWindow.cpp | 3 + 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/Source/Core/DolphinWX/Debugger/MemoryView.cpp b/Source/Core/DolphinWX/Debugger/MemoryView.cpp index f05c1b96fa..4effea6520 100644 --- a/Source/Core/DolphinWX/Debugger/MemoryView.cpp +++ b/Source/Core/DolphinWX/Debugger/MemoryView.cpp @@ -25,10 +25,13 @@ #include "Common/DebugInterface.h" #include "Common/StringUtil.h" #include "Core/HW/Memmap.h" +#include "DolphinWX/Frame.h" #include "DolphinWX/Globals.h" #include "DolphinWX/WxUtils.h" +#include "DolphinWX/Debugger/CodeWindow.h" #include "DolphinWX/Debugger/DebuggerUIUtil.h" #include "DolphinWX/Debugger/MemoryView.h" +#include "DolphinWX/Debugger/WatchWindow.h" enum { @@ -162,6 +165,10 @@ void CMemoryView::OnScrollWheel(wxMouseEvent& event) void CMemoryView::OnPopupMenu(wxCommandEvent& event) { + CFrame* main_frame = (CFrame*)(GetParent()->GetParent()->GetParent()); + CCodeWindow* code_window = main_frame->g_pCodeWindow; + CWatchWindow* watch_window = code_window->m_WatchWindow; + #if wxUSE_CLIPBOARD wxTheClipboard->Open(); #endif @@ -183,6 +190,8 @@ void CMemoryView::OnPopupMenu(wxCommandEvent& event) case IDM_WATCHADDRESS: debugger->AddWatch(selection); + if (watch_window) + watch_window->NotifyUpdate(); Refresh(); break; diff --git a/Source/Core/DolphinWX/Debugger/RegisterView.cpp b/Source/Core/DolphinWX/Debugger/RegisterView.cpp index 6f13a4a2ba..9cf8f6809b 100644 --- a/Source/Core/DolphinWX/Debugger/RegisterView.cpp +++ b/Source/Core/DolphinWX/Debugger/RegisterView.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -15,14 +16,25 @@ #include "Core/HW/ProcessorInterface.h" #include "Core/PowerPC/Gekko.h" #include "Core/PowerPC/PowerPC.h" +#include "DolphinWX/Frame.h" +#include "DolphinWX/Globals.h" #include "DolphinWX/WxUtils.h" +#include "DolphinWX/Debugger/CodeWindow.h" #include "DolphinWX/Debugger/DebuggerUIUtil.h" +#include "DolphinWX/Debugger/MemoryWindow.h" #include "DolphinWX/Debugger/RegisterView.h" +#include "DolphinWX/Debugger/WatchWindow.h" class wxWindow; // F-zero 80005e60 wtf?? +enum +{ + IDM_WATCHADDRESS, + IDM_VIEWMEMORY, +}; + static const char *special_reg_names[] = { "PC", "LR", "CTR", "CR", "FPSCR", "MSR", "SRR0", "SRR1", "Exceptions", "Int Mask", "Int Cause", "DSISR", "DAR", "PT hashmask" }; @@ -49,7 +61,7 @@ static u32 GetSpecialRegValue(int reg) } } -wxString CRegTable::GetValue(int row, int col) +static wxString GetValueByRowCol(int row, int col) { if (row < 32) { @@ -130,6 +142,11 @@ wxString CRegTable::GetValue(int row, int col) return wxEmptyString; } +wxString CRegTable::GetValue(int row, int col) +{ + return GetValueByRowCol(row, col); +} + static void SetSpecialRegValue(int reg, u32 value) { switch (reg) @@ -246,3 +263,42 @@ void CRegisterView::Update() ForceRefresh(); ((CRegTable *)GetTable())->UpdateCachedRegs(); } + +void CRegisterView::OnMouseDownR(wxGridEvent& event) +{ + // popup menu + int row = event.GetRow(); + int col = event.GetCol(); + + wxString strNewVal = GetValueByRowCol(row, col); + TryParse("0x" + WxStrToStr(strNewVal), &addr); + + wxMenu* menu = new wxMenu; + menu->Append(IDM_WATCHADDRESS, _("Add to &watch")); + menu->Append(IDM_VIEWMEMORY, _("View &memory")); + PopupMenu(menu); +} + +void CRegisterView::OnPopupMenu(wxCommandEvent& event) +{ + CFrame* main_frame = (CFrame*)(GetParent()->GetParent()); + CCodeWindow* code_window = main_frame->g_pCodeWindow; + CWatchWindow* watch_window = code_window->m_WatchWindow; + CMemoryWindow* memory_window = code_window->m_MemoryWindow; + + switch (event.GetId()) + { + case IDM_WATCHADDRESS: + PowerPC::watches.Add(addr); + if (watch_window) + watch_window->NotifyUpdate(); + Refresh(); + break; + case IDM_VIEWMEMORY: + if (memory_window) + memory_window->JumpToAddress(addr); + Refresh(); + break; + } + event.Skip(); +} diff --git a/Source/Core/DolphinWX/Debugger/RegisterView.h b/Source/Core/DolphinWX/Debugger/RegisterView.h index 663d8734b5..959446083b 100644 --- a/Source/Core/DolphinWX/Debugger/RegisterView.h +++ b/Source/Core/DolphinWX/Debugger/RegisterView.h @@ -30,14 +30,13 @@ class wxWindow; // Interrupt Mask (PI) // Interrupt Cause(PI) +#define NUM_SPECIALS 14 + class CRegTable : public wxGridTableBase { - enum - { - NUM_SPECIALS = 14, - }; public: + CRegTable() { memset(m_CachedRegs, 0, sizeof(m_CachedRegs)); @@ -72,4 +71,9 @@ class CRegisterView : public wxGrid public: CRegisterView(wxWindow* parent, wxWindowID id); void Update() override; + void OnMouseDownR(wxGridEvent& event); + void OnPopupMenu(wxCommandEvent& event); + +private: + u32 addr = 0; }; diff --git a/Source/Core/DolphinWX/Debugger/RegisterWindow.cpp b/Source/Core/DolphinWX/Debugger/RegisterWindow.cpp index f385bf20d0..2e3d2611dd 100644 --- a/Source/Core/DolphinWX/Debugger/RegisterWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/RegisterWindow.cpp @@ -11,12 +11,15 @@ #include #include +#include "Core/PowerPC/PowerPC.h" #include "DolphinWX/Debugger/RegisterView.h" #include "DolphinWX/Debugger/RegisterWindow.h" class wxWindow; BEGIN_EVENT_TABLE(CRegisterWindow, wxPanel) +EVT_GRID_CELL_RIGHT_CLICK(CRegisterView::OnMouseDownR) +EVT_MENU(-1, CRegisterView::OnPopupMenu) END_EVENT_TABLE() From 290e1bed378d570667eb66170986696ca207d2d6 Mon Sep 17 00:00:00 2001 From: skidau Date: Fri, 24 Oct 2014 12:57:17 +1100 Subject: [PATCH 06/14] Disable block linking while debugger stepping or if there are breakpoints --- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 31 ++- Source/Core/Core/PowerPC/Jit64/Jit.h | 3 + Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp | 30 ++- Source/Core/Core/PowerPC/Jit64IL/JitIL.h | 3 + Source/Core/DolphinWX/Debugger/CodeWindow.cpp | 2 +- Source/Core/DolphinWX/Debugger/CodeWindow.h | 180 +++++++++--------- 6 files changed, 144 insertions(+), 105 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index d091db4ff3..2a5757d726 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -174,13 +174,8 @@ bool Jit64::HandleFault(uintptr_t access_address, SContext* ctx) void Jit64::Init() { jo.optimizeStack = true; - jo.enableBlocklink = true; - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITNoBlockLinking || - SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU) - { - // TODO: support block linking with MMU - jo.enableBlocklink = false; - } + EnableBlockLink(); + jo.fpAccurateFcmp = SConfig::GetInstance().m_LocalCoreStartupParameter.bFPRF; jo.optimizeGatherPipe = true; jo.fastInterrupts = false; @@ -521,11 +516,19 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) { + // We can link blocks as long as we are not single stepping and there are no breakpoints here + EnableBlockLink(); + // Comment out the following to disable breakpoints (speed-up) if (!Profiler::g_ProfileBlocks) { if (GetState() == CPU_STEPPING) + { blockSize = 1; + + // Do not link this block to other blocks While single stepping + jo.enableBlocklink = false; + } Trace(); } } @@ -715,6 +718,9 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING) { + // Turn off block linking if there are breakpoints so that the Step Over command does not link this block. + jo.enableBlocklink = false; + gpr.Flush(); fpr.Flush(); @@ -856,3 +862,14 @@ u32 Jit64::CallerSavedRegistersInUse() } return result & ABI_ALL_CALLER_SAVED; } + +void Jit64::EnableBlockLink() +{ + jo.enableBlocklink = true; + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITNoBlockLinking || + SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU) + { + // TODO: support block linking with MMU + jo.enableBlocklink = false; + } +} diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index 4dfbe56eb8..0cd48c5f57 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -64,6 +64,9 @@ public: ~Jit64() {} void Init() override; + + void EnableBlockLink(); + void Shutdown() override; bool HandleFault(uintptr_t access_address, SContext* ctx) override; diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp index 5a82a796e2..0f37c63c10 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp @@ -244,13 +244,7 @@ namespace JitILProfiler void JitIL::Init() { jo.optimizeStack = true; - jo.enableBlocklink = true; - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITNoBlockLinking || - SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU) - { - // TODO: support block linking with MMU - jo.enableBlocklink = false; - } + EnableBlockLink(); jo.fpAccurateFcmp = false; jo.optimizeGatherPipe = true; @@ -509,11 +503,19 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) { + // We can link blocks as long as we are not single stepping and there are no breakpoints here + EnableBlockLink(); + // Comment out the following to disable breakpoints (speed-up) if (!Profiler::g_ProfileBlocks) { if (GetState() == CPU_STEPPING) + { blockSize = 1; + + // Do not link this block to other blocks While single stepping + jo.enableBlocklink = false; + } Trace(); } } @@ -648,6 +650,9 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING) { + // Turn off block linking if there are breakpoints so that the Step Over command does not link this block. + jo.enableBlocklink = false; + ibuild.EmitBreakPointCheck(ibuild.EmitIntConst(ops[i].address)); } @@ -702,3 +707,14 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc return normalEntry; } + +void JitIL::EnableBlockLink() +{ + jo.enableBlocklink = true; + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITNoBlockLinking || + SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU) + { + // TODO: support block linking with MMU + jo.enableBlocklink = false; + } +} diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitIL.h b/Source/Core/Core/PowerPC/Jit64IL/JitIL.h index 8209cfc5a7..8afa6d9ae5 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/JitIL.h +++ b/Source/Core/Core/PowerPC/Jit64IL/JitIL.h @@ -47,6 +47,9 @@ public: // Initialization, etc void Init() override; + + void EnableBlockLink(); + void Shutdown() override; // Jit! diff --git a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp index b34dfa29b5..481240c498 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp @@ -310,10 +310,10 @@ void CCodeWindow::StepOver() { if (CCPU::IsStepping()) { - PowerPC::breakpoints.ClearAllTemporary(); UGeckoInstruction inst = Memory::Read_Instruction(PC); if (inst.LK) { + PowerPC::breakpoints.ClearAllTemporary(); PowerPC::breakpoints.Add(PC + 4, true); CCPU::EnableStepping(false); JumpToAddress(PC); diff --git a/Source/Core/DolphinWX/Debugger/CodeWindow.h b/Source/Core/DolphinWX/Debugger/CodeWindow.h index 26322b1b90..c0ac8650ca 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindow.h +++ b/Source/Core/DolphinWX/Debugger/CodeWindow.h @@ -36,113 +36,113 @@ class wxMenuBar; class CCodeWindow : public wxPanel { public: - CCodeWindow(const SCoreStartupParameter& _LocalCoreStartupParameter, - CFrame * parent, - wxWindowID id = wxID_ANY, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxTAB_TRAVERSAL | wxBORDER_NONE, + CCodeWindow(const SCoreStartupParameter& _LocalCoreStartupParameter, + CFrame * parent, + wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTAB_TRAVERSAL | wxBORDER_NONE, const wxString& name = _("Code")); - void Load(); - void Save(); + void Load(); + void Save(); - // Parent interaction - CFrame *Parent; - wxMenuBar * GetMenuBar(); - wxToolBar * GetToolBar(); - wxBitmap m_Bitmaps[ToolbarDebugBitmapMax]; + // Parent interaction + CFrame *Parent; + wxMenuBar * GetMenuBar(); + wxToolBar * GetToolBar(); + wxBitmap m_Bitmaps[ToolbarDebugBitmapMax]; - bool UseInterpreter(); - bool BootToPause(); - bool AutomaticStart(); - bool JITNoBlockCache(); - bool JITNoBlockLinking(); - bool JumpToAddress(u32 address); + bool UseInterpreter(); + bool BootToPause(); + bool AutomaticStart(); + bool JITNoBlockCache(); + bool JITNoBlockLinking(); + bool JumpToAddress(u32 address); - void Update() override; - void NotifyMapLoaded(); - void CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParameter, wxMenuBar *pMenuBar); - void CreateMenuOptions(wxMenu *pMenu); - void CreateMenuSymbols(wxMenuBar *pMenuBar); - void RecreateToolbar(wxToolBar*); - void PopulateToolbar(wxToolBar* toolBar); - void UpdateButtonStates(); - void OpenPages(); - void UpdateManager(); + void Update() override; + void NotifyMapLoaded(); + void CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParameter, wxMenuBar *pMenuBar); + void CreateMenuOptions(wxMenu *pMenu); + void CreateMenuSymbols(wxMenuBar *pMenuBar); + void RecreateToolbar(wxToolBar*); + void PopulateToolbar(wxToolBar* toolBar); + void UpdateButtonStates(); + void OpenPages(); + void UpdateManager(); - // Menu bar - // ------------------- - void OnCPUMode(wxCommandEvent& event); // CPU Mode menu - void OnJITOff(wxCommandEvent& event); + // Menu bar + // ------------------- + void OnCPUMode(wxCommandEvent& event); // CPU Mode menu + void OnJITOff(wxCommandEvent& event); - void ToggleCodeWindow(bool bShow); - void ToggleRegisterWindow(bool bShow); - void ToggleWatchWindow(bool bShow); - void ToggleBreakPointWindow(bool bShow); - void ToggleMemoryWindow(bool bShow); - void ToggleJitWindow(bool bShow); - void ToggleSoundWindow(bool bShow); - void ToggleVideoWindow(bool bShow); + void ToggleCodeWindow(bool bShow); + void ToggleRegisterWindow(bool bShow); + void ToggleWatchWindow(bool bShow); + void ToggleBreakPointWindow(bool bShow); + void ToggleMemoryWindow(bool bShow); + void ToggleJitWindow(bool bShow); + void ToggleSoundWindow(bool bShow); + void ToggleVideoWindow(bool bShow); - void OnChangeFont(wxCommandEvent& event); + void OnChangeFont(wxCommandEvent& event); - void OnCodeStep(wxCommandEvent& event); - void OnAddrBoxChange(wxCommandEvent& event); - void OnSymbolsMenu(wxCommandEvent& event); - void OnJitMenu(wxCommandEvent& event); - void OnProfilerMenu(wxCommandEvent& event); + void OnCodeStep(wxCommandEvent& event); + void OnAddrBoxChange(wxCommandEvent& event); + void OnSymbolsMenu(wxCommandEvent& event); + void OnJitMenu(wxCommandEvent& event); + void OnProfilerMenu(wxCommandEvent& event); - // Sub dialogs - CRegisterWindow* m_RegisterWindow; - CWatchWindow* m_WatchWindow; - CBreakPointWindow* m_BreakpointWindow; - CMemoryWindow* m_MemoryWindow; - CJitWindow* m_JitWindow; - DSPDebuggerLLE* m_SoundWindow; - GFXDebuggerPanel* m_VideoWindow; + // Sub dialogs + CRegisterWindow* m_RegisterWindow; + CWatchWindow* m_WatchWindow; + CBreakPointWindow* m_BreakpointWindow; + CMemoryWindow* m_MemoryWindow; + CJitWindow* m_JitWindow; + DSPDebuggerLLE* m_SoundWindow; + GFXDebuggerPanel* m_VideoWindow; - // Settings - bool bAutomaticStart; bool bBootToPause; - bool bShowOnStart[IDM_VIDEOWINDOW - IDM_LOGWINDOW + 1]; - int iNbAffiliation[IDM_CODEWINDOW - IDM_LOGWINDOW + 1]; + // Settings + bool bAutomaticStart; bool bBootToPause; + bool bShowOnStart[IDM_VIDEOWINDOW - IDM_LOGWINDOW + 1]; + int iNbAffiliation[IDM_CODEWINDOW - IDM_LOGWINDOW + 1]; private: - enum - { - // Debugger GUI Objects - ID_CODEVIEW, - ID_CALLSTACKLIST, - ID_CALLERSLIST, - ID_CALLSLIST, - ID_SYMBOLLIST - }; + enum + { + // Debugger GUI Objects + ID_CODEVIEW, + ID_CALLSTACKLIST, + ID_CALLERSLIST, + ID_CALLSLIST, + ID_SYMBOLLIST + }; - void OnSymbolListChange(wxCommandEvent& event); - void OnSymbolListContextMenu(wxContextMenuEvent& event); - void OnCallstackListChange(wxCommandEvent& event); - void OnCallersListChange(wxCommandEvent& event); - void OnCallsListChange(wxCommandEvent& event); - void OnCodeViewChange(wxCommandEvent &event); - void OnHostMessage(wxCommandEvent& event); + void OnSymbolListChange(wxCommandEvent& event); + void OnSymbolListContextMenu(wxContextMenuEvent& event); + void OnCallstackListChange(wxCommandEvent& event); + void OnCallersListChange(wxCommandEvent& event); + void OnCallsListChange(wxCommandEvent& event); + void OnCodeViewChange(wxCommandEvent &event); + void OnHostMessage(wxCommandEvent& event); - // Debugger functions - void SingleStep(); - void StepOver(); - void StepOut(); - void ToggleBreakpoint(); + // Debugger functions + void SingleStep(); + void StepOver(); + void StepOut(); + void ToggleBreakpoint(); - void UpdateLists(); - void UpdateCallstack(); + void UpdateLists(); + void UpdateCallstack(); - void InitBitmaps(); + void InitBitmaps(); - CCodeView* codeview; - wxListBox* callstack; - wxListBox* symbols; - wxListBox* callers; - wxListBox* calls; - Common::Event sync_event; + CCodeView* codeview; + wxListBox* callstack; + wxListBox* symbols; + wxListBox* callers; + wxListBox* calls; + Common::Event sync_event; - DECLARE_EVENT_TABLE() + DECLARE_EVENT_TABLE() }; From b34e220086a79a0e6f1824d2f7c94894a90d2998 Mon Sep 17 00:00:00 2001 From: skidau Date: Fri, 24 Oct 2014 17:16:54 +1100 Subject: [PATCH 07/14] Added a "Delete watch" context menu to the Watch window. Added a "View memory" command to the context menu. --- Source/Core/Common/BreakPoints.cpp | 2 +- Source/Core/Common/BreakPoints.h | 2 +- .../Core/DolphinWX/Debugger/RegisterView.cpp | 6 +- Source/Core/DolphinWX/Debugger/RegisterView.h | 2 +- Source/Core/DolphinWX/Debugger/WatchView.cpp | 67 ++++++++++++++++++- Source/Core/DolphinWX/Debugger/WatchView.h | 7 +- .../Core/DolphinWX/Debugger/WatchWindow.cpp | 2 + 7 files changed, 80 insertions(+), 8 deletions(-) diff --git a/Source/Core/Common/BreakPoints.cpp b/Source/Core/Common/BreakPoints.cpp index 50b4d56be5..8ef93758ab 100644 --- a/Source/Core/Common/BreakPoints.cpp +++ b/Source/Core/Common/BreakPoints.cpp @@ -219,7 +219,7 @@ void TMemCheck::Action(DebugInterface *debug_interface, u32 iValue, u32 addr, bo } -bool Watches::IsAddressWatch(u32 _iAddress) +const bool Watches::IsAddressWatch(u32 _iAddress) { for (const TWatch& bp : m_Watches) if (bp.iAddress == _iAddress) diff --git a/Source/Core/Common/BreakPoints.h b/Source/Core/Common/BreakPoints.h index cd18eedd60..73854b8167 100644 --- a/Source/Core/Common/BreakPoints.h +++ b/Source/Core/Common/BreakPoints.h @@ -118,7 +118,7 @@ public: TWatchesStr GetStrings() const; void AddFromStrings(const TWatchesStr& bps); - bool IsAddressWatch(u32 _iAddress); + const bool IsAddressWatch(u32 _iAddress); // Add BreakPoint void Add(u32 em_address); diff --git a/Source/Core/DolphinWX/Debugger/RegisterView.cpp b/Source/Core/DolphinWX/Debugger/RegisterView.cpp index 9cf8f6809b..928a709f88 100644 --- a/Source/Core/DolphinWX/Debugger/RegisterView.cpp +++ b/Source/Core/DolphinWX/Debugger/RegisterView.cpp @@ -271,7 +271,7 @@ void CRegisterView::OnMouseDownR(wxGridEvent& event) int col = event.GetCol(); wxString strNewVal = GetValueByRowCol(row, col); - TryParse("0x" + WxStrToStr(strNewVal), &addr); + TryParse("0x" + WxStrToStr(strNewVal), &m_selectedAddress); wxMenu* menu = new wxMenu; menu->Append(IDM_WATCHADDRESS, _("Add to &watch")); @@ -289,14 +289,14 @@ void CRegisterView::OnPopupMenu(wxCommandEvent& event) switch (event.GetId()) { case IDM_WATCHADDRESS: - PowerPC::watches.Add(addr); + PowerPC::watches.Add(m_selectedAddress); if (watch_window) watch_window->NotifyUpdate(); Refresh(); break; case IDM_VIEWMEMORY: if (memory_window) - memory_window->JumpToAddress(addr); + memory_window->JumpToAddress(m_selectedAddress); Refresh(); break; } diff --git a/Source/Core/DolphinWX/Debugger/RegisterView.h b/Source/Core/DolphinWX/Debugger/RegisterView.h index 959446083b..ef2cfbd705 100644 --- a/Source/Core/DolphinWX/Debugger/RegisterView.h +++ b/Source/Core/DolphinWX/Debugger/RegisterView.h @@ -75,5 +75,5 @@ public: void OnPopupMenu(wxCommandEvent& event); private: - u32 addr = 0; + u32 m_selectedAddress = 0; }; diff --git a/Source/Core/DolphinWX/Debugger/WatchView.cpp b/Source/Core/DolphinWX/Debugger/WatchView.cpp index 6982dd8816..590c71ae3a 100644 --- a/Source/Core/DolphinWX/Debugger/WatchView.cpp +++ b/Source/Core/DolphinWX/Debugger/WatchView.cpp @@ -6,18 +6,31 @@ #include #include #include +#include #include #include #include "Common/GekkoDisassembler.h" #include "Core/HW/Memmap.h" #include "Core/PowerPC/PowerPC.h" +#include "DolphinWX/Frame.h" #include "DolphinWX/WxUtils.h" +#include "DolphinWX/Debugger/CodeWindow.h" #include "DolphinWX/Debugger/DebuggerUIUtil.h" +#include "DolphinWX/Debugger/MemoryWindow.h" +#include "DolphinWX/Debugger/RegisterView.h" #include "DolphinWX/Debugger/WatchView.h" +#include "DolphinWX/Debugger/WatchWindow.h" class wxWindow; +enum +{ + IDM_DELETEWATCH, + IDM_VIEWMEMORY, +}; + + static std::string GetWatchName(int count) { return PowerPC::watches.GetWatches().at(count - 1).name; @@ -53,7 +66,7 @@ static void SetWatchValue(int count, u32 value) Memory::WriteUnchecked_U32(value, GetWatchAddr(count)); } -wxString CWatchTable::GetValue(int row, int col) +static wxString GetValueByRowCol(int row, int col) { if (row == 0) { @@ -93,6 +106,11 @@ wxString CWatchTable::GetValue(int row, int col) return wxEmptyString; } +wxString CWatchTable::GetValue(int row, int col) +{ + return GetValueByRowCol(row, col); +} + void CWatchTable::SetValue(int row, int col, const wxString& strNewVal) { u32 newVal = 0; @@ -210,3 +228,50 @@ void CWatchView::Update() ((CWatchTable *)GetTable())->UpdateWatch(); } } + +void CWatchView::OnMouseDownR(wxGridEvent& event) +{ + // popup menu + int row = event.GetRow(); + int col = event.GetCol(); + + if (col == 1 || col == 2) + { + wxString strNewVal = GetValueByRowCol(row, col); + TryParse("0x" + WxStrToStr(strNewVal), &m_selectedAddress); + m_selectedRow = row; + + wxMenu* menu = new wxMenu; + menu->Append(IDM_DELETEWATCH, _("&Delete watch")); + menu->Append(IDM_VIEWMEMORY, _("View &memory")); + PopupMenu(menu); + } +} + +void CWatchView::OnPopupMenu(wxCommandEvent& event) +{ + CFrame* main_frame = (CFrame*)(GetParent()->GetParent()); + CCodeWindow* code_window = main_frame->g_pCodeWindow; + CWatchWindow* watch_window = code_window->m_WatchWindow; + CMemoryWindow* memory_window = code_window->m_MemoryWindow; + + wxString strNewVal; + + switch (event.GetId()) + { + case IDM_DELETEWATCH: + strNewVal = GetValueByRowCol(m_selectedRow, 1); + TryParse("0x" + WxStrToStr(strNewVal), &m_selectedAddress); + PowerPC::watches.Remove(m_selectedAddress); + if (watch_window) + watch_window->NotifyUpdate(); + Refresh(); + break; + case IDM_VIEWMEMORY: + if (memory_window) + memory_window->JumpToAddress(m_selectedAddress); + Refresh(); + break; + } + event.Skip(); +} diff --git a/Source/Core/DolphinWX/Debugger/WatchView.h b/Source/Core/DolphinWX/Debugger/WatchView.h index 4f093624a0..dceaa0f3d7 100644 --- a/Source/Core/DolphinWX/Debugger/WatchView.h +++ b/Source/Core/DolphinWX/Debugger/WatchView.h @@ -19,7 +19,6 @@ class CWatchTable : public wxGridTableBase { enum { - NUM_SPECIALS = 1, MAX_SPECIALS = 256, }; @@ -47,4 +46,10 @@ class CWatchView : public wxGrid public: CWatchView(wxWindow* parent, wxWindowID id); void Update() override; + void OnMouseDownR(wxGridEvent& event); + void OnPopupMenu(wxCommandEvent& event); + +private: + u32 m_selectedAddress = 0; + u32 m_selectedRow = 0; }; diff --git a/Source/Core/DolphinWX/Debugger/WatchWindow.cpp b/Source/Core/DolphinWX/Debugger/WatchWindow.cpp index 8f6f578b01..7ac1630625 100644 --- a/Source/Core/DolphinWX/Debugger/WatchWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/WatchWindow.cpp @@ -17,6 +17,8 @@ class wxWindow; BEGIN_EVENT_TABLE(CWatchWindow, wxPanel) +EVT_GRID_CELL_RIGHT_CLICK(CWatchView::OnMouseDownR) +EVT_MENU(-1, CWatchView::OnPopupMenu) END_EVENT_TABLE() From b73130af77e4a978e7837a0e40431af768d2f34c Mon Sep 17 00:00:00 2001 From: skidau Date: Fri, 24 Oct 2014 22:24:17 +1100 Subject: [PATCH 08/14] Added Load/Save function for the Watch window. Made the floating windows toolbars dockable. Scaled down the breakpoint toolbar icons to 16x16. --- Source/Core/Common/BreakPoints.cpp | 4 +- .../DolphinWX/Debugger/BreakpointWindow.cpp | 8 +- .../Core/DolphinWX/Debugger/WatchWindow.cpp | 89 +++++++++++++++++-- Source/Core/DolphinWX/Debugger/WatchWindow.h | 7 +- 4 files changed, 96 insertions(+), 12 deletions(-) diff --git a/Source/Core/Common/BreakPoints.cpp b/Source/Core/Common/BreakPoints.cpp index 8ef93758ab..e0498e34d0 100644 --- a/Source/Core/Common/BreakPoints.cpp +++ b/Source/Core/Common/BreakPoints.cpp @@ -234,7 +234,7 @@ Watches::TWatchesStr Watches::GetStrings() const for (const TWatch& bp : m_Watches) { std::stringstream ss; - ss << std::hex << bp.iAddress << " " << (bp.bOn ? "n" : ""); + ss << std::hex << bp.iAddress << " " << bp.name; bps.push_back(ss.str()); } @@ -249,7 +249,7 @@ void Watches::AddFromStrings(const TWatchesStr& bpstrs) std::stringstream ss; ss << std::hex << bpstr; ss >> bp.iAddress; - bp.bOn = bpstr.find("n") != bpstr.npos; + ss >> bp.name; Add(bp); } } diff --git a/Source/Core/DolphinWX/Debugger/BreakpointWindow.cpp b/Source/Core/DolphinWX/Debugger/BreakpointWindow.cpp index a25800f372..1649991d44 100644 --- a/Source/Core/DolphinWX/Debugger/BreakpointWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/BreakpointWindow.cpp @@ -45,9 +45,9 @@ public: { SetToolBitmapSize(wxSize(24, 24)); - m_Bitmaps[Toolbar_Delete] = wxBitmap(wxGetBitmapFromMemory(toolbar_delete_png).ConvertToImage().Rescale(24, 24)); - m_Bitmaps[Toolbar_Add_BP] = wxBitmap(wxGetBitmapFromMemory(toolbar_add_breakpoint_png).ConvertToImage().Rescale(24, 24)); - m_Bitmaps[Toolbar_Add_MC] = wxBitmap(wxGetBitmapFromMemory(toolbar_add_memcheck_png).ConvertToImage().Rescale(24, 24)); + m_Bitmaps[Toolbar_Delete] = wxBitmap(wxGetBitmapFromMemory(toolbar_delete_png).ConvertToImage().Rescale(16, 16)); + m_Bitmaps[Toolbar_Add_BP] = wxBitmap(wxGetBitmapFromMemory(toolbar_add_breakpoint_png).ConvertToImage().Rescale(16, 16)); + m_Bitmaps[Toolbar_Add_MC] = wxBitmap(wxGetBitmapFromMemory(toolbar_add_memcheck_png).ConvertToImage().Rescale(16, 16)); AddTool(ID_DELETE, _("Delete"), m_Bitmaps[Toolbar_Delete]); Bind(wxEVT_TOOL, &CBreakPointWindow::OnDelete, parent, ID_DELETE); @@ -112,7 +112,7 @@ CBreakPointWindow::CBreakPointWindow(CCodeWindow* _pCodeWindow, wxWindow* parent m_BreakPointListView = new CBreakPointView(this, wxID_ANY); m_mgr.AddPane(new CBreakPointBar(this, wxID_ANY), wxAuiPaneInfo().ToolbarPane().Top(). - LeftDockable(false).RightDockable(false).BottomDockable(false).Floatable(false)); + LeftDockable(true).RightDockable(true).BottomDockable(false).Floatable(false)); m_mgr.AddPane(m_BreakPointListView, wxAuiPaneInfo().CenterPane()); m_mgr.Update(); } diff --git a/Source/Core/DolphinWX/Debugger/WatchWindow.cpp b/Source/Core/DolphinWX/Debugger/WatchWindow.cpp index 7ac1630625..dc25d32d4b 100644 --- a/Source/Core/DolphinWX/Debugger/WatchWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/WatchWindow.cpp @@ -3,6 +3,8 @@ // Refer to the license.txt file included. #include + +#include #include #include #include @@ -10,10 +12,19 @@ #include #include #include +#include +#include "Common/FileUtil.h" +#include "Common/IniFile.h" +#include "Core/PowerPC/PowerPC.h" +#include "DolphinWX/WxUtils.h" #include "DolphinWX/Debugger/WatchView.h" #include "DolphinWX/Debugger/WatchWindow.h" +extern "C" { +#include "DolphinWX/resources/toolbar_debugger_delete.c" +} + class wxWindow; BEGIN_EVENT_TABLE(CWatchWindow, wxPanel) @@ -21,6 +32,40 @@ EVT_GRID_CELL_RIGHT_CLICK(CWatchView::OnMouseDownR) EVT_MENU(-1, CWatchView::OnPopupMenu) END_EVENT_TABLE() +class CWatchToolbar : public wxAuiToolBar +{ +public: +CWatchToolbar(CWatchWindow* parent, const wxWindowID id) + : wxAuiToolBar(parent, id, wxDefaultPosition, wxDefaultSize, + wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_TEXT) +{ + SetToolBitmapSize(wxSize(16, 16)); + + m_Bitmaps[Toolbar_File] = wxBitmap(wxGetBitmapFromMemory(toolbar_delete_png).ConvertToImage().Rescale(16, 16)); + + AddTool(ID_LOAD, _("Load"), m_Bitmaps[Toolbar_File]); + Bind(wxEVT_TOOL, &CWatchWindow::LoadAll, parent, ID_LOAD); + + AddTool(ID_SAVE, _("Save"), m_Bitmaps[Toolbar_File]); + Bind(wxEVT_TOOL, &CWatchWindow::Event_SaveAll, parent, ID_SAVE); +} + +private: + + enum + { + Toolbar_File, + Num_Bitmaps + }; + + enum + { + ID_LOAD, + ID_SAVE + }; + + wxBitmap m_Bitmaps[Num_Bitmaps]; +}; CWatchWindow::CWatchWindow(wxWindow* parent, wxWindowID id, const wxPoint& position, const wxSize& size, @@ -28,17 +73,18 @@ CWatchWindow::CWatchWindow(wxWindow* parent, wxWindowID id, : wxPanel(parent, id, position, size, style, name) , m_GPRGridView(nullptr) { - CreateGUIControls(); -} + m_mgr.SetManagedWindow(this); + m_mgr.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_LIVE_RESIZE); -void CWatchWindow::CreateGUIControls() -{ wxBoxSizer *sGrid = new wxBoxSizer(wxVERTICAL); m_GPRGridView = new CWatchView(this, ID_GPR); sGrid->Add(m_GPRGridView, 1, wxGROW); SetSizer(sGrid); - NotifyUpdate(); + m_mgr.AddPane(new CWatchToolbar(this, wxID_ANY), wxAuiPaneInfo().ToolbarPane().Top(). + LeftDockable(true).RightDockable(true).BottomDockable(false).Floatable(false)); + m_mgr.AddPane(m_GPRGridView, wxAuiPaneInfo().CenterPane()); + m_mgr.Update(); } void CWatchWindow::NotifyUpdate() @@ -46,3 +92,36 @@ void CWatchWindow::NotifyUpdate() if (m_GPRGridView != nullptr) m_GPRGridView->Update(); } + +void CWatchWindow::Event_SaveAll(wxCommandEvent& WXUNUSED(event)) +{ + SaveAll(); +} + +void CWatchWindow::SaveAll() +{ + IniFile ini; + if (ini.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX))) + { + ini.SetLines("Watches", PowerPC::watches.GetStrings()); + ini.Save(File::GetUserPath(F_DEBUGGERCONFIG_IDX)); + } +} + +void CWatchWindow::LoadAll(wxCommandEvent& WXUNUSED(event)) +{ + IniFile ini; + Watches::TWatchesStr watches; + + if (!ini.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX))) + { + return; + } + + if (ini.GetLines("Watches", &watches, false)) + { + PowerPC::watches.AddFromStrings(watches); + } + + NotifyUpdate(); +} diff --git a/Source/Core/DolphinWX/Debugger/WatchWindow.h b/Source/Core/DolphinWX/Debugger/WatchWindow.h index 9a3b9c4d67..2f7dd75839 100644 --- a/Source/Core/DolphinWX/Debugger/WatchWindow.h +++ b/Source/Core/DolphinWX/Debugger/WatchWindow.h @@ -11,6 +11,7 @@ #include #include #include +#include class CWatchView; class wxWindow; @@ -27,11 +28,15 @@ public: const wxString& name = _("Watch")); void NotifyUpdate(); - + void Event_SaveAll(wxCommandEvent& WXUNUSED(event)); + void SaveAll(); + void LoadAll(wxCommandEvent& WXUNUSED(event)); private: DECLARE_EVENT_TABLE(); + wxAuiManager m_mgr; + enum { ID_GPR = 1002 From 8d2931cf1803234ced2429a6bf5dbb8b934e9f38 Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 25 Oct 2014 00:13:53 +1100 Subject: [PATCH 09/14] Breakpoints and watches are now loaded and saved on start/stop. Saved Breakpoints and watches per game in the game ini. --- .../DolphinWX/Debugger/BreakpointWindow.cpp | 25 +++++++++----- .../DolphinWX/Debugger/BreakpointWindow.h | 3 +- .../Core/DolphinWX/Debugger/WatchWindow.cpp | 26 ++++++++++----- Source/Core/DolphinWX/Debugger/WatchWindow.h | 4 ++- Source/Core/DolphinWX/FrameTools.cpp | 33 +++++++++++++++++++ 5 files changed, 72 insertions(+), 19 deletions(-) diff --git a/Source/Core/DolphinWX/Debugger/BreakpointWindow.cpp b/Source/Core/DolphinWX/Debugger/BreakpointWindow.cpp index 1649991d44..4e22b8fbdf 100644 --- a/Source/Core/DolphinWX/Debugger/BreakpointWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/BreakpointWindow.cpp @@ -19,6 +19,7 @@ #include "Common/CommonTypes.h" #include "Common/FileUtil.h" #include "Common/IniFile.h" +#include "Core/ConfigManager.h" #include "Core/HW/Memmap.h" #include "Core/PowerPC/PowerPC.h" #include "DolphinWX/WxUtils.h" @@ -66,7 +67,7 @@ public: } AddTool(ID_LOAD, _("Load"), m_Bitmaps[Toolbar_Delete]); - Bind(wxEVT_TOOL, &CBreakPointWindow::LoadAll, parent, ID_LOAD); + Bind(wxEVT_TOOL, &CBreakPointWindow::Event_LoadAll, parent, ID_LOAD); AddTool(ID_SAVE, _("Save"), m_Bitmaps[Toolbar_Delete]); Bind(wxEVT_TOOL, &CBreakPointWindow::Event_SaveAll, parent, ID_SAVE); @@ -180,32 +181,38 @@ void CBreakPointWindow::SaveAll() { // simply dump all to bp/mc files in a way we can read again IniFile ini; - if (ini.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX))) - { - ini.SetLines("BreakPoints", PowerPC::breakpoints.GetStrings()); - ini.SetLines("MemoryChecks", PowerPC::memchecks.GetStrings()); - ini.Save(File::GetUserPath(F_DEBUGGERCONFIG_IDX)); - } + ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID() + ".ini", false); + ini.SetLines("BreakPoints", PowerPC::breakpoints.GetStrings()); + ini.SetLines("MemoryChecks", PowerPC::memchecks.GetStrings()); + ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID() + ".ini"); } -void CBreakPointWindow::LoadAll(wxCommandEvent& WXUNUSED(event)) +void CBreakPointWindow::Event_LoadAll(wxCommandEvent& WXUNUSED(event)) +{ + LoadAll(); + return; +} + +void CBreakPointWindow::LoadAll() { IniFile ini; BreakPoints::TBreakPointsStr newbps; MemChecks::TMemChecksStr newmcs; - if (!ini.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX))) + if (!ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID() + ".ini", false)) { return; } if (ini.GetLines("BreakPoints", &newbps, false)) { + PowerPC::breakpoints.Clear(); PowerPC::breakpoints.AddFromStrings(newbps); } if (ini.GetLines("MemoryChecks", &newmcs, false)) { + PowerPC::memchecks.Clear(); PowerPC::memchecks.AddFromStrings(newmcs); } diff --git a/Source/Core/DolphinWX/Debugger/BreakpointWindow.h b/Source/Core/DolphinWX/Debugger/BreakpointWindow.h index 8c2ffc9a2b..03549a241c 100644 --- a/Source/Core/DolphinWX/Debugger/BreakpointWindow.h +++ b/Source/Core/DolphinWX/Debugger/BreakpointWindow.h @@ -39,7 +39,8 @@ public: void OnAddMemoryCheck(wxCommandEvent& WXUNUSED(event)); void Event_SaveAll(wxCommandEvent& WXUNUSED(event)); void SaveAll(); - void LoadAll(wxCommandEvent& WXUNUSED(event)); + void Event_LoadAll(wxCommandEvent& WXUNUSED(event)); + void LoadAll(); private: DECLARE_EVENT_TABLE(); diff --git a/Source/Core/DolphinWX/Debugger/WatchWindow.cpp b/Source/Core/DolphinWX/Debugger/WatchWindow.cpp index dc25d32d4b..ef192b7419 100644 --- a/Source/Core/DolphinWX/Debugger/WatchWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/WatchWindow.cpp @@ -16,6 +16,7 @@ #include "Common/FileUtil.h" #include "Common/IniFile.h" +#include "Core/ConfigManager.h" #include "Core/PowerPC/PowerPC.h" #include "DolphinWX/WxUtils.h" #include "DolphinWX/Debugger/WatchView.h" @@ -44,7 +45,7 @@ CWatchToolbar(CWatchWindow* parent, const wxWindowID id) m_Bitmaps[Toolbar_File] = wxBitmap(wxGetBitmapFromMemory(toolbar_delete_png).ConvertToImage().Rescale(16, 16)); AddTool(ID_LOAD, _("Load"), m_Bitmaps[Toolbar_File]); - Bind(wxEVT_TOOL, &CWatchWindow::LoadAll, parent, ID_LOAD); + Bind(wxEVT_TOOL, &CWatchWindow::Event_LoadAll, parent, ID_LOAD); AddTool(ID_SAVE, _("Save"), m_Bitmaps[Toolbar_File]); Bind(wxEVT_TOOL, &CWatchWindow::Event_SaveAll, parent, ID_SAVE); @@ -87,6 +88,11 @@ CWatchWindow::CWatchWindow(wxWindow* parent, wxWindowID id, m_mgr.Update(); } +CWatchWindow::~CWatchWindow() +{ + m_mgr.UnInit(); +} + void CWatchWindow::NotifyUpdate() { if (m_GPRGridView != nullptr) @@ -101,25 +107,29 @@ void CWatchWindow::Event_SaveAll(wxCommandEvent& WXUNUSED(event)) void CWatchWindow::SaveAll() { IniFile ini; - if (ini.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX))) - { - ini.SetLines("Watches", PowerPC::watches.GetStrings()); - ini.Save(File::GetUserPath(F_DEBUGGERCONFIG_IDX)); - } + ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID() + ".ini", false); + ini.SetLines("Watches", PowerPC::watches.GetStrings()); + ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID() + ".ini"); } -void CWatchWindow::LoadAll(wxCommandEvent& WXUNUSED(event)) +void CWatchWindow::Event_LoadAll(wxCommandEvent& WXUNUSED(event)) +{ + LoadAll(); +} + +void CWatchWindow::LoadAll() { IniFile ini; Watches::TWatchesStr watches; - if (!ini.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX))) + if (!ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID() + ".ini", false)) { return; } if (ini.GetLines("Watches", &watches, false)) { + PowerPC::watches.Clear(); PowerPC::watches.AddFromStrings(watches); } diff --git a/Source/Core/DolphinWX/Debugger/WatchWindow.h b/Source/Core/DolphinWX/Debugger/WatchWindow.h index 2f7dd75839..360974dcb3 100644 --- a/Source/Core/DolphinWX/Debugger/WatchWindow.h +++ b/Source/Core/DolphinWX/Debugger/WatchWindow.h @@ -26,11 +26,13 @@ public: const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL | wxNO_BORDER, const wxString& name = _("Watch")); + ~CWatchWindow(); void NotifyUpdate(); void Event_SaveAll(wxCommandEvent& WXUNUSED(event)); void SaveAll(); - void LoadAll(wxCommandEvent& WXUNUSED(event)); + void Event_LoadAll(wxCommandEvent& WXUNUSED(event)); + void LoadAll(); private: DECLARE_EVENT_TABLE(); diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index eb9c6632a7..2ef29ccecc 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -78,7 +78,9 @@ #include "DolphinWX/WXInputBase.h" #include "DolphinWX/WxUtils.h" #include "DolphinWX/Cheats/CheatsWindow.h" +#include "DolphinWX/Debugger/BreakpointWindow.h" #include "DolphinWX/Debugger/CodeWindow.h" +#include "DolphinWX/Debugger/WatchWindow.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" @@ -656,7 +658,19 @@ void CFrame::BootGame(const std::string& filename) } } if (!bootfile.empty()) + { StartGame(bootfile); + if (UseDebugger) + { + if (g_pCodeWindow) + { + if (g_pCodeWindow->m_WatchWindow) + g_pCodeWindow->m_WatchWindow->LoadAll(); + if (g_pCodeWindow->m_BreakpointWindow) + g_pCodeWindow->m_BreakpointWindow->LoadAll(); + } + } + } } // Open file to boot @@ -1163,6 +1177,25 @@ void CFrame::DoStop() } } + if (UseDebugger) + { + if (g_pCodeWindow) + { + if (g_pCodeWindow->m_WatchWindow) + { + g_pCodeWindow->m_WatchWindow->SaveAll(); + PowerPC::watches.Clear(); + } + if (g_pCodeWindow->m_BreakpointWindow) + { + g_pCodeWindow->m_BreakpointWindow->SaveAll(); + PowerPC::breakpoints.Clear(); + PowerPC::memchecks.Clear(); + g_pCodeWindow->m_BreakpointWindow->NotifyUpdate(); + } + } + } + // TODO: Show the author/description dialog here if (Movie::IsRecordingInput()) DoRecordingSave(); From 2a3a8520a2571de587786944ac7654ac29220933 Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 25 Oct 2014 01:04:20 +1100 Subject: [PATCH 10/14] Removed the EXRAM_MASK from the safe address check as it was causing invalid accesses on Wii games in DEBUGFAST builds --- Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp index 0e9853948a..13a33754bc 100644 --- a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp @@ -316,13 +316,6 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress, // The following masks the region used by the GC/Wii virtual memory lib mem_mask |= Memory::ADDR_MASK_MEM1; -#ifdef ENABLE_MEM_CHECK - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) - { - mem_mask |= Memory::EXRAM_MASK; - } -#endif - if (opAddress.IsImm()) { u32 address = (u32)opAddress.offset + offset; @@ -519,13 +512,6 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces // The following masks the region used by the GC/Wii virtual memory lib mem_mask |= Memory::ADDR_MASK_MEM1; -#ifdef ENABLE_MEM_CHECK - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) - { - mem_mask |= Memory::EXRAM_MASK; - } -#endif - bool swap = !(flags & SAFE_LOADSTORE_NO_SWAP); FixupBranch slow, exit; From 73dca1ca33c4699ac6a3f38e9bfb824983af56cb Mon Sep 17 00:00:00 2001 From: skidau Date: Sun, 26 Oct 2014 16:14:17 +1100 Subject: [PATCH 11/14] Added a new option to add memchecks from the Watch window. Fixed watch labels from being truncated at the first whitespace. --- Source/Core/Common/BreakPoints.cpp | 3 +- Source/Core/DolphinWX/Debugger/WatchView.cpp | 46 +++++++++++++++----- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/Source/Core/Common/BreakPoints.cpp b/Source/Core/Common/BreakPoints.cpp index e0498e34d0..ece8add228 100644 --- a/Source/Core/Common/BreakPoints.cpp +++ b/Source/Core/Common/BreakPoints.cpp @@ -249,7 +249,8 @@ void Watches::AddFromStrings(const TWatchesStr& bpstrs) std::stringstream ss; ss << std::hex << bpstr; ss >> bp.iAddress; - ss >> bp.name; + ss >> std::ws; + getline(ss, bp.name); Add(bp); } } diff --git a/Source/Core/DolphinWX/Debugger/WatchView.cpp b/Source/Core/DolphinWX/Debugger/WatchView.cpp index 590c71ae3a..a66ac40961 100644 --- a/Source/Core/DolphinWX/Debugger/WatchView.cpp +++ b/Source/Core/DolphinWX/Debugger/WatchView.cpp @@ -15,6 +15,7 @@ #include "Core/PowerPC/PowerPC.h" #include "DolphinWX/Frame.h" #include "DolphinWX/WxUtils.h" +#include "DolphinWX/Debugger/BreakpointWindow.h" #include "DolphinWX/Debugger/CodeWindow.h" #include "DolphinWX/Debugger/DebuggerUIUtil.h" #include "DolphinWX/Debugger/MemoryWindow.h" @@ -27,6 +28,7 @@ class wxWindow; enum { IDM_DELETEWATCH, + IDM_ADDMEMCHECK, IDM_VIEWMEMORY, }; @@ -196,7 +198,7 @@ wxGridCellAttr *CWatchTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKin attr->SetTextColour(red ? *wxRED : *wxBLACK); - if (row > (int)(PowerPC::watches.GetWatches().size() + 1)) + if (row > (int)(PowerPC::watches.GetWatches().size() + 1) || (PowerPC::GetState() == PowerPC::CPU_POWERDOWN)) { attr->SetReadOnly(true); attr->SetBackgroundColour(*wxLIGHT_GREY); @@ -213,11 +215,6 @@ CWatchView::CWatchView(wxWindow *parent, wxWindowID id) SetRowLabelSize(0); SetColLabelSize(0); DisableDragRowSize(); - - if (PowerPC::GetState() != PowerPC::CPU_POWERDOWN) - { - AutoSizeColumns(); - } } void CWatchView::Update() @@ -235,17 +232,26 @@ void CWatchView::OnMouseDownR(wxGridEvent& event) int row = event.GetRow(); int col = event.GetCol(); + m_selectedRow = row; + if (col == 1 || col == 2) { wxString strNewVal = GetValueByRowCol(row, col); TryParse("0x" + WxStrToStr(strNewVal), &m_selectedAddress); - m_selectedRow = row; - - wxMenu* menu = new wxMenu; - menu->Append(IDM_DELETEWATCH, _("&Delete watch")); - menu->Append(IDM_VIEWMEMORY, _("View &memory")); - PopupMenu(menu); } + + wxMenu* menu = new wxMenu; + if (row != 0 && row != (int)(PowerPC::watches.GetWatches().size() + 1)) + menu->Append(IDM_DELETEWATCH, _("&Delete watch")); + + if (row != 0 && row != (int)(PowerPC::watches.GetWatches().size() + 1) && (col == 1 || col == 2)) + { +#ifdef ENABLE_MEM_CHECK + menu->Append(IDM_ADDMEMCHECK, _("Add memory &breakpoint")); +#endif + menu->Append(IDM_VIEWMEMORY, _("View &memory")); + } + PopupMenu(menu); } void CWatchView::OnPopupMenu(wxCommandEvent& event) @@ -254,8 +260,10 @@ void CWatchView::OnPopupMenu(wxCommandEvent& event) CCodeWindow* code_window = main_frame->g_pCodeWindow; CWatchWindow* watch_window = code_window->m_WatchWindow; CMemoryWindow* memory_window = code_window->m_MemoryWindow; + CBreakPointWindow* breakpoint_window = code_window->m_BreakpointWindow; wxString strNewVal; + TMemCheck MemCheck; switch (event.GetId()) { @@ -267,6 +275,20 @@ void CWatchView::OnPopupMenu(wxCommandEvent& event) watch_window->NotifyUpdate(); Refresh(); break; + case IDM_ADDMEMCHECK: + MemCheck.StartAddress = m_selectedAddress; + MemCheck.EndAddress = m_selectedAddress; + MemCheck.bRange = m_selectedAddress != m_selectedAddress; + MemCheck.OnRead = true; + MemCheck.OnWrite = true; + MemCheck.Log = true; + MemCheck.Break = true; + PowerPC::memchecks.Add(MemCheck); + + if (breakpoint_window) + breakpoint_window->NotifyUpdate(); + Refresh(); + break; case IDM_VIEWMEMORY: if (memory_window) memory_window->JumpToAddress(m_selectedAddress); From 7eebbcdca7f5dff60aff387f789bc1292905c68a Mon Sep 17 00:00:00 2001 From: skidau Date: Sun, 26 Oct 2014 21:19:22 +1100 Subject: [PATCH 12/14] Fixed a crash that would occur when old symbol information was reused --- Source/Core/DolphinWX/FrameTools.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 2ef29ccecc..c4a8009017 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -58,6 +58,7 @@ #include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h" #include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/PowerPC/PPCSymbolDB.h" #include "DiscIO/NANDContentLoader.h" @@ -1193,6 +1194,8 @@ void CFrame::DoStop() PowerPC::memchecks.Clear(); g_pCodeWindow->m_BreakpointWindow->NotifyUpdate(); } + g_symbolDB.Clear(); + Host_NotifyMapLoaded(); } } From 4570dd7eeb9033c0e349d3a9f0126f24010b0699 Mon Sep 17 00:00:00 2001 From: skidau Date: Sun, 26 Oct 2014 23:23:45 +1100 Subject: [PATCH 13/14] Fixed a crash that would occur if a new watch were added by entering a watch name. Code style updates. --- Source/Core/Common/BreakPoints.cpp | 2 +- Source/Core/Common/BreakPoints.h | 2 +- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 2 +- Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp | 2 +- Source/Core/DolphinWX/Debugger/CodeWindow.cpp | 2 +- Source/Core/DolphinWX/Debugger/WatchView.cpp | 38 ++++++++++------- Source/Core/DolphinWX/Debugger/WatchView.h | 4 +- Source/Core/DolphinWX/Debugger/WatchWindow.h | 10 ++--- Source/Core/DolphinWX/FrameTools.cpp | 42 ++++++++----------- 9 files changed, 53 insertions(+), 51 deletions(-) diff --git a/Source/Core/Common/BreakPoints.cpp b/Source/Core/Common/BreakPoints.cpp index ece8add228..8772a2287f 100644 --- a/Source/Core/Common/BreakPoints.cpp +++ b/Source/Core/Common/BreakPoints.cpp @@ -280,7 +280,7 @@ void Watches::Update(int count, u32 em_address) m_Watches.at(count).iAddress = em_address; } -void Watches::UpdateName(int count, std::string name) +void Watches::UpdateName(int count, const std::string name) { m_Watches.at(count).name = name; } diff --git a/Source/Core/Common/BreakPoints.h b/Source/Core/Common/BreakPoints.h index 73854b8167..7534f41400 100644 --- a/Source/Core/Common/BreakPoints.h +++ b/Source/Core/Common/BreakPoints.h @@ -125,7 +125,7 @@ public: void Add(const TWatch& bp); void Update(int count, u32 em_address); - void UpdateName(int count, std::string name); + void UpdateName(int count, const std::string name); // Remove Breakpoint void Remove(u32 _iAddress); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 2a5757d726..021ab386c4 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -867,7 +867,7 @@ void Jit64::EnableBlockLink() { jo.enableBlocklink = true; if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITNoBlockLinking || - SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU) + SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU) { // TODO: support block linking with MMU jo.enableBlocklink = false; diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp index 0f37c63c10..65f86d92cf 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp @@ -712,7 +712,7 @@ void JitIL::EnableBlockLink() { jo.enableBlocklink = true; if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITNoBlockLinking || - SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU) + SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU) { // TODO: support block linking with MMU jo.enableBlocklink = false; diff --git a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp index 481240c498..35678e43dd 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp @@ -342,7 +342,7 @@ void CCodeWindow::StepOut() PowerPC::CoreMode oldMode = PowerPC::GetMode(); PowerPC::SetMode(PowerPC::MODE_INTERPRETER); UGeckoInstruction inst = Memory::Read_Instruction(PC); - GekkoOPInfo *opinfo = GetOpInfo(inst); + GekkoOPInfo* opinfo = GetOpInfo(inst); while (inst.hex != 0x4e800020 && steps < timeout) // check for blr { if (inst.LK) diff --git a/Source/Core/DolphinWX/Debugger/WatchView.cpp b/Source/Core/DolphinWX/Debugger/WatchView.cpp index a66ac40961..ea905a0f71 100644 --- a/Source/Core/DolphinWX/Debugger/WatchView.cpp +++ b/Source/Core/DolphinWX/Debugger/WatchView.cpp @@ -58,9 +58,17 @@ static void UpdateWatchAddr(int count, u32 value) PowerPC::watches.Update(count - 1, value); } -static void SetWatchName(int count, std::string value) +static void SetWatchName(int count, const std::string value) { - PowerPC::watches.UpdateName(count - 1, value); + if ((count - 1) < PowerPC::watches.GetWatches().size()) + { + PowerPC::watches.UpdateName(count - 1, value); + } + else + { + PowerPC::watches.Add(0); + PowerPC::watches.UpdateName(PowerPC::watches.GetWatches().size() - 1, value); + } } static void SetWatchValue(int count, u32 value) @@ -97,7 +105,7 @@ static wxString GetValueByRowCol(int row, int col) { u32 addr = GetWatchAddr(row); if (Memory::IsRAMAddress(addr)) - return Memory::GetString(addr, 32).c_str(); + return Memory::GetString(addr, 32).c_str(); else return wxEmptyString; } @@ -161,9 +169,9 @@ void CWatchTable::UpdateWatch() } } -wxGridCellAttr *CWatchTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKind) +wxGridCellAttr* CWatchTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKind) { - wxGridCellAttr *attr = new wxGridCellAttr(); + wxGridCellAttr* attr = new wxGridCellAttr(); attr->SetBackgroundColour(*wxWHITE); attr->SetFont(DebuggerFont); @@ -191,10 +199,8 @@ wxGridCellAttr *CWatchTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKin else { bool red = false; - switch (col) - { - case 1: red = m_CachedWatchHasChanged[row]; break; - } + if (col == 1) + red = m_CachedWatchHasChanged[row]; attr->SetTextColour(red ? *wxRED : *wxBLACK); @@ -208,7 +214,7 @@ wxGridCellAttr *CWatchTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKin return attr; } -CWatchView::CWatchView(wxWindow *parent, wxWindowID id) +CWatchView::CWatchView(wxWindow* parent, wxWindowID id) : wxGrid(parent, id) { SetTable(new CWatchTable(), false); @@ -269,11 +275,13 @@ void CWatchView::OnPopupMenu(wxCommandEvent& event) { case IDM_DELETEWATCH: strNewVal = GetValueByRowCol(m_selectedRow, 1); - TryParse("0x" + WxStrToStr(strNewVal), &m_selectedAddress); - PowerPC::watches.Remove(m_selectedAddress); - if (watch_window) - watch_window->NotifyUpdate(); - Refresh(); + if (TryParse("0x" + WxStrToStr(strNewVal), &m_selectedAddress)) + { + PowerPC::watches.Remove(m_selectedAddress); + if (watch_window) + watch_window->NotifyUpdate(); + Refresh(); + } break; case IDM_ADDMEMCHECK: MemCheck.StartAddress = m_selectedAddress; diff --git a/Source/Core/DolphinWX/Debugger/WatchView.h b/Source/Core/DolphinWX/Debugger/WatchView.h index dceaa0f3d7..e879696f72 100644 --- a/Source/Core/DolphinWX/Debugger/WatchView.h +++ b/Source/Core/DolphinWX/Debugger/WatchView.h @@ -30,8 +30,8 @@ public: int GetNumberCols() override { return 5; } int GetNumberRows() override { return MAX_SPECIALS; } wxString GetValue(int row, int col) override; - void SetValue(int row, int col, const wxString &) override; - wxGridCellAttr *GetAttr(int, int, wxGridCellAttr::wxAttrKind) override; + void SetValue(int row, int col, const wxString&) override; + wxGridCellAttr* GetAttr(int, int, wxGridCellAttr::wxAttrKind) override; void UpdateWatch(); private: diff --git a/Source/Core/DolphinWX/Debugger/WatchWindow.h b/Source/Core/DolphinWX/Debugger/WatchWindow.h index 360974dcb3..8c070768cd 100644 --- a/Source/Core/DolphinWX/Debugger/WatchWindow.h +++ b/Source/Core/DolphinWX/Debugger/WatchWindow.h @@ -21,11 +21,11 @@ class CWatchWindow { public: CWatchWindow(wxWindow* parent, - wxWindowID id = wxID_ANY, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxTAB_TRAVERSAL | wxNO_BORDER, - const wxString& name = _("Watch")); + wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTAB_TRAVERSAL | wxNO_BORDER, + const wxString& name = _("Watch")); ~CWatchWindow(); void NotifyUpdate(); diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index c4a8009017..0c27b52308 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -661,15 +661,12 @@ void CFrame::BootGame(const std::string& filename) if (!bootfile.empty()) { StartGame(bootfile); - if (UseDebugger) + if (UseDebugger && g_pCodeWindow) { - if (g_pCodeWindow) - { - if (g_pCodeWindow->m_WatchWindow) - g_pCodeWindow->m_WatchWindow->LoadAll(); - if (g_pCodeWindow->m_BreakpointWindow) - g_pCodeWindow->m_BreakpointWindow->LoadAll(); - } + if (g_pCodeWindow->m_WatchWindow) + g_pCodeWindow->m_WatchWindow->LoadAll(); + if (g_pCodeWindow->m_BreakpointWindow) + g_pCodeWindow->m_BreakpointWindow->LoadAll(); } } } @@ -1178,25 +1175,22 @@ void CFrame::DoStop() } } - if (UseDebugger) + if (UseDebugger && g_pCodeWindow) { - if (g_pCodeWindow) + if (g_pCodeWindow->m_WatchWindow) { - if (g_pCodeWindow->m_WatchWindow) - { - g_pCodeWindow->m_WatchWindow->SaveAll(); - PowerPC::watches.Clear(); - } - if (g_pCodeWindow->m_BreakpointWindow) - { - g_pCodeWindow->m_BreakpointWindow->SaveAll(); - PowerPC::breakpoints.Clear(); - PowerPC::memchecks.Clear(); - g_pCodeWindow->m_BreakpointWindow->NotifyUpdate(); - } - g_symbolDB.Clear(); - Host_NotifyMapLoaded(); + g_pCodeWindow->m_WatchWindow->SaveAll(); + PowerPC::watches.Clear(); } + if (g_pCodeWindow->m_BreakpointWindow) + { + g_pCodeWindow->m_BreakpointWindow->SaveAll(); + PowerPC::breakpoints.Clear(); + PowerPC::memchecks.Clear(); + g_pCodeWindow->m_BreakpointWindow->NotifyUpdate(); + } + g_symbolDB.Clear(); + Host_NotifyMapLoaded(); } // TODO: Show the author/description dialog here From daf977e84e82d5687bdad7589541319b4288a5dd Mon Sep 17 00:00:00 2001 From: skidau Date: Mon, 27 Oct 2014 23:38:45 +1100 Subject: [PATCH 14/14] Disabled optimizations, block merging and instruction skipping code while the debugger is stepping. --- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 17 +++++++--- Source/Core/Core/PowerPC/Jit64/Jit.h | 2 ++ .../Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp | 10 ++++-- .../PowerPC/Jit64/Jit_SystemRegisters.cpp | 33 ++++++++++--------- .../JitILCommon/JitILBase_LoadStore.cpp | 1 + 5 files changed, 41 insertions(+), 22 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 021ab386c4..1a2729fac4 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -190,7 +190,7 @@ void Jit64::Init() // BLR optimization has the same consequences as block linking, as well as // depending on the fault handler to be safe in the event of excessive BL. - m_enable_blr_optimization = jo.enableBlocklink && SConfig::GetInstance().m_LocalCoreStartupParameter.bFastmem; + m_enable_blr_optimization = jo.enableBlocklink && SConfig::GetInstance().m_LocalCoreStartupParameter.bFastmem && !SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging; m_clear_cache_asap = false; m_stack = nullptr; @@ -207,9 +207,7 @@ void Jit64::Init() code_block.m_stats = &js.st; code_block.m_gpa = &js.gpa; code_block.m_fpa = &js.fpa; - analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE); - analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_BRANCH_MERGE); - analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_CARRY_MERGE); + EnableOptimization(); } void Jit64::ClearCache() @@ -518,6 +516,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc { // We can link blocks as long as we are not single stepping and there are no breakpoints here EnableBlockLink(); + EnableOptimization(); // Comment out the following to disable breakpoints (speed-up) if (!Profiler::g_ProfileBlocks) @@ -528,6 +527,9 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc // Do not link this block to other blocks While single stepping jo.enableBlocklink = false; + analyzer.ClearOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE); + analyzer.ClearOption(PPCAnalyst::PPCAnalyzer::OPTION_BRANCH_MERGE); + analyzer.ClearOption(PPCAnalyst::PPCAnalyzer::OPTION_CARRY_MERGE); } Trace(); } @@ -873,3 +875,10 @@ void Jit64::EnableBlockLink() jo.enableBlocklink = false; } } + +void Jit64::EnableOptimization() +{ + analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE); + analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_BRANCH_MERGE); + analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_CARRY_MERGE); +} diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index 0cd48c5f57..7fe8b75506 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -65,6 +65,8 @@ public: void Init() override; + void EnableOptimization(); + void EnableBlockLink(); void Shutdown() override; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp index a2abade26b..bb52cb66e5 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp @@ -98,9 +98,12 @@ void Jit64::lXXx(UGeckoInstruction inst) if (accessSize == 8 && js.next_inst.OPCD == 31 && js.next_inst.SUBOP10 == 954 && js.next_inst.RS == inst.RD && js.next_inst.RA == inst.RD && !js.next_inst.Rc) { - js.downcountAmount++; - js.skipnext = true; - signExtend = true; + if (PowerPC::GetState() != PowerPC::CPU_STEPPING) + { + js.downcountAmount++; + js.skipnext = true; + signExtend = true; + } } // TODO(ector): Make it dynamically enable/disable idle skipping where appropriate @@ -109,6 +112,7 @@ void Jit64::lXXx(UGeckoInstruction inst) // IMHO those Idles should always be skipped and replaced by a more controllable "native" Idle methode // ... maybe the throttle one already do that :p if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle && + PowerPC::GetState() != PowerPC::CPU_STEPPING && inst.OPCD == 32 && (inst.hex & 0xFFFF0000) == 0x800D0000 && (Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 || diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp index 2aedc09c8b..73f4630e83 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -228,21 +228,24 @@ void Jit64::mfspr(UGeckoInstruction inst) // Be careful; the actual opcode is for mftb (371), not mfspr (339) if (js.next_inst.OPCD == 31 && js.next_inst.SUBOP10 == 371 && (nextIndex == SPR_TU || nextIndex == SPR_TL)) { - int n = js.next_inst.RD; - js.downcountAmount++; - js.skipnext = true; - gpr.Lock(d, n); - gpr.BindToRegister(d, false); - gpr.BindToRegister(n, false); - if (iIndex == SPR_TL) - MOV(32, gpr.R(d), R(RAX)); - if (nextIndex == SPR_TL) - MOV(32, gpr.R(n), R(RAX)); - SHR(64, R(RAX), Imm8(32)); - if (iIndex == SPR_TU) - MOV(32, gpr.R(d), R(RAX)); - if (nextIndex == SPR_TU) - MOV(32, gpr.R(n), R(RAX)); + if (PowerPC::GetState() != PowerPC::CPU_STEPPING) + { + int n = js.next_inst.RD; + js.downcountAmount++; + js.skipnext = true; + gpr.Lock(d, n); + gpr.BindToRegister(d, false); + gpr.BindToRegister(n, false); + if (iIndex == SPR_TL) + MOV(32, gpr.R(d), R(RAX)); + if (nextIndex == SPR_TL) + MOV(32, gpr.R(n), R(RAX)); + SHR(64, R(RAX), Imm8(32)); + if (iIndex == SPR_TU) + MOV(32, gpr.R(d), R(RAX)); + if (nextIndex == SPR_TU) + MOV(32, gpr.R(n), R(RAX)); + } } else { diff --git a/Source/Core/Core/PowerPC/JitILCommon/JitILBase_LoadStore.cpp b/Source/Core/Core/PowerPC/JitILCommon/JitILBase_LoadStore.cpp index 0e20e79f8c..4dbc9aeda5 100644 --- a/Source/Core/Core/PowerPC/JitILCommon/JitILBase_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/JitILCommon/JitILBase_LoadStore.cpp @@ -37,6 +37,7 @@ void JitILBase::lXz(UGeckoInstruction inst) // Idle Skipping. This really should be done somewhere else. // Either lower in the IR or higher in PPCAnalyist if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle && + PowerPC::GetState() != PowerPC::CPU_STEPPING && inst.OPCD == 32 && // Lwx (inst.hex & 0xFFFF0000) == 0x800D0000 && (Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 ||