diff --git a/Core/Debugger/DisassemblyManager.cpp b/Core/Debugger/DisassemblyManager.cpp index b2d74ef5a1..16548279ba 100644 --- a/Core/Debugger/DisassemblyManager.cpp +++ b/Core/Debugger/DisassemblyManager.cpp @@ -1092,3 +1092,87 @@ bool DisassemblyComment::disassemble(u32 address, DisassemblyLineInfo &dest, boo dest.totalSize = size; return true; } + +bool GetDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData, bool displaySymbols) { + if (displaySymbols) { + const std::string addressSymbol = g_symbolMap->GetLabelString(address); + if (!addressSymbol.empty()) { + for (int k = 0; addressSymbol[k] != 0; k++) { + // abbreviate long names + if (abbreviateLabels && k == 16 && addressSymbol[k+1] != 0) { + *dest++ = '+'; + break; + } + *dest++ = addressSymbol[k]; + } + *dest++ = ':'; + *dest = 0; + return true; + } else { + sprintf(dest," %08X",address); + return false; + } + } else { + if (showData) { + u32 encoding = Memory::IsValidAddress(address) ? Memory::Read_Instruction(address, true).encoding : 0; + sprintf(dest, "%08X %08X", address, encoding); + } else { + sprintf(dest, "%08X", address); + } + return false; + } +} + +// Utilify function from the old debugger. +std::string DisassembleRange(u32 start, u32 size, bool displaySymbols, MIPSDebugInterface *debugger) { + auto memLock = Memory::Lock(); + std::string result; + + // gather all branch targets without labels + std::set branchAddresses; + for (u32 i = 0; i < size; i += debugger->getInstructionSize(0)) { + MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger, start + i); + + if (info.isBranch && g_symbolMap->GetLabelString(info.branchTarget).empty()) { + if (branchAddresses.find(info.branchTarget) == branchAddresses.end()) { + branchAddresses.insert(info.branchTarget); + } + } + } + + u32 disAddress = start; + bool previousLabel = true; + DisassemblyLineInfo line; + while (disAddress < start + size) { + char addressText[64], buffer[512]; + + g_disassemblyManager.getLine(disAddress, displaySymbols, line, debugger); + bool isLabel = GetDisasmAddressText(disAddress, addressText, false, line.type == DISTYPE_OPCODE, displaySymbols); + + if (isLabel) { + if (!previousLabel) + result += "\r\n"; + sprintf(buffer, "%s\r\n\r\n", addressText); + result += buffer; + } else if (branchAddresses.find(disAddress) != branchAddresses.end()) { + if (!previousLabel) + result += "\r\n"; + sprintf(buffer, "pos_%08X:\r\n\r\n", disAddress); + result += buffer; + } + + if (line.info.isBranch && !line.info.isBranchToRegister + && g_symbolMap->GetLabelString(line.info.branchTarget).empty() + && branchAddresses.find(line.info.branchTarget) != branchAddresses.end()) { + sprintf(buffer, "pos_%08X", line.info.branchTarget); + line.params = line.params.substr(0, line.params.find("0x")) + buffer; + } + + sprintf(buffer, "\t%s\t%s\r\n", line.name.c_str(), line.params.c_str()); + result += buffer; + previousLabel = isLabel; + disAddress += line.totalSize; + } + + return result; +} diff --git a/Core/Debugger/DisassemblyManager.h b/Core/Debugger/DisassemblyManager.h index 1478372eb2..720d3b6d67 100644 --- a/Core/Debugger/DisassemblyManager.h +++ b/Core/Debugger/DisassemblyManager.h @@ -226,3 +226,6 @@ extern DisassemblyManager g_disassemblyManager; bool isInInterval(u32 start, u32 size, u32 value); bool IsLikelyStringAt(uint32_t addr); + +std::string DisassembleRange(u32 start, u32 size, bool displaySymbols, MIPSDebugInterface *debugger); +bool GetDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData, bool displaySymbols); diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index 4b3418472b..6303e3ccc0 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -58,7 +58,7 @@ void ShowInMemoryViewerMenuItem(uint32_t addr, ImControl &control) { void ShowInMemoryDumperMenuItem(uint32_t addr, uint32_t size, MemDumpMode mode, ImControl &control) { if (ImGui::MenuItem(mode == MemDumpMode::Raw ? "Dump bytes to file..." : "Disassemble to file...")) { - control.command = { ImCmd::SHOW_IN_MEMORY_DUMPER, addr, size }; + control.command = { ImCmd::SHOW_IN_MEMORY_DUMPER, addr, size, (u32)mode}; } } @@ -1261,7 +1261,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu } if (cfg_.memDumpOpen) { - memDumpWindow_.Draw(cfg_); + memDumpWindow_.Draw(cfg_, mipsDebug); } for (int i = 0; i < 4; i++) { @@ -1302,7 +1302,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu case ImCmd::SHOW_IN_MEMORY_DUMPER: { cfg_.memDumpOpen = true; - memDumpWindow_.SetRange(control.command.param, control.command.param2); + memDumpWindow_.SetRange(control.command.param, control.command.param2, (MemDumpMode)control.command.param3); ImGui::SetWindowFocus(memDumpWindow_.Title()); break; } diff --git a/UI/ImDebugger/ImDisasmView.cpp b/UI/ImDebugger/ImDisasmView.cpp index 3fd883e480..d05a3d6582 100644 --- a/UI/ImDebugger/ImDisasmView.cpp +++ b/UI/ImDebugger/ImDisasmView.cpp @@ -53,33 +53,7 @@ bool ImDisasmView::getDisasmAddressText(u32 address, char* dest, bool abbreviate if (!PSP_IsInited()) return false; - if (displaySymbols_) { - const std::string addressSymbol = g_symbolMap->GetLabelString(address); - if (!addressSymbol.empty()) { - for (int k = 0; addressSymbol[k] != 0; k++) { - // abbreviate long names - if (abbreviateLabels && k == 16 && addressSymbol[k + 1] != 0) { - *dest++ = '+'; - break; - } - *dest++ = addressSymbol[k]; - } - *dest++ = ':'; - *dest = 0; - return true; - } else { - sprintf(dest, " %08X", address); - return false; - } - } else { - if (showData) { - u32 encoding = Memory::IsValidAddress(address) ? Memory::Read_Instruction(address, true).encoding : 0; - sprintf(dest, "%08X %08X", address, encoding); - } else { - sprintf(dest, "%08X", address); - } - return false; - } + return GetDisasmAddressText(address, dest, abbreviateLabels, showData, displaySymbols_); } void ImDisasmView::assembleOpcode(u32 address, const std::string &defaultText) { diff --git a/UI/ImDebugger/ImMemView.cpp b/UI/ImDebugger/ImMemView.cpp index 436690c038..f11e949404 100644 --- a/UI/ImDebugger/ImMemView.cpp +++ b/UI/ImDebugger/ImMemView.cpp @@ -841,7 +841,7 @@ void ImMemView::setHighlightType(MemBlockFlags flags) { } } -void ImMemDumpWindow::Draw(ImConfig &cfg) { +void ImMemDumpWindow::Draw(ImConfig &cfg, MIPSDebugInterface *debug) { ImGui::SetNextWindowSize(ImVec2(200, 300), ImGuiCond_FirstUseEver); if (!ImGui::Begin(Title(), &cfg.memDumpOpen)) { @@ -854,12 +854,19 @@ void ImMemDumpWindow::Draw(ImConfig &cfg) { size_ = 0x01800000; // 24MB } - ImGui::InputScalar("Starting address: ", ImGuiDataType_U32, &address_, NULL, NULL, "%08X"); - ImGui::InputScalar("Size: ", ImGuiDataType_U32, &size_, NULL, NULL, "%08X"); + ImGui::InputScalar("Starting address", ImGuiDataType_U32, &address_, NULL, NULL, "%08X"); + ImGui::InputScalar("Size", ImGuiDataType_U32, &size_, NULL, NULL, "%08X"); - ImGui::InputText("Filename: ", filename_, ARRAY_SIZE(filename_)); + ImGui::InputText("Filename", filename_, ARRAY_SIZE(filename_)); - if (ImGui::Button("Dump!")) { + const char* modes[] = { "Raw", "Disassembly" }; + int modeIndex = static_cast(mode_); + if (ImGui::Combo("Memory Dump Mode", &modeIndex, modes, IM_ARRAYSIZE(modes))) { + // Update the current mode if the user selects a new one + mode_ = static_cast(modeIndex); + } + + if (ImGui::Button(mode_ == MemDumpMode::Raw ? "Dump to file" : "Disassemble to file")) { uint32_t validSize = Memory::ValidSize(address_, size_); if (validSize != size_) { errorMsg_ = "Address range out of bounds"; @@ -873,10 +880,15 @@ void ImMemDumpWindow::Draw(ImConfig &cfg) { if (!file) { errorMsg_ = "Couldn't open file for writing"; } else { - const uint8_t *ptr = Memory::GetPointer(address_); - fwrite(ptr, 1, size_, file); - fclose(file); + if (mode_ == MemDumpMode::Raw) { + const uint8_t *ptr = Memory::GetPointer(address_); + fwrite(ptr, 1, size_, file); + } else { + std::string disassembly = DisassembleRange(address_, size_, true, debug); + fprintf(file, "%s", disassembly.c_str()); + } errorMsg_.clear(); + fclose(file); } } } diff --git a/UI/ImDebugger/ImMemView.h b/UI/ImDebugger/ImMemView.h index 5e2c7de520..750f64aa1c 100644 --- a/UI/ImDebugger/ImMemView.h +++ b/UI/ImDebugger/ImMemView.h @@ -134,15 +134,17 @@ public: static const char *Title() { return "Memory Dumper"; } - void Draw(ImConfig &cfg); - void SetRange(uint32_t addr, uint32_t size) { + void Draw(ImConfig &cfg, MIPSDebugInterface *debug); + void SetRange(uint32_t addr, uint32_t size, MemDumpMode mode) { address_ = addr; size_ = size; + mode_ = mode; } private: uint32_t address_; uint32_t size_; + MemDumpMode mode_ = MemDumpMode::Raw; char filename_[1024]; std::string errorMsg_; }; diff --git a/Windows/Debugger/CtrlDisAsmView.cpp b/Windows/Debugger/CtrlDisAsmView.cpp index dc8bfba1af..eb81d5bfc4 100644 --- a/Windows/Debugger/CtrlDisAsmView.cpp +++ b/Windows/Debugger/CtrlDisAsmView.cpp @@ -218,44 +218,6 @@ static COLORREF scaleColor(COLORREF color, float factor) return (color & 0xFF000000) | (b << 16) | (g << 8) | r; } -bool CtrlDisAsmView::getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData) -{ - if (!PSP_IsInited()) - return false; - - if (displaySymbols) - { - const std::string addressSymbol = g_symbolMap->GetLabelString(address); - if (!addressSymbol.empty()) - { - for (int k = 0; addressSymbol[k] != 0; k++) - { - // abbreviate long names - if (abbreviateLabels && k == 16 && addressSymbol[k+1] != 0) - { - *dest++ = '+'; - break; - } - *dest++ = addressSymbol[k]; - } - *dest++ = ':'; - *dest = 0; - return true; - } else { - sprintf(dest," %08X",address); - return false; - } - } else { - if (showData) { - u32 encoding = Memory::IsValidAddress(address) ? Memory::Read_Instruction(address, true).encoding : 0; - sprintf(dest, "%08X %08X", address, encoding); - } else { - sprintf(dest, "%08X", address); - } - return false; - } -} - std::string trimString(std::string input) { size_t pos = input.find_first_not_of(" \t"); @@ -567,7 +529,7 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam) SetTextColor(hdc,textColor); char addressText[64]; - getDisasmAddressText(address,addressText,true,line.type == DISTYPE_OPCODE); + GetDisasmAddressText(address,addressText,true,line.type == DISTYPE_OPCODE, displaySymbols); TextOutA(hdc,pixelPositions.addressStart,rowY1+2,addressText,(int)strlen(addressText)); if (isInInterval(address,line.totalSize,debugger->GetPC())) @@ -935,7 +897,7 @@ void CtrlDisAsmView::CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructio W32Util::CopyTextToClipboard(wnd, temp); delete [] temp; } else { - std::string disassembly = disassembleRange(startAddr,endAddr-startAddr); + std::string disassembly = DisassembleRange(startAddr,endAddr-startAddr, displaySymbols, debugger); W32Util::CopyTextToClipboard(wnd, disassembly.c_str()); } } @@ -1290,7 +1252,7 @@ void CtrlDisAsmView::search(bool continueSearch) g_disassemblyManager.getLine(searchAddress,displaySymbols,lineInfo, debugger); char addressText[64]; - getDisasmAddressText(searchAddress,addressText,true,lineInfo.type == DISTYPE_OPCODE); + GetDisasmAddressText(searchAddress,addressText,true,lineInfo.type == DISTYPE_OPCODE, displaySymbols); const char* opcode = lineInfo.name.c_str(); const char* arguments = lineInfo.params.c_str(); @@ -1330,65 +1292,6 @@ void CtrlDisAsmView::search(bool continueSearch) searching = false; } -std::string CtrlDisAsmView::disassembleRange(u32 start, u32 size) -{ - auto memLock = Memory::Lock(); - std::string result; - - // gather all branch targets without labels - std::set branchAddresses; - for (u32 i = 0; i < size; i += debugger->getInstructionSize(0)) - { - MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger,start+i); - - if (info.isBranch && g_symbolMap->GetLabelString(info.branchTarget).empty()) - { - if (branchAddresses.find(info.branchTarget) == branchAddresses.end()) - { - branchAddresses.insert(info.branchTarget); - } - } - } - - u32 disAddress = start; - bool previousLabel = true; - DisassemblyLineInfo line; - while (disAddress < start+size) - { - char addressText[64],buffer[512]; - - g_disassemblyManager.getLine(disAddress,displaySymbols,line, debugger); - bool isLabel = getDisasmAddressText(disAddress,addressText,false,line.type == DISTYPE_OPCODE); - - if (isLabel) - { - if (!previousLabel) result += "\r\n"; - sprintf(buffer,"%s\r\n\r\n",addressText); - result += buffer; - } else if (branchAddresses.find(disAddress) != branchAddresses.end()) - { - if (!previousLabel) result += "\r\n"; - sprintf(buffer,"pos_%08X:\r\n\r\n",disAddress); - result += buffer; - } - - if (line.info.isBranch && !line.info.isBranchToRegister - && g_symbolMap->GetLabelString(line.info.branchTarget).empty() - && branchAddresses.find(line.info.branchTarget) != branchAddresses.end()) - { - sprintf(buffer,"pos_%08X",line.info.branchTarget); - line.params = line.params.substr(0,line.params.find("0x")) + buffer; - } - - sprintf(buffer,"\t%s\t%s\r\n",line.name.c_str(),line.params.c_str()); - result += buffer; - previousLabel = isLabel; - disAddress += line.totalSize; - } - - return result; -} - void CtrlDisAsmView::disassembleToFile() { // get size u32 size; @@ -1408,7 +1311,7 @@ void CtrlDisAsmView::disassembleToFile() { return; } - std::string disassembly = disassembleRange(curAddress, size); + std::string disassembly = DisassembleRange(curAddress, size, displaySymbols, debugger); fprintf(output, "%s", disassembly.c_str()); fclose(output); diff --git a/Windows/Debugger/CtrlDisAsmView.h b/Windows/Debugger/CtrlDisAsmView.h index f227cb5aca..fe908ddad0 100644 --- a/Windows/Debugger/CtrlDisAsmView.h +++ b/Windows/Debugger/CtrlDisAsmView.h @@ -70,12 +70,10 @@ class CtrlDisAsmView }; void assembleOpcode(u32 address, const std::string &defaultText); - std::string disassembleRange(u32 start, u32 size); void disassembleToFile(); void search(bool continueSearch); void followBranch(); void calculatePixelPositions(); - bool getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData); void updateStatusBarText(); void drawBranchLine(HDC hdc, std::map &addressPositions, const BranchLine &line); void CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructionsMode mode);