From d68d770c10483e51575f53e73ba56d6a302226cf Mon Sep 17 00:00:00 2001 From: Nicolas Pixel Noble Date: Mon, 22 Apr 2019 14:29:35 -0700 Subject: [PATCH] Debugger GUI --- src/core/debug.cc | 21 ++++-- src/core/debug.h | 21 ++++-- src/core/psxcounters.cc | 2 - src/core/r3000a.cc | 1 - src/gui/widgets/assembly.cc | 144 +++++++++++++++++++++++++++++++----- 5 files changed, 153 insertions(+), 36 deletions(-) diff --git a/src/core/debug.cc b/src/core/debug.cc index 875c7cc48..a321a25e4 100644 --- a/src/core/debug.cc +++ b/src/core/debug.cc @@ -88,32 +88,40 @@ void PCSX::Debug::DebugCheckBP(uint32_t address, BreakpointType type) { if (m_mapping_w16 && type == BW2) MarkMap(address, MAP_W16); if (m_mapping_w32 && type == BW4) MarkMap(address, MAP_W32); - for (auto& bp : m_breakpoints) { - if ((bp.m_type == type) && (bp.m_address == address)) { + for (auto it = m_breakpoints.begin(); it != m_breakpoints.end(); it++) { + if ((it->m_type == type) && (it->m_address == address)) { + m_lastBP = it; PCSX::g_system->pause(); return; } } if (m_breakmp_e && type == BE && !IsMapMarked(address, MAP_EXEC)) { + m_lastBP = m_breakpoints.end(); PCSX::g_system->pause(); return; } else if (m_breakmp_r8 && type == BR1 && !IsMapMarked(address, MAP_R8)) { + m_lastBP = m_breakpoints.end(); PCSX::g_system->pause(); return; } else if (m_breakmp_r16 && type == BR2 && !IsMapMarked(address, MAP_R16)) { + m_lastBP = m_breakpoints.end(); PCSX::g_system->pause(); return; } else if (m_breakmp_r32 && type == BR4 && !IsMapMarked(address, MAP_R32)) { + m_lastBP = m_breakpoints.end(); PCSX::g_system->pause(); return; } else if (m_breakmp_w8 && type == BW1 && !IsMapMarked(address, MAP_W8)) { + m_lastBP = m_breakpoints.end(); PCSX::g_system->pause(); return; } else if (m_breakmp_w16 && type == BW2 && !IsMapMarked(address, MAP_W16)) { + m_lastBP = m_breakpoints.end(); PCSX::g_system->pause(); return; } else if (m_breakmp_w32 && type == BW4 && !IsMapMarked(address, MAP_W32)) { + m_lastBP = m_breakpoints.end(); PCSX::g_system->pause(); return; } @@ -125,11 +133,11 @@ std::string PCSX::Debug::GenerateFlowIDC() { ss << "static main(void) {\r\n"; for (uint32_t i = 0; i < 0x00200000; i++) { if (IsMapMarked(i, MAP_EXEC_JAL)) { - ss << "\tMakeFunction(0X8" << std ::hex << std::setw(7) << std::setfill('0') << i << ", BADADDR);\r\n "; + ss << "\tMakeFunction(0X8" << std::hex << std::setw(7) << std::setfill('0') << i << ", BADADDR);\r\n "; } } ss << "}\r\n"; - return ss.str; + return ss.str(); } std::string PCSX::Debug::GenerateMarkIDC() { @@ -138,10 +146,9 @@ std::string PCSX::Debug::GenerateMarkIDC() { ss << "static main(void) {\r\n"; for (uint32_t i = 0; i < 0x00200000; i++) { if (IsMapMarked(i, MAP_EXEC)) { - ss << "\tMakeCode(0X8" << std ::hex << std::setw(7) << std::setfill('0') << i << ");\r\n"; + ss << "\tMakeCode(0X8" << std::hex << std::setw(7) << std::setfill('0') << i << ");\r\n"; } - } ss << "}\r\n"; - return ss.str; + return ss.str(); } diff --git a/src/core/debug.h b/src/core/debug.h index 94661359f..a4875b8e8 100644 --- a/src/core/debug.h +++ b/src/core/debug.h @@ -19,6 +19,7 @@ #pragma once +#include #include #include @@ -39,6 +40,8 @@ class Debug { class Breakpoint { public: + BreakpointType Type() const { return m_type; } + uint32_t Address() const { return m_address; } Breakpoint(uint32_t address, BreakpointType type) : m_address(address), m_type(type) {} private: @@ -48,18 +51,24 @@ class Debug { }; private: - using BreakpointList = std::list; - using bpiterator = BreakpointList::const_iterator; + typedef std::list BreakpointList; public: - bpiterator bpBegin() const { return m_breakpoints.cbegin(); } - bpiterator bpEnd() const { return m_breakpoints.cend(); } - void erase(bpiterator pos) { m_breakpoints.erase(pos); } + typedef BreakpointList::const_iterator bpiterator; + inline void AddBreakpoint(uint32_t address, BreakpointType type) { m_breakpoints.emplace_back(address, type); } + inline void ForEachBP(std::function lambda) { + for (auto i = m_breakpoints.begin(); i != m_breakpoints.end(); i++) { + if (!lambda(i)) return; + } + } + inline void EraseBP(bpiterator pos) { m_breakpoints.erase(pos); } + inline bool HasLastBP() { return m_lastBP != m_breakpoints.end(); } + inline bpiterator LastBP() { return m_lastBP; } private: BreakpointList m_breakpoints; + bpiterator m_lastBP = m_breakpoints.end(); - bool m_mapping_e = false; bool m_mapping_e = false; bool m_mapping_r8 = false, m_mapping_r16 = false, m_mapping_r32 = false; bool m_mapping_w8 = false, m_mapping_w16 = false, m_mapping_w32 = false; diff --git a/src/core/psxcounters.cc b/src/core/psxcounters.cc index dd42dc566..3536e961c 100644 --- a/src/core/psxcounters.cc +++ b/src/core/psxcounters.cc @@ -202,8 +202,6 @@ void PCSX::Counters::psxRcntUpdate() { PCSX::g_emulator.EmuUpdate(); } } - - PCSX::g_emulator.m_debug->DebugVSync(); } /******************************************************************************/ diff --git a/src/core/r3000a.cc b/src/core/r3000a.cc index e80e38411..46d4c13ea 100644 --- a/src/core/r3000a.cc +++ b/src/core/r3000a.cc @@ -41,7 +41,6 @@ int PCSX::R3000Acpu::psxInit() { } PGXP_Init(); - PCSX::g_emulator.m_debug->PauseDebugger(); return g_emulator.m_psxCpu->Init(); } diff --git a/src/gui/widgets/assembly.cc b/src/gui/widgets/assembly.cc index 689cec8fb..ef88ecb87 100644 --- a/src/gui/widgets/assembly.cc +++ b/src/gui/widgets/assembly.cc @@ -17,8 +17,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ +#include + #include "imgui.h" +#include "core/debug.h" #include "core/disr3000a.h" #include "core/psxmem.h" #include "core/r3000a.h" @@ -156,6 +159,18 @@ class ImGuiAsm : public PCSX::Disasm { sameLine(); ImGui::Text("0x%2.2x", value); } + inline uint8_t* ptr(uint32_t addr) { + uint8_t* lut = m_memory->g_psxMemRLUT[addr >> 16]; + if (lut) { + return lut + (addr & 0xffff); + } else { + static uint8_t dummy[4] = {0, 0, 0, 0}; + return dummy; + } + } + inline uint8_t mem8(uint32_t addr) { return *ptr(addr); } + inline uint16_t mem16(uint32_t addr) { return SWAP_LE16(*(int16_t*)ptr(addr)); } + inline uint32_t mem32(uint32_t addr) { return SWAP_LE32(*(int32_t*)ptr(addr)); } virtual void OfB(int16_t offset, uint8_t reg, int size) { comma(); sameLine(); @@ -166,13 +181,13 @@ class ImGuiAsm : public PCSX::Disasm { ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); switch (size) { case 1: - ImGui::Text("[%8.8x] = %2.2x", addr, psxMu8(addr)); + ImGui::Text("[%8.8x] = %2.2x", addr, mem8(addr)); break; case 2: - ImGui::Text("[%8.8x] = %4.4x", addr, psxMu16(addr)); + ImGui::Text("[%8.8x] = %4.4x", addr, mem16(addr)); break; case 4: - ImGui::Text("[%8.8x] = %8.8x", addr, psxMu32(addr)); + ImGui::Text("[%8.8x] = %8.8x", addr, mem32(addr)); break; } ImGui::PopTextWrapPos(); @@ -202,32 +217,121 @@ void PCSX::Widgets::Assembly::draw(psxRegisters* registers, Memory* memory, cons return; } - uint32_t pc = registers->pc & 0x1fffff; + DummyAsm dummy; + ImGuiAsm imguiAsm(registers, memory); + + uint32_t base = (registers->pc >> 20) & 0xffc; + uint32_t real = registers->pc & 0x1fffff; + uint32_t pc = real; + if ((base == 0x000) || (base == 0x800) || (base == 0xa00)) { + // main memory first + if (real >= 0x00200000) pc = 0; + } else if (base == 0x1f0) { + // parallel port second + if (real >= 0x00010000) { + pc = 0; + } else { + pc += 0x00200000; + } + } else if (base == 0xbfc) { + // bios last + if (real >= 0x00080000) { + pc = 0; + } else { + pc += 0x00210000; + } + } ImGui::Checkbox("Follow PC", &m_followPC); ImGui::BeginChild("##ScrollingRegion", ImVec2(0, 0), true, ImGuiWindowFlags_HorizontalScrollbar); - ImGuiListClipper clipper(2 * 1024 * 1024 / 4); + ImGuiListClipper clipper(0x00290000 / 4); + while (clipper.Step()) { bool skipNext = false; - if (clipper.DisplayStart != 0) { - uint32_t addr = clipper.DisplayStart * 4 - 4; - uint32_t code = *reinterpret_cast(memory->g_psxM + addr); + typedef std::function prependType; + auto process = [&](uint32_t addr, prependType prepend, PCSX::Disasm* disasm) { + uint32_t code = 0; uint32_t nextCode = 0; - if (addr <= 0x1ffff8) { - nextCode = *reinterpret_cast(memory->g_psxM + addr + 4); + uint32_t base = 0; + const char* section = "UNK"; + if (addr < 0x00200000) { + section = "RAM"; + code = *reinterpret_cast(memory->g_psxM + addr); + if (addr <= 0x001ffff8) { + nextCode = *reinterpret_cast(memory->g_psxM + addr + 4); + } + base = 0x80000000; + } else if (addr < 0x00210000) { + section = "PAR"; + addr -= 0x00200000; + code = *reinterpret_cast(memory->g_psxP + addr); + if (addr <= 0x0000fff8) { + nextCode = *reinterpret_cast(memory->g_psxP + addr); + } + base = 0x1f000000; + } else if (addr < 0x00290000) { + section = "ROM"; + addr -= 0x00210000; + code = *reinterpret_cast(memory->g_psxR + addr); + if (addr <= 0x0007fff8) { + nextCode = *reinterpret_cast(memory->g_psxR + addr); + } + base = 0xbfc00000; } - DummyAsm dummy; - dummy.process(code, nextCode, addr | 0x80000000, &skipNext); + prepend(code, section, addr | base); + disasm->process(code, nextCode, addr | base, &skipNext); + }; + if (clipper.DisplayStart != 0) { + uint32_t addr = clipper.DisplayStart * 4 - 4; + process(addr, [](uint32_t, const char*, uint32_t) {}, &dummy); } - ImGuiAsm imguiAsm(registers, memory); for (int x = clipper.DisplayStart; x < clipper.DisplayEnd; x++) { uint32_t addr = x * 4; - uint32_t code = *reinterpret_cast(memory->g_psxM + addr); - uint32_t nextCode = 0; - if (addr <= 0x1ffff8) { - nextCode = *reinterpret_cast(memory->g_psxM + addr + 4); - } - ImGui::Text("%c %8.8x %8.8x: ", addr == pc ? '>' : ' ', addr | 0x80000000, code); - imguiAsm.process(code, nextCode, addr | 0x80000000, &skipNext); + Debug::bpiterator currentBP; + prependType l = [&](uint32_t code, const char* section, uint32_t dispAddr) { + bool hasBP = false; + PCSX::g_emulator.m_debug->ForEachBP([&](PCSX::Debug::bpiterator it) mutable { + uint32_t addr = dispAddr; + uint32_t bpAddr = it->Address(); + uint32_t base = (addr >> 20) & 0xffc; + uint32_t bpBase = (bpAddr >> 20) & 0xffc; + if ((base == 0x000) || (base == 0x800) || (base == 0xa00)) { + addr &= 0x1fffff; + } + if ((bpBase == 0x000) || (bpBase == 0x800) || (bpBase == 0xa00)) { + bpAddr &= 0x1fffff; + } + if ((it->Type() == Debug::BE) && (addr == bpAddr)) { + hasBP = true; + currentBP = it; + return false; + } + return true; + }); + + char p = ' '; + if (addr == pc) p = '>'; + if (hasBP) p = 'o'; + if (addr == pc && hasBP) p = 'X'; + + ImGui::Text("%c %s:%8.8x %8.8x: ", p, section, dispAddr, code); + std::string contextMenuTitle = "assembly address menu "; + contextMenuTitle += dispAddr; + if (ImGui::BeginPopupContextItem(contextMenuTitle.c_str())) { + if (hasBP) { + if (ImGui::Button("Remove breakpoint from here")) { + PCSX::g_emulator.m_debug->EraseBP(currentBP); + hasBP = false; + } + } else { + if (ImGui::Button("Set Breakpoint here")) { + PCSX::g_emulator.m_debug->AddBreakpoint(dispAddr, Debug::BE); + hasBP = true; + } + } + ImGui::EndPopup(); + } + }; + process(addr, l, &imguiAsm); } } if (m_followPC) {