# UNDF: UNDF-2026-000001046 # UNDF: UNDF-2026-XXXXXXXXX --- a/src/cheat.cpp +++ b/src/cheat.cpp @@ -67,6 +67,10 @@ CHEATF_SUBFAST SubCheats[256]; uint32 numsubcheats = 0; int globalCheatDisabled = 0; int disableAutoLSCheats = 0; bool disableShowGG = 0; static _8BYTECHEATMAP* cheatMap = NULL; struct CHEATF *cheats = 0, *cheatsl = 0; + +// O(1) direct-address lookup replacing the O(C) SubCheats[] linear scan. +// Index -1 means no cheat at this address. +static int cheat_idx[0x10000]; #define CHEATC_NONE 0x8000 @@ -79,16 +83,16 @@ static uint16 *CheatComp = 0; static DECLFR(SubCheatsRead) { - CHEATF_SUBFAST *s = SubCheats; - int x=numsubcheats; - - do - { - if(s->addr==A) - { - if(s->compare>=0) - { - uint8 pv=s->PrevRead(A); - - if(pv==s->compare) - return(s->val); - else return(pv); - } - else return(s->val); - } - s++; - } while(--x); - return(0); /* We should never get here. */ + // O(1): look up this address directly instead of scanning all active cheats. + int idx = cheat_idx[A]; + if(idx < 0) return(0); /* should never happen if installed correctly */ + CHEATF_SUBFAST *s = &SubCheats[idx]; + if(s->compare>=0) + { + uint8 pv=s->PrevRead(A); + if(pv==s->compare) + return(s->val); + else return(pv); + } + return(s->val); } void RebuildSubCheats(void) @@ -96,6 +100,8 @@ void RebuildSubCheats(void) uint32 x; struct CHEATF *c = cheats; + // Clear the direct-lookup table for addresses we're about to remove. for (x = 0; x < numsubcheats; x++) { + cheat_idx[SubCheats[x].addr] = -1; SetReadHandler(SubCheats[x].addr, SubCheats[x].addr, SubCheats[x].PrevRead); if (cheatMap) FCEUI_SetCheatMapByte(SubCheats[x].addr, false); @@ -113,6 +119,7 @@ void RebuildSubCheats(void) SubCheats[numsubcheats].val = c->val; SubCheats[numsubcheats].compare = c->compare; SetReadHandler(c->addr, c->addr, SubCheatsRead); + cheat_idx[c->addr] = (int)numsubcheats; if (cheatMap) FCEUI_SetCheatMapByte(SubCheats[numsubcheats].addr, true); numsubcheats++; @@ -123,6 +130,14 @@ void RebuildSubCheats(void) FrozenAddressCount = numsubcheats; } +// Call once at startup to initialise the direct-lookup table. +void FCEU_CheatIdxInit(void) +{ + for(int i = 0; i < 0x10000; i++) + cheat_idx[i] = -1; +}