diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 2290737f36..f58a2aca4f 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; @@ -57,7 +60,9 @@ void HLEInit() void HLEShutdown() { + hleAfterSyscall = HLE_AFTER_NOTHING; moduleDB.clear(); + unresolvedSyscalls.clear(); } void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable) @@ -239,7 +244,30 @@ void hleRunInterrupts() hleAfterSyscall |= HLE_AFTER_RUN_INTERRUPTS; } -inline void hleFinishSyscall() +void hleDebugBreak() +{ + hleAfterSyscall |= HLE_AFTER_DEBUG_BREAK; +} + +// Pauses execution after an HLE call. +bool 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 false; + } + + Core_EnableStepping(true); + host->SetDebugMode(true); + return true; +} + +inline void hleFinishSyscall(int modulenum, int funcnum) { if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0) __KernelForceCallbacks(); @@ -255,6 +283,17 @@ inline void hleFinishSyscall() 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; } @@ -276,7 +315,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(); 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); } } } 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 40f6f0e24f..3c69142866 100644 Binary files a/Windows/ppsspp.rc and b/Windows/ppsspp.rc differ 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