diff --git a/pcsx2/gui/Debugger/CtrlRegisterList.cpp b/pcsx2/gui/Debugger/CtrlRegisterList.cpp index a99f504933..5c27c082ce 100644 --- a/pcsx2/gui/Debugger/CtrlRegisterList.cpp +++ b/pcsx2/gui/Debugger/CtrlRegisterList.cpp @@ -16,509 +16,432 @@ #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_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) +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) { - rowHeight = g_Conf->EmuOptions.Debugger.FontHeight+2; - charWidth = g_Conf->EmuOptions.Debugger.FontWidth; - category = 0; - maxBits = 128; - lastPc = 0xFFFFFFFF; + int rowHeight = g_Conf->EmuOptions.Debugger.FontHeight; + int charWidth = g_Conf->EmuOptions.Debugger.FontWidth; - for (int i = 0; i < cpu->getRegisterCategoryCount(); i++) - { - int count = cpu->getRegisterCount(i); - ChangedReg* regs = new ChangedReg[count]; - memset(regs,0,sizeof(ChangedReg)*count); - changedCategories.push_back(regs); +#ifdef _WIN32 + wxFont font = wxFont(wxSize(charWidth, rowHeight), 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)); +#endif + registerCategories = new wxNotebook(this, -1); + registerCategories->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, &CtrlRegisterList::categoryChangedEvent, this); + for (int cat = 0; cat < cpu->getRegisterCategoryCount(); cat++) + { + int numRegs = cpu->getRegisterCount(cat); - int maxLen = 0; - for (int k = 0; k < cpu->getRegisterCount(i); k++) - { - maxLen = std::max(maxLen,strlen(cpu->getRegisterName(i,k))); - } + changedCategories.push_back(std::vector(numRegs)); - int x = 17+(maxLen+3)*charWidth; - startPositions.push_back(x); - currentRows.push_back(0); - } + wxGrid* regGrid = new wxGrid(registerCategories, -1); - SetDoubleBuffered(true); - SetInitialSize(ClientToWindowSize(GetMinClientSize())); + 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) + { + 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, wxsFormat("%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, cpu->getRegisterName(cat, row)); + break; + } + + regGrid->EnableEditing(false); + regGrid->SetDefaultCellFont(font); + 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); +} + +// 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& 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("%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(); + + 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(); + + // 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) { - 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) - return; + if (cpu->getPC() == lastPc && cpu->getCycles() == lastCycles) + return; - for (size_t cat = 0; cat < changedCategories.size(); cat++) - { - ChangedReg* regs = changedCategories[cat]; - int size = cpu->getRegisterSize(category); + for (int cat = 0; cat < cpu->getRegisterCategoryCount(); cat++) + { + std::vector& regs = changedCategories[cat]; + int size = cpu->getRegisterSize(cat); - 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; - } + if (reg.oldValue._u32[0] != newValue._u32[0] || changed) + { + reg.changed[0] = true; + } + reg.oldValue = newValue; + } + } + } - reg.oldValue = newValue; - } - } - } - - lastPc = cpu->getPC(); + lastPc = cpu->getPC(); + lastCycles = cpu->getCycles(); } void CtrlRegisterList::paintEvent(wxPaintEvent & evt) { - wxPaintDC dc(this); - render(dc); + updateHandler(); + evt.Skip(); } -void CtrlRegisterList::redraw() +void CtrlRegisterList::updateHandler() { - wxClientDC dc(this); - render(dc); + 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(); } -void drawU32Text(wxDC& dc, u32 value, int x, int y) +void CtrlRegisterList::changeValue(RegisterChangeMode mode, int cat, int reg) { - char str[32]; - sprintf(str,"%08X",value); - dc.DrawText(wxString(str,wxConvUTF8),x,y); -} + wxString oldStr; + u128 oldValue = cpu->getRegister(cat, reg); -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); + switch (mode) + { + case LOWER64: + oldStr = wxsFormat("0x%016llX", oldValue._u64[0]); + break; + case UPPER64: + oldStr = wxsFormat("0x%016llX", oldValue._u64[1]); + break; + case CHANGE32: + oldStr = wxsFormat("0x%08X", oldValue._u64[0]); + break; + } - 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(3,maxBits/32-1); - int actualX = size.x-4-(startIndex+1)*(8*charWidth+2); - x = std::max(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); - } + 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; } void CtrlRegisterList::onPopupClick(wxCommandEvent& evt) { - 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 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; } -void CtrlRegisterList::setCurrentRow(int row) +int CtrlRegisterList::getCurrentCategory() const { - 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(); + return registerCategories->GetSelection(); } -void CtrlRegisterList::mouseEvent(wxMouseEvent& evt) + +void CtrlRegisterList::gridEvent(wxGridEvent& evt) { - if (evt.GetEventType() == wxEVT_RIGHT_UP) - { - int y = evt.GetPosition().y; + // 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 (y >= rowHeight) - { - int row = (y-rowHeight)/rowHeight; - if (row != currentRows[category] && row < cpu->getRegisterCount(category)) - setCurrentRow(row); - } + 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(); - wxMenu menu; - int bits = cpu->getRegisterSize(category); + 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"); + } - 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(); + 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; + } - 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"); - } - - 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(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(); - } + menu.Bind(wxEVT_COMMAND_MENU_SELECTED, &CtrlRegisterList::onPopupClick, this); + PopupMenu(&menu, evt.GetPosition()); + } + needsValueUpdating = true; + evt.Skip(); } -void CtrlRegisterList::keydownEvent(wxKeyEvent& evt) +void CtrlRegisterList::categoryChangedEvent(wxBookCtrlEvent& evt) { - switch (evt.GetKeyCode()) - { - case WXK_UP: - setCurrentRow(std::max(currentRows[category]-1,0)); - break; - case WXK_DOWN: - setCurrentRow(std::min(currentRows[category]+1,cpu->getRegisterCount(category))); - break; - case WXK_TAB: - category = (category+1) % cpu->getRegisterCategoryCount(); - Refresh(); - break; - } + needsSizeUpdating = true; + needsValueUpdating = true; + evt.Skip(); +} + +void CtrlRegisterList::keydownEvent(wxEvent& evt) +{ + needsValueUpdating = true; + evt.Skip(); } diff --git a/pcsx2/gui/Debugger/CtrlRegisterList.h b/pcsx2/gui/Debugger/CtrlRegisterList.h index ada912281d..f5e0aeba92 100644 --- a/pcsx2/gui/Debugger/CtrlRegisterList.h +++ b/pcsx2/gui/Debugger/CtrlRegisterList.h @@ -15,75 +15,49 @@ #pragma once #include - +#include +#include #include "DebugTools/DebugInterface.h" #include "DebugTools/DisassemblyManager.h" -class CtrlRegisterList: public wxWindow +class CtrlRegisterList : public wxWindow { public: - 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() + CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu); - 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(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(maxWidth,w); - columnChars += strlen(cpu->getRegisterCategoryName(i))+1; - maxRows = std::max(maxRows,cpu->getRegisterCount(i)); - } - - maxWidth = std::max(columnChars*charWidth,maxWidth+4); - - return wxSize(maxWidth,(maxRows+1)*rowHeight); - } - - virtual wxSize DoGetBestClientSize() const - { - return GetMinClientSize(); - } + // Event handlers + void paintEvent(wxPaintEvent & evt); + void onPopupClick(wxCommandEvent& evt); + void gridEvent(wxGridEvent& evt); + void categoryChangedEvent(wxBookCtrlEvent& evt); + void keydownEvent(wxEvent& evt); private: - enum RegisterChangeMode { LOWER64, UPPER64, CHANGE32 }; + enum RegisterChangeMode { LOWER64, UPPER64, CHANGE32 }; - void render(wxDC& dc); - void refreshChangedRegs(); - void setCurrentRow(int row); - void changeValue(RegisterChangeMode mode); + void refreshChangedRegs(); - void postEvent(wxEventType type, wxString text); - void postEvent(wxEventType type, int value); + 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); - struct ChangedReg - { - u128 oldValue; - bool changed[4]; - }; + struct ChangedReg + { + u128 oldValue; + bool changed[4]; + ChangedReg() { memset(this, 0, sizeof(*this)); } + }; - std::vector changedCategories; - std::vector startPositions; - std::vector currentRows; - DebugInterface* cpu; - int rowHeight,charWidth; - u32 lastPc; - int category; - int maxBits; -}; \ No newline at end of file + std::vector> 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 registerGrids; // Grids displaying register values for each of the tabs. +};