# UNDF: UNDF-2026-000001066 # UNDF: UNDF-2026-XXXXXXXXX --- a/src/z80.cpp +++ b/src/z80.cpp @@ -162,6 +162,9 @@ t_z80regs z80; std::vector breakpoints; std::unordered_set breakpoint_addresses; std::vector watchpoints; +// Fast O(1) lookup sets for watchpoints, separated by access type. +std::unordered_set watchpoint_reads; // addresses watched on READ +std::unordered_set watchpoint_writes; // addresses watched on WRITE --- a/src/z80.cpp +++ b/src/z80.cpp @@ -340,11 +340,11 @@ inline byte read_mem(word addr) { if (!watchpoints.empty()) { - if (std::any_of(watchpoints.begin(), watchpoints.end(), [&](const auto& w) { - return w.address == addr && (w.type & READ); - })) { + if (watchpoint_reads.count(addr)) { z80.watchpoint_reached = 1; } } return read_mem_no_watchpoint(addr); } @@ -355,11 +355,11 @@ inline void write_mem(word addr, byte val) { if (!watchpoints.empty()) { - if (std::any_of(watchpoints.begin(), watchpoints.end(), [&](const auto& w) { - return w.address == addr && (w.type & WRITE); - })) { + if (watchpoint_writes.count(addr)) { z80.watchpoint_reached = 1; } } --- a/src/gui/src/CapriceDevTools.cpp +++ b/src/gui/src/CapriceDevTools.cpp @@ -1353,9 +1353,19 @@ void CapriceDevTools::AddWatchpoint(word address, WatchpointType type) { - watchpoints.emplace_back(address, type); + watchpoints.emplace_back(address, type); + if (type & READ) watchpoint_reads.insert(address); + if (type & WRITE) watchpoint_writes.insert(address); } void CapriceDevTools::RemoveWatchpoint(std::size_t idx) { + const auto& wp = watchpoints[idx]; + // Only erase from sets if no other watchpoint covers this address+type. + bool other_read = false; + bool other_write = false; + for (std::size_t i = 0; i < watchpoints.size(); i++) { + if (i == idx) continue; + if (watchpoints[i].address == wp.address) { + if (watchpoints[i].type & READ) other_read = true; + if (watchpoints[i].type & WRITE) other_write = true; + } + } + if (!other_read && (wp.type & READ)) watchpoint_reads.erase(wp.address); + if (!other_write && (wp.type & WRITE)) watchpoint_writes.erase(wp.address); watchpoints.erase(watchpoints.begin() + idx); }