Merge pull request #1070 from Kingcom/registerlist

Revert to old register list, make it scrollable
This commit is contained in:
ramapcsx2 2015-12-31 17:13:06 +01:00
commit 6e34f183ea
9 changed files with 579 additions and 419 deletions

View File

@ -414,13 +414,16 @@ struct Pcsx2Config
u8 FontWidth; u8 FontWidth;
u8 FontHeight; u8 FontHeight;
u32 WindowWidth;
u32 WindowHeight;
DebugOptions(); DebugOptions();
void LoadSave( IniInterface& conf ); void LoadSave( IniInterface& conf );
bool operator ==( const DebugOptions& right ) const bool operator ==( const DebugOptions& right ) const
{ {
return OpEqu( bitset ) && OpEqu( FontWidth ) && OpEqu( FontHeight ); return OpEqu( bitset ) && OpEqu( FontWidth ) && OpEqu( FontHeight )
&& OpEqu( WindowWidth ) && OpEqu( WindowHeight );
} }
bool operator !=( const DebugOptions& right ) const bool operator !=( const DebugOptions& right ) const

View File

@ -379,6 +379,8 @@ Pcsx2Config::DebugOptions::DebugOptions()
ShowDebuggerOnStart = false; ShowDebuggerOnStart = false;
FontWidth = 8; FontWidth = 8;
FontHeight = 12; FontHeight = 12;
WindowWidth = 0;
WindowHeight = 0;
} }
void Pcsx2Config::DebugOptions::LoadSave( IniInterface& ini ) void Pcsx2Config::DebugOptions::LoadSave( IniInterface& ini )
@ -388,6 +390,8 @@ void Pcsx2Config::DebugOptions::LoadSave( IniInterface& ini )
IniBitBool( ShowDebuggerOnStart ); IniBitBool( ShowDebuggerOnStart );
IniBitfield(FontWidth); IniBitfield(FontWidth);
IniBitfield(FontHeight); IniBitfield(FontHeight);
IniBitfield(WindowWidth);
IniBitfield(WindowHeight);
} }

View File

@ -134,6 +134,7 @@ void SysCoreThread::Reset()
GetVmMemory().DecommitAll(); GetVmMemory().DecommitAll();
SysClearExecutionCache(); SysClearExecutionCache();
sApp.PostAppMethod( &Pcsx2App::leaveDebugMode ); sApp.PostAppMethod( &Pcsx2App::leaveDebugMode );
g_FrameCount = 0;
} }

View File

