From 597be1c9bc6c8e6ed022777af31f7c0a2b63ade7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 12 Dec 2024 19:24:02 +0100 Subject: [PATCH 1/4] Stop pretending that DisassemblyManager isn't a singleton - it currently is. --- Core/Debugger/DisassemblyManager.cpp | 30 +++---- Core/Debugger/DisassemblyManager.h | 19 +++-- .../WebSocket/BreakpointSubscriber.cpp | 3 +- Core/Debugger/WebSocket/DisasmSubscriber.cpp | 26 +++--- Core/Debugger/WebSocket/HLESubscriber.cpp | 12 +-- .../Debugger/WebSocket/SteppingSubscriber.cpp | 10 +-- UI/ImDebugger/ImDebugger.cpp | 2 +- UI/ImDebugger/ImDisasmView.cpp | 82 +++++++++---------- UI/ImDebugger/ImDisasmView.h | 15 ++-- Windows/Debugger/CtrlDisAsmView.cpp | 80 +++++++++--------- Windows/Debugger/CtrlDisAsmView.h | 19 ++--- Windows/Debugger/EditSymbolsWindow.cpp | 3 +- 12 files changed, 143 insertions(+), 158 deletions(-) diff --git a/Core/Debugger/DisassemblyManager.cpp b/Core/Debugger/DisassemblyManager.cpp index a7cc6c4abfd6..b2d74ef5a192 100644 --- a/Core/Debugger/DisassemblyManager.cpp +++ b/Core/Debugger/DisassemblyManager.cpp @@ -36,10 +36,7 @@ #include "Core/Debugger/SymbolMap.h" #include "Core/Debugger/DisassemblyManager.h" -std::map DisassemblyManager::entries; -std::recursive_mutex DisassemblyManager::entriesLock_; -DebugInterface* DisassemblyManager::cpu_; -int DisassemblyManager::maxParamChars = 29; +DisassemblyManager g_disassemblyManager; bool isInInterval(u32 start, u32 size, u32 value) { return start <= value && value <= (start+size-1); @@ -185,6 +182,11 @@ std::map::iterator findDisassemblyEntry(std::map guard(lock_); - DebugInterface *cpu = DisassemblyManager::getCpu(); + DebugInterface *cpu = g_disassemblyManager.getCpu(); for (u32 funcPos = address; funcPos < end; funcPos += 4) { MIPSAnalyst::MipsOpcodeInfo opInfo = MIPSAnalyst::GetOpcodeInfo(cpu, funcPos); @@ -612,7 +614,7 @@ void DisassemblyFunction::load() } } - DebugInterface *cpu = DisassemblyManager::getCpu(); + DebugInterface *cpu = g_disassemblyManager.getCpu(); u32 funcPos = address; u32 funcEnd = address+size; @@ -747,11 +749,7 @@ void DisassemblyFunction::clear() hash = 0; } -bool DisassemblyOpcode::disassemble(u32 address, DisassemblyLineInfo &dest, bool insertSymbols, DebugInterface *cpuDebug) -{ - if (!cpuDebug) - cpuDebug = DisassemblyManager::getCpu(); - +bool DisassemblyOpcode::disassemble(u32 address, DisassemblyLineInfo &dest, bool insertSymbols, DebugInterface *cpuDebug) { char opcode[64],arguments[256]; char dizz[512]; DisAsm(address, dizz, sizeof(dizz)); @@ -778,7 +776,7 @@ void DisassemblyOpcode::getBranchLines(u32 start, u32 size, std::vector getBranchLines(u32 start, u32 size); @@ -212,14 +212,17 @@ class DisassemblyManager { u32 getNthPreviousAddress(u32 address, int n = 1); u32 getNthNextAddress(u32 address, int n = 1); - static DebugInterface *getCpu() { return cpu_; }; - static int getMaxParamChars() { return maxParamChars; }; + DebugInterface *getCpu() { return cpu_; }; + int getMaxParamChars() { return maxParamChars; }; + private: - static std::map entries; - static std::recursive_mutex entriesLock_; - static DebugInterface *cpu_; - static int maxParamChars; + std::map entries; + std::recursive_mutex entriesLock_; + DebugInterface *cpu_; + int maxParamChars = 29; }; +extern DisassemblyManager g_disassemblyManager; + bool isInInterval(u32 start, u32 size, u32 value); bool IsLikelyStringAt(uint32_t addr); diff --git a/Core/Debugger/WebSocket/BreakpointSubscriber.cpp b/Core/Debugger/WebSocket/BreakpointSubscriber.cpp index 2f3b788b3473..f5d75f40235e 100644 --- a/Core/Debugger/WebSocket/BreakpointSubscriber.cpp +++ b/Core/Debugger/WebSocket/BreakpointSubscriber.cpp @@ -227,9 +227,8 @@ void WebSocketCPUBreakpointList(DebuggerRequest &req) { else json.writeString("symbol", symbol); - DisassemblyManager manager; DisassemblyLineInfo line; - manager.getLine(manager.getStartAddress(bp.addr), true, line); + g_disassemblyManager.getLine(g_disassemblyManager.getStartAddress(bp.addr), true, line, currentDebugMIPS); json.writeString("code", line.name + " " + line.params); json.pop(); diff --git a/Core/Debugger/WebSocket/DisasmSubscriber.cpp b/Core/Debugger/WebSocket/DisasmSubscriber.cpp index 023fc989556e..697aab37550c 100644 --- a/Core/Debugger/WebSocket/DisasmSubscriber.cpp +++ b/Core/Debugger/WebSocket/DisasmSubscriber.cpp @@ -34,10 +34,10 @@ class WebSocketDisasmState : public DebuggerSubscriber { public: WebSocketDisasmState() { - disasm_.setCpu(currentDebugMIPS); + g_disassemblyManager.setCpu(currentDebugMIPS); } ~WebSocketDisasmState() { - disasm_.clear(); + g_disassemblyManager.clear(); } void Base(DebuggerRequest &req); @@ -48,8 +48,6 @@ class WebSocketDisasmState : public DebuggerSubscriber { protected: void WriteDisasmLine(JsonWriter &json, const DisassemblyLineInfo &l); void WriteBranchGuide(JsonWriter &json, const BranchLine &l); - - DisassemblyManager disasm_; }; DebuggerSubscriber *WebSocketDisasmInit(DebuggerEventHandlerMap &map) { @@ -316,18 +314,18 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) { if (count != 0) { count = std::min(count, MAX_RANGE); // Let's assume everything is two instructions. - disasm_.analyze(start - 4, count * 8 + 8); - start = disasm_.getStartAddress(start); + g_disassemblyManager.analyze(start - 4, count * 8 + 8); + start = g_disassemblyManager.getStartAddress(start); if (start == -1) req.ParamU32("address", &start); - end = disasm_.getNthNextAddress(start, count); + end = g_disassemblyManager.getNthNextAddress(start, count); } else if (req.ParamU32("end", &end)) { end = std::max(start, end); if (end - start > MAX_RANGE * 4) end = start + MAX_RANGE * 4; // Let's assume everything is two instructions at most. - disasm_.analyze(start - 4, end - start + 8); - start = disasm_.getStartAddress(start); + g_disassemblyManager.analyze(start - 4, end - start + 8); + start = g_disassemblyManager.getStartAddress(start); if (start == -1) req.ParamU32("address", &start); // Correct end and calculate count based on it. @@ -336,11 +334,11 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) { u32 next = start; count = 0; if (stop < start) { - for (next = start; next > stop; next = disasm_.getNthNextAddress(next, 1)) { + for (next = start; next > stop; next = g_disassemblyManager.getNthNextAddress(next, 1)) { count++; } } - for (end = next; end < stop && end >= next; end = disasm_.getNthNextAddress(end, 1)) { + for (end = next; end < stop && end >= next; end = g_disassemblyManager.getNthNextAddress(end, 1)) { count++; } } else { @@ -362,7 +360,7 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) { DisassemblyLineInfo line; uint32_t addr = start; for (uint32_t i = 0; i < count; ++i) { - disasm_.getLine(addr, displaySymbols, line, cpuDebug); + g_disassemblyManager.getLine(addr, displaySymbols, line, cpuDebug); WriteDisasmLine(json, line); addr += line.totalSize; @@ -373,7 +371,7 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) { json.pop(); json.pushArray("branchGuides"); - auto branchGuides = disasm_.getBranchLines(start, end - start); + auto branchGuides = g_disassemblyManager.getBranchLines(start, end - start); for (auto bl : branchGuides) WriteBranchGuide(json, bl); json.pop(); @@ -428,7 +426,7 @@ void WebSocketDisasmState::SearchDisasm(DebuggerRequest &req) { bool found = false; uint32_t addr = start; do { - disasm_.getLine(addr, displaySymbols, line, cpuDebug); + g_disassemblyManager.getLine(addr, displaySymbols, line, cpuDebug); const std::string addressSymbol = g_symbolMap->GetLabelString(addr); std::string mergeForSearch; diff --git a/Core/Debugger/WebSocket/HLESubscriber.cpp b/Core/Debugger/WebSocket/HLESubscriber.cpp index 8e749f19f5e3..110483ed3e6a 100644 --- a/Core/Debugger/WebSocket/HLESubscriber.cpp +++ b/Core/Debugger/WebSocket/HLESubscriber.cpp @@ -297,8 +297,7 @@ void WebSocketHLEFuncAdd(DebuggerRequest &req) { } // Clear cache for branch lines and such. - DisassemblyManager manager; - manager.clear(); + g_disassemblyManager.clear(); JsonWriter &json = req.Respond(); json.writeUint("address", addr); @@ -354,8 +353,7 @@ void WebSocketHLEFuncRemove(DebuggerRequest &req) { } // Clear cache for branch lines and such. - DisassemblyManager manager; - manager.clear(); + g_disassemblyManager.clear(); JsonWriter &json = req.Respond(); json.writeUint("address", funcBegin); @@ -392,8 +390,7 @@ static u32 RemoveFuncSymbolsInRange(u32 addr, u32 size) { } // Clear cache for branch lines and such. - DisassemblyManager manager; - manager.clear(); + g_disassemblyManager.clear(); } return counter; } @@ -592,9 +589,8 @@ void WebSocketHLEBacktrace(DebuggerRequest &req) { json.writeUint("sp", f.sp); json.writeUint("stackSize", f.stackSize); - DisassemblyManager manager; DisassemblyLineInfo line; - manager.getLine(manager.getStartAddress(f.pc), true, line, cpuDebug); + g_disassemblyManager.getLine(g_disassemblyManager.getStartAddress(f.pc), true, line, cpuDebug); json.writeString("code", line.name + " " + line.params); json.pop(); diff --git a/Core/Debugger/WebSocket/SteppingSubscriber.cpp b/Core/Debugger/WebSocket/SteppingSubscriber.cpp index 4f7662bada8e..d596f2038c82 100644 --- a/Core/Debugger/WebSocket/SteppingSubscriber.cpp +++ b/Core/Debugger/WebSocket/SteppingSubscriber.cpp @@ -30,10 +30,10 @@ using namespace MIPSAnalyst; struct WebSocketSteppingState : public DebuggerSubscriber { WebSocketSteppingState() { - disasm_.setCpu(currentDebugMIPS); + g_disassemblyManager.setCpu(currentDebugMIPS); } ~WebSocketSteppingState() { - disasm_.clear(); + g_disassemblyManager.clear(); } void Into(DebuggerRequest &req); @@ -47,8 +47,6 @@ struct WebSocketSteppingState : public DebuggerSubscriber { int GetNextInstructionCount(DebugInterface *cpuDebug); void PrepareResume(); void AddThreadCondition(uint32_t breakpointAddress, uint32_t threadID); - - DisassemblyManager disasm_; }; DebuggerSubscriber *WebSocketSteppingInit(DebuggerEventHandlerMap &map) { @@ -266,8 +264,8 @@ void WebSocketSteppingState::HLE(DebuggerRequest &req) { } uint32_t WebSocketSteppingState::GetNextAddress(DebugInterface *cpuDebug) { - uint32_t current = disasm_.getStartAddress(cpuDebug->GetPC()); - return disasm_.getNthNextAddress(current, 1); + uint32_t current = g_disassemblyManager.getStartAddress(cpuDebug->GetPC()); + return g_disassemblyManager.getNthNextAddress(current, 1); } int WebSocketSteppingState::GetNextInstructionCount(DebugInterface *cpuDebug) { diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index 1b471448439f..5d206b06452b 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -892,7 +892,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu } // TODO: Pass mipsDebug in where needed instead. - DisassemblyManager::setCpu(mipsDebug); + g_disassemblyManager.setCpu(mipsDebug); disasm_.View().setDebugger(mipsDebug); for (int i = 0; i < 4; i++) { mem_[i].View().setDebugger(mipsDebug); diff --git a/UI/ImDebugger/ImDisasmView.cpp b/UI/ImDebugger/ImDisasmView.cpp index e0d53513f74b..606faea5f12d 100644 --- a/UI/ImDebugger/ImDisasmView.cpp +++ b/UI/ImDebugger/ImDisasmView.cpp @@ -33,11 +33,11 @@ ImDisasmView::ImDisasmView() { } ImDisasmView::~ImDisasmView() { - manager.clear(); + g_disassemblyManager.clear(); } void ImDisasmView::ScanVisibleFunctions() { - manager.analyze(windowStart_, manager.getNthNextAddress(windowStart_, visibleRows_) - windowStart_); + g_disassemblyManager.analyze(windowStart_, g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_) - windowStart_); } static ImColor scaleColor(ImColor color, float factor) { @@ -130,7 +130,7 @@ void ImDisasmView::assembleOpcode(u32 address, const std::string &defaultText) { ScanVisibleFunctions(); if (address == curAddress) - gotoAddr(manager.getNthNextAddress(curAddress, 1)); + gotoAddr(g_disassemblyManager.getNthNextAddress(curAddress, 1)); redraw(); } else { @@ -141,7 +141,7 @@ void ImDisasmView::assembleOpcode(u32 address, const std::string &defaultText) { } void ImDisasmView::drawBranchLine(ImDrawList *drawList, Bounds rect, std::map &addressPositions, const BranchLine &line) { - u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_); + u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_); float topY; float bottomY; @@ -235,7 +235,7 @@ std::set ImDisasmView::getSelectedLineArguments() { std::set args; DisassemblyLineInfo line; for (u32 addr = selectRangeStart_; addr < selectRangeEnd_; addr += 4) { - manager.getLine(addr, displaySymbols_, line); + g_disassemblyManager.getLine(addr, displaySymbols_, line, debugger_); size_t p = 0, nextp = line.params.find(','); while (nextp != line.params.npos) { args.emplace(line.params.substr(p, nextp - p)); @@ -350,7 +350,7 @@ void ImDisasmView::Draw(ImDrawList *drawList, ImControl &control) { const u32 pc = debugger_->GetPC(); for (int i = 0; i < visibleRows_; i++) { - manager.getLine(address, displaySymbols_, line); + g_disassemblyManager.getLine(address, displaySymbols_, line, debugger_); float rowY1 = rowHeight_ * i; float rowY2 = rowHeight_ * (i + 1); @@ -413,7 +413,7 @@ void ImDisasmView::Draw(ImDrawList *drawList, ImControl &control) { address += line.totalSize; } - std::vector branchLines = manager.getBranchLines(windowStart_, address - windowStart_); + std::vector branchLines = g_disassemblyManager.getBranchLines(windowStart_, address - windowStart_); for (size_t i = 0; i < branchLines.size(); i++) { drawBranchLine(drawList, bounds, addressPositions, branchLines[i]); } @@ -443,9 +443,9 @@ void ImDisasmView::Draw(ImDrawList *drawList, ImControl &control) { if (is_hovered) { if (io.MouseWheel > 0.0f) { // TODO: Scale steps by the value. - windowStart_ = manager.getNthPreviousAddress(windowStart_, 4); + windowStart_ = g_disassemblyManager.getNthPreviousAddress(windowStart_, 4); } else if (io.MouseWheel < 0.0f) { - windowStart_ = manager.getNthNextAddress(windowStart_, 4); + windowStart_ = g_disassemblyManager.getNthNextAddress(windowStart_, 4); } } @@ -479,9 +479,9 @@ void ImDisasmView::NotifyStep() { void ImDisasmView::ScrollRelative(int amount) { if (amount > 0) { - windowStart_ = manager.getNthNextAddress(windowStart_, amount); + windowStart_ = g_disassemblyManager.getNthNextAddress(windowStart_, amount); } else if (amount < 0) { - windowStart_ = manager.getNthPreviousAddress(windowStart_, amount); + windowStart_ = g_disassemblyManager.getNthPreviousAddress(windowStart_, amount); } ScanVisibleFunctions(); } @@ -489,7 +489,7 @@ void ImDisasmView::ScrollRelative(int amount) { // Follows branches and jumps. void ImDisasmView::FollowBranch() { DisassemblyLineInfo line; - manager.getLine(curAddress_, true, line); + g_disassemblyManager.getLine(curAddress_, true, line, debugger_); if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO) { if (line.info.isBranch) { @@ -551,7 +551,7 @@ void ImDisasmView::ProcessKeyboardShortcuts(bool focused) { return; } - u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_); + u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_); keyTaken = true; ImGuiIO& io = ImGui::GetIO(); @@ -591,27 +591,27 @@ void ImDisasmView::ProcessKeyboardShortcuts(bool focused) { ScanVisibleFunctions(); } if (ImGui::IsKeyPressed(ImGuiKey_PageDown)) { - setCurAddress(manager.getNthPreviousAddress(windowEnd, 1), (io.KeyMods & ImGuiMod_Shift) != 0); + setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowEnd, 1), (io.KeyMods & ImGuiMod_Shift) != 0); } if (ImGui::IsKeyPressed(ImGuiKey_PageUp)) { setCurAddress(windowStart_, ImGui::IsKeyDown(ImGuiKey_LeftShift)); } } else { if (ImGui::IsKeyPressed(ImGuiKey_PageDown)) { - windowStart_ = manager.getNthNextAddress(windowStart_, visibleRows_); + windowStart_ = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_); } if (ImGui::IsKeyPressed(ImGuiKey_PageUp)) { - windowStart_ = manager.getNthPreviousAddress(windowStart_, visibleRows_); + windowStart_ = g_disassemblyManager.getNthPreviousAddress(windowStart_, visibleRows_); } if (ImGui::IsKeyPressed(ImGuiKey_F3)) { SearchNext(!ImGui::IsKeyPressed(ImGuiKey_LeftShift)); } if (ImGui::IsKeyPressed(ImGuiKey_DownArrow)) { - setCurAddress(manager.getNthNextAddress(curAddress_, 1), (io.KeyMods & ImGuiMod_Shift) != 0); + setCurAddress(g_disassemblyManager.getNthNextAddress(curAddress_, 1), (io.KeyMods & ImGuiMod_Shift) != 0); scrollAddressIntoView(); } if (ImGui::IsKeyPressed(ImGuiKey_UpArrow)) { - setCurAddress(manager.getNthPreviousAddress(curAddress_, 1), (io.KeyMods & ImGuiMod_Shift) != 0); + setCurAddress(g_disassemblyManager.getNthPreviousAddress(curAddress_, 1), (io.KeyMods & ImGuiMod_Shift) != 0); scrollAddressIntoView(); } if (ImGui::IsKeyPressed(ImGuiKey_RightArrow)) { @@ -637,11 +637,11 @@ void ImDisasmView::ProcessKeyboardShortcuts(bool focused) { } else { switch (wParam & 0xFFFF) { case VK_NEXT: - if (manager.getNthNextAddress(curAddress, 1) != windowEnd && curAddressIsVisible()) { - setCurAddress(manager.getNthPreviousAddress(windowEnd, 1), KeyDownAsync(VK_SHIFT)); + if (g_disassemblyManager.getNthNextAddress(curAddress, 1) != windowEnd && curAddressIsVisible()) { + setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowEnd, 1), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); } else { - setCurAddress(manager.getNthNextAddress(windowEnd, visibleRows_ - 1), KeyDownAsync(VK_SHIFT)); + setCurAddress(g_disassemblyManager.getNthNextAddress(windowEnd, visibleRows_ - 1), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); } break; @@ -650,7 +650,7 @@ void ImDisasmView::ProcessKeyboardShortcuts(bool focused) { setCurAddress(windowStart_, KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); } else { - setCurAddress(manager.getNthPreviousAddress(windowStart_, visibleRows_), KeyDownAsync(VK_SHIFT)); + setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowStart_, visibleRows_), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); } break; @@ -666,18 +666,18 @@ void ImDisasmView::ProcessKeyboardShortcuts(bool focused) { } void ImDisasmView::scrollAddressIntoView() { - u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_); + u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_); if (curAddress_ < windowStart_) windowStart_ = curAddress_; else if (curAddress_ >= windowEnd) - windowStart_ = manager.getNthPreviousAddress(curAddress_, visibleRows_ - 1); + windowStart_ = g_disassemblyManager.getNthPreviousAddress(curAddress_, visibleRows_ - 1); ScanVisibleFunctions(); } bool ImDisasmView::curAddressIsVisible() { - u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_); + u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_); return curAddress_ >= windowStart_ && curAddress_ < windowEnd; } @@ -828,7 +828,7 @@ void ImDisasmView::PopupMenu(ImControl &control) { g_symbolMap->RemoveFunction(funcBegin, true); g_symbolMap->SortSymbols(); - manager.clear(); + g_disassemblyManager.clear(); mapReloaded_ = true; } else { @@ -852,7 +852,7 @@ void ImDisasmView::PopupMenu(ImControl &control) { snprintf(symname, 128, "u_un_%08X", curAddress_); g_symbolMap->AddFunction(symname, curAddress_, newSize); g_symbolMap->SortSymbols(); - manager.clear(); + g_disassemblyManager.clear(); mapReloaded_ = true; } @@ -902,7 +902,7 @@ void ImDisasmView::updateStatusBarText() { char text[512]; DisassemblyLineInfo line; - manager.getLine(curAddress_, true, line); + g_disassemblyManager.getLine(curAddress_, true, line, debugger_); text[0] = 0; if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO) { @@ -997,7 +997,7 @@ void ImDisasmView::updateStatusBarText() { u32 ImDisasmView::yToAddress(float y) { int line = (int)(y / rowHeight_); - return manager.getNthNextAddress(windowStart_, line); + return g_disassemblyManager.getNthNextAddress(windowStart_, line); } void ImDisasmView::calculatePixelPositions() { @@ -1022,7 +1022,7 @@ void ImDisasmView::SearchNext(bool forward) { } // Note: Search will replace matchAddress_ with the current address. - u32 searchAddress = manager.getNthNextAddress(matchAddress_, 1); + u32 searchAddress = g_disassemblyManager.getNthNextAddress(matchAddress_, 1); // limit address to sensible ranges if (searchAddress < 0x04000000) @@ -1038,7 +1038,7 @@ void ImDisasmView::SearchNext(bool forward) { DisassemblyLineInfo lineInfo; while (searchAddress < 0x0A000000) { - manager.getLine(searchAddress, displaySymbols_, lineInfo); + g_disassemblyManager.getLine(searchAddress, displaySymbols_, lineInfo, debugger_); char addressText[64]; getDisasmAddressText(searchAddress, addressText, true, lineInfo.type == DISTYPE_OPCODE); @@ -1071,7 +1071,7 @@ void ImDisasmView::SearchNext(bool forward) { return; } - searchAddress = manager.getNthNextAddress(searchAddress, 1); + searchAddress = g_disassemblyManager.getNthNextAddress(searchAddress, 1); if (searchAddress >= 0x04200000 && searchAddress < 0x08000000) searchAddress = 0x08000000; } @@ -1102,7 +1102,7 @@ std::string ImDisasmView::disassembleRange(u32 start, u32 size) { while (disAddress < start + size) { char addressText[64], buffer[512]; - manager.getLine(disAddress, displaySymbols_, line); + g_disassemblyManager.getLine(disAddress, displaySymbols_, line, debugger_); bool isLabel = getDisasmAddressText(disAddress, addressText, false, line.type == DISTYPE_OPCODE); if (isLabel) { @@ -1162,23 +1162,23 @@ void ImDisasmView::disassembleToFile() { // get size void ImDisasmView::getOpcodeText(u32 address, char* dest, int bufsize) { DisassemblyLineInfo line; - address = manager.getStartAddress(address); - manager.getLine(address, displaySymbols_, line); + address = g_disassemblyManager.getStartAddress(address); + g_disassemblyManager.getLine(address, displaySymbols_, line, debugger_); snprintf(dest, bufsize, "%s %s", line.name.c_str(), line.params.c_str()); } void ImDisasmView::scrollStepping(u32 newPc) { - u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_); + u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_); - newPc = manager.getStartAddress(newPc); - if (newPc >= windowEnd || newPc >= manager.getNthPreviousAddress(windowEnd, 1)) + newPc = g_disassemblyManager.getStartAddress(newPc); + if (newPc >= windowEnd || newPc >= g_disassemblyManager.getNthPreviousAddress(windowEnd, 1)) { - windowStart_ = manager.getNthPreviousAddress(newPc, visibleRows_ - 2); + windowStart_ = g_disassemblyManager.getNthPreviousAddress(newPc, visibleRows_ - 2); } } u32 ImDisasmView::getInstructionSizeAt(u32 address) { - u32 start = manager.getStartAddress(address); - u32 next = manager.getNthNextAddress(start, 1); + u32 start = g_disassemblyManager.getStartAddress(address); + u32 next = g_disassemblyManager.getNthNextAddress(start, 1); return next - address; } diff --git a/UI/ImDebugger/ImDisasmView.h b/UI/ImDebugger/ImDisasmView.h index 7ebe2adf10fc..f859e3a4f048 100644 --- a/UI/ImDebugger/ImDisasmView.h +++ b/UI/ImDebugger/ImDisasmView.h @@ -40,7 +40,7 @@ class ImDisasmView { void scrollAddressIntoView(); bool curAddressIsVisible(); void ScanVisibleFunctions(); - void clearFunctions() { manager.clear(); }; + void clearFunctions() { g_disassemblyManager.clear(); }; void getOpcodeText(u32 address, char *dest, int bufsize); u32 yToAddress(float y); @@ -49,7 +49,7 @@ class ImDisasmView { if (debugger_ != deb) { debugger_ = deb; curAddress_ = debugger_->GetPC(); - manager.setCpu(deb); + g_disassemblyManager.setCpu(deb); } } @@ -63,11 +63,11 @@ class ImDisasmView { void gotoAddr(unsigned int addr) { if (positionLocked_ != 0) return; - u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_); - u32 newAddress = manager.getStartAddress(addr); + u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_); + u32 newAddress = g_disassemblyManager.getStartAddress(addr); if (newAddress < windowStart_ || newAddress >= windowEnd) { - windowStart_ = manager.getNthPreviousAddress(newAddress, visibleRows_ / 2); + windowStart_ = g_disassemblyManager.getNthPreviousAddress(newAddress, visibleRows_ / 2); } setCurAddress(newAddress); @@ -89,8 +89,8 @@ class ImDisasmView { void editBreakpoint(ImConfig &cfg); void setCurAddress(u32 newAddress, bool extend = false) { - newAddress = manager.getStartAddress(newAddress); - const u32 after = manager.getNthNextAddress(newAddress, 1); + newAddress = g_disassemblyManager.getStartAddress(newAddress); + const u32 after = g_disassemblyManager.getNthNextAddress(newAddress, 1); curAddress_ = newAddress; selectRangeStart_ = extend ? std::min(selectRangeStart_, newAddress) : newAddress; selectRangeEnd_ = extend ? std::max(selectRangeEnd_, after) : after; @@ -137,7 +137,6 @@ class ImDisasmView { std::set getSelectedLineArguments(); void drawArguments(ImDrawList *list, Bounds rc, const DisassemblyLineInfo &line, float x, float y, ImColor textColor, const std::set ¤tArguments); - DisassemblyManager manager; u32 curAddress_ = 0; u32 selectRangeStart_ = 0; u32 selectRangeEnd_ = 0; diff --git a/Windows/Debugger/CtrlDisAsmView.cpp b/Windows/Debugger/CtrlDisAsmView.cpp index cfc3ad04a842..71d05e81d654 100644 --- a/Windows/Debugger/CtrlDisAsmView.cpp +++ b/Windows/Debugger/CtrlDisAsmView.cpp @@ -63,7 +63,7 @@ void CtrlDisAsmView::deinit() void CtrlDisAsmView::scanVisibleFunctions() { - manager.analyze(windowStart,manager.getNthNextAddress(windowStart,visibleRows)-windowStart); + g_disassemblyManager.analyze(windowStart, g_disassemblyManager.getNthNextAddress(windowStart,visibleRows)-windowStart); } LRESULT CALLBACK CtrlDisAsmView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -206,7 +206,7 @@ CtrlDisAsmView::~CtrlDisAsmView() { DeleteObject(font); DeleteObject(boldfont); - manager.clear(); + g_disassemblyManager.clear(); } static COLORREF scaleColor(COLORREF color, float factor) @@ -326,7 +326,7 @@ void CtrlDisAsmView::assembleOpcode(u32 address, const std::string &defaultText) scanVisibleFunctions(); if (address == curAddress) - gotoAddr(manager.getNthNextAddress(curAddress,1)); + gotoAddr(g_disassemblyManager.getNthNextAddress(curAddress,1)); redraw(); } else { @@ -337,7 +337,7 @@ void CtrlDisAsmView::assembleOpcode(u32 address, const std::string &defaultText) void CtrlDisAsmView::drawBranchLine(HDC hdc, std::map &addressPositions, const BranchLine &line) { HPEN pen; - u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); + u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows); int topY; int bottomY; @@ -433,7 +433,7 @@ std::set CtrlDisAsmView::getSelectedLineArguments() { DisassemblyLineInfo line; for (u32 addr = selectRangeStart; addr < selectRangeEnd; addr += 4) { - manager.getLine(addr, displaySymbols, line); + g_disassemblyManager.getLine(addr, displaySymbols, line, debugger); size_t p = 0, nextp = line.params.find(','); while (nextp != line.params.npos) { args.emplace(line.params.substr(p, nextp - p)); @@ -520,7 +520,7 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam) DisassemblyLineInfo line; for (int i = 0; i < visibleRows; i++) { - manager.getLine(address,displaySymbols,line); + g_disassemblyManager.getLine(address,displaySymbols,line, debugger); int rowY1 = rowHeight*i; int rowY2 = rowHeight*(i+1); @@ -594,7 +594,7 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam) address += line.totalSize; } - std::vector branchLines = manager.getBranchLines(windowStart,address-windowStart); + std::vector branchLines = g_disassemblyManager.getBranchLines(windowStart,address-windowStart); for (size_t i = 0; i < branchLines.size(); i++) { drawBranchLine(hdc,addressPositions,branchLines[i]); @@ -627,16 +627,16 @@ void CtrlDisAsmView::onVScroll(WPARAM wParam, LPARAM lParam) switch (wParam & 0xFFFF) { case SB_LINEDOWN: - windowStart = manager.getNthNextAddress(windowStart,1); + windowStart = g_disassemblyManager.getNthNextAddress(windowStart,1); break; case SB_LINEUP: - windowStart = manager.getNthPreviousAddress(windowStart,1); + windowStart = g_disassemblyManager.getNthPreviousAddress(windowStart,1); break; case SB_PAGEDOWN: - windowStart = manager.getNthNextAddress(windowStart,visibleRows); + windowStart = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows); break; case SB_PAGEUP: - windowStart = manager.getNthPreviousAddress(windowStart,visibleRows); + windowStart = g_disassemblyManager.getNthPreviousAddress(windowStart,visibleRows); break; default: return; @@ -649,7 +649,7 @@ void CtrlDisAsmView::onVScroll(WPARAM wParam, LPARAM lParam) void CtrlDisAsmView::followBranch() { DisassemblyLineInfo line; - manager.getLine(curAddress,true,line); + g_disassemblyManager.getLine(curAddress, true, line, debugger); if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO) { @@ -721,7 +721,7 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam) return; dontRedraw = false; - u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); + u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows); keyTaken = true; if (KeyDownAsync(VK_CONTROL)) @@ -764,7 +764,7 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam) scanVisibleFunctions(); break; case VK_NEXT: - setCurAddress(manager.getNthPreviousAddress(windowEnd,1),KeyDownAsync(VK_SHIFT)); + setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowEnd,1),KeyDownAsync(VK_SHIFT)); break; case VK_PRIOR: setCurAddress(windowStart,KeyDownAsync(VK_SHIFT)); @@ -774,19 +774,19 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam) switch (wParam & 0xFFFF) { case VK_DOWN: - setCurAddress(manager.getNthNextAddress(curAddress,1), KeyDownAsync(VK_SHIFT)); + setCurAddress(g_disassemblyManager.getNthNextAddress(curAddress,1), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); break; case VK_UP: - setCurAddress(manager.getNthPreviousAddress(curAddress,1), KeyDownAsync(VK_SHIFT)); + setCurAddress(g_disassemblyManager.getNthPreviousAddress(curAddress,1), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); break; case VK_NEXT: - if (manager.getNthNextAddress(curAddress,1) != windowEnd && curAddressIsVisible()) { - setCurAddress(manager.getNthPreviousAddress(windowEnd,1), KeyDownAsync(VK_SHIFT)); + if (g_disassemblyManager.getNthNextAddress(curAddress,1) != windowEnd && curAddressIsVisible()) { + setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowEnd,1), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); } else { - setCurAddress(manager.getNthNextAddress(windowEnd,visibleRows-1), KeyDownAsync(VK_SHIFT)); + setCurAddress(g_disassemblyManager.getNthNextAddress(windowEnd,visibleRows-1), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); } break; @@ -795,7 +795,7 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam) setCurAddress(windowStart, KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); } else { - setCurAddress(manager.getNthPreviousAddress(windowStart,visibleRows), KeyDownAsync(VK_SHIFT)); + setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowStart,visibleRows), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); } break; @@ -836,19 +836,19 @@ void CtrlDisAsmView::onKeyUp(WPARAM wParam, LPARAM lParam) void CtrlDisAsmView::scrollAddressIntoView() { - u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); + u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows); if (curAddress < windowStart) windowStart = curAddress; else if (curAddress >= windowEnd) - windowStart = manager.getNthPreviousAddress(curAddress,visibleRows-1); + windowStart = g_disassemblyManager.getNthPreviousAddress(curAddress,visibleRows-1); scanVisibleFunctions(); } bool CtrlDisAsmView::curAddressIsVisible() { - u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); + u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows); return curAddress >= windowStart && curAddress < windowEnd; } @@ -1060,7 +1060,7 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) g_symbolMap->RemoveFunction(funcBegin,true); g_symbolMap->SortSymbols(); - manager.clear(); + g_disassemblyManager.clear(); SendMessage(GetParent(wnd), WM_DEB_MAPLOADED, 0, 0); } @@ -1094,7 +1094,7 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) snprintf(symname,128,"u_un_%08X",curAddress); g_symbolMap->AddFunction(symname,curAddress,newSize); g_symbolMap->SortSymbols(); - manager.clear(); + g_disassemblyManager.clear(); SendMessage(GetParent(wnd), WM_DEB_MAPLOADED, 0, 0); } @@ -1143,7 +1143,7 @@ void CtrlDisAsmView::updateStatusBarText() char text[512]; DisassemblyLineInfo line; - manager.getLine(curAddress,true,line); + g_disassemblyManager.getLine(curAddress,true,line, debugger); text[0] = 0; if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO) @@ -1242,7 +1242,7 @@ void CtrlDisAsmView::updateStatusBarText() u32 CtrlDisAsmView::yToAddress(int y) { int line = y/rowHeight; - return manager.getNthNextAddress(windowStart,line); + return g_disassemblyManager.getNthNextAddress(windowStart,line); } void CtrlDisAsmView::calculatePixelPositions() @@ -1272,9 +1272,9 @@ void CtrlDisAsmView::search(bool continueSearch) searchQuery[i] = tolower(searchQuery[i]); } SetFocus(wnd); - searchAddress = manager.getNthNextAddress(curAddress,1); + searchAddress = g_disassemblyManager.getNthNextAddress(curAddress,1); } else { - searchAddress = manager.getNthNextAddress(matchAddress,1); + searchAddress = g_disassemblyManager.getNthNextAddress(matchAddress,1); } // limit address to sensible ranges @@ -1291,7 +1291,7 @@ void CtrlDisAsmView::search(bool continueSearch) DisassemblyLineInfo lineInfo; while (searchAddress < 0x0A000000) { - manager.getLine(searchAddress,displaySymbols,lineInfo); + g_disassemblyManager.getLine(searchAddress,displaySymbols,lineInfo, debugger); char addressText[64]; getDisasmAddressText(searchAddress,addressText,true,lineInfo.type == DISTYPE_OPCODE); @@ -1326,7 +1326,7 @@ void CtrlDisAsmView::search(bool continueSearch) return; } - searchAddress = manager.getNthNextAddress(searchAddress,1); + searchAddress = g_disassemblyManager.getNthNextAddress(searchAddress,1); if (searchAddress >= 0x04200000 && searchAddress < 0x08000000) searchAddress = 0x08000000; } @@ -1361,7 +1361,7 @@ std::string CtrlDisAsmView::disassembleRange(u32 start, u32 size) { char addressText[64],buffer[512]; - manager.getLine(disAddress,displaySymbols,line); + g_disassemblyManager.getLine(disAddress,displaySymbols,line, debugger); bool isLabel = getDisasmAddressText(disAddress,addressText,false,line.type == DISTYPE_OPCODE); if (isLabel) @@ -1423,25 +1423,25 @@ void CtrlDisAsmView::disassembleToFile() { void CtrlDisAsmView::getOpcodeText(u32 address, char* dest, int bufsize) { DisassemblyLineInfo line; - address = manager.getStartAddress(address); - manager.getLine(address,displaySymbols,line); + address = g_disassemblyManager.getStartAddress(address); + g_disassemblyManager.getLine(address,displaySymbols,line, debugger); snprintf(dest, bufsize, "%s %s",line.name.c_str(),line.params.c_str()); } void CtrlDisAsmView::scrollStepping(u32 newPc) { - u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); + u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows); - newPc = manager.getStartAddress(newPc); - if (newPc >= windowEnd || newPc >= manager.getNthPreviousAddress(windowEnd,1)) + newPc = g_disassemblyManager.getStartAddress(newPc); + if (newPc >= windowEnd || newPc >= g_disassemblyManager.getNthPreviousAddress(windowEnd,1)) { - windowStart = manager.getNthPreviousAddress(newPc,visibleRows-2); + windowStart = g_disassemblyManager.getNthPreviousAddress(newPc,visibleRows-2); } } u32 CtrlDisAsmView::getInstructionSizeAt(u32 address) { - u32 start = manager.getStartAddress(address); - u32 next = manager.getNthNextAddress(start,1); + u32 start = g_disassemblyManager.getStartAddress(address); + u32 next = g_disassemblyManager.getNthNextAddress(start,1); return next - address; } diff --git a/Windows/Debugger/CtrlDisAsmView.h b/Windows/Debugger/CtrlDisAsmView.h index 5bb06ef651ce..aa8541349c63 100644 --- a/Windows/Debugger/CtrlDisAsmView.h +++ b/Windows/Debugger/CtrlDisAsmView.h @@ -29,7 +29,6 @@ class CtrlDisAsmView HFONT boldfont; RECT rect; - DisassemblyManager manager; u32 curAddress; u32 selectRangeStart; u32 selectRangeEnd; @@ -101,7 +100,7 @@ class CtrlDisAsmView bool curAddressIsVisible(); void redraw(); void scanVisibleFunctions(); - void clearFunctions() { manager.clear(); }; + void clearFunctions() { g_disassemblyManager.clear(); }; void getOpcodeText(u32 address, char* dest, int bufsize); int getRowHeight() { return rowHeight; }; @@ -112,7 +111,7 @@ class CtrlDisAsmView { debugger=deb; curAddress=debugger->GetPC(); - manager.setCpu(deb); + g_disassemblyManager.setCpu(deb); } DebugInterface *getDebugger() { @@ -126,12 +125,12 @@ class CtrlDisAsmView { if (positionLocked_ != 0) return; - u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); - u32 newAddress = manager.getStartAddress(addr); + u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows); + u32 newAddress = g_disassemblyManager.getStartAddress(addr); if (newAddress < windowStart || newAddress >= windowEnd) { - windowStart = manager.getNthPreviousAddress(newAddress,visibleRows/2); + windowStart = g_disassemblyManager.getNthPreviousAddress(newAddress,visibleRows/2); } setCurAddress(newAddress); @@ -158,9 +157,9 @@ class CtrlDisAsmView void scrollWindow(int lines) { if (lines < 0) - windowStart = manager.getNthPreviousAddress(windowStart,abs(lines)); + windowStart = g_disassemblyManager.getNthPreviousAddress(windowStart,abs(lines)); else - windowStart = manager.getNthNextAddress(windowStart,lines); + windowStart = g_disassemblyManager.getNthNextAddress(windowStart,lines); scanVisibleFunctions(); redraw(); @@ -168,8 +167,8 @@ class CtrlDisAsmView void setCurAddress(u32 newAddress, bool extend = false) { - newAddress = manager.getStartAddress(newAddress); - const u32 after = manager.getNthNextAddress(newAddress,1); + newAddress = g_disassemblyManager.getStartAddress(newAddress); + const u32 after = g_disassemblyManager.getNthNextAddress(newAddress,1); curAddress = newAddress; selectRangeStart = extend ? std::min(selectRangeStart, newAddress) : newAddress; selectRangeEnd = extend ? std::max(selectRangeEnd, after) : after; diff --git a/Windows/Debugger/EditSymbolsWindow.cpp b/Windows/Debugger/EditSymbolsWindow.cpp index 0f9b797d7d0c..a50144b67b7a 100644 --- a/Windows/Debugger/EditSymbolsWindow.cpp +++ b/Windows/Debugger/EditSymbolsWindow.cpp @@ -178,8 +178,7 @@ void EditSymbolsWindow::Remove() { } // Clear cache for branch lines and such. - DisassemblyManager manager; - manager.clear(); + g_disassemblyManager.clear(); } } From 4b36664dd6c37afb6061fe999c830290315e6db3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 11 Dec 2024 13:36:25 +0100 Subject: [PATCH 2/4] Move more things to State.cpp/h, break out some stuff into a function --- GPU/Debugger/State.cpp | 182 +++++++++++++++++++++ GPU/Debugger/State.h | 10 +- Windows/GEDebugger/GEDebugger.cpp | 5 +- Windows/GEDebugger/GEDebugger.h | 2 +- Windows/GEDebugger/VertexPreview.cpp | 230 ++++----------------------- 5 files changed, 228 insertions(+), 201 deletions(-) diff --git a/GPU/Debugger/State.cpp b/GPU/Debugger/State.cpp index 4db525f9c481..b242c515f6ba 100644 --- a/GPU/Debugger/State.cpp +++ b/GPU/Debugger/State.cpp @@ -6,6 +6,7 @@ #include "GPU/Common/GPUDebugInterface.h" #include "GPU/GeDisasm.h" #include "GPU/Common/VertexDecoderCommon.h" +#include "GPU/Common/SplineCommon.h" #include "Core/System.h" void FormatStateRow(GPUDebugInterface *gpudebug, char *dest, size_t destSize, CmdFormatType fmt, u32 value, bool enabled, u32 otherValue, u32 otherValue2) { @@ -646,3 +647,184 @@ static void FormatVertColRawColor(char *dest, size_t destSize, const void *data, break; } } + + +static void SwapUVs(GPUDebugVertex &a, GPUDebugVertex &b) { + float tempu = a.u; + float tempv = a.v; + a.u = b.u; + a.v = b.v; + b.u = tempu; + b.v = tempv; +} + +static void RotateUVThrough(GPUDebugVertex v[4]) { + float x1 = v[2].x; + float x2 = v[0].x; + float y1 = v[2].y; + float y2 = v[0].y; + + if ((x1 < x2 && y1 > y2) || (x1 > x2 && y1 < y2)) + SwapUVs(v[1], v[3]); +} + +void ExpandRectangles(std::vector &vertices, std::vector &indices, int &count, bool throughMode) { + static std::vector newVerts; + static std::vector newInds; + + bool useInds = true; + size_t numInds = indices.size(); + if (indices.empty()) { + useInds = false; + numInds = count; + } + + //rectangles always need 2 vertices, disregard the last one if there's an odd number + numInds = numInds & ~1; + + // Will need 4 coords and 6 points per rectangle (currently 2 each.) + newVerts.resize(numInds * 2); + newInds.resize(numInds * 3); + + u16 v = 0; + GPUDebugVertex *vert = &newVerts[0]; + u16 *ind = &newInds[0]; + for (size_t i = 0; i < numInds; i += 2) { + const auto &orig_tl = useInds ? vertices[indices[i + 0]] : vertices[i + 0]; + const auto &orig_br = useInds ? vertices[indices[i + 1]] : vertices[i + 1]; + + vert[0] = orig_br; + + // Top right. + vert[1] = orig_br; + vert[1].y = orig_tl.y; + vert[1].v = orig_tl.v; + + vert[2] = orig_tl; + + // Bottom left. + vert[3] = orig_br; + vert[3].x = orig_tl.x; + vert[3].u = orig_tl.u; + + // That's the four corners. Now process UV rotation. + // This is the same for through and non-through, since it's already transformed. + RotateUVThrough(vert); + + // Build the two 3 point triangles from our 4 coordinates. + *ind++ = v + 0; + *ind++ = v + 1; + *ind++ = v + 2; + *ind++ = v + 3; + *ind++ = v + 0; + *ind++ = v + 2; + + vert += 4; + v += 4; + } + + std::swap(vertices, newVerts); + std::swap(indices, newInds); + count *= 3; +} + +void ExpandBezier(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds) { + using namespace Spline; + + int count_u = (op >> 0) & 0xFF; + int count_v = (op >> 8) & 0xFF; + // Real hardware seems to draw nothing when given < 4 either U or V. + if (count_u < 4 || count_v < 4) + return; + + BezierSurface surface; + surface.num_points_u = count_u; + surface.num_points_v = count_v; + surface.tess_u = gstate.getPatchDivisionU(); + surface.tess_v = gstate.getPatchDivisionV(); + surface.num_patches_u = (count_u - 1) / 3; + surface.num_patches_v = (count_v - 1) / 3; + surface.primType = gstate.getPatchPrimitiveType(); + surface.patchFacing = false; + + int num_points = count_u * count_v; + // Make an array of pointers to the control points, to get rid of indices. + std::vector points(num_points); + for (int idx = 0; idx < num_points; idx++) + points[idx] = simpleVerts.data() + (!indices.empty() ? indices[idx] : idx); + + int total_patches = surface.num_patches_u * surface.num_patches_v; + generatedVerts.resize((surface.tess_u + 1) * (surface.tess_v + 1) * total_patches); + generatedInds.resize(surface.tess_u * surface.tess_v * 6 * total_patches); + + OutputBuffers output; + output.vertices = generatedVerts.data(); + output.indices = generatedInds.data(); + output.count = 0; + + ControlPoints cpoints; + cpoints.pos = new Vec3f[num_points]; + cpoints.tex = new Vec2f[num_points]; + cpoints.col = new Vec4f[num_points]; + cpoints.Convert(points.data(), num_points); + + surface.Init((int)generatedVerts.size()); + SoftwareTessellation(output, surface, gstate.vertType, cpoints); + count = output.count; + + delete[] cpoints.pos; + delete[] cpoints.tex; + delete[] cpoints.col; +} + +void ExpandSpline(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds) { + using namespace Spline; + + int count_u = (op >> 0) & 0xFF; + int count_v = (op >> 8) & 0xFF; + // Real hardware seems to draw nothing when given < 4 either U or V. + if (count_u < 4 || count_v < 4) + return; + + SplineSurface surface; + surface.num_points_u = count_u; + surface.num_points_v = count_v; + surface.tess_u = gstate.getPatchDivisionU(); + surface.tess_v = gstate.getPatchDivisionV(); + surface.type_u = (op >> 16) & 0x3; + surface.type_v = (op >> 18) & 0x3; + surface.num_patches_u = count_u - 3; + surface.num_patches_v = count_v - 3; + surface.primType = gstate.getPatchPrimitiveType(); + surface.patchFacing = false; + + int num_points = count_u * count_v; + // Make an array of pointers to the control points, to get rid of indices. + std::vector points(num_points); + for (int idx = 0; idx < num_points; idx++) + points[idx] = simpleVerts.data() + (!indices.empty() ? indices[idx] : idx); + + int patch_div_s = surface.num_patches_u * surface.tess_u; + int patch_div_t = surface.num_patches_v * surface.tess_v; + generatedVerts.resize((patch_div_s + 1) * (patch_div_t + 1)); + generatedInds.resize(patch_div_s * patch_div_t * 6); + + OutputBuffers output; + output.vertices = generatedVerts.data(); + output.indices = generatedInds.data(); + output.count = 0; + + ControlPoints cpoints; + cpoints.pos = (Vec3f *)AllocateAlignedMemory(sizeof(Vec3f) * num_points, 16); + cpoints.tex = (Vec2f *)AllocateAlignedMemory(sizeof(Vec2f) * num_points, 16); + cpoints.col = (Vec4f *)AllocateAlignedMemory(sizeof(Vec4f) * num_points, 16); + cpoints.Convert(points.data(), num_points); + + surface.Init((int)generatedVerts.size()); + SoftwareTessellation(output, surface, gstate.vertType, cpoints); + count = output.count; + + FreeAlignedMemory(cpoints.pos); + FreeAlignedMemory(cpoints.tex); + FreeAlignedMemory(cpoints.col); +} diff --git a/GPU/Debugger/State.h b/GPU/Debugger/State.h index 916c568b14e5..715610d3e0c9 100644 --- a/GPU/Debugger/State.h +++ b/GPU/Debugger/State.h @@ -7,7 +7,7 @@ #include "Common/CommonTypes.h" #include "GPU/Debugger/GECommandTable.h" -// Extracted from Windows/GE Debugger/TabState.cpp +#include "GPU/Common/SplineCommon.h" enum VertexListCols { VERTEXLIST_COL_X, @@ -39,3 +39,11 @@ class VertexDecoder; void FormatStateRow(GPUDebugInterface *debug, char *dest, size_t destSize, CmdFormatType fmt, u32 value, bool enabled, u32 otherValue, u32 otherValue2); void FormatVertCol(char *dest, size_t destSize, const GPUDebugVertex &vert, int col); void FormatVertColRaw(VertexDecoder *decoder, char *dest, size_t destSize, int row, int col); + + +// These are utilities used by the debugger vertex preview. + +// Later I hope to re-use more of the real logic. +void ExpandBezier(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds); +void ExpandSpline(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds); +void ExpandRectangles(std::vector &vertices, std::vector &indices, int &count, bool throughMode); diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 7004ed80b7bb..19bf460eff4b 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -568,7 +568,10 @@ void CGEDebugger::UpdatePreviews() { UpdatePrimaryPreview(state); UpdateSecondPreview(state); - u32 primOp = PrimPreviewOp(); + u32 primOp = 0; + if (!showClut_) { + primOp = PrimPreviewOp(); + } if (primOp != 0) { UpdatePrimPreview(primOp, 3); } diff --git a/Windows/GEDebugger/GEDebugger.h b/Windows/GEDebugger/GEDebugger.h index bb747f332e3f..bb8b8e08ac4a 100644 --- a/Windows/GEDebugger/GEDebugger.h +++ b/Windows/GEDebugger/GEDebugger.h @@ -102,7 +102,7 @@ class CGEDebugger : public Dialog { void UpdatePreviews(); void UpdatePrimaryPreview(const GPUgstate &state); void UpdateSecondPreview(const GPUgstate &state); - u32 PrimPreviewOp(); + static u32 PrimPreviewOp(); void UpdatePrimPreview(u32 op, int which); void CleanupPrimPreview(); void HandleRedraw(int which); diff --git a/Windows/GEDebugger/VertexPreview.cpp b/Windows/GEDebugger/VertexPreview.cpp index f2c9e1bd5502..a0715bc5f0b1 100644 --- a/Windows/GEDebugger/VertexPreview.cpp +++ b/Windows/GEDebugger/VertexPreview.cpp @@ -25,6 +25,7 @@ #include "GPU/GPUCommon.h" #include "GPU/Common/GPUDebugInterface.h" #include "GPU/Common/SplineCommon.h" +#include "GPU/Debugger/State.h" #include "GPU/GPUState.h" #include "Common/Log.h" #include "Common/MemoryUtil.h" @@ -73,202 +74,20 @@ static void BindPreviewProgram(GLSLProgram *&prog) { glsl_bind(prog); } -static void SwapUVs(GPUDebugVertex &a, GPUDebugVertex &b) { - float tempu = a.u; - float tempv = a.v; - a.u = b.u; - a.v = b.v; - b.u = tempu; - b.v = tempv; -} - -static void RotateUVThrough(GPUDebugVertex v[4]) { - float x1 = v[2].x; - float x2 = v[0].x; - float y1 = v[2].y; - float y2 = v[0].y; - - if ((x1 < x2 && y1 > y2) || (x1 > x2 && y1 < y2)) - SwapUVs(v[1], v[3]); -} - -static void ExpandRectangles(std::vector &vertices, std::vector &indices, int &count, bool throughMode) { - static std::vector newVerts; - static std::vector newInds; - - bool useInds = true; - size_t numInds = indices.size(); - if (indices.empty()) { - useInds = false; - numInds = count; - } - - //rectangles always need 2 vertices, disregard the last one if there's an odd number - numInds = numInds & ~1; - - // Will need 4 coords and 6 points per rectangle (currently 2 each.) - newVerts.resize(numInds * 2); - newInds.resize(numInds * 3); - - u16 v = 0; - GPUDebugVertex *vert = &newVerts[0]; - u16 *ind = &newInds[0]; - for (size_t i = 0; i < numInds; i += 2) { - const auto &orig_tl = useInds ? vertices[indices[i + 0]] : vertices[i + 0]; - const auto &orig_br = useInds ? vertices[indices[i + 1]] : vertices[i + 1]; - - vert[0] = orig_br; - - // Top right. - vert[1] = orig_br; - vert[1].y = orig_tl.y; - vert[1].v = orig_tl.v; - - vert[2] = orig_tl; - - // Bottom left. - vert[3] = orig_br; - vert[3].x = orig_tl.x; - vert[3].u = orig_tl.u; - - // That's the four corners. Now process UV rotation. - // This is the same for through and non-through, since it's already transformed. - RotateUVThrough(vert); - - // Build the two 3 point triangles from our 4 coordinates. - *ind++ = v + 0; - *ind++ = v + 1; - *ind++ = v + 2; - *ind++ = v + 3; - *ind++ = v + 0; - *ind++ = v + 2; - - vert += 4; - v += 4; - } - - std::swap(vertices, newVerts); - std::swap(indices, newInds); - count *= 3; -} - u32 CGEDebugger::PrimPreviewOp() { DisplayList list; - if (gpuDebug != nullptr && gpuDebug->GetCurrentDisplayList(list) && !showClut_) { + if (gpuDebug != nullptr && gpuDebug->GetCurrentDisplayList(list)) { const u32 op = Memory::Read_U32(list.pc); const u32 cmd = op >> 24; if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE) { return op; } } - return 0; } -static void ExpandBezier(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds) { - using namespace Spline; - - int count_u = (op >> 0) & 0xFF; - int count_v = (op >> 8) & 0xFF; - // Real hardware seems to draw nothing when given < 4 either U or V. - if (count_u < 4 || count_v < 4) - return; - - BezierSurface surface; - surface.num_points_u = count_u; - surface.num_points_v = count_v; - surface.tess_u = gstate.getPatchDivisionU(); - surface.tess_v = gstate.getPatchDivisionV(); - surface.num_patches_u = (count_u - 1) / 3; - surface.num_patches_v = (count_v - 1) / 3; - surface.primType = gstate.getPatchPrimitiveType(); - surface.patchFacing = false; - - int num_points = count_u * count_v; - // Make an array of pointers to the control points, to get rid of indices. - std::vector points(num_points); - for (int idx = 0; idx < num_points; idx++) - points[idx] = simpleVerts.data() + (!indices.empty() ? indices[idx] : idx); - - int total_patches = surface.num_patches_u * surface.num_patches_v; - generatedVerts.resize((surface.tess_u + 1) * (surface.tess_v + 1) * total_patches); - generatedInds.resize(surface.tess_u * surface.tess_v * 6 * total_patches); - - OutputBuffers output; - output.vertices = generatedVerts.data(); - output.indices = generatedInds.data(); - output.count = 0; - - ControlPoints cpoints; - cpoints.pos = new Vec3f[num_points]; - cpoints.tex = new Vec2f[num_points]; - cpoints.col = new Vec4f[num_points]; - cpoints.Convert(points.data(), num_points); - - surface.Init((int)generatedVerts.size()); - SoftwareTessellation(output, surface, gstate.vertType, cpoints); - count = output.count; - - delete [] cpoints.pos; - delete [] cpoints.tex; - delete [] cpoints.col; -} - -static void ExpandSpline(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds) { - using namespace Spline; - - int count_u = (op >> 0) & 0xFF; - int count_v = (op >> 8) & 0xFF; - // Real hardware seems to draw nothing when given < 4 either U or V. - if (count_u < 4 || count_v < 4) - return; - - SplineSurface surface; - surface.num_points_u = count_u; - surface.num_points_v = count_v; - surface.tess_u = gstate.getPatchDivisionU(); - surface.tess_v = gstate.getPatchDivisionV(); - surface.type_u = (op >> 16) & 0x3; - surface.type_v = (op >> 18) & 0x3; - surface.num_patches_u = count_u - 3; - surface.num_patches_v = count_v - 3; - surface.primType = gstate.getPatchPrimitiveType(); - surface.patchFacing = false; - - int num_points = count_u * count_v; - // Make an array of pointers to the control points, to get rid of indices. - std::vector points(num_points); - for (int idx = 0; idx < num_points; idx++) - points[idx] = simpleVerts.data() + (!indices.empty() ? indices[idx] : idx); - - int patch_div_s = surface.num_patches_u * surface.tess_u; - int patch_div_t = surface.num_patches_v * surface.tess_v; - generatedVerts.resize((patch_div_s + 1) * (patch_div_t + 1)); - generatedInds.resize(patch_div_s * patch_div_t * 6); - - OutputBuffers output; - output.vertices = generatedVerts.data(); - output.indices = generatedInds.data(); - output.count = 0; - - ControlPoints cpoints; - cpoints.pos = (Vec3f *)AllocateAlignedMemory(sizeof(Vec3f) * num_points, 16); - cpoints.tex = (Vec2f *)AllocateAlignedMemory(sizeof(Vec2f) * num_points, 16); - cpoints.col = (Vec4f *)AllocateAlignedMemory(sizeof(Vec4f) * num_points, 16); - cpoints.Convert(points.data(), num_points); - - surface.Init((int)generatedVerts.size()); - SoftwareTessellation(output, surface, gstate.vertType, cpoints); - count = output.count; - - FreeAlignedMemory(cpoints.pos); - FreeAlignedMemory(cpoints.tex); - FreeAlignedMemory(cpoints.col); -} - -void CGEDebugger::UpdatePrimPreview(u32 op, int which) { +bool GetPrimPreview(u32 op, int which, GEPrimitiveType &prim, std::vector &vertices, std::vector &indices, int &count) { u32 prim_type = GE_PRIM_INVALID; - int count = 0; int count_u = 0; int count_v = 0; @@ -287,24 +106,21 @@ void CGEDebugger::UpdatePrimPreview(u32 op, int which) { if (prim_type >= 7) { ERROR_LOG(Log::G3D, "Unsupported prim type: %x", op); - return; + return false; } if (!gpuDebug) { ERROR_LOG(Log::G3D, "Invalid debugging environment, shutting down?"); - return; + return false; } - which &= previewsEnabled_; if (count == 0 || which == 0) { - return; + return false; } - const GEPrimitiveType prim = static_cast(prim_type); - static std::vector vertices; - static std::vector indices; + prim = static_cast(prim_type); if (!gpuDebug->GetCurrentSimpleVertices(count, vertices, indices)) { ERROR_LOG(Log::G3D, "Vertex preview not yet supported"); - return; + return false; } if (cmd != GE_CMD_PRIM) { @@ -341,9 +157,6 @@ void CGEDebugger::UpdatePrimPreview(u32 op, int which) { ExpandRectangles(vertices, indices, count, gpuDebug->GetGState().isModeThrough()); } - float fw, fh; - float x, y; - // TODO: Probably there's a better way and place to do this. u16 minIndex = 0; u16 maxIndex = count - 1; @@ -372,8 +185,6 @@ void CGEDebugger::UpdatePrimPreview(u32 op, int which) { const float invTexWidth = 1.0f / gpuDebug->GetGState().getTextureWidth(0); const float invTexHeight = 1.0f / gpuDebug->GetGState().getTextureHeight(0); - const float invRealTexWidth = 1.0f / gstate_c.curTextureWidth; - const float invRealTexHeight = 1.0f / gstate_c.curTextureHeight; bool clampS = gpuDebug->GetGState().isTexCoordClampedS(); bool clampT = gpuDebug->GetGState().isTexCoordClampedT(); for (u16 i = minIndex; i <= maxIndex; ++i) { @@ -385,6 +196,28 @@ void CGEDebugger::UpdatePrimPreview(u32 op, int which) { wrapCoord(vertices[i].v); } + return true; +} + +void CGEDebugger::UpdatePrimPreview(u32 op, int which) { + which &= previewsEnabled_; + + static std::vector vertices; + static std::vector indices; + + int count = 0; + GEPrimitiveType prim; + if (!GetPrimPreview(op, which, prim, vertices, indices, count)) { + return; + } + + float fw, fh; + float x, y; + + const float invRealTexWidth = 1.0f / gstate_c.curTextureWidth; + const float invRealTexHeight = 1.0f / gstate_c.curTextureHeight; + + // Preview positions on the framebuffer if (which & 1) { primaryWindow->Begin(); primaryWindow->GetContentSize(x, y, fw, fh); @@ -451,6 +284,7 @@ void CGEDebugger::UpdatePrimPreview(u32 op, int which) { primaryWindow->End(); } + // Preview UVs on the texture if (which & 2) { secondWindow->Begin(); secondWindow->GetContentSize(x, y, fw, fh); @@ -533,7 +367,7 @@ void CGEDebugger::HandleRedraw(int which) { } u32 op = PrimPreviewOp(); - if (op) { + if (op && !showClut_) { UpdatePrimPreview(op, which); } } From 4020fd8ec56e4e11721997a0efec5208e61d0057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 11 Dec 2024 13:38:05 +0100 Subject: [PATCH 3/4] Move the last of the vertex preview code to State.cpp --- GPU/Debugger/State.cpp | 119 ++++++++++++++++++++++++++- GPU/Debugger/State.h | 4 +- Windows/GEDebugger/VertexPreview.cpp | 113 ------------------------- 3 files changed, 117 insertions(+), 119 deletions(-) diff --git a/GPU/Debugger/State.cpp b/GPU/Debugger/State.cpp index b242c515f6ba..03361880bbf6 100644 --- a/GPU/Debugger/State.cpp +++ b/GPU/Debugger/State.cpp @@ -668,7 +668,7 @@ static void RotateUVThrough(GPUDebugVertex v[4]) { SwapUVs(v[1], v[3]); } -void ExpandRectangles(std::vector &vertices, std::vector &indices, int &count, bool throughMode) { +static void ExpandRectangles(std::vector &vertices, std::vector &indices, int &count, bool throughMode) { static std::vector newVerts; static std::vector newInds; @@ -728,7 +728,7 @@ void ExpandRectangles(std::vector &vertices, std::vector &i count *= 3; } -void ExpandBezier(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds) { +static void ExpandBezier(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds) { using namespace Spline; int count_u = (op >> 0) & 0xFF; @@ -777,7 +777,7 @@ void ExpandBezier(int &count, int op, const std::vector &simpleVer delete[] cpoints.col; } -void ExpandSpline(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds) { +static void ExpandSpline(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds) { using namespace Spline; int count_u = (op >> 0) & 0xFF; @@ -828,3 +828,116 @@ void ExpandSpline(int &count, int op, const std::vector &simpleVer FreeAlignedMemory(cpoints.tex); FreeAlignedMemory(cpoints.col); } + +bool GetPrimPreview(u32 op, int which, GEPrimitiveType &prim, std::vector &vertices, std::vector &indices, int &count) { + u32 prim_type = GE_PRIM_INVALID; + int count_u = 0; + int count_v = 0; + + const u32 cmd = op >> 24; + if (cmd == GE_CMD_PRIM) { + prim_type = (op >> 16) & 0x7; + count = op & 0xFFFF; + } else { + const GEPrimitiveType primLookup[] = { GE_PRIM_TRIANGLES, GE_PRIM_LINES, GE_PRIM_POINTS, GE_PRIM_POINTS }; + if (gstate.getPatchPrimitiveType() < ARRAY_SIZE(primLookup)) + prim_type = primLookup[gstate.getPatchPrimitiveType()]; + count_u = (op & 0x00FF) >> 0; + count_v = (op & 0xFF00) >> 8; + count = count_u * count_v; + } + + if (prim_type >= 7) { + ERROR_LOG(Log::G3D, "Unsupported prim type: %x", op); + return false; + } + if (!gpuDebug) { + ERROR_LOG(Log::G3D, "Invalid debugging environment, shutting down?"); + return false; + } + if (count == 0 || which == 0) { + return false; + } + + prim = static_cast(prim_type); + + if (!gpuDebug->GetCurrentSimpleVertices(count, vertices, indices)) { + ERROR_LOG(Log::G3D, "Vertex preview not yet supported"); + return false; + } + + if (cmd != GE_CMD_PRIM) { + static std::vector generatedVerts; + static std::vector generatedInds; + + static std::vector simpleVerts; + simpleVerts.resize(vertices.size()); + for (size_t i = 0; i < vertices.size(); ++i) { + // For now, let's just copy back so we can use TessellateBezierPatch/TessellateSplinePatch... + simpleVerts[i].uv[0] = vertices[i].u; + simpleVerts[i].uv[1] = vertices[i].v; + simpleVerts[i].pos = Vec3Packedf(vertices[i].x, vertices[i].y, vertices[i].z); + } + + if (cmd == GE_CMD_BEZIER) { + ExpandBezier(count, op, simpleVerts, indices, generatedVerts, generatedInds); + } else if (cmd == GE_CMD_SPLINE) { + ExpandSpline(count, op, simpleVerts, indices, generatedVerts, generatedInds); + } + + vertices.resize(generatedVerts.size()); + for (size_t i = 0; i < vertices.size(); ++i) { + vertices[i].u = generatedVerts[i].uv[0]; + vertices[i].v = generatedVerts[i].uv[1]; + vertices[i].x = generatedVerts[i].pos.x; + vertices[i].y = generatedVerts[i].pos.y; + vertices[i].z = generatedVerts[i].pos.z; + } + indices = generatedInds; + } + + if (prim == GE_PRIM_RECTANGLES) { + ExpandRectangles(vertices, indices, count, gpuDebug->GetGState().isModeThrough()); + } + + // TODO: Probably there's a better way and place to do this. + u16 minIndex = 0; + u16 maxIndex = count - 1; + if (!indices.empty()) { + _dbg_assert_(count <= indices.size()); + minIndex = 0xFFFF; + maxIndex = 0; + for (int i = 0; i < count; ++i) { + if (minIndex > indices[i]) { + minIndex = indices[i]; + } + if (maxIndex < indices[i]) { + maxIndex = indices[i]; + } + } + } + + auto wrapCoord = [](float &coord) { + if (coord < 0.0f) { + coord += ceilf(-coord); + } + if (coord > 1.0f) { + coord -= floorf(coord); + } + }; + + const float invTexWidth = 1.0f / gpuDebug->GetGState().getTextureWidth(0); + const float invTexHeight = 1.0f / gpuDebug->GetGState().getTextureHeight(0); + bool clampS = gpuDebug->GetGState().isTexCoordClampedS(); + bool clampT = gpuDebug->GetGState().isTexCoordClampedT(); + for (u16 i = minIndex; i <= maxIndex; ++i) { + vertices[i].u *= invTexWidth; + vertices[i].v *= invTexHeight; + if (!clampS) + wrapCoord(vertices[i].u); + if (!clampT) + wrapCoord(vertices[i].v); + } + + return true; +} diff --git a/GPU/Debugger/State.h b/GPU/Debugger/State.h index 715610d3e0c9..1c311f5c1f70 100644 --- a/GPU/Debugger/State.h +++ b/GPU/Debugger/State.h @@ -44,6 +44,4 @@ void FormatVertColRaw(VertexDecoder *decoder, char *dest, size_t destSize, int r // These are utilities used by the debugger vertex preview. // Later I hope to re-use more of the real logic. -void ExpandBezier(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds); -void ExpandSpline(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds); -void ExpandRectangles(std::vector &vertices, std::vector &indices, int &count, bool throughMode); +bool GetPrimPreview(u32 op, int which, GEPrimitiveType &prim, std::vector &vertices, std::vector &indices, int &count); diff --git a/Windows/GEDebugger/VertexPreview.cpp b/Windows/GEDebugger/VertexPreview.cpp index a0715bc5f0b1..486c989321cf 100644 --- a/Windows/GEDebugger/VertexPreview.cpp +++ b/Windows/GEDebugger/VertexPreview.cpp @@ -86,119 +86,6 @@ u32 CGEDebugger::PrimPreviewOp() { return 0; } -bool GetPrimPreview(u32 op, int which, GEPrimitiveType &prim, std::vector &vertices, std::vector &indices, int &count) { - u32 prim_type = GE_PRIM_INVALID; - int count_u = 0; - int count_v = 0; - - const u32 cmd = op >> 24; - if (cmd == GE_CMD_PRIM) { - prim_type = (op >> 16) & 0x7; - count = op & 0xFFFF; - } else { - const GEPrimitiveType primLookup[] = { GE_PRIM_TRIANGLES, GE_PRIM_LINES, GE_PRIM_POINTS, GE_PRIM_POINTS }; - if (gstate.getPatchPrimitiveType() < ARRAY_SIZE(primLookup)) - prim_type = primLookup[gstate.getPatchPrimitiveType()]; - count_u = (op & 0x00FF) >> 0; - count_v = (op & 0xFF00) >> 8; - count = count_u * count_v; - } - - if (prim_type >= 7) { - ERROR_LOG(Log::G3D, "Unsupported prim type: %x", op); - return false; - } - if (!gpuDebug) { - ERROR_LOG(Log::G3D, "Invalid debugging environment, shutting down?"); - return false; - } - if (count == 0 || which == 0) { - return false; - } - - prim = static_cast(prim_type); - - if (!gpuDebug->GetCurrentSimpleVertices(count, vertices, indices)) { - ERROR_LOG(Log::G3D, "Vertex preview not yet supported"); - return false; - } - - if (cmd != GE_CMD_PRIM) { - static std::vector generatedVerts; - static std::vector generatedInds; - - static std::vector simpleVerts; - simpleVerts.resize(vertices.size()); - for (size_t i = 0; i < vertices.size(); ++i) { - // For now, let's just copy back so we can use TessellateBezierPatch/TessellateSplinePatch... - simpleVerts[i].uv[0] = vertices[i].u; - simpleVerts[i].uv[1] = vertices[i].v; - simpleVerts[i].pos = Vec3Packedf(vertices[i].x, vertices[i].y, vertices[i].z); - } - - if (cmd == GE_CMD_BEZIER) { - ExpandBezier(count, op, simpleVerts, indices, generatedVerts, generatedInds); - } else if (cmd == GE_CMD_SPLINE) { - ExpandSpline(count, op, simpleVerts, indices, generatedVerts, generatedInds); - } - - vertices.resize(generatedVerts.size()); - for (size_t i = 0; i < vertices.size(); ++i) { - vertices[i].u = generatedVerts[i].uv[0]; - vertices[i].v = generatedVerts[i].uv[1]; - vertices[i].x = generatedVerts[i].pos.x; - vertices[i].y = generatedVerts[i].pos.y; - vertices[i].z = generatedVerts[i].pos.z; - } - indices = generatedInds; - } - - if (prim == GE_PRIM_RECTANGLES) { - ExpandRectangles(vertices, indices, count, gpuDebug->GetGState().isModeThrough()); - } - - // TODO: Probably there's a better way and place to do this. - u16 minIndex = 0; - u16 maxIndex = count - 1; - if (!indices.empty()) { - _dbg_assert_(count <= indices.size()); - minIndex = 0xFFFF; - maxIndex = 0; - for (int i = 0; i < count; ++i) { - if (minIndex > indices[i]) { - minIndex = indices[i]; - } - if (maxIndex < indices[i]) { - maxIndex = indices[i]; - } - } - } - - auto wrapCoord = [](float &coord) { - if (coord < 0.0f) { - coord += ceilf(-coord); - } - if (coord > 1.0f) { - coord -= floorf(coord); - } - }; - - const float invTexWidth = 1.0f / gpuDebug->GetGState().getTextureWidth(0); - const float invTexHeight = 1.0f / gpuDebug->GetGState().getTextureHeight(0); - bool clampS = gpuDebug->GetGState().isTexCoordClampedS(); - bool clampT = gpuDebug->GetGState().isTexCoordClampedT(); - for (u16 i = minIndex; i <= maxIndex; ++i) { - vertices[i].u *= invTexWidth; - vertices[i].v *= invTexHeight; - if (!clampS) - wrapCoord(vertices[i].u); - if (!clampT) - wrapCoord(vertices[i].v); - } - - return true; -} - void CGEDebugger::UpdatePrimPreview(u32 op, int which) { which &= previewsEnabled_; From 8d1fbe952229534d751eeda67d7c520f8cbf054d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 12 Dec 2024 19:36:55 +0100 Subject: [PATCH 4/4] Move more utility functions from the Win32 GE debugger to the common code --- GPU/Debugger/State.cpp | 145 ++++++++++++++++++++++++++++++ GPU/Debugger/State.h | 3 + UI/ImDebugger/ImGe.cpp | 18 +++- Windows/GEDebugger/GEDebugger.cpp | 143 +---------------------------- Windows/GEDebugger/GEDebugger.h | 2 - 5 files changed, 165 insertions(+), 146 deletions(-) diff --git a/GPU/Debugger/State.cpp b/GPU/Debugger/State.cpp index 03361880bbf6..54d5be6062ae 100644 --- a/GPU/Debugger/State.cpp +++ b/GPU/Debugger/State.cpp @@ -1,8 +1,10 @@ #include #include "Common/Common.h" #include "Common/StringUtils.h" +#include "Common/Data/Convert/ColorConv.h" #include "GPU/Debugger/State.h" #include "GPU/GPU.h" +#include "GPU/Common/GPUStateUtils.h" #include "GPU/Common/GPUDebugInterface.h" #include "GPU/GeDisasm.h" #include "GPU/Common/VertexDecoderCommon.h" @@ -941,3 +943,146 @@ bool GetPrimPreview(u32 op, int which, GEPrimitiveType &prim, std::vector> 24) & 0xFF, ((pix >> 24) & 0xFF) * (1.0f / 255.0f)); + break; + + case GPU_DBG_FORMAT_FLOAT: + { + float pixf = *(float *)&pix; + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); + snprintf(desc, 256, "%d,%d: %f / %f", x, y, pixf, depthScale.DecodeToU16(pixf)); + break; + } + + case GPU_DBG_FORMAT_FLOAT_DIV_256: + { + double z = *(float *)&pix; + int z24 = (int)(z * 16777215.0); + + DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); + // TODO: Use GetDepthScaleFactors here too, verify it's the same. + int z16 = z24 - 0x800000 + 0x8000; + + int z16_2 = factors.DecodeToU16(z); + + snprintf(desc, 256, "%d,%d: %d / %f", x, y, z16, (z - 0.5 + (1.0 / 512.0)) * 256.0); + } + break; + + default: + snprintf(desc, 256, "Unexpected format"); + } +} + +void DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]) { + u32 r = -1, g = -1, b = -1, a = -1; + + switch (fmt) { + case GPU_DBG_FORMAT_565: + r = Convert5To8((pix >> 0) & 0x1F); + g = Convert6To8((pix >> 5) & 0x3F); + b = Convert5To8((pix >> 11) & 0x1F); + break; + case GPU_DBG_FORMAT_565_REV: + b = Convert5To8((pix >> 0) & 0x1F); + g = Convert6To8((pix >> 5) & 0x3F); + r = Convert5To8((pix >> 11) & 0x1F); + break; + case GPU_DBG_FORMAT_5551: + r = Convert5To8((pix >> 0) & 0x1F); + g = Convert5To8((pix >> 5) & 0x1F); + b = Convert5To8((pix >> 10) & 0x1F); + a = (pix >> 15) & 1 ? 255 : 0; + break; + case GPU_DBG_FORMAT_5551_REV: + a = pix & 1 ? 255 : 0; + b = Convert5To8((pix >> 1) & 0x1F); + g = Convert5To8((pix >> 6) & 0x1F); + r = Convert5To8((pix >> 11) & 0x1F); + break; + case GPU_DBG_FORMAT_5551_BGRA: + b = Convert5To8((pix >> 0) & 0x1F); + g = Convert5To8((pix >> 5) & 0x1F); + r = Convert5To8((pix >> 10) & 0x1F); + a = (pix >> 15) & 1 ? 255 : 0; + break; + case GPU_DBG_FORMAT_4444: + r = Convert4To8((pix >> 0) & 0x0F); + g = Convert4To8((pix >> 4) & 0x0F); + b = Convert4To8((pix >> 8) & 0x0F); + a = Convert4To8((pix >> 12) & 0x0F); + break; + case GPU_DBG_FORMAT_4444_REV: + a = Convert4To8((pix >> 0) & 0x0F); + b = Convert4To8((pix >> 4) & 0x0F); + g = Convert4To8((pix >> 8) & 0x0F); + r = Convert4To8((pix >> 12) & 0x0F); + break; + case GPU_DBG_FORMAT_4444_BGRA: + b = Convert4To8((pix >> 0) & 0x0F); + g = Convert4To8((pix >> 4) & 0x0F); + r = Convert4To8((pix >> 8) & 0x0F); + a = Convert4To8((pix >> 12) & 0x0F); + break; + case GPU_DBG_FORMAT_8888: + r = (pix >> 0) & 0xFF; + g = (pix >> 8) & 0xFF; + b = (pix >> 16) & 0xFF; + a = (pix >> 24) & 0xFF; + break; + case GPU_DBG_FORMAT_8888_BGRA: + b = (pix >> 0) & 0xFF; + g = (pix >> 8) & 0xFF; + r = (pix >> 16) & 0xFF; + a = (pix >> 24) & 0xFF; + break; + + default: + snprintf(desc, 256, "Unexpected format"); + return; + } + + snprintf(desc, 256, "%d,%d: r=%d, g=%d, b=%d, a=%d", x, y, r, g, b, a); +} diff --git a/GPU/Debugger/State.h b/GPU/Debugger/State.h index 1c311f5c1f70..5ac998a44332 100644 --- a/GPU/Debugger/State.h +++ b/GPU/Debugger/State.h @@ -8,6 +8,7 @@ #include "GPU/Debugger/GECommandTable.h" #include "GPU/Common/SplineCommon.h" +#include "GPU/Common/GPUDebugInterface.h" enum VertexListCols { VERTEXLIST_COL_X, @@ -45,3 +46,5 @@ void FormatVertColRaw(VertexDecoder *decoder, char *dest, size_t destSize, int r // Later I hope to re-use more of the real logic. bool GetPrimPreview(u32 op, int which, GEPrimitiveType &prim, std::vector &vertices, std::vector &indices, int &count); +void DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]); +void DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]); diff --git a/UI/ImDebugger/ImGe.cpp b/UI/ImDebugger/ImGe.cpp index 52fae575671c..96a5ac0bc461 100644 --- a/UI/ImDebugger/ImGe.cpp +++ b/UI/ImDebugger/ImGe.cpp @@ -243,6 +243,17 @@ void ImGeDisasmView::Draw(GPUDebugInterface *gpuDebug) { } } +static const char *DLStateToString(DisplayListState state) { + switch (state) { + case PSP_GE_DL_STATE_NONE: return "None"; + case PSP_GE_DL_STATE_QUEUED: return "Queued"; + case PSP_GE_DL_STATE_RUNNING: return "Running"; + case PSP_GE_DL_STATE_COMPLETED: return "Completed"; + case PSP_GE_DL_STATE_PAUSED: return "Paused"; + default: return "N/A (bad)"; + } +} + void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface *gpuDebug) { ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); if (!ImGui::Begin(Title(), &cfg.geDebuggerOpen)) { @@ -333,14 +344,17 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa const auto &list = gpuDebug->GetDisplayList(index); char title[64]; snprintf(title, sizeof(title), "List %d", list.id); - if (ImGui::CollapsingHeader(title, ImGuiTreeNodeFlags_DefaultOpen)) { + if (ImGui::CollapsingHeader(title)) { + ImGui::Text("State: %s", DLStateToString(list.state)); ImGui::TextUnformatted("PC:"); ImGui::SameLine(); ImClickableAddress(list.pc, control, ImCmd::SHOW_IN_GE_DISASM); ImGui::Text("StartPC:"); ImGui::SameLine(); ImClickableAddress(list.startpc, control, ImCmd::SHOW_IN_GE_DISASM); - ImGui::Text("Pending interrupt: %d", (int)list.pendingInterrupt); + if (list.pendingInterrupt) { + ImGui::TextUnformatted("(Pending interrupt)"); + } ImGui::Text("Stack depth: %d", (int)list.stackptr); ImGui::Text("BBOX result: %d", (int)list.bboxResult); } diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 19bf460eff4b..2878ad186734 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -53,6 +53,7 @@ #include "GPU/Debugger/Breakpoints.h" #include "GPU/Debugger/Debugger.h" #include "GPU/Debugger/Record.h" +#include "GPU/Debugger/State.h" #include "GPU/Debugger/Stepping.h" using namespace GPUBreakpoints; @@ -829,148 +830,6 @@ void CGEDebugger::SecondPreviewHover(int x, int y) { SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, w_desc); } -void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]) { - switch (fmt) { - case GPU_DBG_FORMAT_565: - case GPU_DBG_FORMAT_565_REV: - case GPU_DBG_FORMAT_5551: - case GPU_DBG_FORMAT_5551_REV: - case GPU_DBG_FORMAT_5551_BGRA: - case GPU_DBG_FORMAT_4444: - case GPU_DBG_FORMAT_4444_REV: - case GPU_DBG_FORMAT_4444_BGRA: - case GPU_DBG_FORMAT_8888: - case GPU_DBG_FORMAT_8888_BGRA: - DescribePixelRGBA(pix, fmt, x, y, desc); - break; - - case GPU_DBG_FORMAT_16BIT: - snprintf(desc, 256, "%d,%d: %d / %f", x, y, pix, pix * (1.0f / 65535.0f)); - break; - - case GPU_DBG_FORMAT_8BIT: - snprintf(desc, 256, "%d,%d: %d / %f", x, y, pix, pix * (1.0f / 255.0f)); - break; - - case GPU_DBG_FORMAT_24BIT_8X: - { - DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); - // These are only ever going to be depth values, so let's also show scaled to 16 bit. - snprintf(desc, 256, "%d,%d: %d / %f / %f", x, y, pix & 0x00FFFFFF, (pix & 0x00FFFFFF) * (1.0f / 16777215.0f), depthScale.DecodeToU16((pix & 0x00FFFFFF) * (1.0f / 16777215.0f))); - break; - } - - case GPU_DBG_FORMAT_24BIT_8X_DIV_256: - { - // These are only ever going to be depth values, so let's also show scaled to 16 bit. - int z24 = pix & 0x00FFFFFF; - int z16 = z24 - 0x800000 + 0x8000; - snprintf(desc, 256, "%d,%d: %d / %f", x, y, z16, z16 * (1.0f / 65535.0f)); - } - break; - - case GPU_DBG_FORMAT_24X_8BIT: - snprintf(desc, 256, "%d,%d: %d / %f", x, y, (pix >> 24) & 0xFF, ((pix >> 24) & 0xFF) * (1.0f / 255.0f)); - break; - - case GPU_DBG_FORMAT_FLOAT: { - float pixf = *(float *)&pix; - DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); - snprintf(desc, 256, "%d,%d: %f / %f", x, y, pixf, depthScale.DecodeToU16(pixf)); - break; - } - - case GPU_DBG_FORMAT_FLOAT_DIV_256: - { - double z = *(float *)&pix; - int z24 = (int)(z * 16777215.0); - - DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); - // TODO: Use GetDepthScaleFactors here too, verify it's the same. - int z16 = z24 - 0x800000 + 0x8000; - - int z16_2 = factors.DecodeToU16(z); - - snprintf(desc, 256, "%d,%d: %d / %f", x, y, z16, (z - 0.5 + (1.0 / 512.0)) * 256.0); - } - break; - - default: - snprintf(desc, 256, "Unexpected format"); - } -} - -void CGEDebugger::DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]) { - u32 r = -1, g = -1, b = -1, a = -1; - - switch (fmt) { - case GPU_DBG_FORMAT_565: - r = Convert5To8((pix >> 0) & 0x1F); - g = Convert6To8((pix >> 5) & 0x3F); - b = Convert5To8((pix >> 11) & 0x1F); - break; - case GPU_DBG_FORMAT_565_REV: - b = Convert5To8((pix >> 0) & 0x1F); - g = Convert6To8((pix >> 5) & 0x3F); - r = Convert5To8((pix >> 11) & 0x1F); - break; - case GPU_DBG_FORMAT_5551: - r = Convert5To8((pix >> 0) & 0x1F); - g = Convert5To8((pix >> 5) & 0x1F); - b = Convert5To8((pix >> 10) & 0x1F); - a = (pix >> 15) & 1 ? 255 : 0; - break; - case GPU_DBG_FORMAT_5551_REV: - a = pix & 1 ? 255 : 0; - b = Convert5To8((pix >> 1) & 0x1F); - g = Convert5To8((pix >> 6) & 0x1F); - r = Convert5To8((pix >> 11) & 0x1F); - break; - case GPU_DBG_FORMAT_5551_BGRA: - b = Convert5To8((pix >> 0) & 0x1F); - g = Convert5To8((pix >> 5) & 0x1F); - r = Convert5To8((pix >> 10) & 0x1F); - a = (pix >> 15) & 1 ? 255 : 0; - break; - case GPU_DBG_FORMAT_4444: - r = Convert4To8((pix >> 0) & 0x0F); - g = Convert4To8((pix >> 4) & 0x0F); - b = Convert4To8((pix >> 8) & 0x0F); - a = Convert4To8((pix >> 12) & 0x0F); - break; - case GPU_DBG_FORMAT_4444_REV: - a = Convert4To8((pix >> 0) & 0x0F); - b = Convert4To8((pix >> 4) & 0x0F); - g = Convert4To8((pix >> 8) & 0x0F); - r = Convert4To8((pix >> 12) & 0x0F); - break; - case GPU_DBG_FORMAT_4444_BGRA: - b = Convert4To8((pix >> 0) & 0x0F); - g = Convert4To8((pix >> 4) & 0x0F); - r = Convert4To8((pix >> 8) & 0x0F); - a = Convert4To8((pix >> 12) & 0x0F); - break; - case GPU_DBG_FORMAT_8888: - r = (pix >> 0) & 0xFF; - g = (pix >> 8) & 0xFF; - b = (pix >> 16) & 0xFF; - a = (pix >> 24) & 0xFF; - break; - case GPU_DBG_FORMAT_8888_BGRA: - b = (pix >> 0) & 0xFF; - g = (pix >> 8) & 0xFF; - r = (pix >> 16) & 0xFF; - a = (pix >> 24) & 0xFF; - break; - - default: - snprintf(desc, 256, "Unexpected format"); - return; - } - - snprintf(desc, 256, "%d,%d: r=%d, g=%d, b=%d, a=%d", x, y, r, g, b, a); -} - void CGEDebugger::UpdateTextureLevel(int level) { GPUgstate state{}; if (gpuDebug != nullptr) { diff --git a/Windows/GEDebugger/GEDebugger.h b/Windows/GEDebugger/GEDebugger.h index bb8b8e08ac4a..61d90107ef82 100644 --- a/Windows/GEDebugger/GEDebugger.h +++ b/Windows/GEDebugger/GEDebugger.h @@ -115,8 +115,6 @@ class CGEDebugger : public Dialog { void SecondPreviewHover(int x, int y); void PreviewExport(const GPUDebugBuffer *buffer); void PreviewToClipboard(const GPUDebugBuffer *buffer, bool saveAlpha); - static void DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]); - static void DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]); void UpdateMenus(); void UpdateTab(GEDebuggerTab *tab); void AddTab(GEDebuggerTab *tab, GETabPosition mask);