summaryrefslogtreecommitdiff
path: root/Source/Core/DolphinWX/Debugger/CodeView.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/DolphinWX/Debugger/CodeView.cpp')
-rw-r--r--Source/Core/DolphinWX/Debugger/CodeView.cpp232
1 files changed, 127 insertions, 105 deletions
diff --git a/Source/Core/DolphinWX/Debugger/CodeView.cpp b/Source/Core/DolphinWX/Debugger/CodeView.cpp
index 22119b6bac..8bc07036b3 100644
--- a/Source/Core/DolphinWX/Debugger/CodeView.cpp
+++ b/Source/Core/DolphinWX/Debugger/CodeView.cpp
@@ -53,9 +53,9 @@ CCodeView::CCodeView(DebugInterface* debuginterface, SymbolDB* symboldb, wxWindo
wxWindowID Id)
: wxControl(parent, Id), m_debugger(debuginterface), m_symbol_db(symboldb), m_plain(false),
m_curAddress(debuginterface->GetPC()), m_align(debuginterface->GetInstructionSize(0)),
- m_rowHeight(13), m_selection(0), m_oldSelection(0), m_selecting(false), m_lx(-1), m_ly(-1)
+ m_rowHeight(FromDIP(13)), m_left_col_width(FromDIP(LEFT_COL_WIDTH)), m_selection(0),
+ m_oldSelection(0), m_selecting(false)
{
- Bind(wxEVT_ERASE_BACKGROUND, &CCodeView::OnErase, this);
Bind(wxEVT_PAINT, &CCodeView::OnPaint, this);
Bind(wxEVT_MOUSEWHEEL, &CCodeView::OnScrollWheel, this);
Bind(wxEVT_LEFT_DOWN, &CCodeView::OnMouseDown, this);
@@ -65,6 +65,13 @@ CCodeView::CCodeView(DebugInterface* debuginterface, SymbolDB* symboldb, wxWindo
Bind(wxEVT_RIGHT_UP, &CCodeView::OnMouseUpR, this);
Bind(wxEVT_MENU, &CCodeView::OnPopupMenu, this);
Bind(wxEVT_SIZE, &CCodeView::OnResize, this);
+
+ // Disable the erase event, the entire window is being painted so the erase
+ // event will just cause unnecessary flicker.
+ SetBackgroundStyle(wxBG_STYLE_PAINT);
+#if defined(__WXMSW__) || defined(__WXGTK__)
+ SetDoubleBuffered(true);
+#endif
}
int CCodeView::YToAddress(int y)
@@ -80,7 +87,7 @@ void CCodeView::OnMouseDown(wxMouseEvent& event)
int x = event.m_x;
int y = event.m_y;
- if (x > 16)
+ if (x > m_left_col_width)
{
m_oldSelection = m_selection;
m_selection = YToAddress(y);
@@ -131,7 +138,7 @@ void CCodeView::OnMouseMove(wxMouseEvent& event)
{
wxRect rc = GetClientRect();
- if (event.m_leftDown && event.m_x > 16)
+ if (event.m_leftDown && event.m_x > m_left_col_width)
{
if (event.m_y < 0)
{
@@ -162,7 +169,7 @@ void CCodeView::RaiseEvent()
void CCodeView::OnMouseUpL(wxMouseEvent& event)
{
- if (event.m_x > 16)
+ if (event.m_x > m_left_col_width)
{
m_curAddress = YToAddress(event.m_y);
m_selecting = false;
@@ -222,10 +229,6 @@ void CCodeView::InsertBlrNop(int Blr)
void CCodeView::OnPopupMenu(wxCommandEvent& event)
{
-#if wxUSE_CLIPBOARD
- wxTheClipboard->Open();
-#endif
-
switch (event.GetId())
{
case IDM_GOTOINMEMVIEW:
@@ -234,11 +237,15 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
#if wxUSE_CLIPBOARD
case IDM_COPYADDRESS:
+ {
+ wxClipboardLocker locker;
wxTheClipboard->SetData(new wxTextDataObject(wxString::Format("%08x", m_selection)));
- break;
+ }
+ break;
case IDM_COPYCODE:
{
+ wxClipboardLocker locker;
std::string disasm = m_debugger->Disassemble(m_selection);
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(disasm)));
}
@@ -246,8 +253,9 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
case IDM_COPYHEX:
{
- std::string temp = StringFromFormat("%08x", m_debugger->ReadInstruction(m_selection));
- wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
+ wxClipboardLocker locker;
+ wxTheClipboard->SetData(
+ new wxTextDataObject(wxString::Format("%08x", m_debugger->ReadInstruction(m_selection))));
}
break;
@@ -266,6 +274,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
std::string disasm = m_debugger->Disassemble(addr);
text += StringFromFormat("%08x: ", addr) + disasm + "\r\n";
}
+ wxClipboardLocker locker;
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(text)));
}
}
@@ -283,6 +292,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
InsertBlrNop(0);
Refresh();
break;
+
case IDM_INSERTNOP:
InsertBlrNop(1);
Refresh();
@@ -332,12 +342,11 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
case IDM_PATCHALERT:
break;
- }
-#if wxUSE_CLIPBOARD
- wxTheClipboard->Close();
-#endif
- event.Skip();
+ default:
+ event.Skip();
+ break;
+ }
}
void CCodeView::OnMouseUpR(wxMouseEvent& event)
@@ -363,104 +372,112 @@ void CCodeView::OnMouseUpR(wxMouseEvent& event)
menu.Append(IDM_JITRESULTS, _("PPC vs X86"))->Enable(Core::IsRunning());
menu.Append(IDM_INSERTBLR, _("Insert &blr"))->Enable(Core::IsRunning());
menu.Append(IDM_INSERTNOP, _("Insert &nop"))->Enable(Core::IsRunning());
- menu.Append(IDM_PATCHALERT, _("Patch alert"))->Enable(Core::IsRunning());
+ // menu.Append(IDM_PATCHALERT, _("Patch alert"))->Enable(Core::IsRunning());
PopupMenu(&menu);
event.Skip();
}
-void CCodeView::OnErase(wxEraseEvent& event)
-{
-}
-
void CCodeView::OnPaint(wxPaintEvent& event)
{
// -------------------------
// General settings
// -------------------------
- std::unique_ptr<wxGraphicsContext> ctx(wxGraphicsContext::Create(wxPaintDC(this)));
+ wxPaintDC paint_dc(this);
wxRect rc = GetClientRect();
+ int char_width;
- ctx->SetFont(DebuggerFont, *wxBLACK);
-
- wxDouble w, h;
- ctx->GetTextExtent("0WJyq", &w, &h);
-
- if (h > m_rowHeight)
- m_rowHeight = h;
+ paint_dc.SetFont(DebuggerFont);
+ {
+ wxFontMetrics metrics = paint_dc.GetFontMetrics();
+ char_width = metrics.averageWidth;
+ if (metrics.height > m_rowHeight)
+ m_rowHeight = metrics.height;
+ }
- ctx->GetTextExtent("W", &w, &h);
- int charWidth = w;
+ std::unique_ptr<wxGraphicsContext> ctx(wxGraphicsContext::Create(paint_dc));
+ ctx->DisableOffset(); // Incompatible with matrix transforms
+ ctx->SetFont(DebuggerFont, *wxBLACK);
- struct branch
+ struct Branch
{
int src, dst, srcAddr;
};
- branch branches[256];
- int numBranches = 0;
- // TODO: Add any drawing code here...
- int width = rc.width;
- int numRows = ((rc.height / m_rowHeight) / 2) + 2;
+ Branch branches[256];
+ int num_branches = 0;
+ const int num_rows = ((rc.height / m_rowHeight) / 2) + 2;
+
+ const double scale = FromDIP(1024) / 1024.0;
+ const int pen_width = static_cast<int>(std::ceil(scale));
+ const int col_width = rc.width - m_left_col_width;
+ const int text_col = m_left_col_width + pen_width / 2 + 1; // 1 unscaled pixel
+ const int bp_offset_x = FromDIP(LEFT_COL_WIDTH / 8);
+ const wxSize bp_size = FromDIP(wxSize(LEFT_COL_WIDTH * 3 / 4, LEFT_COL_WIDTH * 3 / 4));
+ const int bp_offset_y = (m_rowHeight - bp_size.GetHeight()) / 2;
// ------------
// -------------------------
// Colors and brushes
// -------------------------
- const wxColour bgColor = *wxWHITE;
- wxPen nullPen(bgColor);
- wxPen currentPen(*wxBLACK_PEN);
- wxPen selPen(*wxGREY_PEN);
- nullPen.SetStyle(wxPENSTYLE_TRANSPARENT);
- currentPen.SetStyle(wxPENSTYLE_SOLID);
- wxBrush currentBrush(*wxLIGHT_GREY_BRUSH);
- wxBrush pcBrush(*wxGREEN_BRUSH);
- wxBrush bpBrush(*wxRED_BRUSH);
-
- wxBrush bgBrush(bgColor);
- wxBrush nullBrush(bgColor);
- nullBrush.SetStyle(wxBRUSHSTYLE_TRANSPARENT);
-
- ctx->SetPen(nullPen);
- ctx->SetBrush(bgBrush);
- ctx->DrawRectangle(0, 0, 16, rc.height);
- ctx->DrawRectangle(0, 0, rc.width, 5);
+ wxColour branch_color = wxTheColourDatabase->Find("PURPLE");
+ wxColour blr_color = wxTheColourDatabase->Find("DARK GREEN");
+ wxColour instr_color = wxTheColourDatabase->Find("VIOLET");
+ wxGraphicsPen null_pen = ctx->CreatePen(*wxTRANSPARENT_PEN);
+ wxGraphicsPen focus_pen = ctx->CreatePen(wxPen(*wxBLACK, pen_width));
+ wxGraphicsPen selection_pen = ctx->CreatePen(wxPen("GREY", pen_width));
+ wxGraphicsBrush pc_brush = ctx->CreateBrush(*wxGREEN_BRUSH);
+ wxGraphicsBrush bp_brush = ctx->CreateBrush(*wxRED_BRUSH);
+ wxGraphicsBrush back_brush = ctx->CreateBrush(*wxWHITE_BRUSH);
+ wxGraphicsBrush null_brush = ctx->CreateBrush(*wxTRANSPARENT_BRUSH);
+
// ------------
// -----------------------------
// Walk through all visible rows
// -----------------------------
- for (int i = -numRows; i <= numRows; i++)
+ for (int i = -num_rows; i <= num_rows; i++)
{
unsigned int address = m_curAddress + (i * m_align);
- int rowY1 = (rc.height / 2) + (m_rowHeight * i) - (m_rowHeight / 2);
- int rowY2 = (rc.height / 2) + (m_rowHeight * i) + (m_rowHeight / 2);
+ int row_y = (rc.height / 2) + (m_rowHeight * i) - (m_rowHeight / 2);
wxString temp = wxString::Format("%08x", address);
u32 color = m_debugger->GetColor(address);
- wxBrush rowBrush(wxColour(color >> 16, color >> 8, color));
- ctx->SetBrush(nullBrush);
- ctx->SetPen(nullPen);
- ctx->DrawRectangle(0, rowY1, 16, rowY2 - rowY1 + 2);
-
- if (m_selecting && (address == m_selection))
- ctx->SetPen(selPen);
- else
- ctx->SetPen(i == 0 ? currentPen : nullPen);
+ wxBrush row_brush(wxColour(color >> 16, color >> 8, color));
+ ctx->SetBrush(back_brush);
+ ctx->SetPen(null_pen);
+ ctx->DrawRectangle(0, row_y, m_left_col_width, m_rowHeight);
if (address == m_debugger->GetPC())
- ctx->SetBrush(pcBrush);
+ ctx->SetBrush(pc_brush);
else
- ctx->SetBrush(rowBrush);
+ ctx->SetBrush(row_brush);
+
+ ctx->SetPen(null_pen);
+ ctx->DrawRectangle(m_left_col_width, row_y, col_width, m_rowHeight);
+ if (i == 0 || (m_selecting && address == m_selection))
+ {
+ if (m_selecting && address == m_selection)
+ ctx->SetPen(selection_pen);
+ else
+ ctx->SetPen(focus_pen);
+ ctx->SetBrush(null_brush);
+ // In a graphics context, the border of a rectangle is drawn along the edge,
+ // it does not count towards the width of the rectangle (i.e. drawn right on
+ // the pixel boundary of the fill area, half inside, half outside. For example
+ // a rect with a 1px pen at (5,5)->(10,10) will have an actual screen size of
+ // (4.5,4.5)->(10.5,10.5) with the line being aliased on the half-pixels)
+ double offset = pen_width / 2.0;
+ ctx->DrawRectangle(m_left_col_width + offset, row_y + offset, col_width - pen_width,
+ m_rowHeight - pen_width);
+ }
- ctx->DrawRectangle(16, rowY1, width, rowY2 - rowY1 + 1);
- ctx->SetBrush(currentBrush);
if (!m_plain)
{
// the address text is dark red
- ctx->SetFont(DebuggerFont, wxColour("#600000"));
- ctx->DrawText(temp, 17, rowY1);
+ ctx->SetFont(DebuggerFont, wxColour(0x60, 0x00, 0x00));
+ ctx->DrawText(temp, text_col, row_y);
ctx->SetFont(DebuggerFont, *wxBLACK);
}
@@ -488,31 +505,32 @@ void CCodeView::OnPaint(wxPaintEvent& event)
{
u32 offs = std::stoul(hex_str, nullptr, 16);
- branches[numBranches].src = rowY1 + (m_rowHeight / 2);
- branches[numBranches].srcAddr = (address / m_align);
- branches[numBranches++].dst =
- (int)(rowY1 + ((s64)(u32)offs - (s64)(u32)address) * m_rowHeight / m_align +
+ branches[num_branches].src = row_y + (m_rowHeight / 2);
+ branches[num_branches].srcAddr = (address / m_align);
+ branches[num_branches++].dst =
+ (int)(row_y + ((s64)(u32)offs - (s64)(u32)address) * m_rowHeight / m_align +
m_rowHeight / 2);
desc = StringFromFormat("-->%s", m_debugger->GetDescription(offs).c_str());
// the -> arrow illustrations are purple
- ctx->SetFont(DebuggerFont, wxTheColourDatabase->Find("PURPLE"));
+ ctx->SetFont(DebuggerFont, branch_color);
}
else
{
ctx->SetFont(DebuggerFont, *wxBLACK);
}
- ctx->DrawText(StrToWxStr(operands), 17 + 17 * charWidth, rowY1);
+ ctx->DrawText(StrToWxStr(operands), text_col + 17 * char_width, row_y);
// ------------
// Show blr as its' own color
if (opcode == "blr")
- ctx->SetFont(DebuggerFont, wxTheColourDatabase->Find("DARK GREEN"));
+ ctx->SetFont(DebuggerFont, blr_color);
else
- ctx->SetFont(DebuggerFont, wxTheColourDatabase->Find("VIOLET"));
+ ctx->SetFont(DebuggerFont, instr_color);
- ctx->DrawText(StrToWxStr(opcode), 17 + (m_plain ? 1 * charWidth : 9 * charWidth), rowY1);
+ ctx->DrawText(StrToWxStr(opcode), text_col + (m_plain ? 1 * char_width : 9 * char_width),
+ row_y);
if (desc.empty())
{
@@ -527,15 +545,16 @@ void CCodeView::OnPaint(wxPaintEvent& event)
// UnDecorateSymbolName(desc,temp,255,UNDNAME_COMPLETE);
if (!desc.empty())
{
- ctx->DrawText(StrToWxStr(desc), 17 + 35 * charWidth, rowY1);
+ ctx->DrawText(StrToWxStr(desc), text_col + 45 * char_width, row_y);
}
}
// Show red breakpoint dot
if (m_debugger->IsBreakpoint(address))
{
- ctx->SetBrush(bpBrush);
- ctx->DrawRectangle(2, rowY1 + 1, 11, 11);
+ ctx->SetPen(null_pen);
+ ctx->SetBrush(bp_brush);
+ ctx->DrawEllipse(bp_offset_x, row_y + bp_offset_y, bp_size.GetWidth(), bp_size.GetHeight());
}
}
} // end of for
@@ -544,22 +563,24 @@ void CCodeView::OnPaint(wxPaintEvent& event)
// -------------------------
// Colors and brushes
// -------------------------
- ctx->SetPen(currentPen);
+ ctx->SetPen(focus_pen);
+
+ wxGraphicsPath branch_path = ctx->CreatePath();
- for (int i = 0; i < numBranches; i++)
+ for (int i = 0; i < num_branches; ++i)
{
- int x = 17 + 49 * charWidth + (branches[i].srcAddr % 9) * 8;
- MoveTo(x - 2, branches[i].src);
+ int x = text_col + 52 * char_width + (branches[i].srcAddr % 9) * 8;
+ branch_path.MoveToPoint(x - 2 * scale, branches[i].src);
if (branches[i].dst < rc.height + 400 && branches[i].dst > -400)
{
- LineTo(ctx, x + 2, branches[i].src);
- LineTo(ctx, x + 2, branches[i].dst);
- LineTo(ctx, x - 4, branches[i].dst);
+ branch_path.AddLineToPoint(x + 2 * scale, branches[i].src);
+ branch_path.AddLineToPoint(x + 2 * scale, branches[i].dst);
+ branch_path.AddLineToPoint(x - 4 * scale, branches[i].dst);
- MoveTo(x, branches[i].dst - 4);
- LineTo(ctx, x - 4, branches[i].dst);
- LineTo(ctx, x + 1, branches[i].dst + 5);
+ branch_path.MoveToPoint(x, branches[i].dst - 4 * scale);
+ branch_path.AddLineToPoint(x - 4 * scale, branches[i].dst);
+ branch_path.AddLineToPoint(x + 1 * scale, branches[i].dst + 5 * scale);
}
// else
//{
@@ -575,16 +596,17 @@ void CCodeView::OnPaint(wxPaintEvent& event)
// LineTo(ctx, x, branches[i].dst+4);
// LineTo(ctx, x-2, branches[i].dst);
}
- // ------------
-}
-void CCodeView::LineTo(std::unique_ptr<wxGraphicsContext>& ctx, int x, int y)
-{
- std::vector<wxPoint2DDouble> points{wxPoint2DDouble(m_lx, m_ly), wxPoint2DDouble(x, y)};
-
- ctx->DrawLines(points.size(), points.data());
- m_lx = x;
- m_ly = y;
+ // If the pen width is odd then we need to offset the path so that lines are drawn in
+ // the middle of pixels instead of the edge so we don't get aliasing.
+ if (pen_width & 1)
+ {
+ wxGraphicsMatrix matrix = ctx->CreateMatrix();
+ matrix.Translate(0.5, 0.5);
+ branch_path.Transform(matrix);
+ }
+ ctx->StrokePath(branch_path);
+ // ------------
}
void CCodeView::OnResize(wxSizeEvent& event)