diff --git a/Source/Project64/UserInterface/Debugger/Breakpoints.cpp b/Source/Project64/UserInterface/Debugger/Breakpoints.cpp index 86c367b19..2ede9595b 100644 --- a/Source/Project64/UserInterface/Debugger/Breakpoints.cpp +++ b/Source/Project64/UserInterface/Debugger/Breakpoints.cpp @@ -18,6 +18,7 @@ #include CBreakpoints::CBreakpoints() : + m_bHaveRegBP(false), m_GPRWriteBP(0), m_GPRReadBP(0), m_HIWriteBP(false), @@ -359,22 +360,17 @@ size_t CBreakpoints::NumMemLocks() return m_MemLocks.size(); } -bool CBreakpoints::HaveAnyGPRWriteBP(void) { return m_GPRWriteBP != 0; } -bool CBreakpoints::HaveAnyGPRReadBP(void) { return m_GPRReadBP != 0; } -bool CBreakpoints::HaveGPRWriteBP(int nReg) { return (m_GPRWriteBP & (1 << nReg)) != 0; } -bool CBreakpoints::HaveGPRReadBP(int nReg) { return (m_GPRReadBP & (1 << nReg)) != 0; } -void CBreakpoints::ToggleGPRWriteBP(int nReg) { m_GPRWriteBP ^= (1 << nReg); } -void CBreakpoints::ToggleGPRReadBP(int nReg) { m_GPRReadBP ^= (1 << nReg); } +void CBreakpoints::UpdateHaveRegBP(void) +{ + m_bHaveRegBP = HaveAnyGPRWriteBP() || HaveAnyGPRReadBP() || HaveHIWriteBP() || HaveHIReadBP() || HaveLOWriteBP() || HaveLOReadBP(); +} -bool CBreakpoints::HaveHIWriteBP(void) { return m_HIWriteBP; } -bool CBreakpoints::HaveHIReadBP(void) { return m_HIReadBP; } -bool CBreakpoints::HaveLOWriteBP(void) { return m_LOWriteBP; } -bool CBreakpoints::HaveLOReadBP(void) { return m_LOReadBP; } - -void CBreakpoints::ToggleHIWriteBP(void) { m_HIWriteBP = !m_HIWriteBP; } -void CBreakpoints::ToggleHIReadBP(void) { m_HIReadBP = !m_HIReadBP; } -void CBreakpoints::ToggleLOWriteBP(void) { m_LOWriteBP = !m_LOWriteBP; } -void CBreakpoints::ToggleLOReadBP(void) { m_LOReadBP = !m_LOReadBP; } +void CBreakpoints::ToggleGPRWriteBP(int nReg) { m_GPRWriteBP ^= (1 << nReg); UpdateHaveRegBP(); } +void CBreakpoints::ToggleGPRReadBP(int nReg) { m_GPRReadBP ^= (1 << nReg); UpdateHaveRegBP(); } +void CBreakpoints::ToggleHIWriteBP(void) { m_HIWriteBP = !m_HIWriteBP; UpdateHaveRegBP(); } +void CBreakpoints::ToggleHIReadBP(void) { m_HIReadBP = !m_HIReadBP; UpdateHaveRegBP(); } +void CBreakpoints::ToggleLOWriteBP(void) { m_LOWriteBP = !m_LOWriteBP; UpdateHaveRegBP(); } +void CBreakpoints::ToggleLOReadBP(void) { m_LOReadBP = !m_LOReadBP; UpdateHaveRegBP(); } void CBreakpoints::PreUpdateBP() { diff --git a/Source/Project64/UserInterface/Debugger/Breakpoints.h b/Source/Project64/UserInterface/Debugger/Breakpoints.h index 17a0a496e..a7576a055 100644 --- a/Source/Project64/UserInterface/Debugger/Breakpoints.h +++ b/Source/Project64/UserInterface/Debugger/Breakpoints.h @@ -67,17 +67,19 @@ public: void ClearMemLocks(void); size_t NumMemLocks(void); - bool HaveAnyGPRReadBP(void); - bool HaveAnyGPRWriteBP(void); - bool HaveGPRWriteBP(int nReg); - bool HaveGPRReadBP(int nReg); + inline bool HaveRegBP(void) { return m_bHaveRegBP; } + inline bool HaveAnyGPRWriteBP(void) { return m_GPRWriteBP != 0; } + inline bool HaveAnyGPRReadBP(void) { return m_GPRReadBP != 0; } + inline bool HaveGPRWriteBP(int nReg) { return (m_GPRWriteBP & (1 << nReg)) != 0; } + inline bool HaveGPRReadBP(int nReg) { return (m_GPRReadBP & (1 << nReg)) != 0; } + inline bool HaveHIWriteBP(void) { return m_HIWriteBP; } + inline bool HaveHIReadBP(void) { return m_HIReadBP; } + inline bool HaveLOWriteBP(void) { return m_LOWriteBP; } + inline bool HaveLOReadBP(void) { return m_LOReadBP; } + + void UpdateHaveRegBP(void); void ToggleGPRWriteBP(int nReg); void ToggleGPRReadBP(int nReg); - - bool HaveHIWriteBP(void); - bool HaveHIReadBP(void); - bool HaveLOWriteBP(void); - bool HaveLOReadBP(void); void ToggleHIWriteBP(void); void ToggleHIReadBP(void); void ToggleLOWriteBP(void); @@ -95,6 +97,7 @@ private: memlocks_t m_MemLocks; + bool m_bHaveRegBP; uint32_t m_GPRWriteBP, m_GPRReadBP; bool m_HIWriteBP, m_HIReadBP, m_LOWriteBP, m_LOReadBP; }; \ No newline at end of file diff --git a/Source/Project64/UserInterface/Debugger/Debugger-StackTrace.cpp b/Source/Project64/UserInterface/Debugger/Debugger-StackTrace.cpp index 9d7108242..54e8052f3 100644 --- a/Source/Project64/UserInterface/Debugger/Debugger-StackTrace.cpp +++ b/Source/Project64/UserInterface/Debugger/Debugger-StackTrace.cpp @@ -24,28 +24,6 @@ CDebugStackTrace::~CDebugStackTrace() { } -void CDebugStackTrace::PushEntry(uint32_t routineAddress, uint32_t callingAddress) -{ - if (m_EntriesIndex < STACKTRACE_MAX_ENTRIES) - { - m_Entries[m_EntriesIndex] = { routineAddress, callingAddress }; - m_EntriesIndex++; - } -} - -void CDebugStackTrace::PopEntry() -{ - if (m_EntriesIndex > 0) - { - m_EntriesIndex--; - } -} - -void CDebugStackTrace::ClearEntries() -{ - m_EntriesIndex = 0; -} - LRESULT CDebugStackTrace::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { DlgResize_Init(); diff --git a/Source/Project64/UserInterface/Debugger/Debugger-StackTrace.h b/Source/Project64/UserInterface/Debugger/Debugger-StackTrace.h index a7f3f5681..0b63d94e1 100644 --- a/Source/Project64/UserInterface/Debugger/Debugger-StackTrace.h +++ b/Source/Project64/UserInterface/Debugger/Debugger-StackTrace.h @@ -32,9 +32,27 @@ public: void Refresh(); - void PushEntry(uint32_t routineAddress, uint32_t callingAddress); - void PopEntry(); - void ClearEntries(); + inline void PushEntry(uint32_t routineAddress, uint32_t callingAddress) + { + if (m_EntriesIndex < STACKTRACE_MAX_ENTRIES) + { + m_Entries[m_EntriesIndex] = { routineAddress, callingAddress }; + m_EntriesIndex++; + } + } + + inline void PopEntry() + { + if (m_EntriesIndex > 0) + { + m_EntriesIndex--; + } + } + + inline void ClearEntries() + { + m_EntriesIndex = 0; + } private: diff --git a/Source/Project64/UserInterface/Debugger/Debugger.cpp b/Source/Project64/UserInterface/Debugger/Debugger.cpp index 6882787d4..bc1d83895 100644 --- a/Source/Project64/UserInterface/Debugger/Debugger.cpp +++ b/Source/Project64/UserInterface/Debugger/Debugger.cpp @@ -540,19 +540,19 @@ void CDebuggerUI::HandleCartToRamDMA(void) // Called from the interpreter core at the beginning of every CPU step void CDebuggerUI::CPUStepStarted() { + uint32_t pc = g_Reg->m_PROGRAM_COUNTER; + COpInfo opInfo(R4300iOp::m_Opcode); + bool bStoreOp = opInfo.IsStoreCommand(); + uint32_t storeAddress = bStoreOp ? opInfo.GetLoadStoreAddress() : 0; + if (isStepping() && bCPULoggingEnabled()) { Debug_RefreshCPULogWindow(); } - uint32_t pc = g_Reg->m_PROGRAM_COUNTER; - COpInfo opInfo(R4300iOp::m_Opcode); - - if (opInfo.IsStoreCommand()) + if(bStoreOp && m_Breakpoints->NumMemLocks() > 0) { - uint32_t memoryAddress = opInfo.GetLoadStoreAddress(); - - if (m_Breakpoints->MemLockExists(memoryAddress, opInfo.NumBytesToStore())) + if (m_Breakpoints->MemLockExists(storeAddress, opInfo.NumBytesToStore())) { // Memory is locked, skip op g_Settings->SaveBool(Debugger_SkipOp, true); @@ -560,37 +560,35 @@ void CDebuggerUI::CPUStepStarted() } } - m_ScriptSystem->HookCPUExec()->InvokeByAddressInRange(pc); - if (SkipOp()) { return; } - - m_ScriptSystem->HookCPUExecOpcode()->InvokeByAddressInRange_MaskedOpcode(pc, R4300iOp::m_Opcode.Hex); - if (SkipOp()) { return; } - - m_ScriptSystem->HookCPUGPRValue()->InvokeByAddressInRange_GPRValue(pc); - if (SkipOp()) { return; } - - // Memory events, pi cart -> ram dma - if (opInfo.IsLoadStoreCommand()) // Read and write instructions + if (m_ScriptSystem->HaveCallbacks()) { - uint32_t memoryAddress = opInfo.GetLoadStoreAddress(); + m_ScriptSystem->HookCPUExec()->InvokeByAddressInRange(pc); + if (SkipOp()) { return; } - if (opInfo.IsLoadCommand()) // Read instructions + m_ScriptSystem->HookCPUExecOpcode()->InvokeByAddressInRange_MaskedOpcode(pc, R4300iOp::m_Opcode.Hex); + if (SkipOp()) { return; } + + m_ScriptSystem->HookCPUGPRValue()->InvokeByAddressInRange_GPRValue(pc); + if (SkipOp()) { return; } + + if (bStoreOp) { - m_ScriptSystem->HookCPURead()->InvokeByAddressInRange(memoryAddress); + m_ScriptSystem->HookCPUWrite()->InvokeByAddressInRange(storeAddress); if (SkipOp()) { return; } } - else // Write instructions - { - m_ScriptSystem->HookCPUWrite()->InvokeByAddressInRange(memoryAddress); - if (SkipOp()) { return; } - if (memoryAddress == 0xA460000C) // PI_WR_LEN_REG - { - HandleCartToRamDMA(); - } + if (opInfo.IsLoadCommand()) + { + m_ScriptSystem->HookCPURead()->InvokeByAddressInRange(opInfo.GetLoadStoreAddress()); + if (SkipOp()) { return; } } } + if (bStoreOp && storeAddress == 0xA460000C) // PI_WR_LEN_REG + { + HandleCartToRamDMA(); + } + if (CDebugSettings::ExceptionBreakpoints() != 0) { if (pc == 0x80000000 || pc == 0x80000080 || @@ -603,36 +601,39 @@ void CDebuggerUI::CPUStepStarted() } } - if (m_Breakpoints->HaveAnyGPRWriteBP()) + if (m_Breakpoints->HaveRegBP()) { - int nReg = 0; - opInfo.WritesGPR(&nReg); + if (m_Breakpoints->HaveAnyGPRWriteBP()) + { + int nReg = 0; + opInfo.WritesGPR(&nReg); - if (nReg != 0 && m_Breakpoints->HaveGPRWriteBP(nReg)) + if (nReg != 0 && m_Breakpoints->HaveGPRWriteBP(nReg)) + { + g_Settings->SaveBool(Debugger_SteppingOps, true); + } + } + + if (m_Breakpoints->HaveAnyGPRReadBP()) + { + int nReg1 = 0, nReg2 = 0; + opInfo.ReadsGPR(&nReg1, &nReg2); + + if ((nReg1 != 0 && m_Breakpoints->HaveGPRReadBP(nReg1)) || + (nReg2 != 0 && m_Breakpoints->HaveGPRReadBP(nReg2))) + { + g_Settings->SaveBool(Debugger_SteppingOps, true); + } + } + + if (m_Breakpoints->HaveHIWriteBP() && opInfo.WritesHI() || + m_Breakpoints->HaveLOWriteBP() && opInfo.WritesLO() || + m_Breakpoints->HaveHIReadBP() && opInfo.ReadsHI() || + m_Breakpoints->HaveLOReadBP() && opInfo.ReadsLO()) { g_Settings->SaveBool(Debugger_SteppingOps, true); } } - - if (m_Breakpoints->HaveAnyGPRReadBP()) - { - int nReg1 = 0, nReg2 = 0; - opInfo.ReadsGPR(&nReg1, &nReg2); - - if ((nReg1 != 0 && m_Breakpoints->HaveGPRReadBP(nReg1)) || - (nReg2 != 0 && m_Breakpoints->HaveGPRReadBP(nReg2))) - { - g_Settings->SaveBool(Debugger_SteppingOps, true); - } - } - - if (m_Breakpoints->HaveHIWriteBP() && opInfo.WritesHI() || - m_Breakpoints->HaveLOWriteBP() && opInfo.WritesLO() || - m_Breakpoints->HaveHIReadBP() && opInfo.ReadsHI() || - m_Breakpoints->HaveLOReadBP() && opInfo.ReadsLO()) - { - g_Settings->SaveBool(Debugger_SteppingOps, true); - } } // Called before opcode is executed (not called if SkipOp is set) @@ -647,15 +648,15 @@ void CDebuggerUI::CPUStep() // Called after opcode has been executed void CDebuggerUI::CPUStepEnded() { + if (m_StackTrace == NULL) + { + return; + } + OPCODE Opcode = R4300iOp::m_Opcode; uint32_t op = Opcode.op; uint32_t funct = Opcode.funct; - if (m_StackTrace == NULL) - { - m_StackTrace = new CDebugStackTrace(this); - } - if (op == R4300i_JAL || ((op == R4300i_SPECIAL) && (funct == R4300i_SPECIAL_JALR) && (Opcode.rd == 31))) // JAL or JALR RA, x { m_StackTrace->PushEntry(R4300iOp::m_JumpToLocation, g_Reg->m_PROGRAM_COUNTER); diff --git a/Source/Project64/UserInterface/Debugger/ScriptHook.cpp b/Source/Project64/UserInterface/Debugger/ScriptHook.cpp index 9a9f616f6..6e0296e77 100644 --- a/Source/Project64/UserInterface/Debugger/ScriptHook.cpp +++ b/Source/Project64/UserInterface/Debugger/ScriptHook.cpp @@ -17,6 +17,7 @@ int CScriptHook::Add(CScriptInstance* scriptInstance, void* heapptr, uint32_t pa jsCallback.param4 = param4; jsCallback.bOnce = bOnce; m_Callbacks.push_back(jsCallback); + m_ScriptSystem->CallbackAdded(); return jsCallback.callbackId; } @@ -122,6 +123,7 @@ void CScriptHook::RemoveById(int callbackId) if (m_Callbacks[i].callbackId == callbackId) { m_Callbacks.erase(m_Callbacks.begin() + i); + m_ScriptSystem->CallbackRemoved(); return; } } @@ -135,6 +137,7 @@ void CScriptHook::RemoveByParam(uint32_t param) if (m_Callbacks[i].param == param) { m_Callbacks.erase(m_Callbacks.begin() + i); + m_ScriptSystem->CallbackRemoved(); return; } } @@ -148,6 +151,7 @@ void CScriptHook::RemoveByInstance(CScriptInstance* scriptInstance) if (m_Callbacks[i].scriptInstance == scriptInstance) { m_Callbacks.erase(m_Callbacks.begin() + i); + m_ScriptSystem->CallbackRemoved(); } } } diff --git a/Source/Project64/UserInterface/Debugger/ScriptSystem.cpp b/Source/Project64/UserInterface/Debugger/ScriptSystem.cpp index 22b4f2e36..e9d3b7fe2 100644 --- a/Source/Project64/UserInterface/Debugger/ScriptSystem.cpp +++ b/Source/Project64/UserInterface/Debugger/ScriptSystem.cpp @@ -21,6 +21,7 @@ CScriptSystem::CScriptSystem(CDebuggerUI* debugger) WSAStartup(MAKEWORD(2, 2), &wsaData); m_NextCallbackId = 0; + m_NumCallbacks = 0; m_Debugger = debugger; @@ -207,4 +208,17 @@ CScriptHook* CScriptSystem::GetHook(const char* hookId) int CScriptSystem::GetNextCallbackId() { return m_NextCallbackId++; -} \ No newline at end of file +} + +void CScriptSystem::CallbackAdded() +{ + m_NumCallbacks++; +} + +void CScriptSystem::CallbackRemoved() +{ + if (m_NumCallbacks > 0) + { + m_NumCallbacks--; + } +} diff --git a/Source/Project64/UserInterface/Debugger/ScriptSystem.h b/Source/Project64/UserInterface/Debugger/ScriptSystem.h index b95b6115f..356ff1f0e 100644 --- a/Source/Project64/UserInterface/Debugger/ScriptSystem.h +++ b/Source/Project64/UserInterface/Debugger/ScriptSystem.h @@ -43,7 +43,7 @@ private: } INSTANCE_ENTRY; CDebuggerUI* m_Debugger; - + int m_NumCallbacks; char* m_APIScript; vector m_Hooks; @@ -103,6 +103,13 @@ public: CScriptHook* GetHook(const char* hookId); int GetNextCallbackId(); + void CallbackAdded(); + void CallbackRemoved(); + + inline int HaveCallbacks() + { + return m_NumCallbacks != 0; + } void DeleteStoppedInstances(); INSTANCE_STATE GetInstanceState(char* scriptName);