diff options
| author | Jules Blok <jules.blok@gmail.com> | 2015-06-10 00:00:12 +0200 |
|---|---|---|
| committer | Jules Blok <jules.blok@gmail.com> | 2015-06-10 00:00:12 +0200 |
| commit | 7dfced21a2e5aac7195e0e1ad76468e30306766b (patch) | |
| tree | bd671b639d3d911460b767caabad8fc8a759a6bf /Source/Core/DolphinWX/Debugger/MemoryView.cpp | |
| parent | c25be031fc1031d795157d8344b87b7841145197 (diff) | |
| parent | 7b0a65e295c784f9d573f2ef52d4e2a7b9bb2889 (diff) | |
Merge branch 'master' into stable
Diffstat (limited to 'Source/Core/DolphinWX/Debugger/MemoryView.cpp')
| -rw-r--r-- | Source/Core/DolphinWX/Debugger/MemoryView.cpp | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/Source/Core/DolphinWX/Debugger/MemoryView.cpp b/Source/Core/DolphinWX/Debugger/MemoryView.cpp new file mode 100644 index 0000000000..b5ecfa339b --- /dev/null +++ b/Source/Core/DolphinWX/Debugger/MemoryView.cpp @@ -0,0 +1,423 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include <cmath> +#include <string> +#include <wx/brush.h> +#include <wx/clipbrd.h> +#include <wx/colour.h> +#include <wx/control.h> +#include <wx/dataobj.h> +#include <wx/dcclient.h> +#include <wx/font.h> +#include <wx/menu.h> +#include <wx/pen.h> + +#include "Common/CommonTypes.h" +#include "Common/DebugInterface.h" +#include "Common/StringUtil.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/MemoryView.h" +#include "DolphinWX/Debugger/WatchWindow.h" + +enum +{ + IDM_GOTOINMEMVIEW = 12000, + IDM_COPYADDRESS, + IDM_COPYHEX, + IDM_COPYCODE, + IDM_RUNTOHERE, + IDM_DYNARECRESULTS, + IDM_WATCHADDRESS, + IDM_TOGGLEMEMORY, + IDM_VIEWASFP, + IDM_VIEWASASCII, + IDM_VIEWASHEX, +}; + +CMemoryView::CMemoryView(DebugInterface* debuginterface, wxWindow* parent) + : wxControl(parent, wxID_ANY) + , curAddress(debuginterface->GetPC()) + , debugger(debuginterface) + , align(debuginterface->GetInstructionSize(0)) + , rowHeight(13) + , selection(0) + , oldSelection(0) + , selecting(false) + , memory(0) + , viewAsType(VIEWAS_FP) +{ + Bind(wxEVT_PAINT, &CMemoryView::OnPaint, this); + Bind(wxEVT_LEFT_DOWN, &CMemoryView::OnMouseDownL, this); + Bind(wxEVT_LEFT_UP, &CMemoryView::OnMouseUpL, this); + Bind(wxEVT_MOTION, &CMemoryView::OnMouseMove, this); + Bind(wxEVT_RIGHT_DOWN, &CMemoryView::OnMouseDownR, this); + Bind(wxEVT_MOUSEWHEEL, &CMemoryView::OnScrollWheel, this); + Bind(wxEVT_MENU, &CMemoryView::OnPopupMenu, this); + Bind(wxEVT_SIZE, &CMemoryView::OnResize, this); +} + +int CMemoryView::YToAddress(int y) +{ + wxRect rc = GetClientRect(); + int ydiff = y - rc.height / 2 - rowHeight / 2; + ydiff = (int)(floorf((float)ydiff / (float)rowHeight)) + 1; + return curAddress + ydiff * align; +} + +void CMemoryView::OnMouseDownL(wxMouseEvent& event) +{ + int x = event.m_x; + int y = event.m_y; + + if (x > 16) + { + oldSelection = selection; + selection = YToAddress(y); + bool oldselecting = selecting; + selecting = true; + + if (!oldselecting || (selection != oldSelection)) + Refresh(); + } + else + { + debugger->ToggleMemCheck(YToAddress(y)); + + Refresh(); + + // Propagate back to the parent window to update the breakpoint list. + wxCommandEvent evt(wxEVT_HOST_COMMAND, IDM_UPDATE_BREAKPOINTS); + GetEventHandler()->AddPendingEvent(evt); + } + + event.Skip(); +} + +void CMemoryView::OnMouseMove(wxMouseEvent& event) +{ + wxRect rc = GetClientRect(); + + if (event.m_leftDown && event.m_x > 16) + { + if (event.m_y < 0) + { + curAddress -= align; + Refresh(); + } + else if (event.m_y > rc.height) + { + curAddress += align; + Refresh(); + } + else + OnMouseDownL(event); + } + + event.Skip(); +} + +void CMemoryView::OnMouseUpL(wxMouseEvent& event) +{ + if (event.m_x > 16) + { + curAddress = YToAddress(event.m_y); + selecting = false; + Refresh(); + } + + event.Skip(); +} + +void CMemoryView::OnScrollWheel(wxMouseEvent& event) +{ + const bool scroll_down = (event.GetWheelRotation() < 0); + const int num_lines = event.GetLinesPerAction(); + + if (scroll_down) + { + curAddress += num_lines * 4; + } + else + { + curAddress -= num_lines * 4; + } + + Refresh(); + event.Skip(); +} + +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 + + switch (event.GetId()) + { +#if wxUSE_CLIPBOARD + case IDM_COPYADDRESS: + wxTheClipboard->SetData(new wxTextDataObject(wxString::Format("%08x", selection))); + break; + + case IDM_COPYHEX: + { + std::string temp = StringFromFormat("%08x", debugger->ReadExtraMemory(memory, selection)); + wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp))); + } + break; +#endif + + case IDM_WATCHADDRESS: + debugger->AddWatch(selection); + if (watch_window) + watch_window->NotifyUpdate(); + Refresh(); + break; + + case IDM_TOGGLEMEMORY: + memory ^= 1; + Refresh(); + break; + + case IDM_VIEWASFP: + viewAsType = VIEWAS_FP; + Refresh(); + break; + + case IDM_VIEWASASCII: + viewAsType = VIEWAS_ASCII; + Refresh(); + break; + case IDM_VIEWASHEX: + viewAsType = VIEWAS_HEX; + Refresh(); + break; + } + +#if wxUSE_CLIPBOARD + wxTheClipboard->Close(); +#endif + event.Skip(); +} + +void CMemoryView::OnMouseDownR(wxMouseEvent& event) +{ + // popup menu + wxMenu menu; + //menu.Append(IDM_GOTOINMEMVIEW, _("&Goto in mem view")); +#if wxUSE_CLIPBOARD + 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; + viewAsSubMenu->Append(IDM_VIEWASFP, _("FP value")); + viewAsSubMenu->Append(IDM_VIEWASASCII, "ASCII"); + viewAsSubMenu->Append(IDM_VIEWASHEX, _("Hex")); + menu.AppendSubMenu(viewAsSubMenu, _("View As:")); + + PopupMenu(&menu); +} + +void CMemoryView::OnPaint(wxPaintEvent& event) +{ + wxPaintDC dc(this); + wxRect rc = GetClientRect(); + wxFont hFont("Courier"); + hFont.SetFamily(wxFONTFAMILY_TELETYPE); + + wxCoord w,h; + dc.GetTextExtent("0WJyq", &w, &h, nullptr, nullptr, &hFont); + if (h > rowHeight) + rowHeight = h; + dc.GetTextExtent("0WJyq", &w, &h, nullptr, nullptr, &DebuggerFont); + if (h > rowHeight) + rowHeight = h; + + if (viewAsType==VIEWAS_HEX) + dc.SetFont(hFont); + else + dc.SetFont(DebuggerFont); + + dc.GetTextExtent("W", &w, &h); + int fontSize = w; + int textPlacement = 17 + 9 * fontSize; + + // TODO: Add any drawing code here... + int width = rc.width; + int numRows = (rc.height / rowHeight) / 2 + 2; + dc.SetBackgroundMode(wxTRANSPARENT); + const wxColour bgColor = *wxWHITE; + wxPen nullPen(bgColor); + wxPen currentPen(*wxBLACK_PEN); + wxPen selPen(*wxGREY_PEN); + nullPen.SetStyle(wxTRANSPARENT); + + wxBrush currentBrush(*wxLIGHT_GREY_BRUSH); + wxBrush pcBrush(*wxGREEN_BRUSH); + wxBrush mcBrush(*wxBLUE_BRUSH); + wxBrush bgBrush(bgColor); + wxBrush nullBrush(bgColor); + nullBrush.SetStyle(wxTRANSPARENT); + + dc.SetPen(nullPen); + dc.SetBrush(bgBrush); + dc.DrawRectangle(0, 0, 16, rc.height); + dc.DrawRectangle(0, 0, rc.width, 5+8); + + // TODO - clean up this freaking mess!!!!! + for (int row = -numRows; row <= numRows; row++) + { + unsigned int address = curAddress + row * align; + + int rowY1 = rc.height / 2 + rowHeight * row - rowHeight / 2; + int rowY2 = rc.height / 2 + rowHeight * row + rowHeight / 2; + + wxString temp = wxString::Format("%08x", address); + u32 col = debugger->GetColor(address); + wxBrush rowBrush(wxColour(col >> 16, col >> 8, col)); + dc.SetBrush(nullBrush); + dc.SetPen(nullPen); + dc.DrawRectangle(0, rowY1, 16, rowY2); + + if (selecting && (address == selection)) + dc.SetPen(selPen); + else + dc.SetPen(row == 0 ? currentPen : nullPen); + + if (address == debugger->GetPC()) + dc.SetBrush(pcBrush); + else + dc.SetBrush(rowBrush); + + dc.DrawRectangle(16, rowY1, width, rowY2 - 1); + dc.SetBrush(currentBrush); + dc.SetTextForeground("#600000"); // Dark red + dc.DrawText(temp, 17, rowY1); + + if (viewAsType != VIEWAS_HEX) + { + char mem[256]; + debugger->GetRawMemoryString(memory, address, mem, 256); + dc.SetTextForeground(wxTheColourDatabase->Find("NAVY")); + dc.DrawText(StrToWxStr(mem), 17+fontSize*(8), rowY1); + dc.SetTextForeground(*wxBLACK); + } + + if (!PowerPC::HostIsRAMAddress(address)) + continue; + + if (debugger->IsAlive()) + { + std::string dis; + u32 mem_data = debugger->ReadExtraMemory(memory, address); + + if (viewAsType == VIEWAS_FP) + { + float flt = *(float *)(&mem_data); + dis = StringFromFormat("f: %f", flt); + } + else if (viewAsType == VIEWAS_ASCII) + { + u32 a[4] = { + (mem_data & 0xff000000) >> 24, + (mem_data & 0xff0000) >> 16, + (mem_data & 0xff00) >> 8, + (mem_data & 0xff) + }; + + for (auto& word : a) + { + if (word == '\0') + word = ' '; + } + + dis = StringFromFormat("%c%c%c%c", a[0], a[1], a[2], a[3]); + } + else if (viewAsType == VIEWAS_HEX) + { + u32 mema[8] = { + debugger->ReadExtraMemory(memory, address), + debugger->ReadExtraMemory(memory, address+4), + debugger->ReadExtraMemory(memory, address+8), + debugger->ReadExtraMemory(memory, address+12), + debugger->ReadExtraMemory(memory, address+16), + debugger->ReadExtraMemory(memory, address+20), + debugger->ReadExtraMemory(memory, address+24), + debugger->ReadExtraMemory(memory, address+28) + }; + + for (auto& word : mema) + { + switch (dataType) + { + case 0: + dis += StringFromFormat(" %02X %02X %02X %02X", + ((word & 0xff000000) >> 24) & 0xFF, + ((word & 0xff0000) >> 16) & 0xFF, + ((word & 0xff00) >> 8) & 0xFF, + word & 0xff); + break; + case 1: + dis += StringFromFormat(" %02X%02X %02X%02X", + ((word & 0xff000000) >> 24) & 0xFF, + ((word & 0xff0000) >> 16) & 0xFF, + ((word & 0xff00) >> 8) & 0xFF, + word & 0xff); + break; + case 2: + dis += StringFromFormat(" %02X%02X%02X%02X", + ((word & 0xff000000) >> 24) & 0xFF, + ((word & 0xff0000) >> 16) & 0xFF, + ((word & 0xff00) >> 8) & 0xFF, + word & 0xff); + break; + } + } + } + else + { + dis = "INVALID VIEWAS TYPE"; + } + + if (viewAsType != VIEWAS_HEX) + dc.DrawText(StrToWxStr(dis), textPlacement + fontSize*(8 + 8), rowY1); + else + dc.DrawText(StrToWxStr(dis), textPlacement, rowY1); + + dc.SetTextForeground(*wxBLUE); + + std::string desc = debugger->GetDescription(address); + if (!desc.empty()) + dc.DrawText(StrToWxStr(desc), 17+fontSize*((8+8+8+30)*2), rowY1); + + // Show blue memory check dot + if (debugger->IsMemCheck(address)) + { + dc.SetBrush(mcBrush); + dc.DrawRectangle(8, rowY1 + 1, 11, 11); + } + } + } + + dc.SetPen(currentPen); +} + +void CMemoryView::OnResize(wxSizeEvent& event) +{ + Refresh(); + event.Skip(); +} |
