diff --git a/pcsx2/Config.h b/pcsx2/Config.h index c5307a0657..a767b0ef27 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -414,13 +414,16 @@ struct Pcsx2Config u8 FontWidth; u8 FontHeight; + u32 WindowWidth; + u32 WindowHeight; DebugOptions(); void LoadSave( IniInterface& conf ); bool operator ==( const DebugOptions& right ) const { - return OpEqu( bitset ) && OpEqu( FontWidth ) && OpEqu( FontHeight ); + return OpEqu( bitset ) && OpEqu( FontWidth ) && OpEqu( FontHeight ) + && OpEqu( WindowWidth ) && OpEqu( WindowHeight ); } bool operator !=( const DebugOptions& right ) const diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index a70cab4ca8..c70a636cab 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -379,6 +379,8 @@ Pcsx2Config::DebugOptions::DebugOptions() ShowDebuggerOnStart = false; FontWidth = 8; FontHeight = 12; + WindowWidth = 0; + WindowHeight = 0; } void Pcsx2Config::DebugOptions::LoadSave( IniInterface& ini ) @@ -388,6 +390,8 @@ void Pcsx2Config::DebugOptions::LoadSave( IniInterface& ini ) IniBitBool( ShowDebuggerOnStart ); IniBitfield(FontWidth); IniBitfield(FontHeight); + IniBitfield(WindowWidth); + IniBitfield(WindowHeight); } diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp index 04e3925e4b..fa2cd2da02 100644 --- a/pcsx2/System/SysCoreThread.cpp +++ b/pcsx2/System/SysCoreThread.cpp @@ -134,6 +134,7 @@ void SysCoreThread::Reset() GetVmMemory().DecommitAll(); SysClearExecutionCache(); sApp.PostAppMethod( &Pcsx2App::leaveDebugMode ); + g_FrameCount = 0; } diff --git a/pcsx2/gui/Debugger/CtrlDisassemblyView.cpp b/pcsx2/gui/Debugger/CtrlDisassemblyView.cpp index 9247557555..d90a476317 100644 --- a/pcsx2/gui/Debugger/CtrlDisassemblyView.cpp +++ b/pcsx2/gui/Debugger/CtrlDisassemblyView.cpp @@ -23,6 +23,7 @@ #include "BreakpointWindow.h" #include "AppConfig.h" #include "System.h" +#include "DisassemblyDialog.h" #include #include @@ -147,8 +148,8 @@ CtrlDisassemblyView::CtrlDisassemblyView(wxWindow* parent, DebugInterface* _cpu) { manager.setCpu(cpu); windowStart = 0x100000; - rowHeight = g_Conf->EmuOptions.Debugger.FontHeight+2; - charWidth = g_Conf->EmuOptions.Debugger.FontWidth; + rowHeight = getDebugFontHeight()+2; + charWidth = getDebugFontWidth(); displaySymbols = true; visibleRows = 1; diff --git a/pcsx2/gui/Debugger/CtrlMemView.cpp b/pcsx2/gui/Debugger/CtrlMemView.cpp index 064755542b..93950b66ca 100644 --- a/pcsx2/gui/Debugger/CtrlMemView.cpp +++ b/pcsx2/gui/Debugger/CtrlMemView.cpp @@ -20,6 +20,7 @@ #include "BreakpointWindow.h" #include "DebugEvents.h" +#include "DisassemblyDialog.h" #include #include @@ -55,8 +56,8 @@ enum MemoryViewMenuIdentifiers CtrlMemView::CtrlMemView(wxWindow* parent, DebugInterface* _cpu) : wxWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS|wxVSCROLL), cpu(_cpu) { - rowHeight = g_Conf->EmuOptions.Debugger.FontHeight; - charWidth = g_Conf->EmuOptions.Debugger.FontWidth; + rowHeight = getDebugFontHeight(); + charWidth = getDebugFontWidth(); windowStart = 0x480000; curAddress = windowStart; rowSize = 16; diff --git a/pcsx2/gui/Debugger/CtrlRegisterList.cpp b/pcsx2/gui/Debugger/CtrlRegisterList.cpp index c5ba5acf88..42799563b2 100644 --- a/pcsx2/gui/Debugger/CtrlRegisterList.cpp +++ b/pcsx2/gui/Debugger/CtrlRegisterList.cpp @@ -16,456 +16,547 @@ #include "PrecompiledHeader.h" #include "CtrlRegisterList.h" #include "DebugTools/Debug.h" + #include "DebugEvents.h" #include "AppConfig.h" +#include "DisassemblyDialog.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_SIZE(CtrlRegisterList::sizeEvent) + 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) + : wxScrolledWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS|wxBORDER_NONE|wxVSCROLL), cpu(_cpu) { - int rowHeight = g_Conf->EmuOptions.Debugger.FontHeight; - int charWidth = g_Conf->EmuOptions.Debugger.FontWidth; + rowHeight = getDebugFontHeight()+2; + charWidth = getDebugFontWidth(); + 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(numRegs)); + int maxLen = 0; + for (int k = 0; k < cpu->getRegisterCount(i); k++) + { + maxLen = std::max(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)); + SetDoubleBuffered(true); + SetInitialSize(ClientToWindowSize(GetMinClientSize())); - 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); + wxSize actualSize = getOptimalSize(); + SetVirtualSize(actualSize); + SetScrollbars(1, rowHeight, actualSize.x, actualSize.y / rowHeight, 0, 0); } -// 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) +wxSize CtrlRegisterList::getOptimalSize() const { - wxGrid* regGrid = registerGrids[cat]; - int numRows = regGrid->GetNumberRows(); - int numCols = regGrid->GetNumberCols(); + int columnChars = 0; + int maxWidth = 0; + int maxRows = 0; - 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 i = 0; i < cpu->getRegisterCategoryCount(); i++) + { + int bits = std::min(maxBits, cpu->getRegisterSize(i)); + int start = startPositions[i]; - for (int col = 0; col < numCols; col++) - { - const wxColor colorChanged = wxColor(0xFF0000FF); - const wxColor colorUnchanged = wxColor(0xFF004000); - wxColor textColor; - wxString cellValue; + int w = start + (bits / 4) * charWidth; + if (bits > 32) + w += (bits / 32) * 2 - 2; - 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); - } - } -} + maxWidth = std::max(maxWidth, w); + columnChars += strlen(cpu->getRegisterCategoryName(i)) + 1; + maxRows = std::max(maxRows, cpu->getRegisterCount(i)); + } -void CtrlRegisterList::updateSize(int cat) -{ - wxGrid* regGrid = registerGrids[cat]; + maxWidth = std::max(columnChars*charWidth, maxWidth + 4); - 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); + return wxSize(maxWidth, (maxRows + 1)*rowHeight); } 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& 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) +void CtrlRegisterList::redraw() { - updateHandler(); - evt.Skip(); + Update(); } -void CtrlRegisterList::updateHandler() +void CtrlRegisterList::sizeEvent(wxSizeEvent& evt) { - 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(); + Refresh(); + evt.Skip(); } -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::OnDraw(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 = GetClientSize(); + 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(0xFFFFCFC8))); + dc.SetPen(wxPen(wxColor(0xFFFFEFE8))); + dc.DrawRectangle(0,y,size.x,rowHeight); + } else if (i % 2) + { + wxColor color = wxColor(237,242,255,255); + dc.SetBrush(wxBrush(color)); + dc.SetPen(wxPen(color)); + dc.DrawRectangle(0, y, size.x, rowHeight); + } + + const char* name = cpu->getRegisterName(category,i); + dc.SetTextForeground(colorNormal); + dc.DrawText(wxString(name,wxConvUTF8),nameStart,y+2); + + u128 value = cpu->getRegister(category,i); + ChangedReg& changed = changedRegs[i]; + + switch (type) + { + case DebugInterface::NORMAL: // display them in 32 bit parts + switch (registerBits) + { + case 128: + { + int startIndex = std::min(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); + } } 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()); + int xOffset, yOffset; + ((wxScrolledWindow*) this)->GetViewStart(&xOffset, &yOffset); - 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(); + wxClientDC dc(this); + wxPoint pos = evt.GetPosition(); + int x = dc.DeviceToLogicalX(pos.x) + xOffset; + int y = dc.DeviceToLogicalY(pos.y) + yOffset; - 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"); - } + if (evt.GetEventType() == wxEVT_RIGHT_UP) + { + if (y >= rowHeight) + { + int row = (y-rowHeight)/rowHeight; + if (row != currentRows[category] && row < cpu->getRegisterCount(category)) + setCurrentRow(row); + } - 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; - } + wxMenu menu; + int bits = cpu->getRegisterSize(category); - menu.Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CtrlRegisterList::onPopupClick), nullptr, this); - PopupMenu(&menu, evt.GetPosition()); - needsValueUpdating = true; - } - else - { - evt.Skip(); - } -} + 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(); -void CtrlRegisterList::categoryChangedEvent(wxBookCtrlEvent& evt) -{ - needsSizeUpdating = true; - needsValueUpdating = true; - 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"); + } + + switch (maxBits) + { + case 128: + menu.Check(ID_REGISTERLIST_DISPLAY128,true); + break; + case 64: + menu.Check(ID_REGISTERLIST_DISPLAY64,true); + break; + case 32: + menu.Check(ID_REGISTERLIST_DISPLAY32,true); + break; + } + + menu.Connect(wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&CtrlRegisterList::onPopupClick, NULL, this); + PopupMenu(&menu,evt.GetPosition()); + return; + } + + if (evt.ButtonIsDown(wxMOUSE_BTN_LEFT) || evt.ButtonIsDown(wxMOUSE_BTN_RIGHT)) + { + if (y < rowHeight) + { + int piece = GetSize().x/cpu->getRegisterCategoryCount(); + int cat = std::min(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(currentRows[category]-1,0)); + break; + case WXK_DOWN: + setCurrentRow(std::min(currentRows[category]+1,cpu->getRegisterCount(category)-1)); + break; + case WXK_TAB: + category = (category+1) % cpu->getRegisterCategoryCount(); + Refresh(); + break; + } } diff --git a/pcsx2/gui/Debugger/CtrlRegisterList.h b/pcsx2/gui/Debugger/CtrlRegisterList.h index 5cdf928aaa..6ca8c6adf8 100644 --- a/pcsx2/gui/Debugger/CtrlRegisterList.h +++ b/pcsx2/gui/Debugger/CtrlRegisterList.h @@ -15,50 +15,60 @@ #pragma once #include -#include -#include + #include "DebugTools/DebugInterface.h" #include "DebugTools/DisassemblyManager.h" -class CtrlRegisterList : public wxWindow +class CtrlRegisterList: public wxScrolledWindow { public: - CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu); + CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu); + + void mouseEvent(wxMouseEvent& evt); + void keydownEvent(wxKeyEvent& evt); + void onPopupClick(wxCommandEvent& evt); + void sizeEvent(wxSizeEvent& evt); + void redraw(); + DECLARE_EVENT_TABLE() + + virtual wxSize GetMinClientSize() const + { + wxSize optimalSize = getOptimalSize(); + if (GetWindowStyle() & wxVSCROLL) + optimalSize.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X); - // Event handlers - void paintEvent(wxPaintEvent & evt); - void onPopupClick(wxCommandEvent& evt); - void gridEvent(wxGridEvent& evt); - void categoryChangedEvent(wxBookCtrlEvent& evt); - void keydownEvent(wxKeyEvent& evt); - DECLARE_EVENT_TABLE() + return wxSize(optimalSize.x,0); + } + + virtual wxSize DoGetBestClientSize() const + { + return GetMinClientSize(); + } private: - enum RegisterChangeMode { LOWER64, UPPER64, CHANGE32 }; + enum RegisterChangeMode { LOWER64, UPPER64, CHANGE32 }; - void refreshChangedRegs(); + void OnDraw(wxDC& dc); + void refreshChangedRegs(); + void setCurrentRow(int row); + void changeValue(RegisterChangeMode mode); + wxSize getOptimalSize() const; - void changeValue(RegisterChangeMode mode, int cat, int reg); - void 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 changedCategories; + std::vector startPositions; + std::vector currentRows; - 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. -}; + DebugInterface* cpu; + int rowHeight,charWidth; + u32 lastPc; + int category; + int maxBits; +}; \ No newline at end of file diff --git a/pcsx2/gui/Debugger/DisassemblyDialog.cpp b/pcsx2/gui/Debugger/DisassemblyDialog.cpp index 1f642918e2..ad9d7ba724 100644 --- a/pcsx2/gui/Debugger/DisassemblyDialog.cpp +++ b/pcsx2/gui/Debugger/DisassemblyDialog.cpp @@ -39,6 +39,7 @@ BEGIN_EVENT_TABLE(DisassemblyDialog, wxFrame) EVT_COMMAND( wxID_ANY, debEVT_UPDATE, DisassemblyDialog::onDebuggerEvent ) EVT_COMMAND( wxID_ANY, debEVT_BREAKPOINTWINDOW, DisassemblyDialog::onDebuggerEvent ) EVT_COMMAND( wxID_ANY, debEVT_MAPLOADED, DisassemblyDialog::onDebuggerEvent ) + EVT_SIZE(DisassemblyDialog::onSizeEvent) EVT_CLOSE( DisassemblyDialog::onClose ) END_EVENT_TABLE() @@ -176,7 +177,7 @@ void CpuTabPage::update() { breakpointList->reloadBreakpoints(); - if (threadList != NULL) + if (threadList != NULL && cpu->isAlive()) { threadList->reloadThreads(); @@ -217,6 +218,8 @@ DisassemblyDialog::DisassemblyDialog(wxWindow* parent): wxFrame( parent, wxID_ANY, L"Debugger", wxDefaultPosition,wxDefaultSize,wxRESIZE_BORDER|wxCLOSE_BOX|wxCAPTION|wxSYSTEM_MENU ), currentCpu(NULL) { + int width = g_Conf->EmuOptions.Debugger.WindowWidth; + int height = g_Conf->EmuOptions.Debugger.WindowHeight; topSizer = new wxBoxSizer( wxVERTICAL ); wxPanel *panel = new wxPanel(this, wxID_ANY, @@ -252,7 +255,7 @@ DisassemblyDialog::DisassemblyDialog(wxWindow* parent): topSizer->Add(topRowSizer,0,wxLEFT|wxRIGHT|wxTOP,3); // create middle part of the window - wxNotebook* middleBook = new wxNotebook(panel,wxID_ANY); + middleBook = new wxNotebook(panel,wxID_ANY); middleBook->SetBackgroundColour(wxColour(0xFFF0F0F0)); eeTab = new CpuTabPage(middleBook,&r5900Debug); iopTab = new CpuTabPage(middleBook,&r3000Debug); @@ -267,9 +270,23 @@ DisassemblyDialog::DisassemblyDialog(wxWindow* parent): SetMinSize(wxSize(1000,600)); panel->GetSizer()->Fit(this); + if (width != 0 && height != 0) + SetSize(width,height); + setDebugMode(true,true); } +void DisassemblyDialog::onSizeEvent(wxSizeEvent& event) +{ + if (event.GetEventType() == wxEVT_SIZE) + { + g_Conf->EmuOptions.Debugger.WindowWidth = event.GetSize().x; + g_Conf->EmuOptions.Debugger.WindowHeight = event.GetSize().y; + } + + event.Skip(); +} + #ifdef WIN32 WXLRESULT DisassemblyDialog::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { @@ -469,7 +486,7 @@ void DisassemblyDialog::onDebuggerEvent(wxCommandEvent& evt) if (type == debEVT_SETSTATUSBARTEXT) { DebugInterface* cpu = reinterpret_cast(evt.GetClientData()); - if (cpu != NULL && cpu == currentCpu->getCpu()) + if (cpu != NULL && currentCpu != NULL && cpu == currentCpu->getCpu()) GetStatusBar()->SetLabel(evt.GetString()); } else if (type == debEVT_UPDATELAYOUT) { @@ -568,6 +585,19 @@ void DisassemblyDialog::setDebugMode(bool debugMode, bool switchPC) if (running) { + if (currentCpu == NULL) + { + wxWindow* currentPage = middleBook->GetCurrentPage(); + + if (currentPage == eeTab) + currentCpu = eeTab; + else if (currentPage == iopTab) + currentCpu = iopTab; + + if (currentCpu != NULL) + currentCpu->update(); + } + if (debugMode) { CBreakPoints::ClearTemporaryBreakPoints(); @@ -596,6 +626,12 @@ void DisassemblyDialog::setDebugMode(bool debugMode, bool switchPC) stepOverButton->Enable(false); stepOutButton->Enable(false); } + } else { + breakRunButton->SetLabel(L"Run"); + stepIntoButton->Enable(false); + stepOverButton->Enable(false); + stepOutButton->Enable(false); + currentCpu = NULL; } update(); diff --git a/pcsx2/gui/Debugger/DisassemblyDialog.h b/pcsx2/gui/Debugger/DisassemblyDialog.h index 2dcd9fad04..11a0b69358 100644 --- a/pcsx2/gui/Debugger/DisassemblyDialog.h +++ b/pcsx2/gui/Debugger/DisassemblyDialog.h @@ -23,6 +23,7 @@ #include "CtrlMemView.h" #include "DebugEvents.h" #include "DebuggerLists.h" +#include "../MSWstuff.h" class DebuggerHelpDialog: public wxDialog { @@ -30,6 +31,16 @@ public: DebuggerHelpDialog(wxWindow* parent); }; +inline int getDebugFontWidth() +{ + return (int) ceil(g_Conf->EmuOptions.Debugger.FontWidth*MSW_GetDPIScale()); +} + +inline int getDebugFontHeight() +{ + return (int)ceil(g_Conf->EmuOptions.Debugger.FontHeight*MSW_GetDPIScale()); +} + class CpuTabPage: public wxPanel { public: @@ -91,6 +102,7 @@ protected: void onDebuggerEvent(wxCommandEvent& evt); void onPageChanging(wxCommandEvent& evt); void onBreakpointClick(wxCommandEvent& evt); + void onSizeEvent(wxSizeEvent& event); void onClose(wxCloseEvent& evt); void stepOver(); void stepInto(); @@ -100,6 +112,7 @@ private: CpuTabPage* eeTab; CpuTabPage* iopTab; CpuTabPage* currentCpu; + wxNotebook* middleBook; wxBoxSizer* topSizer; wxButton* breakRunButton;