From b8ae91237e1d55ffe8da2fac86ced7f1e94ba4cf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 21:04:28 -0800 Subject: [PATCH 1/5] Oops, missed some state in HLE to reset. --- Core/HLE/HLE.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 2290737f36..7812209467 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -57,7 +57,9 @@ void HLEInit() void HLEShutdown() { + hleAfterSyscall = HLE_AFTER_NOTHING; moduleDB.clear(); + unresolvedSyscalls.clear(); } void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable) From dc21d5c462d0d9daf8e6c976306d228a3844d71b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 21:47:54 -0800 Subject: [PATCH 2/5] Add a mechanism for HLE to trigger a debug break. --- Core/HLE/HLE.cpp | 32 ++++++++++++++++++++++++++++++-- Core/HLE/HLE.h | 2 ++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 7812209467..dd9fe56a1a 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -28,6 +28,7 @@ #include "sceKernelThread.h" #include "sceKernelInterrupt.h" #include "../MIPS/MIPSCodeUtils.h" +#include "../Host.h" enum { @@ -43,6 +44,8 @@ enum HLE_AFTER_RESCHED_CALLBACKS = 0x08, // Run interrupts (and probably reschedule) after the syscall. HLE_AFTER_RUN_INTERRUPTS = 0x10, + // Switch to CORE_STEPPING after the syscall (for debugging.) + HLE_AFTER_DEBUG_BREAK = 0x20, }; static std::vector moduleDB; @@ -241,8 +244,33 @@ void hleRunInterrupts() hleAfterSyscall |= HLE_AFTER_RUN_INTERRUPTS; } -inline void hleFinishSyscall() +void hleDebugBreak() { + hleAfterSyscall |= HLE_AFTER_DEBUG_BREAK; +} + +// Pauses execution after an HLE call. +void hleExecuteDebugBreak(const HLEFunction &func) +{ + const u32 NID_SUSPEND_INTR = 0x092968F4, NID_RESUME_INTR = 0x5F10D406; + + // Never break on these, they're noise. + u32 blacklistedNIDs[] = {NID_SUSPEND_INTR, NID_RESUME_INTR, NID_IDLE}; + for (int i = 0; i < ARRAY_SIZE(blacklistedNIDs); ++i) + { + if (func.ID == blacklistedNIDs[i]) + return; + } + + Core_EnableStepping(true); + host->SetDebugMode(true); +} + +inline void hleFinishSyscall(int modulenum, int funcnum) +{ + if ((hleAfterSyscall & HLE_AFTER_DEBUG_BREAK) != 0) + hleExecuteDebugBreak(moduleDB[modulenum].funcTable[funcnum]); + if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0) __KernelForceCallbacks(); @@ -278,7 +306,7 @@ void CallSyscall(u32 op) func(); if (hleAfterSyscall != HLE_AFTER_NOTHING) - hleFinishSyscall(); + hleFinishSyscall(modulenum, funcnum); } else { diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index 05ff70c612..fb0eefa1be 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -83,6 +83,8 @@ void hleReSchedule(const char *reason); void hleReSchedule(bool callbacks, const char *reason); // Run interrupts after the syscall finishes. void hleRunInterrupts(); +// Pause emulation after the syscall finishes. +void hleDebugBreak(); void HLEInit(); void HLEShutdown(); From 1d7a42f0b8b82999ccb9b6edcd8ebcce0edd409d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 21:48:19 -0800 Subject: [PATCH 3/5] Add a button on Windows to enable HLE stepping. --- Windows/Debugger/Debugger_Disasm.cpp | 33 +++++++++++++++++++-------- Windows/ppsspp.rc | Bin 28756 -> 28864 bytes Windows/resource.h | 3 ++- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Windows/Debugger/Debugger_Disasm.cpp b/Windows/Debugger/Debugger_Disasm.cpp index b326bc75bc..6d2097f1ee 100644 --- a/Windows/Debugger/Debugger_Disasm.cpp +++ b/Windows/Debugger/Debugger_Disasm.cpp @@ -14,6 +14,7 @@ #include "../../Core/Core.h" #include "../../Core/CPU.h" +#include "../../Core/HLE/HLE.h" #include "base/stringutil.h" @@ -136,10 +137,10 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) break; case IDC_FUNCTIONLIST: - switch (HIWORD(wParam)) - { - case CBN_DBLCLK: - case CBN_SELCHANGE: + switch (HIWORD(wParam)) + { + case CBN_DBLCLK: + case CBN_SELCHANGE: { HWND lb = GetDlgItem(m_hDlg,LOWORD(wParam)); int n = ListBox_GetCurSel(lb); @@ -154,9 +155,9 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) break; case IDC_GOTOINT: - switch (HIWORD(wParam)) - { - case LBN_SELCHANGE: + switch (HIWORD(wParam)) + { + case LBN_SELCHANGE: { HWND lb =GetDlgItem(m_hDlg,LOWORD(wParam)); int n = ComboBox_GetCurSel(lb); @@ -192,7 +193,7 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) SetDebugMode(false); CBreakPoints::AddBreakPoint(cpu->GetPC()+cpu->getInstructionSize(0),true); _dbg_update_(); - Core_EnableStepping(false); + Core_EnableStepping(false); MainWindow::UpdateMenus(); Sleep(1); ptr->gotoPC(); @@ -200,6 +201,16 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) } break; + case IDC_STEPHLE: + { + hleDebugBreak(); + SetDebugMode(false); + _dbg_update_(); + Core_EnableStepping(false); + MainWindow::UpdateMenus(); + } + break; + case IDC_STOP: { SetDebugMode(true); @@ -241,8 +252,8 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) HWND list = GetDlgItem(hDlg,IDC_CALLSTACK); ComboBox_ResetContent(list); - u32 pc = currentMIPS->pc; - u32 ra = currentMIPS->r[MIPS_REG_RA]; + u32 pc = currentMIPS->pc; + u32 ra = currentMIPS->r[MIPS_REG_RA]; DWORD addr = Memory::ReadUnchecked_U32(pc); int count=1; ComboBox_SetItemData(list,ComboBox_AddString(list,symbolMap.GetDescription(pc)),pc); @@ -341,6 +352,7 @@ void CDisasm::SetDebugMode(bool _bDebug) EnableWindow( GetDlgItem(hDlg, IDC_GO), TRUE); EnableWindow( GetDlgItem(hDlg, IDC_STEP), TRUE); EnableWindow( GetDlgItem(hDlg, IDC_STEPOVER), TRUE); + EnableWindow( GetDlgItem(hDlg, IDC_STEPHLE), TRUE); EnableWindow( GetDlgItem(hDlg, IDC_STOP), FALSE); EnableWindow( GetDlgItem(hDlg, IDC_SKIP), TRUE); CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); @@ -353,6 +365,7 @@ void CDisasm::SetDebugMode(bool _bDebug) EnableWindow( GetDlgItem(hDlg, IDC_GO), FALSE); EnableWindow( GetDlgItem(hDlg, IDC_STEP), FALSE); EnableWindow( GetDlgItem(hDlg, IDC_STEPOVER), FALSE); + EnableWindow( GetDlgItem(hDlg, IDC_STEPHLE), FALSE); EnableWindow( GetDlgItem(hDlg, IDC_STOP), TRUE); EnableWindow( GetDlgItem(hDlg, IDC_SKIP), FALSE); } diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 40f6f0e24f4608edab308ad315a56c3577fc3b70..3c691428661e75dc9a4105a434f708ed81e8a7dd 100644 GIT binary patch delta 84 zcmccefbqaX#tkZ*jGU7j*_Dm`7*ZK37)lrv7}OX%76usMbELmB`x$P-Nf delta 21 dcmX@`knzd`#tkZ*lkc!|O!i~bSbTsp9RO+K2$cW; diff --git a/Windows/resource.h b/Windows/resource.h index 09a16838bb..134447f2a5 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -246,13 +246,14 @@ #define ID_OPTIONS_WIREFRAME 40123 #define ID_OPTIONS_HARDWARETRANSFORM 40124 #define ID_OPTIONS_FASTMEMORY 40125 +#define IDC_STEPHLE 40126 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 232 -#define _APS_NEXT_COMMAND_VALUE 40126 +#define _APS_NEXT_COMMAND_VALUE 40127 #define _APS_NEXT_CONTROL_VALUE 1162 #define _APS_NEXT_SYMED_VALUE 101 #endif From 6a6db5f53a558ebab998e37a1fe26c72b912dc30 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 21:58:54 -0800 Subject: [PATCH 4/5] Remember to break on HLE after an ignored syscall. --- Core/HLE/HLE.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index dd9fe56a1a..f58a2aca4f 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -250,7 +250,7 @@ void hleDebugBreak() } // Pauses execution after an HLE call. -void hleExecuteDebugBreak(const HLEFunction &func) +bool hleExecuteDebugBreak(const HLEFunction &func) { const u32 NID_SUSPEND_INTR = 0x092968F4, NID_RESUME_INTR = 0x5F10D406; @@ -259,18 +259,16 @@ void hleExecuteDebugBreak(const HLEFunction &func) for (int i = 0; i < ARRAY_SIZE(blacklistedNIDs); ++i) { if (func.ID == blacklistedNIDs[i]) - return; + return false; } Core_EnableStepping(true); host->SetDebugMode(true); + return true; } inline void hleFinishSyscall(int modulenum, int funcnum) { - if ((hleAfterSyscall & HLE_AFTER_DEBUG_BREAK) != 0) - hleExecuteDebugBreak(moduleDB[modulenum].funcTable[funcnum]); - if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0) __KernelForceCallbacks(); @@ -285,6 +283,17 @@ inline void hleFinishSyscall(int modulenum, int funcnum) else if ((hleAfterSyscall & HLE_AFTER_ALL_CALLBACKS) != 0) __KernelCheckCallbacks(); + if ((hleAfterSyscall & HLE_AFTER_DEBUG_BREAK) != 0) + { + if (!hleExecuteDebugBreak(moduleDB[modulenum].funcTable[funcnum])) + { + // We'll do it next syscall. + hleAfterSyscall = HLE_AFTER_DEBUG_BREAK; + hleAfterSyscallReschedReason[0] = 0; + return; + } + } + hleAfterSyscall = HLE_AFTER_NOTHING; hleAfterSyscallReschedReason[0] = 0; } From b8fcdc37e653c2e5d2e422ea68d3564a6c783cc5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 22:12:52 -0800 Subject: [PATCH 5/5] When not ignoring bad mem access, break to debug. --- Core/MemMapFunctions.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Core/MemMapFunctions.cpp b/Core/MemMapFunctions.cpp index e468e79a51..faa0e5fa18 100644 --- a/Core/MemMapFunctions.cpp +++ b/Core/MemMapFunctions.cpp @@ -20,6 +20,7 @@ #include "MemMap.h" #include "Config.h" +#include "Host.h" #include "MIPS/MIPS.h" @@ -84,8 +85,8 @@ inline void ReadFromHardware(T &var, const u32 address) { WARN_LOG(MEMMAP, "ReadFromHardware: Invalid address %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); if (!g_Config.bIgnoreBadMemAccess) { - // TODO: Not sure what the best way to crash is... - exit(0); + Core_EnableStepping(true); + host->SetDebugMode(true); } var = 0; } @@ -112,8 +113,8 @@ inline void WriteToHardware(u32 address, const T data) { WARN_LOG(MEMMAP, "WriteToHardware: Invalid address %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); if (!g_Config.bIgnoreBadMemAccess) { - // TODO: Not sure what the best way to crash is... - exit(0); + Core_EnableStepping(true); + host->SetDebugMode(true); } } }