@ -23,6 +23,7 @@
#include "BreakpointWindow.h" #include "BreakpointWindow.h"
#include "AppConfig.h" #include "AppConfig.h"
#include "System.h" #include "System.h"
#include "DisassemblyDialog.h"
#include <wx/mstream.h> #include <wx/mstream.h>
#include <wx/clipbrd.h> #include <wx/clipbrd.h>
@ -147,8 +148,8 @@ CtrlDisassemblyView::CtrlDisassemblyView(wxWindow* parent, DebugInterface* _cpu)
{ {
manager.setCpu(cpu); manager.setCpu(cpu);
windowStart = 0x100000; windowStart = 0x100000;
rowHeight = g_Conf->EmuOptions.Debugger.FontHeight+2; rowHeight = getDebugFontHeight()+2;
charWidth = g_Conf->EmuOptions.Debugger.FontWidth; charWidth = getDebugFontWidth();
displaySymbols = true; displaySymbols = true;
visibleRows = 1; visibleRows = 1;

View File

@ -20,6 +20,7 @@
#include "BreakpointWindow.h" #include "BreakpointWindow.h"
#include "DebugEvents.h" #include "DebugEvents.h"
#include "DisassemblyDialog.h"
#include <wchar.h> #include <wchar.h>
#include <wx/clipbrd.h> #include <wx/clipbrd.h>
@ -55,8 +56,8 @@ enum MemoryViewMenuIdentifiers
CtrlMemView::CtrlMemView(wxWindow* parent, DebugInterface* _cpu) CtrlMemView::CtrlMemView(wxWindow* parent, DebugInterface* _cpu)
: wxWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS|wxVSCROLL), cpu(_cpu) : wxWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS|wxVSCROLL), cpu(_cpu)
{ {
rowHeight = g_Conf->EmuOptions.Debugger.FontHeight; rowHeight = getDebugFontHeight();
charWidth = g_Conf->EmuOptions.Debugger.FontWidth; charWidth = getDebugFontWidth();
windowStart = 0x480000; windowStart = 0x480000;
curAddress = windowStart; curAddress = windowStart;
rowSize = 16; rowSize = 16;

View File

@ -16,456 +16,547 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "CtrlRegisterList.h" #include "CtrlRegisterList.h"
#include "DebugTools/Debug.h" #include "DebugTools/Debug.h"
#include "DebugEvents.h" #include "DebugEvents.h"
#include "AppConfig.h" #include "AppConfig.h"
#include "DisassemblyDialog.h"
BEGIN_EVENT_TABLE(CtrlRegisterList, wxWindow) BEGIN_EVENT_TABLE(CtrlRegisterList, wxWindow)
EVT_PAINT(CtrlRegisterList::paintEvent) EVT_SIZE(CtrlRegisterList::sizeEvent)
EVT_GRID_LABEL_LEFT_CLICK(CtrlRegisterList::gridEvent) EVT_LEFT_DOWN(CtrlRegisterList::mouseEvent)
EVT_GRID_LABEL_RIGHT_CLICK(CtrlRegisterList::gridEvent) EVT_RIGHT_DOWN(CtrlRegisterList::mouseEvent)
EVT_GRID_CELL_LEFT_CLICK(CtrlRegisterList::gridEvent) EVT_RIGHT_UP(CtrlRegisterList::mouseEvent)
EVT_GRID_CELL_RIGHT_CLICK(CtrlRegisterList::gridEvent) EVT_MOTION(CtrlRegisterList::mouseEvent)
EVT_KEY_DOWN(CtrlRegisterList::keydownEvent) EVT_KEY_DOWN(CtrlRegisterList::keydownEvent)
EVT_BOOKCTRL_PAGE_CHANGED(-1, CtrlRegisterList::categoryChangedEvent)
END_EVENT_TABLE() END_EVENT_TABLE()
enum DisassemblyMenuIdentifiers enum DisassemblyMenuIdentifiers
{ {
ID_REGISTERLIST_DISPLAY32 = 1, ID_REGISTERLIST_DISPLAY32 = 1,
ID_REGISTERLIST_DISPLAY64, ID_REGISTERLIST_DISPLAY64,
ID_REGISTERLIST_DISPLAY128, ID_REGISTERLIST_DISPLAY128,
ID_REGISTERLIST_CHANGELOWER, ID_REGISTERLIST_CHANGELOWER,
ID_REGISTERLIST_CHANGEUPPER, ID_REGISTERLIST_CHANGEUPPER,
ID_REGISTERLIST_CHANGEVALUE ID_REGISTERLIST_CHANGEVALUE
}; };
CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu) :
wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS | wxBORDER_NONE), CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu)
cpu(_cpu), : wxScrolledWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS|wxBORDER_NONE|wxVSCROLL), cpu(_cpu)
lastPc(0),
lastCycles(0),
maxBits(128),
needsSizeUpdating(true),
needsValueUpdating(true)
{ {
int rowHeight = g_Conf->EmuOptions.Debugger.FontHeight; rowHeight = getDebugFontHeight()+2;
int charWidth = g_Conf->EmuOptions.Debugger.FontWidth; charWidth = getDebugFontWidth();
category = 0;
maxBits = 128;
lastPc = 0xFFFFFFFF;
for (int i = 0; i < cpu->getRegisterCategoryCount(); i++)
{
int count = cpu->getRegisterCount(i);
#ifdef _WIN32 ChangedReg* regs = new ChangedReg[count];
wxFont font = wxFont(wxSize(charWidth, rowHeight), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, memset(regs,0,sizeof(ChangedReg)*count);
false, L"Lucida Console"); changedCategories.push_back(regs);
wxFont labelFont = font.Bold();
#else
wxFont font = wxFont(8, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, L"Lucida Console");
font.SetPixelSize(wxSize(charWidth, rowHeight));
wxFont labelFont = font;
labelFont.SetWeight(wxFONTWEIGHT_BOLD);
#endif
registerCategories = new wxNotebook(this, wxID_ANY);
// 'c' and 'C', much time wasted.
#if wxMAJOR_VERSION >= 3
registerCategories->Connect(wxEVT_BOOKCTRL_PAGE_CHANGED, wxBookCtrlEventHandler(CtrlRegisterList::categoryChangedEvent), nullptr, this);
#else
registerCategories->Connect(wxEVT_COMMAND_BOOKCTRL_PAGE_CHANGED, wxBookctrlEventHandler(CtrlRegisterList::categoryChangedEvent), nullptr, this);
#endif
for (int cat = 0; cat < cpu->getRegisterCategoryCount(); cat++)
{
int numRegs = cpu->getRegisterCount(cat);
changedCategories.push_back(std::vector<ChangedReg>(numRegs)); int maxLen = 0;
for (int k = 0; k < cpu->getRegisterCount(i); k++)
{
maxLen = std::max<int>(maxLen,strlen(cpu->getRegisterName(i,k)));
}
wxGrid* regGrid = new wxGrid(registerCategories, -1); int x = 17+(maxLen+3)*charWidth;
startPositions.push_back(x);
currentRows.push_back(0);
}
registerGrids.push_back(regGrid); SetDoubleBuffered(true);
registerCategories->AddPage(regGrid, wxString(cpu->getRegisterCategoryName(cat), wxConvUTF8)); SetInitialSize(ClientToWindowSize(GetMinClientSize()));
DebugInterface::RegisterType type = cpu->getRegisterType(cat); wxSize actualSize = getOptimalSize();
int registerBits = cpu->getRegisterSize(cat); SetVirtualSize(actualSize);
SetScrollbars(1, rowHeight, actualSize.x, actualSize.y / rowHeight, 0, 0);
int numCols;
switch (type)
{
case DebugInterface::NORMAL: // display them in 32 bit parts
numCols = registerBits / 32;
regGrid->CreateGrid(numRegs, numCols);
for (int row = 0; row < numRegs; row++)
regGrid->SetRowLabelValue(row, wxString(cpu->getRegisterName(cat, row), wxConvUTF8));
for (int col = 0; col < numCols; col++)
regGrid->SetColLabelValue(col, wxsFormat(L"%d-%d", 32 * (numCols - col) - 1, 32 * (numCols - col - 1)));
break;
case DebugInterface::SPECIAL:
regGrid->CreateGrid(numRegs, 1);
for (int row = 0; row < numRegs; row++)
regGrid->SetRowLabelValue(row, wxString(cpu->getRegisterName(cat, row), wxConvUTF8));
break;
}
regGrid->EnableEditing(false);
regGrid->SetDefaultCellFont(font);
regGrid->SetLabelFont(labelFont);
regGrid->DisableDragGridSize();
regGrid->DisableDragRowSize();
regGrid->DisableDragColSize();
regGrid->Connect(wxEVT_PAINT, wxPaintEventHandler(CtrlRegisterList::paintEvent), nullptr, this);
regGrid->Connect(wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler(CtrlRegisterList::gridEvent), nullptr, this);
regGrid->Connect(wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler(CtrlRegisterList::gridEvent), nullptr, this);
regGrid->Connect(wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler(CtrlRegisterList::gridEvent), nullptr, this);
regGrid->Connect(wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler(CtrlRegisterList::gridEvent), nullptr, this);
regGrid->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(CtrlRegisterList::keydownEvent), nullptr, this);
}
for (int cat = 0; cat < cpu->getRegisterCategoryCount(); cat++)
updateValues(cat);
updateSize(getCurrentCategory()); // getCurrentCategory() = 0
SetDoubleBuffered(true);
} }
// Called when this window needs to update the strings in the cells. wxSize CtrlRegisterList::getOptimalSize() const
// This has to be called every repaint of the window since the registers
// can change unpredictably and there seems to be currently is no mechanism
// for the rest of pcsx2 alerting the debugger when values change.
void CtrlRegisterList::updateValues(int cat)
{ {
wxGrid* regGrid = registerGrids[cat]; int columnChars = 0;
int numRows = regGrid->GetNumberRows(); int maxWidth = 0;
int numCols = regGrid->GetNumberCols(); int maxRows = 0;
std::vector<ChangedReg>& changedRegs = changedCategories[cat]; for (int i = 0; i < cpu->getRegisterCategoryCount(); i++)
DebugInterface::RegisterType type = cpu->getRegisterType(cat); {
for (int row = 0; row < numRows; row++) int bits = std::min<u32>(maxBits, cpu->getRegisterSize(i));
{ int start = startPositions[i];
wxColor bgColor = regGrid->GetGridCursorRow() == row ? wxColor(0xFFFFDFE0) :
wxColor(0xFFFFEFFF);
u128 value = cpu->getRegister(cat, row);
ChangedReg& changed = changedRegs[row];
for (int col = 0; col < numCols; col++) int w = start + (bits / 4) * charWidth;
{ if (bits > 32)
const wxColor colorChanged = wxColor(0xFF0000FF); w += (bits / 32) * 2 - 2;
const wxColor colorUnchanged = wxColor(0xFF004000);
wxColor textColor;
wxString cellValue;
switch (type) maxWidth = std::max<int>(maxWidth, w);
{ columnChars += strlen(cpu->getRegisterCategoryName(i)) + 1;
case DebugInterface::NORMAL: maxRows = std::max<int>(maxRows, cpu->getRegisterCount(i));
cellValue = wxsFormat(L"%08X", value._u32[numCols - col - 1]); }
textColor = changed.changed[numCols - col - 1] ? colorChanged : colorUnchanged;
break;
case DebugInterface::SPECIAL:
cellValue = cpu->getRegisterString(cat, row);
textColor = (changed.changed[0] || changed.changed[1] || changed.changed[2] || changed.changed[3]) ?
colorChanged : colorUnchanged;
break;
default: pxAssert(0 && "Unreachable switch case");
}
if (regGrid->GetCellTextColour(row, col) != textColor)
regGrid->SetCellTextColour(row, col, textColor);
if (regGrid->GetCellValue(row, col) != cellValue)
regGrid->SetCellValue(row, col, cellValue);
if (regGrid->GetCellBackgroundColour(row, col) != bgColor)
regGrid->SetCellBackgroundColour(row, col, bgColor);
}
}
}
void CtrlRegisterList::updateSize(int cat) maxWidth = std::max<int>(columnChars*charWidth, maxWidth + 4);
{
wxGrid* regGrid = registerGrids[cat];
int regBits = cpu->getRegisterSize(cat); return wxSize(maxWidth, (maxRows + 1)*rowHeight);
int numCols = regGrid->GetNumberCols();
#if wxMAJOR_VERSION >= 3
int shownCols = 0;
while (shownCols < numCols && regGrid->IsColShown(shownCols)) shownCols++;
if (shownCols > maxBits / 32)
shownCols = (maxBits / 32);
else if (shownCols < regBits / 32)
shownCols = std::min(maxBits / 32, regBits / 32);
for (int col = 0; col < numCols; col++)
if (col < shownCols)
regGrid->ShowCol(numCols - col - 1); // Big-endian representation so flip order
else
regGrid->HideCol(numCols - col - 1); // Big-endian representation so flip order
#endif
regGrid->AutoSize();
wxSize pageSize = regGrid->GetSize();
// Hack: Sometimes the vertical scroll bar covers some of the text so add some room
pageSize.x += 20;
// Hack: AFAIK wxNotebook does not provide a way to get the necessary size
// for the tabs so we use a rough approximation and hope that the tabs
// will have enough room to all be shown. 50 pixels per tab should hopefully work.
int minX = registerCategories->GetPageCount() * 50;
pageSize.x = std::max(pageSize.x, minX);
// Hack: Sometimes showing all the rows on the screen take up too much
// vertical room and squeezes other components (breakpoint window, etc.)
// into nothing so we limit the vertical size with this heuristic.
// If necessary, this will automatically create a vertical scroll bar so
// all rows can be accessed.
int screenSize = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y);
pageSize.y = std::min(std::max(screenSize - 400, screenSize / 2), pageSize.y);
regGrid->SetSize(pageSize);
wxSize size = registerCategories->CalcSizeFromPage(pageSize);
if (registerCategories->GetSize() != size)
registerCategories->SetSize(size);
SetMinSize(size); // registerCategories is the whole window so same min-size
// Need to update the whole debugger window since other components
// may be resized due to this component being resized
postEvent(debEVT_UPDATELAYOUT, 0);
} }
void CtrlRegisterList::postEvent(wxEventType type, wxString text) void CtrlRegisterList::postEvent(wxEventType type, wxString text)
{ {
wxCommandEvent event(type, GetId()); wxCommandEvent event( type, GetId() );
event.SetEventObject(this); event.SetEventObject(this);
event.SetString(text); event.SetString(text);
wxPostEvent(this, event); wxPostEvent(this,event);
} }
void CtrlRegisterList::postEvent(wxEventType type, int value) void CtrlRegisterList::postEvent(wxEventType type, int value)
{ {
wxCommandEvent event(type, GetId()); wxCommandEvent event( type, GetId() );
event.SetEventObject(this); event.SetEventObject(this);
event.SetInt(value); event.SetInt(value);
wxPostEvent(this, event); wxPostEvent(this,event);
} }
// Sets the "changed" flag for values that have changed from the last cycle.
// These values are colored differently when they are displayed.
void CtrlRegisterList::refreshChangedRegs() void CtrlRegisterList::refreshChangedRegs()
{ {
if (cpu->getPC() == lastPc && cpu->getCycles() == lastCycles) if (cpu->getPC() == lastPc)
return; return;
for (int cat = 0; cat < cpu->getRegisterCategoryCount(); cat++) for (size_t cat = 0; cat < changedCategories.size(); cat++)
{ {
std::vector<ChangedReg>& regs = changedCategories[cat]; ChangedReg* regs = changedCategories[cat];
int size = cpu->getRegisterSize(cat); int size = cpu->getRegisterSize(category);
for (int i = 0; i < cpu->getRegisterCount(cat); i++) for (int i = 0; i < cpu->getRegisterCount(cat); i++)
{ {
ChangedReg& reg = regs[i]; ChangedReg& reg = regs[i];
memset(&reg.changed, 0, sizeof(reg.changed)); memset(&reg.changed,0,sizeof(reg.changed));
u128 newValue = cpu->getRegister(cat, i); u128 newValue = cpu->getRegister(cat,i);
if (reg.oldValue != newValue) if (reg.oldValue != newValue)
{ {
bool changed = false; bool changed = false;
if (size >= 128 && (reg.oldValue._u32[3] != newValue._u32[3] || reg.oldValue._u32[2] != newValue._u32[2])) if (size >= 128 && (reg.oldValue._u32[3] != newValue._u32[3] || reg.oldValue._u32[2] != newValue._u32[2]))
{ {
changed = true; changed = true;
reg.changed[3] = true; reg.changed[3] = true;
reg.changed[2] = true; reg.changed[2] = true;
} }
if (size >= 64 && (reg.oldValue._u32[1] != newValue._u32[1] || changed)) if (size >= 64 && (reg.oldValue._u32[1] != newValue._u32[1] || changed))
{ {
changed = true; changed = true;
reg.changed[1] = true; reg.changed[1] = true;
} }
if (reg.oldValue._u32[0] != newValue._u32[0] || changed) if (reg.oldValue._u32[0] != newValue._u32[0] || changed)
{ {
reg.changed[0] = true; reg.changed[0] = true;
} }
reg.oldValue = newValue;
}
}
}
lastPc = cpu->getPC(); reg.oldValue = newValue;
lastCycles = cpu->getCycles(); }
}
}
lastPc = cpu->getPC();
} }
void CtrlRegisterList::paintEvent(wxPaintEvent & evt) void CtrlRegisterList::redraw()
{ {
updateHandler(); Update();
evt.Skip();
} }
void CtrlRegisterList::updateHandler() void CtrlRegisterList::sizeEvent(wxSizeEvent& evt)
{ {
if (cpu->isCpuPaused() || needsValueUpdating) Refresh();
{ evt.Skip();
refreshChangedRegs();
updateValues(getCurrentCategory());
needsValueUpdating = false;
}
if (needsSizeUpdating)
{
updateSize(getCurrentCategory());
needsSizeUpdating = false;
}
// The wxGrid allows selecting boxes with a bold outline
// but we don't want this, and there is no setting to turn off this feature
wxGrid* regGrid = registerGrids[getCurrentCategory()];
regGrid->ClearSelection();
} }
void CtrlRegisterList::changeValue(RegisterChangeMode mode, int cat, int reg) void drawU32Text(wxDC& dc, u32 value, int x, int y)
{ {
wxString oldStr; char str[32];
u128 oldValue = cpu->getRegister(cat, reg); sprintf(str,"%08X",value);
dc.DrawText(wxString(str,wxConvUTF8),x,y);
}
switch (mode) void CtrlRegisterList::OnDraw(wxDC& dc)
{ {
case LOWER64: #ifdef WIN32
oldStr = wxsFormat(L"0x%016llX", oldValue._u64[0]); wxFont font = wxFont(wxSize(charWidth,rowHeight-2),wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL,false,L"Lucida Console");
break; #else
case UPPER64: wxFont font = wxFont(8,wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL,false,L"Lucida Console");
oldStr = wxsFormat(L"0x%016llX", oldValue._u64[1]); font.SetPixelSize(wxSize(charWidth,rowHeight-2));
break; #endif
case CHANGE32: dc.SetFont(font);
oldStr = wxsFormat(L"0x%08X", oldValue._u64[0]);
break; // clear background
} wxColor white = wxColor(0xFFFFFFFF);
u64 newValue; dc.SetBrush(wxBrush(white));
if (executeExpressionWindow(this, cpu, newValue, oldStr)) dc.SetPen(wxPen(white));
{
switch (mode) wxSize size = GetClientSize();
{ dc.DrawRectangle(0,0,size.x,size.y);
case LOWER64:
oldValue._u64[0] = newValue; refreshChangedRegs();
break;
case UPPER64: wxColor colorChanged = wxColor(0xFF0000FF);
oldValue._u64[1] = newValue; wxColor colorUnchanged = wxColor(0xFF004000);
break; wxColor colorNormal = wxColor(0xFF600000);
case CHANGE32:
oldValue._u32[0] = newValue; // draw categories
break; int piece = size.x/cpu->getRegisterCategoryCount();
} for (int i = 0; i < cpu->getRegisterCategoryCount(); i++)
cpu->setRegister(cat, reg, oldValue); {
oldValue = cpu->getRegister(cat, reg); const char* name = cpu->getRegisterCategoryName(i);
}
needsValueUpdating = true; int x = i*piece;
needsSizeUpdating = true;
if (i == category)
{
dc.SetBrush(wxBrush(wxColor(0xFF70FF70)));
dc.SetPen(wxPen(wxColor(0xFF000000)));
} else {
dc.SetBrush(wxBrush(wxColor(0xFFFFEFE8)));
dc.SetPen(wxPen(wxColor(0xFF000000)));
}
if (i == cpu->getRegisterCategoryCount()-1)
piece += size.x-piece*cpu->getRegisterCategoryCount()-1;
dc.DrawRectangle(x,0,piece+1,rowHeight);
// center text
x += (piece-strlen(name)*charWidth)/2;
dc.DrawText(wxString(name,wxConvUTF8),x,2);
}
int nameStart = 17;
int valueStart = startPositions[category];
ChangedReg* changedRegs = changedCategories[category];
int registerBits = cpu->getRegisterSize(category);
DebugInterface::RegisterType type = cpu->getRegisterType(category);
for (int i = 0; i < cpu->getRegisterCount(category); i++)
{
int x = valueStart;
int y = rowHeight*(i+1);
if (currentRows[category] == i)
{
dc.SetBrush(wxBrush(wxColor(0xFFFFCFC8)));
dc.SetPen(wxPen(wxColor(0xFFFFEFE8)));
dc.DrawRectangle(0,y,size.x,rowHeight);
} else if (i % 2)
{
wxColor color = wxColor(237,242,255,255);
dc.SetBrush(wxBrush(color));
dc.SetPen(wxPen(color));
dc.DrawRectangle(0, y, size.x, rowHeight);
}
const char* name = cpu->getRegisterName(category,i);
dc.SetTextForeground(colorNormal);
dc.DrawText(wxString(name,wxConvUTF8),nameStart,y+2);
u128 value = cpu->getRegister(category,i);
ChangedReg& changed = changedRegs[i];
switch (type)
{
case DebugInterface::NORMAL: // display them in 32 bit parts
switch (registerBits)
{
case 128:
{
int startIndex = std::min<int>(3,maxBits/32-1);
int actualX = size.x-4-(startIndex+1)*(8*charWidth+2);
x = std::max<int>(actualX,x);
if (startIndex != 3)
{
bool c = false;
for (int i = 3; i > startIndex; i--)
c = c || changed.changed[i];
if (c)
{
dc.SetTextForeground(colorChanged);
dc.DrawText(L"+",x-charWidth,y+2);
}
}
for (int i = startIndex; i >= 0; i--)
{
if (changed.changed[i])
dc.SetTextForeground(colorChanged);
else
dc.SetTextForeground(colorUnchanged);
drawU32Text(dc,value._u32[i],x,y+2);
x += charWidth*8+2;
}
break;
}
case 64:
{
if (maxBits < 64 && changed.changed[1])
{
dc.SetTextForeground(colorChanged);
dc.DrawText(L"+",x-charWidth,y+2);
}
for (int i = 1; i >= 0; i--)
{
if (changed.changed[i])
dc.SetTextForeground(colorChanged);
else
dc.SetTextForeground(colorUnchanged);
drawU32Text(dc,value._u32[i],x,y+2);
x += charWidth*8+2;
}
break;
}
case 32:
{
if (changed.changed[0])
dc.SetTextForeground(colorChanged);
else
dc.SetTextForeground(colorUnchanged);
drawU32Text(dc,value._u32[0],x,y+2);
break;
}
}
break;
case DebugInterface::SPECIAL: // let debug interface format them and just display them
{
if (changed.changed[0] || changed.changed[1] || changed.changed[2] || changed.changed[3])
dc.SetTextForeground(colorChanged);
else
dc.SetTextForeground(colorUnchanged);
dc.DrawText(cpu->getRegisterString(category,i),x,y+2);
break;
}
}
}
}
void CtrlRegisterList::changeValue(RegisterChangeMode mode)
{
wchar_t str[64];
u128 oldValue = cpu->getRegister(category,currentRows[category]);
switch (mode)
{
case LOWER64:
swprintf(str,64,L"0x%016llX",oldValue._u64[0]);
break;
case UPPER64:
swprintf(str,64,L"0x%016llX",oldValue._u64[1]);
break;
case CHANGE32:
swprintf(str,64,L"0x%08X",oldValue._u32[0]);
break;
}
u64 newValue;
if (executeExpressionWindow(this,cpu,newValue,str))
{
switch (mode)
{
case LOWER64:
oldValue._u64[0] = newValue;
break;
case UPPER64:
oldValue._u64[1] = newValue;
break;
case CHANGE32:
oldValue._u32[0] = newValue;
break;
}
cpu->setRegister(category,currentRows[category],oldValue);
}
} }
void CtrlRegisterList::onPopupClick(wxCommandEvent& evt) void CtrlRegisterList::onPopupClick(wxCommandEvent& evt)
{ {
int cat = getCurrentCategory(); switch (evt.GetId())
wxGrid* regGrid = registerGrids[cat]; {
int reg = regGrid->GetGridCursorRow(); case ID_REGISTERLIST_DISPLAY32:
switch (evt.GetId()) maxBits = 32;
{ SetInitialSize(ClientToWindowSize(GetMinClientSize()));
case ID_REGISTERLIST_DISPLAY32: postEvent(debEVT_UPDATELAYOUT,0);
maxBits = 32; Refresh();
postEvent(debEVT_UPDATELAYOUT, 0); break;
Refresh(); case ID_REGISTERLIST_DISPLAY64:
break; maxBits = 64;
case ID_REGISTERLIST_DISPLAY64: SetInitialSize(ClientToWindowSize(GetMinClientSize()));
maxBits = 64; postEvent(debEVT_UPDATELAYOUT,0);
postEvent(debEVT_UPDATELAYOUT, 0); Refresh();
Refresh(); break;
break; case ID_REGISTERLIST_DISPLAY128:
case ID_REGISTERLIST_DISPLAY128: maxBits = 128;
maxBits = 128; SetInitialSize(ClientToWindowSize(GetMinClientSize()));
postEvent(debEVT_UPDATELAYOUT, 0); postEvent(debEVT_UPDATELAYOUT,0);
Refresh(); Refresh();
break; break;
case ID_REGISTERLIST_CHANGELOWER: case ID_REGISTERLIST_CHANGELOWER:
changeValue(LOWER64, cat, reg); changeValue(LOWER64);
Refresh(); Refresh();
break; break;
case ID_REGISTERLIST_CHANGEUPPER: case ID_REGISTERLIST_CHANGEUPPER:
changeValue(UPPER64, cat, reg); changeValue(UPPER64);
Refresh(); Refresh();
break; break;
case ID_REGISTERLIST_CHANGEVALUE: case ID_REGISTERLIST_CHANGEVALUE:
if (cpu->getRegisterSize(cat) == 32) if (cpu->getRegisterSize(category) == 32)
changeValue(CHANGE32, cat, reg); changeValue(CHANGE32);
else else
changeValue(LOWER64, cat, reg); changeValue(LOWER64);
Refresh(); Refresh();
break; break;
default: default:
wxMessageBox(L"Unimplemented.", L"Unimplemented.", wxICON_INFORMATION); wxMessageBox( L"Unimplemented.", L"Unimplemented.", wxICON_INFORMATION);
break; break;
} }
needsValueUpdating = true;
needsSizeUpdating = true;
} }
int CtrlRegisterList::getCurrentCategory() const void CtrlRegisterList::setCurrentRow(int row)
{ {
return registerCategories->GetSelection(); char str[256];
u128 value ;
wxString text;
const char* name = cpu->getRegisterName(category,row);
switch (cpu->getRegisterType(category))
{
case DebugInterface::NORMAL:
value = cpu->getRegister(category,row);
switch (cpu->getRegisterSize(category))
{
case 128:
sprintf(str,"%s = 0x%08X%08X%08X%08X",name,value._u32[3],value._u32[2],value._u32[1],value._u32[0]);
break;
case 64:
sprintf(str,"%s = 0x%08X%08X",name,value._u32[1],value._u32[0]);
break;
case 32:
sprintf(str,"%s = 0x%08X",name,value._u32[0]);
break;
}
text = wxString(str,wxConvUTF8);
break;
case DebugInterface::SPECIAL:
text = wxString(name,wxConvUTF8) + L" = " + cpu->getRegisterString(category,row);
break;
}
currentRows[category] = row;
postEvent(debEVT_SETSTATUSBARTEXT,text);
Refresh();
} }
void CtrlRegisterList::mouseEvent(wxMouseEvent& evt)
void CtrlRegisterList::gridEvent(wxGridEvent& evt)
{ {
// Mouse events int xOffset, yOffset;
if (evt.GetEventType() == wxEVT_GRID_CELL_RIGHT_CLICK || ((wxScrolledWindow*) this)->GetViewStart(&xOffset, &yOffset);
evt.GetEventType() == wxEVT_GRID_LABEL_RIGHT_CLICK)
{
wxMenu menu;
int bits = cpu->getRegisterSize(getCurrentCategory());
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY32, L"Display 32 bit"); wxClientDC dc(this);
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY64, L"Display 64 bit"); wxPoint pos = evt.GetPosition();
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY128, L"Display 128 bit"); int x = dc.DeviceToLogicalX(pos.x) + xOffset;
menu.AppendSeparator(); int y = dc.DeviceToLogicalY(pos.y) + yOffset;
if (bits >= 64) if (evt.GetEventType() == wxEVT_RIGHT_UP)
{ {
menu.Append(ID_REGISTERLIST_CHANGELOWER, L"Change lower 64 bit"); if (y >= rowHeight)
menu.Append(ID_REGISTERLIST_CHANGEUPPER, L"Change upper 64 bit"); {
} int row = (y-rowHeight)/rowHeight;
else { if (row != currentRows[category] && row < cpu->getRegisterCount(category))
menu.Append(ID_REGISTERLIST_CHANGEVALUE, L"Change value"); setCurrentRow(row);
} }
switch (maxBits) wxMenu menu;
{ int bits = cpu->getRegisterSize(category);
case 128:
menu.Check(ID_REGISTERLIST_DISPLAY128, true);
break;
case 64:
menu.Check(ID_REGISTERLIST_DISPLAY64, true);
break;
case 32:
menu.Check(ID_REGISTERLIST_DISPLAY32, true);
break;
}
menu.Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CtrlRegisterList::onPopupClick), nullptr, this); menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY32, L"Display 32 bit");
PopupMenu(&menu, evt.GetPosition()); menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY64, L"Display 64 bit");
needsValueUpdating = true; menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY128, L"Display 128 bit");
} menu.AppendSeparator();
else
{
evt.Skip();
}
}
void CtrlRegisterList::categoryChangedEvent(wxBookCtrlEvent& evt) if (bits >= 64)
{ {
needsSizeUpdating = true; menu.Append(ID_REGISTERLIST_CHANGELOWER, L"Change lower 64 bit");
needsValueUpdating = true; menu.Append(ID_REGISTERLIST_CHANGEUPPER, L"Change upper 64 bit");
evt.Skip(); } else {
menu.Append(ID_REGISTERLIST_CHANGEVALUE, L"Change value");
}
switch (maxBits)
{
case 128:
menu.Check(ID_REGISTERLIST_DISPLAY128,true);
break;
case 64:
menu.Check(ID_REGISTERLIST_DISPLAY64,true);
break;
case 32:
menu.Check(ID_REGISTERLIST_DISPLAY32,true);
break;
}
menu.Connect(wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&CtrlRegisterList::onPopupClick, NULL, this);
PopupMenu(&menu,evt.GetPosition());
return;
}
if (evt.ButtonIsDown(wxMOUSE_BTN_LEFT) || evt.ButtonIsDown(wxMOUSE_BTN_RIGHT))
{
if (y < rowHeight)
{
int piece = GetSize().x/cpu->getRegisterCategoryCount();
int cat = std::min<int>(x/piece,cpu->getRegisterCategoryCount()-1);
if (cat != category)
{
category = cat;
Refresh();
}
} else {
int row = (y-rowHeight)/rowHeight;
if (row != currentRows[category] && row < cpu->getRegisterCount(category))
setCurrentRow(row);
}
SetFocus();
SetFocusFromKbd();
}
} }
void CtrlRegisterList::keydownEvent(wxKeyEvent& evt) void CtrlRegisterList::keydownEvent(wxKeyEvent& evt)
{ {
needsValueUpdating = true; switch (evt.GetKeyCode())
evt.Skip(); {
case WXK_UP:
setCurrentRow(std::max<int>(currentRows[category]-1,0));
break;
case WXK_DOWN:
setCurrentRow(std::min<int>(currentRows[category]+1,cpu->getRegisterCount(category)-1));
break;
case WXK_TAB:
category = (category+1) % cpu->getRegisterCategoryCount();
Refresh();
break;
}
} }

