mirror of https://github.com/PCSX2/pcsx2.git
Revert to old register list
This commit is contained in:
parent
902e295089
commit
11bcb328f8
|
@ -16,456 +16,509 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include "CtrlRegisterList.h"
|
||||
#include "DebugTools/Debug.h"
|
||||
|
||||
#include "DebugEvents.h"
|
||||
#include "AppConfig.h"
|
||||
|
||||
BEGIN_EVENT_TABLE(CtrlRegisterList, wxWindow)
|
||||
EVT_PAINT(CtrlRegisterList::paintEvent)
|
||||
EVT_GRID_LABEL_LEFT_CLICK(CtrlRegisterList::gridEvent)
|
||||
EVT_GRID_LABEL_RIGHT_CLICK(CtrlRegisterList::gridEvent)
|
||||
EVT_GRID_CELL_LEFT_CLICK(CtrlRegisterList::gridEvent)
|
||||
EVT_GRID_CELL_RIGHT_CLICK(CtrlRegisterList::gridEvent)
|
||||
EVT_KEY_DOWN(CtrlRegisterList::keydownEvent)
|
||||
EVT_BOOKCTRL_PAGE_CHANGED(-1, CtrlRegisterList::categoryChangedEvent)
|
||||
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
|
||||
{
|
||||
ID_REGISTERLIST_DISPLAY32 = 1,
|
||||
ID_REGISTERLIST_DISPLAY64,
|
||||
ID_REGISTERLIST_DISPLAY128,
|
||||
ID_REGISTERLIST_CHANGELOWER,
|
||||
ID_REGISTERLIST_CHANGEUPPER,
|
||||
ID_REGISTERLIST_CHANGEVALUE
|
||||
ID_REGISTERLIST_DISPLAY32 = 1,
|
||||
ID_REGISTERLIST_DISPLAY64,
|
||||
ID_REGISTERLIST_DISPLAY128,
|
||||
ID_REGISTERLIST_CHANGELOWER,
|
||||
ID_REGISTERLIST_CHANGEUPPER,
|
||||
ID_REGISTERLIST_CHANGEVALUE
|
||||
};
|
||||
|
||||
CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu) :
|
||||
wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS | wxBORDER_NONE),
|
||||
cpu(_cpu),
|
||||
lastPc(0),
|
||||
lastCycles(0),
|
||||
maxBits(128),
|
||||
needsSizeUpdating(true),
|
||||
needsValueUpdating(true)
|
||||
|
||||
CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu)
|
||||
: wxWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS|wxBORDER_NONE), cpu(_cpu)
|
||||
{
|
||||
int rowHeight = g_Conf->EmuOptions.Debugger.FontHeight;
|
||||
int charWidth = g_Conf->EmuOptions.Debugger.FontWidth;
|
||||
rowHeight = g_Conf->EmuOptions.Debugger.FontHeight+2;
|
||||
charWidth = g_Conf->EmuOptions.Debugger.FontWidth;
|
||||
category = 0;
|
||||
maxBits = 128;
|
||||
lastPc = 0xFFFFFFFF;
|
||||
|
||||
for (int i = 0; i < cpu->getRegisterCategoryCount(); i++)
|
||||
{
|
||||
int count = cpu->getRegisterCount(i);
|
||||
|
||||
#ifdef _WIN32
|
||||
wxFont font = wxFont(wxSize(charWidth, rowHeight), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL,
|
||||
false, L"Lucida Console");
|
||||
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);
|
||||
ChangedReg* regs = new ChangedReg[count];
|
||||
memset(regs,0,sizeof(ChangedReg)*count);
|
||||
changedCategories.push_back(regs);
|
||||
|
||||
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);
|
||||
registerCategories->AddPage(regGrid, wxString(cpu->getRegisterCategoryName(cat), wxConvUTF8));
|
||||
|
||||
DebugInterface::RegisterType type = cpu->getRegisterType(cat);
|
||||
int registerBits = cpu->getRegisterSize(cat);
|
||||
|
||||
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.
|
||||
// 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 = 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)
|
||||
{
|
||||
wxGrid* regGrid = registerGrids[cat];
|
||||
|
||||
int regBits = cpu->getRegisterSize(cat);
|
||||
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);
|
||||
SetDoubleBuffered(true);
|
||||
SetInitialSize(ClientToWindowSize(GetMinClientSize()));
|
||||
}
|
||||
|
||||
void CtrlRegisterList::postEvent(wxEventType type, wxString text)
|
||||
{
|
||||
wxCommandEvent event(type, GetId());
|
||||
event.SetEventObject(this);
|
||||
event.SetString(text);
|
||||
wxPostEvent(this, event);
|
||||
wxCommandEvent event( type, GetId() );
|
||||
event.SetEventObject(this);
|
||||
event.SetString(text);
|
||||
wxPostEvent(this,event);
|
||||
}
|
||||
|
||||
void CtrlRegisterList::postEvent(wxEventType type, int value)
|
||||
{
|
||||
wxCommandEvent event(type, GetId());
|
||||
event.SetEventObject(this);
|
||||
event.SetInt(value);
|
||||
wxPostEvent(this, event);
|
||||
wxCommandEvent event( type, GetId() );
|
||||
event.SetEventObject(this);
|
||||
event.SetInt(value);
|
||||
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()
|
||||
{
|
||||
if (cpu->getPC() == lastPc && cpu->getCycles() == lastCycles)
|
||||
return;
|
||||
if (cpu->getPC() == lastPc)
|
||||
return;
|
||||
|
||||
for (int cat = 0; cat < cpu->getRegisterCategoryCount(); cat++)
|
||||
{
|
||||
std::vector<ChangedReg>& regs = changedCategories[cat];
|
||||
int size = cpu->getRegisterSize(cat);
|
||||
for (size_t cat = 0; cat < changedCategories.size(); cat++)
|
||||
{
|
||||
ChangedReg* regs = changedCategories[cat];
|
||||
int size = cpu->getRegisterSize(category);
|
||||
|
||||
for (int i = 0; i < cpu->getRegisterCount(cat); i++)
|
||||
{
|
||||
ChangedReg& reg = regs[i];
|
||||
memset(®.changed, 0, sizeof(reg.changed));
|
||||
for (int i = 0; i < cpu->getRegisterCount(cat); i++)
|
||||
{
|
||||
ChangedReg& reg = regs[i];
|
||||
memset(®.changed,0,sizeof(reg.changed));
|
||||
|
||||
u128 newValue = cpu->getRegister(cat, i);
|
||||
u128 newValue = cpu->getRegister(cat,i);
|
||||
|
||||
if (reg.oldValue != newValue)
|
||||
{
|
||||
bool changed = false;
|
||||
if (reg.oldValue != newValue)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (size >= 128 && (reg.oldValue._u32[3] != newValue._u32[3] || reg.oldValue._u32[2] != newValue._u32[2]))
|
||||
{
|
||||
changed = true;
|
||||
reg.changed[3] = true;
|
||||
reg.changed[2] = true;
|
||||
}
|
||||
if (size >= 128 && (reg.oldValue._u32[3] != newValue._u32[3] || reg.oldValue._u32[2] != newValue._u32[2]))
|
||||
{
|
||||
changed = true;
|
||||
reg.changed[3] = true;
|
||||
reg.changed[2] = true;
|
||||
}
|
||||
|
||||
if (size >= 64 && (reg.oldValue._u32[1] != newValue._u32[1] || changed))
|
||||
{
|
||||
changed = true;
|
||||
reg.changed[1] = true;
|
||||
}
|
||||
if (size >= 64 && (reg.oldValue._u32[1] != newValue._u32[1] || changed))
|
||||
{
|
||||
changed = true;
|
||||
reg.changed[1] = true;
|
||||
}
|
||||
|
||||
if (reg.oldValue._u32[0] != newValue._u32[0] || changed)
|
||||
{
|
||||
reg.changed[0] = true;
|
||||
}
|
||||
reg.oldValue = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reg.oldValue._u32[0] != newValue._u32[0] || changed)
|
||||
{
|
||||
reg.changed[0] = true;
|
||||
}
|
||||
|
||||
lastPc = cpu->getPC();
|
||||
lastCycles = cpu->getCycles();
|
||||
reg.oldValue = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastPc = cpu->getPC();
|
||||
}
|
||||
|
||||
void CtrlRegisterList::paintEvent(wxPaintEvent & evt)
|
||||
{
|
||||
updateHandler();
|
||||
evt.Skip();
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
void CtrlRegisterList::updateHandler()
|
||||
void CtrlRegisterList::redraw()
|
||||
{
|
||||
if (cpu->isCpuPaused() || needsValueUpdating)
|
||||
{
|
||||
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();
|
||||
wxClientDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
void CtrlRegisterList::changeValue(RegisterChangeMode mode, int cat, int reg)
|
||||
void drawU32Text(wxDC& dc, u32 value, int x, int y)
|
||||
{
|
||||
wxString oldStr;
|
||||
u128 oldValue = cpu->getRegister(cat, reg);
|
||||
char str[32];
|
||||
sprintf(str,"%08X",value);
|
||||
dc.DrawText(wxString(str,wxConvUTF8),x,y);
|
||||
}
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case LOWER64:
|
||||
oldStr = wxsFormat(L"0x%016llX", oldValue._u64[0]);
|
||||
break;
|
||||
case UPPER64:
|
||||
oldStr = wxsFormat(L"0x%016llX", oldValue._u64[1]);
|
||||
break;
|
||||
case CHANGE32:
|
||||
oldStr = wxsFormat(L"0x%08X", oldValue._u64[0]);
|
||||
break;
|
||||
}
|
||||
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);
|
||||
|
||||
u64 newValue;
|
||||
if (executeExpressionWindow(this, cpu, newValue, oldStr))
|
||||
{
|
||||
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(cat, reg, oldValue);
|
||||
oldValue = cpu->getRegister(cat, reg);
|
||||
}
|
||||
needsValueUpdating = true;
|
||||
needsSizeUpdating = true;
|
||||
dc.SetBrush(wxBrush(white));
|
||||
dc.SetPen(wxPen(white));
|
||||
|
||||
wxSize size = GetSize();
|
||||
dc.DrawRectangle(0,0,size.x,size.y);
|
||||
|
||||
refreshChangedRegs();
|
||||
|
||||
wxColor colorChanged = wxColor(0xFF0000FF);
|
||||
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);
|
||||
|
||||
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)
|
||||
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(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];
|
||||
|
||||
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)
|
||||
{
|
||||
int cat = getCurrentCategory();
|
||||
wxGrid* regGrid = registerGrids[cat];
|
||||
int reg = regGrid->GetGridCursorRow();
|
||||
switch (evt.GetId())
|
||||
{
|
||||
case ID_REGISTERLIST_DISPLAY32:
|
||||
maxBits = 32;
|
||||
postEvent(debEVT_UPDATELAYOUT, 0);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_DISPLAY64:
|
||||
maxBits = 64;
|
||||
postEvent(debEVT_UPDATELAYOUT, 0);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_DISPLAY128:
|
||||
maxBits = 128;
|
||||
postEvent(debEVT_UPDATELAYOUT, 0);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_CHANGELOWER:
|
||||
changeValue(LOWER64, cat, reg);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_CHANGEUPPER:
|
||||
changeValue(UPPER64, cat, reg);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_CHANGEVALUE:
|
||||
if (cpu->getRegisterSize(cat) == 32)
|
||||
changeValue(CHANGE32, cat, reg);
|
||||
else
|
||||
changeValue(LOWER64, cat, reg);
|
||||
Refresh();
|
||||
break;
|
||||
default:
|
||||
wxMessageBox(L"Unimplemented.", L"Unimplemented.", wxICON_INFORMATION);
|
||||
break;
|
||||
}
|
||||
needsValueUpdating = true;
|
||||
needsSizeUpdating = true;
|
||||
switch (evt.GetId())
|
||||
{
|
||||
case ID_REGISTERLIST_DISPLAY32:
|
||||
maxBits = 32;
|
||||
SetInitialSize(ClientToWindowSize(GetMinClientSize()));
|
||||
postEvent(debEVT_UPDATELAYOUT,0);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_DISPLAY64:
|
||||
maxBits = 64;
|
||||
SetInitialSize(ClientToWindowSize(GetMinClientSize()));
|
||||
postEvent(debEVT_UPDATELAYOUT,0);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_DISPLAY128:
|
||||
maxBits = 128;
|
||||
SetInitialSize(ClientToWindowSize(GetMinClientSize()));
|
||||
postEvent(debEVT_UPDATELAYOUT,0);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_CHANGELOWER:
|
||||
changeValue(LOWER64);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_CHANGEUPPER:
|
||||
changeValue(UPPER64);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_CHANGEVALUE:
|
||||
if (cpu->getRegisterSize(category) == 32)
|
||||
changeValue(CHANGE32);
|
||||
else
|
||||
changeValue(LOWER64);
|
||||
Refresh();
|
||||
break;
|
||||
default:
|
||||
wxMessageBox( L"Unimplemented.", L"Unimplemented.", wxICON_INFORMATION);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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::gridEvent(wxGridEvent& evt)
|
||||
void CtrlRegisterList::mouseEvent(wxMouseEvent& evt)
|
||||
{
|
||||
// Mouse events
|
||||
if (evt.GetEventType() == wxEVT_GRID_CELL_RIGHT_CLICK ||
|
||||
evt.GetEventType() == wxEVT_GRID_LABEL_RIGHT_CLICK)
|
||||
{
|
||||
wxMenu menu;
|
||||
int bits = cpu->getRegisterSize(getCurrentCategory());
|
||||
if (evt.GetEventType() == wxEVT_RIGHT_UP)
|
||||
{
|
||||
int y = evt.GetPosition().y;
|
||||
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY32, L"Display 32 bit");
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY64, L"Display 64 bit");
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY128, L"Display 128 bit");
|
||||
menu.AppendSeparator();
|
||||
if (y >= rowHeight)
|
||||
{
|
||||
int row = (y-rowHeight)/rowHeight;
|
||||
if (row != currentRows[category] && row < cpu->getRegisterCount(category))
|
||||
setCurrentRow(row);
|
||||
}
|
||||
|
||||
if (bits >= 64)
|
||||
{
|
||||
menu.Append(ID_REGISTERLIST_CHANGELOWER, L"Change lower 64 bit");
|
||||
menu.Append(ID_REGISTERLIST_CHANGEUPPER, L"Change upper 64 bit");
|
||||
}
|
||||
else {
|
||||
menu.Append(ID_REGISTERLIST_CHANGEVALUE, L"Change value");
|
||||
}
|
||||
wxMenu menu;
|
||||
int bits = cpu->getRegisterSize(category);
|
||||
|
||||
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.AppendRadioItem(ID_REGISTERLIST_DISPLAY32, L"Display 32 bit");
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY64, L"Display 64 bit");
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY128, L"Display 128 bit");
|
||||
menu.AppendSeparator();
|
||||
|
||||
menu.Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CtrlRegisterList::onPopupClick), nullptr, this);
|
||||
PopupMenu(&menu, evt.GetPosition());
|
||||
needsValueUpdating = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
evt.Skip();
|
||||
}
|
||||
}
|
||||
if (bits >= 64)
|
||||
{
|
||||
menu.Append(ID_REGISTERLIST_CHANGELOWER, L"Change lower 64 bit");
|
||||
menu.Append(ID_REGISTERLIST_CHANGEUPPER, L"Change upper 64 bit");
|
||||
} else {
|
||||
menu.Append(ID_REGISTERLIST_CHANGEVALUE, L"Change value");
|
||||
}
|
||||
|
||||
void CtrlRegisterList::categoryChangedEvent(wxBookCtrlEvent& evt)
|
||||
{
|
||||
needsSizeUpdating = true;
|
||||
needsValueUpdating = true;
|
||||
evt.Skip();
|
||||
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))
|
||||
{
|
||||
int x = evt.GetPosition().x;
|
||||
int y = evt.GetPosition().y;
|
||||
|
||||
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)
|
||||
{
|
||||
needsValueUpdating = true;
|
||||
evt.Skip();
|
||||
switch (evt.GetKeyCode())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,50 +15,75 @@
|
|||
|
||||
#pragma once
|
||||
#include <wx/wx.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/grid.h>
|
||||
|
||||
#include "DebugTools/DebugInterface.h"
|
||||
#include "DebugTools/DisassemblyManager.h"
|
||||
|
||||
class CtrlRegisterList : public wxWindow
|
||||
class CtrlRegisterList: public wxWindow
|
||||
{
|
||||
public:
|
||||
CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu);
|
||||
CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu);
|
||||
|
||||
void paintEvent(wxPaintEvent & evt);
|
||||
void mouseEvent(wxMouseEvent& evt);
|
||||
void keydownEvent(wxKeyEvent& evt);
|
||||
void onPopupClick(wxCommandEvent& evt);
|
||||
void redraw();
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
// Event handlers
|
||||
void paintEvent(wxPaintEvent & evt);
|
||||
void onPopupClick(wxCommandEvent& evt);
|
||||
void gridEvent(wxGridEvent& evt);
|
||||
void categoryChangedEvent(wxBookCtrlEvent& evt);
|
||||
void keydownEvent(wxKeyEvent& evt);
|
||||
DECLARE_EVENT_TABLE()
|
||||
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:
|
||||
enum RegisterChangeMode { LOWER64, UPPER64, CHANGE32 };
|
||||
enum RegisterChangeMode { LOWER64, UPPER64, CHANGE32 };
|
||||
|
||||
void refreshChangedRegs();
|
||||
void render(wxDC& dc);
|
||||
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, int value);
|
||||
void postEvent(wxEventType type, wxString text);
|
||||
void postEvent(wxEventType type, int value);
|
||||
|
||||
struct ChangedReg
|
||||
{
|
||||
u128 oldValue;
|
||||
bool changed[4];
|
||||
ChangedReg() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
struct ChangedReg
|
||||
{
|
||||
u128 oldValue;
|
||||
bool changed[4];
|
||||
};
|
||||
|
||||
std::vector<ChangedReg*> changedCategories;
|
||||
std::vector<int> startPositions;
|
||||
std::vector<int> currentRows;
|
||||
|
||||
std::vector<std::vector<ChangedReg>> changedCategories;
|
||||
|
||||
DebugInterface* cpu; // Used to get register values and other info from the emu
|
||||
u32 lastPc, lastCycles;
|
||||
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.
|
||||
};
|
||||
DebugInterface* cpu;
|
||||
int rowHeight,charWidth;
|
||||
u32 lastPc;
|
||||
int category;
|
||||
int maxBits;
|
||||
};
|
Loading…
Reference in New Issue