From 8f171c70f5cf048b0fe66d9dcb5f4bdbcfd5a1f9 Mon Sep 17 00:00:00 2001 From: Ty Lamontagne Date: Sun, 1 Aug 2021 18:16:36 -0400 Subject: [PATCH] Debugger: Add option to display VU0F registers as floats --- pcsx2/DebugTools/DebugInterface.cpp | 19 +-- pcsx2/gui/Debugger/CtrlRegisterList.cpp | 163 ++++++++++++++++-------- pcsx2/gui/Debugger/CtrlRegisterList.h | 3 +- 3 files changed, 122 insertions(+), 63 deletions(-) diff --git a/pcsx2/DebugTools/DebugInterface.cpp b/pcsx2/DebugTools/DebugInterface.cpp index c2ad8c5cfb..4b8314c17d 100644 --- a/pcsx2/DebugTools/DebugInterface.cpp +++ b/pcsx2/DebugTools/DebugInterface.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2014 PCSX2 Dev Team + * Copyright (C) 2002-2021 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -375,13 +375,13 @@ DebugInterface::RegisterType R5900DebugInterface::getRegisterType(int cat) { case EECAT_GPR: case EECAT_CP0: - case EECAT_VU0F: case EECAT_VU0I: case EECAT_FCR: case EECAT_GSPRIV: default: return NORMAL; case EECAT_FPR: + case EECAT_VU0F: return SPECIAL; } } @@ -485,18 +485,19 @@ wxString R5900DebugInterface::getRegisterString(int cat, int num) { switch (cat) { - case EECAT_GPR: - case EECAT_CP0: - case EECAT_FCR: - return getRegister(cat,num).ToString(); - case EECAT_FPR: + case EECAT_GPR: + case EECAT_CP0: + case EECAT_FCR: + case EECAT_VU0F: + return getRegister(cat, num).ToString(); + case EECAT_FPR: { char str[64]; sprintf(str,"%f",fpuRegs.fpr[num].f); return wxString(str,wxConvUTF8); } - default: - return L""; + default: + return L""; } } diff --git a/pcsx2/gui/Debugger/CtrlRegisterList.cpp b/pcsx2/gui/Debugger/CtrlRegisterList.cpp index bbe670af79..d8ebb07629 100644 --- a/pcsx2/gui/Debugger/CtrlRegisterList.cpp +++ b/pcsx2/gui/Debugger/CtrlRegisterList.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2014 PCSX2 Dev Team + * Copyright (C) 2002-2021 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -36,6 +36,7 @@ enum DisassemblyMenuIdentifiers ID_REGISTERLIST_DISPLAY64, ID_REGISTERLIST_DISPLAY128, ID_REGISTERLIST_DISPLAY128STRINGS, + ID_REGISTERLIST_DISPLAYVU0FFLOATS, ID_REGISTERLIST_CHANGELOWER, ID_REGISTERLIST_CHANGEUPPER, ID_REGISTERLIST_CHANGEVALUE, @@ -53,10 +54,11 @@ CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu) maxBits = 128; lastPc = 0xFFFFFFFF; resolvePointerStrings = false; + displayVU0FAsFloat = false; for (int i = 0; i < cpu->getRegisterCategoryCount(); i++) { - int count = cpu->getRegisterCount(i); + const int count = cpu->getRegisterCount(i); ChangedReg* regs = new ChangedReg[count]; memset(regs,0,sizeof(ChangedReg)*count); @@ -68,7 +70,7 @@ CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu) maxLen = std::max(maxLen,strlen(cpu->getRegisterName(i,k))); } - int x = 17+(maxLen+2)*charWidth; + const int x = 17+(maxLen+2)*charWidth; startPositions.push_back(x); currentRows.push_back(0); } @@ -76,7 +78,7 @@ CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu) SetDoubleBuffered(true); SetInitialSize(ClientToWindowSize(GetMinClientSize())); - wxSize actualSize = getOptimalSize(); + const wxSize actualSize = getOptimalSize(); SetVirtualSize(actualSize); SetScrollbars(1, rowHeight, actualSize.x, actualSize.y / rowHeight, 0, 0); } @@ -97,7 +99,12 @@ wxSize CtrlRegisterList::getOptimalSize() const for (int i = 0; i < cpu->getRegisterCategoryCount(); i++) { int bits = std::min(maxBits, cpu->getRegisterSize(i)); - int start = startPositions[i]; + + // Workaround for displaying VU0F registers as floats + if (i == EECAT_VU0F && displayVU0FAsFloat) + bits = 128; + + const int start = startPositions[i]; int w = start + (bits / 4) * charWidth; if (bits > 32) @@ -137,14 +144,14 @@ void CtrlRegisterList::refreshChangedRegs() for (size_t cat = 0; cat < changedCategories.size(); cat++) { ChangedReg* regs = changedCategories[cat]; - int size = cpu->getRegisterSize(category); + const int size = cpu->getRegisterSize(category); 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); + const u128 newValue = cpu->getRegister(cat,i); if (reg.oldValue != newValue) { @@ -211,7 +218,7 @@ void CtrlRegisterList::OnDraw(wxDC& dc) int endRow = startRow + ceil(float(GetClientSize().y) / rowHeight); // draw categories - int width = GetClientSize().x; + const int width = GetClientSize().x; if (startRow == 0) { int piece = width /cpu->getRegisterCategoryCount(); @@ -245,17 +252,37 @@ void CtrlRegisterList::OnDraw(wxDC& dc) startRow = std::max(0,startRow-1); endRow = std::min(cpu->getRegisterCount(category)-1,endRow-1); - int nameStart = 17; - int valueStart = startPositions[category]; + // Add a title to help identify registers W Z Y X + if (category == EECAT_VU0F) + { + const int piece = width / 5; // 4 registers + space for register name + + const wxString titles[4] = { "W","Z","Y","X" }; + const int titleAmt = abs((maxBits / 32) - 4); + + for (int iter = 4; iter > titleAmt; iter--) + { + dc.SetBrush(wxBrush(wxColor(0xFFFFEFE8))); + dc.SetPen(wxPen(wxColor(0xFF000000))); + + dc.DrawRectangle((piece * iter) + 3, rowHeight,piece,rowHeight); + dc.DrawText(titles[iter - 1], (piece * iter) + piece / 2,rowHeight + 2); + } + } + + const int nameStart = 17; + const int valueStart = startPositions[category]; ChangedReg* changedRegs = changedCategories[category]; - int registerBits = cpu->getRegisterSize(category); + const int registerBits = cpu->getRegisterSize(category); DebugInterface::RegisterType type = cpu->getRegisterType(category); for (int i = startRow; i <= endRow; i++) { int x = valueStart; - int y = rowHeight*(i+1); + // Skip a row if we are showing our VU0f registers + // This makes room for the WZYX title + const int y = rowHeight*(i + (category == EECAT_VU0F ? 2 : 1)); wxColor backgroundColor; if (currentRows[category] == i) @@ -273,11 +300,37 @@ void CtrlRegisterList::OnDraw(wxDC& dc) dc.SetTextForeground(colorNormal); dc.DrawText(wxString(name,wxConvUTF8),nameStart,y+2); - u128 value = cpu->getRegister(category,i); - ChangedReg& changed = changedRegs[i]; + const u128 value = cpu->getRegister(category,i); + const ChangedReg& changed = changedRegs[i]; switch (type) { + [[fallthrough]]; // If we fallthrough, display VU0f as hexadecimal + 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); + + if (category == EECAT_VU0F) + { + if (displayVU0FAsFloat) + { + char str[256]; + const u128 val = cpu->getRegister(category, i); + // Use std::bit_cast in C++20. The below is technically UB + sprintf(str, "%7.2f %7.2f %7.2f %7.2f", *(float*)&val._u32[3], *(float*)&val._u32[2], *(float*)&val._u32[1], *(float*)&val._u32[0]); + + dc.DrawText(wxString(str), x, y + 2); + break; + } + } + else + { + dc.DrawText(cpu->getRegisterString(category, i), x, y + 2); + break; + } case DebugInterface::NORMAL: // display them in 32 bit parts switch (registerBits) { @@ -286,7 +339,7 @@ void CtrlRegisterList::OnDraw(wxDC& dc) int startIndex = std::min(3, maxBits / 32 - 1); if (resolvePointerStrings && cpu->isAlive()) { - char *strval = cpu->stringFromPointer(value._u32[0]); + const char *strval = cpu->stringFromPointer(value._u32[0]); if (strval) { static wxColor clr = wxColor(0xFF228822); dc.SetTextForeground(clr); @@ -295,7 +348,7 @@ void CtrlRegisterList::OnDraw(wxDC& dc) } } - int actualX = width-4-(startIndex+1)*(8*charWidth+2); + const int actualX = width-4-(startIndex+1)*(8*charWidth+2); x = std::max(actualX,x); if (startIndex != 3) @@ -355,15 +408,6 @@ void CtrlRegisterList::OnDraw(wxDC& dc) } } 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; } } } @@ -441,6 +485,12 @@ void CtrlRegisterList::onPopupClick(wxCommandEvent& evt) postEvent(debEVT_UPDATELAYOUT, 0); Refresh(); break; + case ID_REGISTERLIST_DISPLAYVU0FFLOATS: + displayVU0FAsFloat = !displayVU0FAsFloat; + SetInitialSize(ClientToWindowSize(GetMinClientSize())); + postEvent(debEVT_UPDATELAYOUT, 0); + Refresh(); + break; case ID_REGISTERLIST_CHANGELOWER: changeValue(LOWER64); Refresh(); @@ -514,25 +564,48 @@ void CtrlRegisterList::mouseEvent(wxMouseEvent& evt) wxClientDC dc(this); wxPoint pos = evt.GetPosition(); - int x = dc.DeviceToLogicalX(pos.x) + xOffset; - int y = dc.DeviceToLogicalY(pos.y) + yOffset * rowHeight; + const int x = dc.DeviceToLogicalX(pos.x) + xOffset; + const int y = dc.DeviceToLogicalY(pos.y) + yOffset * rowHeight; if (evt.GetEventType() == wxEVT_RIGHT_UP) { if (y >= rowHeight) { - int row = (y-rowHeight)/rowHeight; + const int row = (y-rowHeight)/rowHeight; if (row != currentRows[category] && row < cpu->getRegisterCount(category)) setCurrentRow(row); } wxMenu menu; - int bits = cpu->getRegisterSize(category); + const int bits = cpu->getRegisterSize(category); + + if (!(category == EECAT_VU0F && displayVU0FAsFloat)) + { + 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.AppendRadioItem(ID_REGISTERLIST_DISPLAY128STRINGS, L"Display 128 bit + Resolve string pointers"); + + switch (maxBits) + { + case 128: + if (resolvePointerStrings) + menu.Check(ID_REGISTERLIST_DISPLAY128STRINGS, true); + else + 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 (category == EECAT_VU0F) + menu.AppendCheckItem(ID_REGISTERLIST_DISPLAYVU0FFLOATS, L"Display VU0f registers as floats")->Check(displayVU0FAsFloat); - 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.AppendRadioItem(ID_REGISTERLIST_DISPLAY128STRINGS, L"Display 128 bit + Resolve string pointers"); menu.AppendSeparator(); if (bits >= 64) @@ -547,22 +620,6 @@ void CtrlRegisterList::mouseEvent(wxMouseEvent& evt) menu.Append(ID_REGISTERLIST_GOTOINMEMORYVIEW, L"Follow in Memory view"); menu.Append(ID_REGISTERLIST_GOTOINDISASM, L"Follow in Disasm"); - switch (maxBits) - { - case 128: - if (resolvePointerStrings) - menu.Check(ID_REGISTERLIST_DISPLAY128STRINGS, true); - else - 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.Bind(wxEVT_MENU, &CtrlRegisterList::onPopupClick, this); PopupMenu(&menu,evt.GetPosition()); return; @@ -572,8 +629,8 @@ void CtrlRegisterList::mouseEvent(wxMouseEvent& evt) { if (y < rowHeight) { - int piece = GetSize().x/cpu->getRegisterCategoryCount(); - int cat = std::min(x/piece,cpu->getRegisterCategoryCount()-1); + const int piece = GetSize().x/cpu->getRegisterCategoryCount(); + const int cat = std::min(x/piece,cpu->getRegisterCategoryCount()-1); if (cat != category) { @@ -581,7 +638,7 @@ void CtrlRegisterList::mouseEvent(wxMouseEvent& evt) Refresh(); } } else { - int row = (y-rowHeight)/rowHeight; + const int row = (y - (rowHeight * 2) )/rowHeight; if (row != currentRows[category] && row < cpu->getRegisterCount(category)) setCurrentRow(row); } @@ -595,7 +652,7 @@ void CtrlRegisterList::ensureVisible(int index) { //scroll vertically to keep a logical position visible int x, y; GetViewStart(&x, &y); - int visibleOffset = floor(float(GetClientSize().y) / rowHeight) - 1; + const int visibleOffset = floor(float(GetClientSize().y) / rowHeight) - 1; if (index < y) Scroll(x, index); else if (index > y + visibleOffset) diff --git a/pcsx2/gui/Debugger/CtrlRegisterList.h b/pcsx2/gui/Debugger/CtrlRegisterList.h index 720e9185a3..bfd45621e2 100644 --- a/pcsx2/gui/Debugger/CtrlRegisterList.h +++ b/pcsx2/gui/Debugger/CtrlRegisterList.h @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2014 PCSX2 Dev Team + * Copyright (C) 2002-2021 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -74,4 +74,5 @@ private: int category; int maxBits; bool resolvePointerStrings; + bool displayVU0FAsFloat; };