View File

@ -15,50 +15,60 @@
#pragma once #pragma once
#include <wx/wx.h> #include <wx/wx.h>
#include <wx/notebook.h>
#include <wx/grid.h>
#include "DebugTools/DebugInterface.h" #include "DebugTools/DebugInterface.h"
#include "DebugTools/DisassemblyManager.h" #include "DebugTools/DisassemblyManager.h"
class CtrlRegisterList : public wxWindow class CtrlRegisterList: public wxScrolledWindow
{ {
public: public:
CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu); CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu);
void mouseEvent(wxMouseEvent& evt);
void keydownEvent(wxKeyEvent& evt);
void onPopupClick(wxCommandEvent& evt);
void sizeEvent(wxSizeEvent& evt);
void redraw();
DECLARE_EVENT_TABLE()
virtual wxSize GetMinClientSize() const
{
wxSize optimalSize = getOptimalSize();
if (GetWindowStyle() & wxVSCROLL)
optimalSize.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
// Event handlers return wxSize(optimalSize.x,0);
void paintEvent(wxPaintEvent & evt); }
void onPopupClick(wxCommandEvent& evt);
void gridEvent(wxGridEvent& evt); virtual wxSize DoGetBestClientSize() const
void categoryChangedEvent(wxBookCtrlEvent& evt); {
void keydownEvent(wxKeyEvent& evt); return GetMinClientSize();
DECLARE_EVENT_TABLE() }
private: private:
enum RegisterChangeMode { LOWER64, UPPER64, CHANGE32 }; enum RegisterChangeMode { LOWER64, UPPER64, CHANGE32 };
void refreshChangedRegs(); void OnDraw(wxDC& dc);
void refreshChangedRegs();
void setCurrentRow(int row);
void changeValue(RegisterChangeMode mode);
wxSize getOptimalSize() const;
void changeValue(RegisterChangeMode mode, int cat, int reg); void postEvent(wxEventType type, wxString text);
void updateHandler(); void postEvent(wxEventType type, int value);
void updateValues(int cat);
void updateSize(int cat);
int getCurrentCategory() const;
void postEvent(wxEventType type, wxString text);
void postEvent(wxEventType type, int value);
struct ChangedReg struct ChangedReg
{ {
u128 oldValue; u128 oldValue;
bool changed[4]; bool changed[4];
ChangedReg() { memset(this, 0, sizeof(*this)); } };
};
std::vector<ChangedReg*> changedCategories;
std::vector<int> startPositions;
std::vector<int> currentRows;
std::vector<std::vector<ChangedReg>> changedCategories; DebugInterface* cpu;
int rowHeight,charWidth;
DebugInterface* cpu; // Used to get register values and other info from the emu u32 lastPc;
u32 lastPc, lastCycles; int category;
int maxBits; // maximum number of bits beings displayed int maxBits;
bool needsSizeUpdating, needsValueUpdating; // flags set in events to signal that values/sizes should be updated on the next display };
wxNotebook* registerCategories; // Occupies this entire window. Is the tabbed window for selecting register categories.
std::vector<wxGrid*> registerGrids; // Grids displaying register values for each of the tabs.
};

