From 20e0185707b8d0fba3bf2002a0c3b6ffd0db4f3e Mon Sep 17 00:00:00 2001 From: Artem Lytkin Date: Thu, 3 Sep 2026 20:36:19 +0300 Subject: [PATCH] Win32 debugger: refresh the breakpoint list after memcheck changes The list reloads on SystemNotification::DISASSEMBLY, which every CPU breakpoint mutation in BreakpointManager has posted since 8d0d601b5, but none of the MemCheck ones do, so a memory breakpoint added from the list (or the disasm view's dialog, the ImDebugger, the WebSocket API) only showed up after the next Break. The enable checkbox then toggled against the list's stale copy of the memcheck, so re-enabling one it had just disabled disabled it again. Post the notification from the memcheck mutations too, and from the condition setters of both kinds, since the list's cached copy also feeds the edit dialog. --- Core/Debugger/Breakpoints.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Core/Debugger/Breakpoints.cpp b/Core/Debugger/Breakpoints.cpp index 67981bf320..bcdc07ec3d 100644 --- a/Core/Debugger/Breakpoints.cpp +++ b/Core/Debugger/Breakpoints.cpp @@ -320,6 +320,7 @@ void BreakpointManager::ChangeBreakPointAddCond(u32 addr, const BreakPointCond & breakPoints_[bp].hasCond = true; breakPoints_[bp].cond = cond; currentMIPS->InvalidateICacheRangeDeferred(addr - 4, 8); + System_Notify(SystemNotification::DISASSEMBLY); } } @@ -328,6 +329,7 @@ void BreakpointManager::ChangeBreakPointRemoveCond(u32 addr) { if (bp != INVALID_BREAKPOINT) { breakPoints_[bp].hasCond = false; currentMIPS->InvalidateICacheRangeDeferred(addr - 4, 8); + System_Notify(SystemNotification::DISASSEMBLY); } } @@ -438,6 +440,7 @@ int BreakpointManager::AddMemCheck(u32 start, u32 end, MemCheckCondition cond, B } updateMemChecks_ = true; currentMIPS->ClearJitCacheDeferred(); // memchecks apply to all memory accesses + System_Notify(SystemNotification::DISASSEMBLY); return (int)memChecks_.size() - 1; } else { // Update with additional cond and action bits. Not sure if we should OR or override? @@ -449,6 +452,7 @@ int BreakpointManager::AddMemCheck(u32 start, u32 end, MemCheckCondition cond, B } updateMemChecks_ = true; currentMIPS->ClearJitCacheDeferred(); // memchecks apply to all memory accesses + System_Notify(SystemNotification::DISASSEMBLY); return (int)mc; } } @@ -464,6 +468,7 @@ void BreakpointManager::RemoveMemCheck(u32 start, u32 end) MemBlockReleaseDetailed(); updateMemChecks_ = true; currentMIPS->ClearJitCacheDeferred(); // memchecks apply to all memory accesses + System_Notify(SystemNotification::DISASSEMBLY); } } @@ -476,6 +481,7 @@ void BreakpointManager::ChangeMemCheck(u32 start, u32 end, MemCheckCondition con memChecks_[mc].action = action; updateMemChecks_ = true; currentMIPS->ClearJitCacheDeferred(); // memchecks apply to all memory accesses + System_Notify(SystemNotification::DISASSEMBLY); } } @@ -498,6 +504,7 @@ void BreakpointManager::ChangeMemCheckAddCond(u32 start, u32 end, const BreakPoi memChecks_[mc].hasCondition = true; memChecks_[mc].condition = cond; // No need to update jit for a condition add/remove, they're not baked in. + System_Notify(SystemNotification::DISASSEMBLY); } } @@ -506,6 +513,7 @@ void BreakpointManager::ChangeMemCheckRemoveCond(u32 start, u32 end) { if (mc != INVALID_MEMCHECK) { memChecks_[mc].hasCondition = false; // No need to update jit for a condition add/remove, they're not baked in. + System_Notify(SystemNotification::DISASSEMBLY); } }