mirror of https://github.com/PCSX2/pcsx2.git
Rewrite of CtrlRegisterList class to enable scrolling.
This commit is contained in:
parent
abdb8266b6
commit
f7e10ed53e
|
@ -20,14 +20,7 @@
|
||||||
#include "DebugEvents.h"
|
#include "DebugEvents.h"
|
||||||
#include "AppConfig.h"
|
#include "AppConfig.h"
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(CtrlRegisterList, wxWindow)
|
|
||||||
EVT_PAINT(CtrlRegisterList::paintEvent)
|
|
||||||
EVT_LEFT_DOWN(CtrlRegisterList::mouseEvent)
|
|
||||||
EVT_RIGHT_DOWN(CtrlRegisterList::mouseEvent)
|
|
||||||
EVT_RIGHT_UP(CtrlRegisterList::mouseEvent)
|
|
||||||
EVT_MOTION(CtrlRegisterList::mouseEvent)
|
|
||||||
EVT_KEY_DOWN(CtrlRegisterList::keydownEvent)
|
|
||||||
END_EVENT_TABLE()
|
|
||||||
|
|
||||||
enum DisassemblyMenuIdentifiers
|
enum DisassemblyMenuIdentifiers
|
||||||
{
|
{
|
||||||
|
@ -39,37 +32,186 @@ enum DisassemblyMenuIdentifiers
|
||||||
ID_REGISTERLIST_CHANGEVALUE
|
ID_REGISTERLIST_CHANGEVALUE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu) :
|
||||||
CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu)
|
wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS | wxBORDER_NONE),
|
||||||
: wxWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS|wxBORDER_NONE), cpu(_cpu)
|
cpu(_cpu),
|
||||||
|
lastPc(0),
|
||||||
|
maxBits(128),
|
||||||
|
lastCycles(0),
|
||||||
|
needsValueUpdating(true),
|
||||||
|
needsSizeUpdating(true)
|
||||||
{
|
{
|
||||||
rowHeight = g_Conf->EmuOptions.Debugger.FontHeight+2;
|
int rowHeight = g_Conf->EmuOptions.Debugger.FontHeight + 2;
|
||||||
charWidth = g_Conf->EmuOptions.Debugger.FontWidth;
|
int charWidth = g_Conf->EmuOptions.Debugger.FontWidth;
|
||||||
category = 0;
|
|
||||||
maxBits = 128;
|
|
||||||
lastPc = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
for (int i = 0; i < cpu->getRegisterCategoryCount(); i++)
|
|
||||||
|
#ifdef WIN32
|
||||||
|
wxFont font = wxFont(wxSize(charWidth, rowHeight - 2), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL,
|
||||||
|
false, L"Lucida Console");
|
||||||
|
#else
|
||||||
|
wxFont font = wxFont(8, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, L"Lucida Console");
|
||||||
|
font.SetPixelSize(wxSize(charWidth, rowHeight - 2));
|
||||||
|
#endif
|
||||||
|
registerCategories = new wxNotebook(this, -1);
|
||||||
|
registerCategories->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, &CtrlRegisterList::categoryChangedEvent, this);
|
||||||
|
for (int cat = 0; cat < cpu->getRegisterCategoryCount(); cat++)
|
||||||
{
|
{
|
||||||
int count = cpu->getRegisterCount(i);
|
int numRegs = cpu->getRegisterCount(cat);
|
||||||
|
|
||||||
ChangedReg* regs = new ChangedReg[count];
|
changedCategories.push_back(std::vector<ChangedReg>(numRegs));
|
||||||
memset(regs,0,sizeof(ChangedReg)*count);
|
|
||||||
changedCategories.push_back(regs);
|
|
||||||
|
|
||||||
int maxLen = 0;
|
wxGrid* regGrid = new wxGrid(registerCategories, -1);
|
||||||
for (int k = 0; k < cpu->getRegisterCount(i); k++)
|
|
||||||
|
registerGrids.push_back(regGrid);
|
||||||
|
registerCategories->AddPage(regGrid, cpu->getRegisterCategoryName(cat));
|
||||||
|
|
||||||
|
DebugInterface::RegisterType type = cpu->getRegisterType(cat);
|
||||||
|
int registerBits = cpu->getRegisterSize(cat);
|
||||||
|
|
||||||
|
int numCols;
|
||||||
|
switch (type)
|
||||||
{
|
{
|
||||||
maxLen = std::max<int>(maxLen,strlen(cpu->getRegisterName(i,k)));
|
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, cpu->getRegisterName(cat, row));
|
||||||
|
for (int col = 0; col < numCols; col++)
|
||||||
|
regGrid->SetColLabelValue(col, std::to_string(32 * (numCols - col) - 1) + std::string("-") +
|
||||||
|
std::to_string(32 * (numCols - col - 1)));
|
||||||
|
break;
|
||||||
|
case DebugInterface::SPECIAL:
|
||||||
|
regGrid->CreateGrid(numRegs, 1);
|
||||||
|
for (int row = 0; row < numRegs; row++)
|
||||||
|
regGrid->SetRowLabelValue(row, cpu->getRegisterName(cat, row));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = 17+(maxLen+3)*charWidth;
|
regGrid->EnableEditing(false);
|
||||||
startPositions.push_back(x);
|
regGrid->SetDefaultCellFont(font);
|
||||||
currentRows.push_back(0);
|
regGrid->DisableDragGridSize();
|
||||||
|
regGrid->DisableDragRowSize();
|
||||||
|
regGrid->DisableDragColSize();
|
||||||
|
regGrid->Bind(wxEVT_PAINT, &CtrlRegisterList::paintEvent, this);
|
||||||
|
regGrid->Bind(wxEVT_GRID_LABEL_LEFT_CLICK, &CtrlRegisterList::gridEvent, this);
|
||||||
|
regGrid->Bind(wxEVT_GRID_LABEL_RIGHT_CLICK, &CtrlRegisterList::gridEvent, this);
|
||||||
|
regGrid->Bind(wxEVT_GRID_CELL_RIGHT_CLICK, &CtrlRegisterList::gridEvent, this);
|
||||||
|
regGrid->Bind(wxEVT_GRID_CELL_LEFT_CLICK, &CtrlRegisterList::gridEvent, this);
|
||||||
|
regGrid->Bind(wxEVT_KEY_DOWN, &CtrlRegisterList::keydownEvent, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int cat = 0; cat < cpu->getRegisterCategoryCount(); cat++)
|
||||||
|
updateValues(cat);
|
||||||
|
|
||||||
|
updateSize(getCurrentCategory()); // getCurrentCategory() = 0
|
||||||
|
|
||||||
SetDoubleBuffered(true);
|
SetDoubleBuffered(true);
|
||||||
SetInitialSize(ClientToWindowSize(GetMinClientSize()));
|
}
|
||||||
|
|
||||||
|
// Called when this window needs to update the strings in the cells.
|
||||||
|
// 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 numRows = regGrid->GetNumberRows();
|
||||||
|
int numCols = regGrid->GetNumberCols();
|
||||||
|
|
||||||
|
std::vector<ChangedReg>& changedRegs = changedCategories[cat];
|
||||||
|
DebugInterface::RegisterType type = cpu->getRegisterType(cat);
|
||||||
|
for (int row = 0; row < numRows; row++)
|
||||||
|
{
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
const wxColor colorChanged = wxColor(0xFF0000FF);
|
||||||
|
const wxColor colorUnchanged = wxColor(0xFF004000);
|
||||||
|
wxColor textColor;
|
||||||
|
wxString cellValue;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case DebugInterface::NORMAL:
|
||||||
|
cellValue = wxString::Format("%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)
|
||||||
|
{
|
||||||
|
wxGrid* regGrid = registerGrids[cat];
|
||||||
|
|
||||||
|
// Make sure that the number of shown cols is correct.
|
||||||
|
{
|
||||||
|
int regBits = cpu->getRegisterSize(cat);
|
||||||
|
int numCols = regGrid->GetNumberCols();
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
regGrid->AutoSize();
|
||||||
|
wxSize pageSize = regGrid->GetSize();
|
||||||
|
|
||||||
|
// Hacks below
|
||||||
|
{
|
||||||
|
// 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 to 1/2 screen size.
|
||||||
|
// 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(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)
|
||||||
|
@ -88,15 +230,18 @@ void CtrlRegisterList::postEvent(wxEventType type, int 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)
|
if (cpu->getPC() == lastPc && cpu->getCycles() == lastCycles)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (size_t cat = 0; cat < changedCategories.size(); cat++)
|
for (int cat = 0; cat < cpu->getRegisterCategoryCount(); cat++)
|
||||||
{
|
{
|
||||||
ChangedReg* regs = changedCategories[cat];
|
std::vector<ChangedReg>& regs = changedCategories[cat];
|
||||||
int size = cpu->getRegisterSize(category);
|
int size = cpu->getRegisterSize(cat);
|
||||||
|
|
||||||
for (int i = 0; i < cpu->getRegisterCount(cat); i++)
|
for (int i = 0; i < cpu->getRegisterCount(cat); i++)
|
||||||
{
|
{
|
||||||
|
@ -126,199 +271,46 @@ void CtrlRegisterList::refreshChangedRegs()
|
||||||
{
|
{
|
||||||
reg.changed[0] = true;
|
reg.changed[0] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg.oldValue = newValue;
|
reg.oldValue = newValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastPc = cpu->getPC();
|
lastPc = cpu->getPC();
|
||||||
|
lastCycles = cpu->getCycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CtrlRegisterList::paintEvent(wxPaintEvent & evt)
|
void CtrlRegisterList::paintEvent(wxPaintEvent & evt)
|
||||||
{
|
{
|
||||||
wxPaintDC dc(this);
|
updateHandler();
|
||||||
render(dc);
|
evt.Skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CtrlRegisterList::redraw()
|
void CtrlRegisterList::updateHandler()
|
||||||
{
|
{
|
||||||
wxClientDC dc(this);
|
if (cpu->isCpuPaused() || needsValueUpdating)
|
||||||
render(dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawU32Text(wxDC& dc, u32 value, int x, int y)
|
|
||||||
{
|
{
|
||||||
char str[32];
|
|
||||||
sprintf(str,"%08X",value);
|
|
||||||
dc.DrawText(wxString(str,wxConvUTF8),x,y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CtrlRegisterList::render(wxDC& dc)
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
wxFont font = wxFont(wxSize(charWidth,rowHeight-2),wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL,false,L"Lucida Console");
|
|
||||||
#else
|
|
||||||
wxFont font = wxFont(8,wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL,false,L"Lucida Console");
|
|
||||||
font.SetPixelSize(wxSize(charWidth,rowHeight-2));
|
|
||||||
#endif
|
|
||||||
dc.SetFont(font);
|
|
||||||
|
|
||||||
// clear background
|
|
||||||
wxColor white = wxColor(0xFFFFFFFF);
|
|
||||||
|
|
||||||
dc.SetBrush(wxBrush(white));
|
|
||||||
dc.SetPen(wxPen(white));
|
|
||||||
|
|
||||||
wxSize size = GetSize();
|
|
||||||
dc.DrawRectangle(0,0,size.x,size.y);
|
|
||||||
|
|
||||||
refreshChangedRegs();
|
refreshChangedRegs();
|
||||||
|
updateValues(getCurrentCategory());
|
||||||
|
needsValueUpdating = false;
|
||||||
|
}
|
||||||
|
|
||||||
wxColor colorChanged = wxColor(0xFF0000FF);
|
if (needsSizeUpdating)
|
||||||
wxColor colorUnchanged = wxColor(0xFF004000);
|
|
||||||
wxColor colorNormal = wxColor(0xFF600000);
|
|
||||||
|
|
||||||
// draw categories
|
|
||||||
int piece = size.x/cpu->getRegisterCategoryCount();
|
|
||||||
for (int i = 0; i < cpu->getRegisterCategoryCount(); i++)
|
|
||||||
{
|
{
|
||||||
const char* name = cpu->getRegisterCategoryName(i);
|
updateSize(getCurrentCategory());
|
||||||
|
needsSizeUpdating = false;
|
||||||
int x = i*piece;
|
|
||||||
|
|
||||||
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)
|
wxGrid* regGrid = registerGrids[getCurrentCategory()];
|
||||||
piece += size.x-piece*cpu->getRegisterCategoryCount()-1;
|
regGrid->ClearSelection();
|
||||||
|
|
||||||
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];
|
void CtrlRegisterList::changeValue(RegisterChangeMode mode, int cat, int reg)
|
||||||
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(0xFFFFEFE8)));
|
|
||||||
dc.SetPen(wxPen(wxColor(0xFFFFEFE8)));
|
|
||||||
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];
|
wchar_t str[64];
|
||||||
|
|
||||||
u128 oldValue = cpu->getRegister(category,currentRows[category]);
|
u128 oldValue = cpu->getRegister(cat, reg);
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
|
@ -348,106 +340,72 @@ void CtrlRegisterList::changeValue(RegisterChangeMode mode)
|
||||||
oldValue._u32[0] = newValue;
|
oldValue._u32[0] = newValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
cpu->setRegister(cat, reg, oldValue);
|
||||||
cpu->setRegister(category,currentRows[category],oldValue);
|
oldValue = cpu->getRegister(cat, reg);
|
||||||
}
|
}
|
||||||
|
needsValueUpdating = true;
|
||||||
|
needsSizeUpdating = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CtrlRegisterList::onPopupClick(wxCommandEvent& evt)
|
void CtrlRegisterList::onPopupClick(wxCommandEvent& evt)
|
||||||
{
|
{
|
||||||
|
int cat = getCurrentCategory();
|
||||||
|
wxGrid* regGrid = registerGrids[cat];
|
||||||
|
int reg = regGrid->GetGridCursorRow();
|
||||||
switch (evt.GetId())
|
switch (evt.GetId())
|
||||||
{
|
{
|
||||||
case ID_REGISTERLIST_DISPLAY32:
|
case ID_REGISTERLIST_DISPLAY32:
|
||||||
maxBits = 32;
|
maxBits = 32;
|
||||||
SetInitialSize(ClientToWindowSize(GetMinClientSize()));
|
|
||||||
postEvent(debEVT_UPDATELAYOUT, 0);
|
postEvent(debEVT_UPDATELAYOUT, 0);
|
||||||
Refresh();
|
Refresh();
|
||||||
break;
|
break;
|
||||||
case ID_REGISTERLIST_DISPLAY64:
|
case ID_REGISTERLIST_DISPLAY64:
|
||||||
maxBits = 64;
|
maxBits = 64;
|
||||||
SetInitialSize(ClientToWindowSize(GetMinClientSize()));
|
|
||||||
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);
|
changeValue(LOWER64, cat, reg);
|
||||||
Refresh();
|
Refresh();
|
||||||
break;
|
break;
|
||||||
case ID_REGISTERLIST_CHANGEUPPER:
|
case ID_REGISTERLIST_CHANGEUPPER:
|
||||||
changeValue(UPPER64);
|
changeValue(UPPER64, cat, reg);
|
||||||
Refresh();
|
Refresh();
|
||||||
break;
|
break;
|
||||||
case ID_REGISTERLIST_CHANGEVALUE:
|
case ID_REGISTERLIST_CHANGEVALUE:
|
||||||
if (cpu->getRegisterSize(category) == 32)
|
if (cpu->getRegisterSize(cat) == 32)
|
||||||
changeValue(CHANGE32);
|
changeValue(CHANGE32, cat, reg);
|
||||||
else
|
else
|
||||||
changeValue(LOWER64);
|
changeValue(LOWER64, cat, reg);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CtrlRegisterList::setCurrentRow(int row)
|
int CtrlRegisterList::getCurrentCategory() const
|
||||||
{
|
{
|
||||||
char str[256];
|
return registerCategories->GetSelection();
|
||||||
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)
|
||||||
{
|
{
|
||||||
if (evt.GetEventType() == wxEVT_RIGHT_UP)
|
// Mouse events
|
||||||
|
if (evt.GetEventType() == wxEVT_GRID_CELL_RIGHT_CLICK ||
|
||||||
|
evt.GetEventType() == wxEVT_GRID_LABEL_RIGHT_CLICK)
|
||||||
{
|
{
|
||||||
int y = evt.GetPosition().y;
|
|
||||||
|
|
||||||
if (y >= rowHeight)
|
|
||||||
{
|
|
||||||
int row = (y-rowHeight)/rowHeight;
|
|
||||||
if (row != currentRows[category] && row < cpu->getRegisterCount(category))
|
|
||||||
setCurrentRow(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxMenu menu;
|
wxMenu menu;
|
||||||
int bits = cpu->getRegisterSize(category);
|
int bits = cpu->getRegisterSize(getCurrentCategory());
|
||||||
|
|
||||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY32, L"Display 32 bit");
|
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY32, L"Display 32 bit");
|
||||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY64, L"Display 64 bit");
|
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY64, L"Display 64 bit");
|
||||||
|
@ -458,7 +416,8 @@ void CtrlRegisterList::mouseEvent(wxMouseEvent& evt)
|
||||||
{
|
{
|
||||||
menu.Append(ID_REGISTERLIST_CHANGELOWER, L"Change lower 64 bit");
|
menu.Append(ID_REGISTERLIST_CHANGELOWER, L"Change lower 64 bit");
|
||||||
menu.Append(ID_REGISTERLIST_CHANGEUPPER, L"Change upper 64 bit");
|
menu.Append(ID_REGISTERLIST_CHANGEUPPER, L"Change upper 64 bit");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
menu.Append(ID_REGISTERLIST_CHANGEVALUE, L"Change value");
|
menu.Append(ID_REGISTERLIST_CHANGEVALUE, L"Change value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,50 +434,22 @@ void CtrlRegisterList::mouseEvent(wxMouseEvent& evt)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.Connect(wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&CtrlRegisterList::onPopupClick, NULL, this);
|
menu.Bind(wxEVT_COMMAND_MENU_SELECTED, &CtrlRegisterList::onPopupClick, this);
|
||||||
PopupMenu(&menu, evt.GetPosition());
|
PopupMenu(&menu, evt.GetPosition());
|
||||||
return;
|
}
|
||||||
|
needsValueUpdating = true;
|
||||||
|
evt.Skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evt.ButtonIsDown(wxMOUSE_BTN_LEFT) || evt.ButtonIsDown(wxMOUSE_BTN_RIGHT))
|
void CtrlRegisterList::categoryChangedEvent(wxBookCtrlEvent& evt)
|
||||||
{
|
{
|
||||||
int x = evt.GetPosition().x;
|
needsSizeUpdating = true;
|
||||||
int y = evt.GetPosition().y;
|
needsValueUpdating = true;
|
||||||
|
evt.Skip();
|
||||||
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();
|
void CtrlRegisterList::keydownEvent(wxEvent& evt)
|
||||||
SetFocusFromKbd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CtrlRegisterList::keydownEvent(wxKeyEvent& evt)
|
|
||||||
{
|
{
|
||||||
switch (evt.GetKeyCode())
|
needsValueUpdating = true;
|
||||||
{
|
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)));
|
|
||||||
break;
|
|
||||||
case WXK_TAB:
|
|
||||||
category = (category+1) % cpu->getRegisterCategoryCount();
|
|
||||||
Refresh();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -12,9 +12,10 @@
|
||||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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"
|
||||||
|
@ -24,50 +25,22 @@ class CtrlRegisterList: public wxWindow
|
||||||
public:
|
public:
|
||||||
CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu);
|
CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu);
|
||||||
|
|
||||||
|
// Event handlers
|
||||||
void paintEvent(wxPaintEvent & evt);
|
void paintEvent(wxPaintEvent & evt);
|
||||||
void mouseEvent(wxMouseEvent& evt);
|
|
||||||
void keydownEvent(wxKeyEvent& evt);
|
|
||||||
void onPopupClick(wxCommandEvent& evt);
|
void onPopupClick(wxCommandEvent& evt);
|
||||||
void redraw();
|
void gridEvent(wxGridEvent& evt);
|
||||||
DECLARE_EVENT_TABLE()
|
void categoryChangedEvent(wxBookCtrlEvent& evt);
|
||||||
|
void keydownEvent(wxEvent& evt);
|
||||||
virtual wxSize GetMinClientSize() const
|
|
||||||
{
|
|
||||||
int columnChars = 0;
|
|
||||||
int maxWidth = 0;
|
|
||||||
int maxRows = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < cpu->getRegisterCategoryCount(); i++)
|
|
||||||
{
|
|
||||||
int bits = std::min<u32>(maxBits,cpu->getRegisterSize(i));
|
|
||||||
int start = startPositions[i];
|
|
||||||
|
|
||||||
int w = start+(bits/4) * charWidth;
|
|
||||||
if (bits > 32)
|
|
||||||
w += (bits/32)*2-2;
|
|
||||||
|
|
||||||
maxWidth = std::max<int>(maxWidth,w);
|
|
||||||
columnChars += strlen(cpu->getRegisterCategoryName(i))+1;
|
|
||||||
maxRows = std::max<int>(maxRows,cpu->getRegisterCount(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
maxWidth = std::max<int>(columnChars*charWidth,maxWidth+4);
|
|
||||||
|
|
||||||
return wxSize(maxWidth,(maxRows+1)*rowHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual wxSize DoGetBestClientSize() const
|
|
||||||
{
|
|
||||||
return GetMinClientSize();
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
enum RegisterChangeMode { LOWER64, UPPER64, CHANGE32 };
|
enum RegisterChangeMode { LOWER64, UPPER64, CHANGE32 };
|
||||||
|
|
||||||
void render(wxDC& dc);
|
|
||||||
void refreshChangedRegs();
|
void refreshChangedRegs();
|
||||||
void setCurrentRow(int row);
|
|
||||||
void changeValue(RegisterChangeMode mode);
|
|
||||||
|
|
||||||
|
void changeValue(RegisterChangeMode mode, int cat, int reg);
|
||||||
|
void updateHandler();
|
||||||
|
void updateValues(int cat);
|
||||||
|
void updateSize(int cat);
|
||||||
|
int getCurrentCategory() const;
|
||||||
void postEvent(wxEventType type, wxString text);
|
void postEvent(wxEventType type, wxString text);
|
||||||
void postEvent(wxEventType type, int value);
|
void postEvent(wxEventType type, int value);
|
||||||
|
|
||||||
|
@ -75,15 +48,16 @@ private:
|
||||||
{
|
{
|
||||||
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;
|
|
||||||
|
|
||||||
DebugInterface* cpu;
|
std::vector<std::vector<ChangedReg>> changedCategories;
|
||||||
int rowHeight,charWidth;
|
|
||||||
u32 lastPc;
|
DebugInterface* cpu; // Used to get register values and other info from the emu
|
||||||
int category;
|
u32 lastPc, lastCycles;
|
||||||
int maxBits;
|
int maxBits; // maximum number of bits beings displayed
|
||||||
|
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.
|
||||||
};
|
};
|
Loading…
Reference in New Issue