summaryrefslogtreecommitdiff
path: root/Source/Core/DolphinWX/Debugger/WatchView.cpp
diff options
context:
space:
mode:
authorJules Blok <jules.blok@gmail.com>2015-06-10 00:00:12 +0200
committerJules Blok <jules.blok@gmail.com>2015-06-10 00:00:12 +0200
commit7dfced21a2e5aac7195e0e1ad76468e30306766b (patch)
treebd671b639d3d911460b767caabad8fc8a759a6bf /Source/Core/DolphinWX/Debugger/WatchView.cpp
parentc25be031fc1031d795157d8344b87b7841145197 (diff)
parent7b0a65e295c784f9d573f2ef52d4e2a7b9bb2889 (diff)
Merge branch 'master' into stable
Diffstat (limited to 'Source/Core/DolphinWX/Debugger/WatchView.cpp')
-rw-r--r--Source/Core/DolphinWX/Debugger/WatchView.cpp306
1 files changed, 306 insertions, 0 deletions
diff --git a/Source/Core/DolphinWX/Debugger/WatchView.cpp b/Source/Core/DolphinWX/Debugger/WatchView.cpp
new file mode 100644
index 0000000000..be5c5dad64
--- /dev/null
+++ b/Source/Core/DolphinWX/Debugger/WatchView.cpp
@@ -0,0 +1,306 @@
+// Copyright 2014 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include <wx/colour.h>
+#include <wx/grid.h>
+#include <wx/menu.h>
+
+#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/BreakpointWindow.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"
+
+enum
+{
+ IDM_DELETEWATCH = 1,
+ IDM_ADDMEMCHECK,
+ IDM_VIEWMEMORY,
+};
+
+
+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 PowerPC::HostRead_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, const std::string& value)
+{
+ if ((count - 1) < (int)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)
+{
+ PowerPC::HostWrite_U32(value, GetWatchAddr(count));
+}
+
+static wxString GetValueByRowCol(int row, int col)
+{
+ if (row == 0)
+ {
+ // Column Labels
+ switch (col)
+ {
+ case 0: return _("Label");
+ case 1: return _("Address");
+ case 2: return _("Hexadecimal");
+ case 3: return _("Decimal");
+ case 4: return _("String");
+ default: return wxEmptyString;
+ }
+ }
+ else if (row <= (int)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("%u", GetWatchValue(row));
+ case 4:
+ {
+ u32 addr = GetWatchAddr(row);
+ if (PowerPC::HostIsRAMAddress(addr))
+ return PowerPC::HostGetString(addr, 32).c_str();
+ else
+ return wxEmptyString;
+ }
+ default: return wxEmptyString;
+ }
+ }
+ }
+ 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;
+ 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;
+ if (col == 1)
+ red = m_CachedWatchHasChanged[row];
+
+ attr->SetTextColour(red ? *wxRED : *wxBLACK);
+
+ if (row > (int)(PowerPC::watches.GetWatches().size() + 1) || (PowerPC::GetState() == PowerPC::CPU_POWERDOWN))
+ {
+ attr->SetReadOnly(true);
+ attr->SetBackgroundColour(*wxLIGHT_GREY);
+ }
+ }
+
+ return attr;
+}
+
+CWatchView::CWatchView(wxWindow* parent, wxWindowID id)
+ : wxGrid(parent, id)
+{
+ m_watch_table = new CWatchTable();
+
+ SetTable(m_watch_table, true);
+ SetRowLabelSize(0);
+ SetColLabelSize(0);
+ DisableDragRowSize();
+
+ Bind(wxEVT_GRID_CELL_RIGHT_CLICK, &CWatchView::OnMouseDownR, this);
+ Bind(wxEVT_MENU, &CWatchView::OnPopupMenu, this);
+}
+
+void CWatchView::Update()
+{
+ if (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
+ {
+ m_watch_table->UpdateWatch();
+ ForceRefresh();
+ }
+}
+
+void CWatchView::OnMouseDownR(wxGridEvent& event)
+{
+ // popup menu
+ 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);
+ }
+
+ wxMenu menu;
+ 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)
+{
+ 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;
+ CBreakPointWindow* breakpoint_window = code_window->m_BreakpointWindow;
+
+ wxString strNewVal;
+ TMemCheck MemCheck;
+
+ switch (event.GetId())
+ {
+ case IDM_DELETEWATCH:
+ strNewVal = GetValueByRowCol(m_selectedRow, 1);
+ 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;
+ MemCheck.EndAddress = m_selectedAddress;
+ MemCheck.bRange = false;
+ 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);
+ Refresh();
+ break;
+ }
+ event.Skip();
+}