View File

@ -39,6 +39,7 @@ BEGIN_EVENT_TABLE(DisassemblyDialog, wxFrame)
EVT_COMMAND( wxID_ANY, debEVT_UPDATE, DisassemblyDialog::onDebuggerEvent ) EVT_COMMAND( wxID_ANY, debEVT_UPDATE, DisassemblyDialog::onDebuggerEvent )
EVT_COMMAND( wxID_ANY, debEVT_BREAKPOINTWINDOW, DisassemblyDialog::onDebuggerEvent ) EVT_COMMAND( wxID_ANY, debEVT_BREAKPOINTWINDOW, DisassemblyDialog::onDebuggerEvent )
EVT_COMMAND( wxID_ANY, debEVT_MAPLOADED, DisassemblyDialog::onDebuggerEvent ) EVT_COMMAND( wxID_ANY, debEVT_MAPLOADED, DisassemblyDialog::onDebuggerEvent )
EVT_SIZE(DisassemblyDialog::onSizeEvent)
EVT_CLOSE( DisassemblyDialog::onClose ) EVT_CLOSE( DisassemblyDialog::onClose )
END_EVENT_TABLE() END_EVENT_TABLE()
@ -176,7 +177,7 @@ void CpuTabPage::update()
{ {
breakpointList->reloadBreakpoints(); breakpointList->reloadBreakpoints();
if (threadList != NULL) if (threadList != NULL && cpu->isAlive())
{ {
threadList->reloadThreads(); threadList->reloadThreads();
@ -217,6 +218,8 @@ DisassemblyDialog::DisassemblyDialog(wxWindow* parent):
wxFrame( parent, wxID_ANY, L"Debugger", wxDefaultPosition,wxDefaultSize,wxRESIZE_BORDER|wxCLOSE_BOX|wxCAPTION|wxSYSTEM_MENU ), wxFrame( parent, wxID_ANY, L"Debugger", wxDefaultPosition,wxDefaultSize,wxRESIZE_BORDER|wxCLOSE_BOX|wxCAPTION|wxSYSTEM_MENU ),
currentCpu(NULL) currentCpu(NULL)
{ {
int width = g_Conf->EmuOptions.Debugger.WindowWidth;
int height = g_Conf->EmuOptions.Debugger.WindowHeight;
topSizer = new wxBoxSizer( wxVERTICAL ); topSizer = new wxBoxSizer( wxVERTICAL );
wxPanel *panel = new wxPanel(this, wxID_ANY, wxPanel *panel = new wxPanel(this, wxID_ANY,
@ -252,7 +255,7 @@ DisassemblyDialog::DisassemblyDialog(wxWindow* parent):
topSizer->Add(topRowSizer,0,wxLEFT|wxRIGHT|wxTOP,3); topSizer->Add(topRowSizer,0,wxLEFT|wxRIGHT|wxTOP,3);
// create middle part of the window // create middle part of the window
wxNotebook* middleBook = new wxNotebook(panel,wxID_ANY); middleBook = new wxNotebook(panel,wxID_ANY);
middleBook->SetBackgroundColour(wxColour(0xFFF0F0F0)); middleBook->SetBackgroundColour(wxColour(0xFFF0F0F0));
eeTab = new CpuTabPage(middleBook,&r5900Debug); eeTab = new CpuTabPage(middleBook,&r5900Debug);
iopTab = new CpuTabPage(middleBook,&r3000Debug); iopTab = new CpuTabPage(middleBook,&r3000Debug);
@ -267,9 +270,23 @@ DisassemblyDialog::DisassemblyDialog(wxWindow* parent):
SetMinSize(wxSize(1000,600)); SetMinSize(wxSize(1000,600));
panel->GetSizer()->Fit(this); panel->GetSizer()->Fit(this);
if (width != 0 && height != 0)
SetSize(width,height);
setDebugMode(true,true); setDebugMode(true,true);
} }
void DisassemblyDialog::onSizeEvent(wxSizeEvent& event)
{
if (event.GetEventType() == wxEVT_SIZE)
{
g_Conf->EmuOptions.Debugger.WindowWidth = event.GetSize().x;
g_Conf->EmuOptions.Debugger.WindowHeight = event.GetSize().y;
}
event.Skip();
}
#ifdef WIN32 #ifdef WIN32
WXLRESULT DisassemblyDialog::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) WXLRESULT DisassemblyDialog::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{ {
@ -469,7 +486,7 @@ void DisassemblyDialog::onDebuggerEvent(wxCommandEvent& evt)
if (type == debEVT_SETSTATUSBARTEXT) if (type == debEVT_SETSTATUSBARTEXT)
{ {
DebugInterface* cpu = reinterpret_cast<DebugInterface*>(evt.GetClientData()); DebugInterface* cpu = reinterpret_cast<DebugInterface*>(evt.GetClientData());
if (cpu != NULL && cpu == currentCpu->getCpu()) if (cpu != NULL && currentCpu != NULL && cpu == currentCpu->getCpu())
GetStatusBar()->SetLabel(evt.GetString()); GetStatusBar()->SetLabel(evt.GetString());
} else if (type == debEVT_UPDATELAYOUT) } else if (type == debEVT_UPDATELAYOUT)
{ {
@ -568,6 +585,19 @@ void DisassemblyDialog::setDebugMode(bool debugMode, bool switchPC)
if (running) if (running)
{ {
if (currentCpu == NULL)
{
wxWindow* currentPage = middleBook->GetCurrentPage();
if (currentPage == eeTab)
currentCpu = eeTab;
else if (currentPage == iopTab)
currentCpu = iopTab;
if (currentCpu != NULL)
currentCpu->update();
}
if (debugMode) if (debugMode)
{ {
CBreakPoints::ClearTemporaryBreakPoints(); CBreakPoints::ClearTemporaryBreakPoints();
@ -596,6 +626,12 @@ void DisassemblyDialog::setDebugMode(bool debugMode, bool switchPC)
stepOverButton->Enable(false); stepOverButton->Enable(false);
stepOutButton->Enable(false); stepOutButton->Enable(false);
} }
} else {
breakRunButton->SetLabel(L"Run");
stepIntoButton->Enable(false);
stepOverButton->Enable(false);
stepOutButton->Enable(false);
currentCpu = NULL;
} }
update(); update();

View File

@ -23,6 +23,7 @@
#include "CtrlMemView.h" #include "CtrlMemView.h"
#include "DebugEvents.h" #include "DebugEvents.h"
#include "DebuggerLists.h" #include "DebuggerLists.h"
#include "../MSWstuff.h"
class DebuggerHelpDialog: public wxDialog class DebuggerHelpDialog: public wxDialog
{ {
@ -30,6 +31,16 @@ public:
DebuggerHelpDialog(wxWindow* parent); DebuggerHelpDialog(wxWindow* parent);
}; };
inline int getDebugFontWidth()
{
return (int) ceil(g_Conf->EmuOptions.Debugger.FontWidth*MSW_GetDPIScale());
}
inline int getDebugFontHeight()
{
return (int)ceil(g_Conf->EmuOptions.Debugger.FontHeight*MSW_GetDPIScale());
}
class CpuTabPage: public wxPanel class CpuTabPage: public wxPanel
{ {
public: public:
@ -91,6 +102,7 @@ protected:
void onDebuggerEvent(wxCommandEvent& evt); void onDebuggerEvent(wxCommandEvent& evt);
void onPageChanging(wxCommandEvent& evt); void onPageChanging(wxCommandEvent& evt);
void onBreakpointClick(wxCommandEvent& evt); void onBreakpointClick(wxCommandEvent& evt);
void onSizeEvent(wxSizeEvent& event);
void onClose(wxCloseEvent& evt); void onClose(wxCloseEvent& evt);
void stepOver(); void stepOver();
void stepInto(); void stepInto();
@ -100,6 +112,7 @@ private:
CpuTabPage* eeTab; CpuTabPage* eeTab;
CpuTabPage* iopTab; CpuTabPage* iopTab;
CpuTabPage* currentCpu; CpuTabPage* currentCpu;
wxNotebook* middleBook;
wxBoxSizer* topSizer; wxBoxSizer* topSizer;
wxButton* breakRunButton; wxButton* breakRunButton;