java-topology/defects/desmume-0001/patch/desmume-0001.patch

95 lines
3.9 KiB
Diff

# UNDF: UNDF-2026-000001078
--- a/desmume/src/NDSSystem.cpp
+++ b/desmume/src/NDSSystem.cpp
@@ -1,5 +1,6 @@
#include <string.h>
#include <algorithm>
+#include <unordered_set>
// ...
@@ -1955,6 +1955,14 @@ template<bool doarm9, bool doarm7>
static /*donotinline*/ std::pair<s32,s32> armInnerLoop(
const u64 nds_timer_base, const s32 s32next, s32 arm9, s32 arm7)
{
+ // DEFECT (removed): O(B) linear scan of breakPoints vector on every CPU instruction.
+ // With B breakpoints set, the NDS_ARM9 and NDS_ARM7 loops each scan the full vector
+ // per instruction, giving O(B * I) per second where I is the instruction rate
+ // (~66 MHz ARM9 + ~33 MHz ARM7). Fix: replace std::vector<u32> *breakPoints with
+ // std::unordered_set<u32> *breakPoints (O(1) lookup).
+ //
+ // In armcpu.h: change std::vector<u32> *breakPoints;
+ // to std::unordered_set<u32> *breakPoints;
+ //
+ // In armcpu.cpp armcpu_init(): change armcpu->breakPoints = new std::vector<u32>;
+ // to armcpu->breakPoints = new std::unordered_set<u32>;
+ //
+ // In disView.cpp: change push_back -> insert; erase(begin()+i) -> erase(value).
s32 timer = minarmtime<doarm9,doarm7>(arm9,arm7);
while(timer < s32next && !sequencer.reschedule && execute)
{
// breakpoint handling
#if defined(HOST_WINDOWS) && !defined(TARGET_INTERFACE)
- const std::vector<u32> *breakpointList9 = NDS_ARM9.breakPoints;
- for (int i = 0; i < breakpointList9->size(); ++i) {
- if (NDS_ARM9.instruct_adr == (*breakpointList9)[i] && !NDS_ARM9.debugStep) {
+ // PATCHED: O(1) hash-set lookup instead of O(B) linear scan.
+ if (NDS_ARM9.breakPoints->count(NDS_ARM9.instruct_adr) && !NDS_ARM9.debugStep) {
emu_paused = true;
paused = true;
execute = false;
// update debug display
PostMessageA(DisViewWnd[0], WM_COMMAND, IDC_DISASMSEEK, NDS_ARM9.instruct_adr);
InvalidateRect(DisViewWnd[0], NULL, FALSE);
return std::make_pair(arm9, arm7);
- }
}
- const std::vector<u32> *breakpointList7 = NDS_ARM7.breakPoints;
- for (int i = 0; i < breakpointList7->size(); ++i) {
- if (NDS_ARM7.instruct_adr == (*breakpointList7)[i] && !NDS_ARM7.debugStep) {
+ if (NDS_ARM7.breakPoints->count(NDS_ARM7.instruct_adr) && !NDS_ARM7.debugStep) {
emu_paused = true;
paused = true;
execute = false;
// update debug display
PostMessageA(DisViewWnd[1], WM_COMMAND, IDC_DISASMSEEK, NDS_ARM7.instruct_adr);
InvalidateRect(DisViewWnd[1], NULL, FALSE);
return std::make_pair(arm9, arm7);
- }
}
#endif //HOST_WINDOWS
--- a/desmume/src/armcpu.h
+++ b/desmume/src/armcpu.h
@@ -313,7 +313,8 @@ typedef struct armcpu_t {
// ...
- std::vector<u32> *breakPoints;
+ // PATCHED: unordered_set gives O(1) lookup vs O(B) linear scan in armInnerLoop.
+ std::unordered_set<u32> *breakPoints;
// ...
--- a/desmume/src/armcpu.cpp
+++ b/desmume/src/armcpu.cpp
@@ -149,7 +149,7 @@ void armcpu_init(armcpu_t *armcpu, u32 adr)
- armcpu->breakPoints = new std::vector<u32>;
+ armcpu->breakPoints = new std::unordered_set<u32>;
--- a/desmume/src/frontend/windows/disView.cpp
+++ b/desmume/src/frontend/windows/disView.cpp
@@ -550,7 +550,7 @@ LRESULT CALLBACK DisViewWndProc(...)
- NDS_ARM7.breakPoints->push_back(adr);
+ NDS_ARM7.breakPoints->insert(adr);
...
- if (DisView7->break_pos < NDS_ARM7.breakPoints->size()) {
- NDS_ARM7.breakPoints->erase(NDS_ARM7.breakPoints->begin() + DisView7->break_pos);
+ if (NDS_ARM7.breakPoints->count(adr)) {
+ NDS_ARM7.breakPoints->erase(adr);
@@ -883,7 +883,7 @@ LRESULT CALLBACK DisViewWndProc(...)
- NDS_ARM9.breakPoints->push_back(adr);
+ NDS_ARM9.breakPoints->insert(adr);
...
- if (DisView9->break_pos < NDS_ARM9.breakPoints->size()) {
- NDS_ARM9.breakPoints->erase(NDS_ARM9.breakPoints->begin() + DisView9->break_pos);
+ if (NDS_ARM9.breakPoints->count(adr)) {
+ NDS_ARM9.breakPoints->erase(adr);