From a0000a85472e05005d9e85eaad54fc85d8a25926 Mon Sep 17 00:00:00 2001 From: Ty Lamontagne Date: Sat, 14 Jan 2023 22:29:42 -0500 Subject: [PATCH] Debugger: Implement boot and debug Creates a breakpoint automatically on the ELF entry point --- pcsx2-qt/Debugger/DebuggerWindow.cpp | 22 +++--- pcsx2-qt/MainWindow.cpp | 1 + pcsx2/DebugTools/Breakpoints.cpp | 11 ++- pcsx2/DebugTools/DebugInterface.cpp | 2 + pcsx2/DebugTools/DebugInterface.h | 6 ++ pcsx2/R5900OpcodeImpl.cpp | 109 +++++++++++++++------------ pcsx2/R5900OpcodeTables.h | 1 + 7 files changed, 92 insertions(+), 60 deletions(-) diff --git a/pcsx2-qt/Debugger/DebuggerWindow.cpp b/pcsx2-qt/Debugger/DebuggerWindow.cpp index b723e85f5b..734f52e7e8 100644 --- a/pcsx2-qt/Debugger/DebuggerWindow.cpp +++ b/pcsx2-qt/Debugger/DebuggerWindow.cpp @@ -88,16 +88,18 @@ void DebuggerWindow::onVMStateChanged() m_actionStepInto->setEnabled(true); m_actionStepOver->setEnabled(true); m_actionStepOut->setEnabled(true); - CBreakPoints::ClearTemporaryBreakPoints(); - - if (CBreakPoints::GetBreakpointTriggered()) - { - CBreakPoints::SetBreakpointTriggered(false); - // Our current PC is on a breakpoint. - // When we run the core again, we want to skip this breakpoint and run - CBreakPoints::SetSkipFirst(BREAKPOINT_EE, r5900Debug.getPC()); - CBreakPoints::SetSkipFirst(BREAKPOINT_IOP, r3000Debug.getPC()); - } + Host::RunOnCPUThread([] { + if (CBreakPoints::GetBreakpointTriggered()) + { + CBreakPoints::ClearTemporaryBreakPoints(); + CBreakPoints::SetBreakpointTriggered(false); + // Our current PC is on a breakpoint. + // When we run the core again, we want to skip this breakpoint and run + CBreakPoints::SetSkipFirst(BREAKPOINT_EE, r5900Debug.getPC()); + CBreakPoints::SetSkipFirst(BREAKPOINT_IOP, r3000Debug.getPC()); + } + }); + } return; } diff --git a/pcsx2-qt/MainWindow.cpp b/pcsx2-qt/MainWindow.cpp index 3a564834c4..9117342303 100644 --- a/pcsx2-qt/MainWindow.cpp +++ b/pcsx2-qt/MainWindow.cpp @@ -1489,6 +1489,7 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point) { // TODO: Hook this up once it's implemented. action = menu.addAction(tr("Boot and Debug")); + connect(action, &QAction::triggered, [this, entry]() { DebugInterface::setPauseOnEntry(true); startGameListEntry(entry); getDebuggerWindow()->show(); }); } menu.addSeparator(); diff --git a/pcsx2/DebugTools/Breakpoints.cpp b/pcsx2/DebugTools/Breakpoints.cpp index c1bfabafaf..6b2e95bd23 100644 --- a/pcsx2/DebugTools/Breakpoints.cpp +++ b/pcsx2/DebugTools/Breakpoints.cpp @@ -19,6 +19,7 @@ #include "MIPSAnalyst.h" #include #include "R5900.h" +#include "R3000A.h" #include "System.h" std::vector CBreakPoints::breakPoints_; @@ -432,7 +433,15 @@ void CBreakPoints::Update(BreakPointCpu cpu, u32 addr) resume = true; } - SysClearExecutionCache(); + if (cpu & BREAKPOINT_EE) + { + Cpu->Reset(); + } + + if (cpu & BREAKPOINT_IOP) + { + psxCpu->Reset(); + } if (resume) r5900Debug.resumeCpu(); diff --git a/pcsx2/DebugTools/DebugInterface.cpp b/pcsx2/DebugTools/DebugInterface.cpp index 8608596e4e..89dd345436 100644 --- a/pcsx2/DebugTools/DebugInterface.cpp +++ b/pcsx2/DebugTools/DebugInterface.cpp @@ -217,6 +217,8 @@ private: // DebugInterface // +bool DebugInterface::m_pause_on_entry = false; + bool DebugInterface::isAlive() { return VMManager::HasValidVM() && g_FrameCount > 0; diff --git a/pcsx2/DebugTools/DebugInterface.h b/pcsx2/DebugTools/DebugInterface.h index 3eef482ddd..299ecd11c9 100644 --- a/pcsx2/DebugTools/DebugInterface.h +++ b/pcsx2/DebugTools/DebugInterface.h @@ -92,6 +92,12 @@ public: void pauseCpu(); void resumeCpu(); char* stringFromPointer(u32 p); + + static void setPauseOnEntry(bool pauseOnEntry) { m_pause_on_entry = pauseOnEntry; }; + static bool getPauseOnEntry() { return m_pause_on_entry; } + +private: + static bool m_pause_on_entry; }; class R5900DebugInterface : public DebugInterface diff --git a/pcsx2/R5900OpcodeImpl.cpp b/pcsx2/R5900OpcodeImpl.cpp index c9908b83cd..644e10601e 100644 --- a/pcsx2/R5900OpcodeImpl.cpp +++ b/pcsx2/R5900OpcodeImpl.cpp @@ -25,6 +25,8 @@ #include "GS.h" #include "CDVD/CDVD.h" #include "ps2/BiosTools.h" +#include "DebugTools/DebugInterface.h" +#include "DebugTools/Breakpoints.h" GS_VideoMode gsVideoMode = GS_VideoMode::Uninitialized; bool gsIsInterlaced = false; @@ -884,64 +886,73 @@ void SYSCALL() { case Syscall::SetGsCrt: { - //Function "SetGsCrt(Interlace, Mode, Field)" - //Useful for fetching information of interlace/video/field display parameters of the Graphics Synthesizer + //Function "SetGsCrt(Interlace, Mode, Field)" + //Useful for fetching information of interlace/video/field display parameters of the Graphics Synthesizer - gsIsInterlaced = cpuRegs.GPR.n.a0.UL[0] & 1; - bool gsIsFrameMode = cpuRegs.GPR.n.a2.UL[0] & 1; - const char* inter = (gsIsInterlaced) ? "Interlaced" : "Progressive"; - const char* field = (gsIsFrameMode) ? "FRAME" : "FIELD"; - std::string mode; - // Warning info might be incorrect! - switch (cpuRegs.GPR.n.a1.UC[0]) - { - case 0x0: - case 0x2: - mode = "NTSC 640x448 @ 59.940 (59.82)"; gsSetVideoMode(GS_VideoMode::NTSC); break; + gsIsInterlaced = cpuRegs.GPR.n.a0.UL[0] & 1; + bool gsIsFrameMode = cpuRegs.GPR.n.a2.UL[0] & 1; + const char* inter = (gsIsInterlaced) ? "Interlaced" : "Progressive"; + const char* field = (gsIsFrameMode) ? "FRAME" : "FIELD"; + std::string mode; + // Warning info might be incorrect! + switch (cpuRegs.GPR.n.a1.UC[0]) + { + case 0x0: + case 0x2: + mode = "NTSC 640x448 @ 59.940 (59.82)"; gsSetVideoMode(GS_VideoMode::NTSC); break; - case 0x1: - case 0x3: - mode = "PAL 640x512 @ 50.000 (49.76)"; gsSetVideoMode(GS_VideoMode::PAL); break; + case 0x1: + case 0x3: + mode = "PAL 640x512 @ 50.000 (49.76)"; gsSetVideoMode(GS_VideoMode::PAL); break; - case 0x1A: mode = "VESA 640x480 @ 59.940"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x1B: mode = "VESA 640x480 @ 72.809"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x1C: mode = "VESA 640x480 @ 75.000"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x1D: mode = "VESA 640x480 @ 85.008"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x1A: mode = "VESA 640x480 @ 59.940"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x1B: mode = "VESA 640x480 @ 72.809"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x1C: mode = "VESA 640x480 @ 75.000"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x1D: mode = "VESA 640x480 @ 85.008"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x2A: mode = "VESA 800x600 @ 56.250"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x2B: mode = "VESA 800x600 @ 60.317"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x2C: mode = "VESA 800x600 @ 72.188"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x2D: mode = "VESA 800x600 @ 75.000"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x2E: mode = "VESA 800x600 @ 85.061"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x2A: mode = "VESA 800x600 @ 56.250"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x2B: mode = "VESA 800x600 @ 60.317"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x2C: mode = "VESA 800x600 @ 72.188"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x2D: mode = "VESA 800x600 @ 75.000"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x2E: mode = "VESA 800x600 @ 85.061"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x3B: mode = "VESA 1024x768 @ 60.004"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x3C: mode = "VESA 1024x768 @ 70.069"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x3D: mode = "VESA 1024x768 @ 75.029"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x3E: mode = "VESA 1024x768 @ 84.997"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x3B: mode = "VESA 1024x768 @ 60.004"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x3C: mode = "VESA 1024x768 @ 70.069"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x3D: mode = "VESA 1024x768 @ 75.029"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x3E: mode = "VESA 1024x768 @ 84.997"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x4A: mode = "VESA 1280x1024 @ 63.981"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x4B: mode = "VESA 1280x1024 @ 79.976"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x4A: mode = "VESA 1280x1024 @ 63.981"; gsSetVideoMode(GS_VideoMode::VESA); break; + case 0x4B: mode = "VESA 1280x1024 @ 79.976"; gsSetVideoMode(GS_VideoMode::VESA); break; - case 0x50: mode = "SDTV 720x480 @ 59.94"; gsSetVideoMode(GS_VideoMode::SDTV_480P); break; - case 0x51: mode = "HDTV 1920x1080 @ 60.00"; gsSetVideoMode(GS_VideoMode::HDTV_1080I); break; - case 0x52: mode = "HDTV 1280x720 @ ??.???"; gsSetVideoMode(GS_VideoMode::HDTV_720P); break; - case 0x53: mode = "SDTV 768x576 @ ??.???"; gsSetVideoMode(GS_VideoMode::SDTV_576P); break; - case 0x54: mode = "HDTV 1920x1080 @ ??.???"; gsSetVideoMode(GS_VideoMode::HDTV_1080P); break; + case 0x50: mode = "SDTV 720x480 @ 59.94"; gsSetVideoMode(GS_VideoMode::SDTV_480P); break; + case 0x51: mode = "HDTV 1920x1080 @ 60.00"; gsSetVideoMode(GS_VideoMode::HDTV_1080I); break; + case 0x52: mode = "HDTV 1280x720 @ ??.???"; gsSetVideoMode(GS_VideoMode::HDTV_720P); break; + case 0x53: mode = "SDTV 768x576 @ ??.???"; gsSetVideoMode(GS_VideoMode::SDTV_576P); break; + case 0x54: mode = "HDTV 1920x1080 @ ??.???"; gsSetVideoMode(GS_VideoMode::HDTV_1080P); break; - case 0x72: - case 0x82: - mode = "DVD NTSC 640x448 @ ??.???"; gsSetVideoMode(GS_VideoMode::DVD_NTSC); break; - case 0x73: - case 0x83: - mode = "DVD PAL 720x480 @ ??.???"; gsSetVideoMode(GS_VideoMode::DVD_PAL); break; + case 0x72: + case 0x82: + mode = "DVD NTSC 640x448 @ ??.???"; gsSetVideoMode(GS_VideoMode::DVD_NTSC); break; + case 0x73: + case 0x83: + mode = "DVD PAL 720x480 @ ??.???"; gsSetVideoMode(GS_VideoMode::DVD_PAL); break; - default: - DevCon.Error("Mode %x is not supported. Report me upstream", cpuRegs.GPR.n.a1.UC[0]); - gsSetVideoMode(GS_VideoMode::Unknown); - } - DevCon.Warning("Set GS CRTC configuration. %s %s (%s)",mode.c_str(), inter, field); - } - break; + default: + DevCon.Error("Mode %x is not supported. Report me upstream", cpuRegs.GPR.n.a1.UC[0]); + gsSetVideoMode(GS_VideoMode::Unknown); + } + DevCon.Warning("Set GS CRTC configuration. %s %s (%s)",mode.c_str(), inter, field); + } + break; + case Syscall::ExecPS2: + { + if (DebugInterface::getPauseOnEntry()) + { + CBreakPoints::AddBreakPoint(BREAKPOINT_EE, cpuRegs.GPR.n.a0.UL[0], true); + DebugInterface::setPauseOnEntry(false); + } + } + break; case Syscall::SetOsdConfigParam: AllowParams1 = true; break; diff --git a/pcsx2/R5900OpcodeTables.h b/pcsx2/R5900OpcodeTables.h index c279d600a3..9067ee4d65 100644 --- a/pcsx2/R5900OpcodeTables.h +++ b/pcsx2/R5900OpcodeTables.h @@ -19,6 +19,7 @@ enum Syscall : u8 { SetGsCrt = 2, + ExecPS2 = 7, SetVTLBRefillHandler = 13, StartThread = 34, ChangeThreadPriority = 41,