diff --git a/src/cheat.cpp b/src/cheat.cpp index c6ec6be7..10ee4105 100644 --- a/src/cheat.cpp +++ b/src/cheat.cpp @@ -63,7 +63,7 @@ CHEATF_SUBFAST SubCheats[256] = { 0 }; uint32 numsubcheats = 0; int globalCheatDisabled = 0; int disableAutoLSCheats = 0; -static unsigned char cheatMap[0x10000 / 8] = { 0 }; +static _8BYTECHEATMAP* cheatMap = NULL; struct CHEATF *cheats = 0, *cheatsl = 0; @@ -105,7 +105,8 @@ void RebuildSubCheats(void) for (x = 0; x < numsubcheats; x++) { SetReadHandler(SubCheats[x].addr, SubCheats[x].addr, SubCheats[x].PrevRead); - SetByteCheat(SubCheats[x].addr, false); + if (cheatMap) + FCEUI_SetCheatMapByte(SubCheats[x].addr, false); } numsubcheats = 0; @@ -121,7 +122,8 @@ void RebuildSubCheats(void) SubCheats[numsubcheats].val = c->val; SubCheats[numsubcheats].compare = c->compare; SetReadHandler(c->addr, c->addr, SubCheatsRead); - SetByteCheat(SubCheats[numsubcheats].addr, true); + if (cheatMap) + FCEUI_SetCheatMapByte(SubCheats[numsubcheats].addr, true); numsubcheats++; } c = c->next; @@ -134,16 +136,18 @@ void RebuildSubCheats(void) void FCEU_PowerCheats() { numsubcheats = 0; /* Quick hack to prevent setting of ancient read addresses. */ - memset(cheatMap, 0, sizeof(cheatMap)); + if (cheatMap) + FCEUI_RefreshCheatMap(); RebuildSubCheats(); } int FCEU_CalcCheatAffectedBytes(uint32 address, uint32 size) { uint32 count = 0; - for (uint32 i = 0; i < size; ++i) - if (IsByteCheat(address + i)) - ++count; + if (cheatMap) + for (uint32 i = 0; i < size; ++i) + if (FCEUI_FindCheatMapByte(address + i)) + ++count; return count; } @@ -205,7 +209,8 @@ void FCEU_LoadGameCheats(FILE *override, int override_existing) if (override_existing) { numsubcheats = 0; - memset(cheatMap, 0, sizeof(cheatMap)); + if (cheatMap) + FCEUI_RefreshCheatMap(); } if(override) @@ -896,13 +901,35 @@ int FCEU_DisableAllCheats(){ return count; } -int IsByteCheat(uint8 address) +inline int FCEUI_FindCheatMapByte(uint16 address) { return cheatMap[address / 8] >> (address % 8) & 1; } -void SetByteCheat(uint8 address, bool cheat) +inline void FCEUI_SetCheatMapByte(uint16 address, bool cheat) { cheat ? cheatMap[address / 8] |= (1 << address % 8) : cheatMap[address / 8] ^= (1 << address % 8); } +inline void FCEUI_CreateCheatMap() +{ + if (!cheatMap) + cheatMap = (unsigned char*)malloc(CHEATMAP_SIZE); + FCEUI_RefreshCheatMap(); +} + +inline void FCEUI_RefreshCheatMap() +{ + memset(cheatMap, 0, CHEATMAP_SIZE); + for (int i = 0; i < numsubcheats; ++i) + FCEUI_SetCheatMapByte(SubCheats[i].addr, true); +} + +inline void FCEUI_ReleaseCheatMap() +{ + if (cheatMap) + { + free(cheatMap); + cheatMap = NULL; + } +} \ No newline at end of file diff --git a/src/cheat.h b/src/cheat.h index 0b488420..4ea6f12c 100644 --- a/src/cheat.h +++ b/src/cheat.h @@ -11,6 +11,17 @@ void FCEU_ApplyPeriodicCheats(void); void FCEU_PowerCheats(void); int FCEU_CalcCheatAffectedBytes(uint32 address, uint32 size); +// Trying to find a more efficient way for determining if an address has a cheat +// each bit of 1 byte represents to 8 bytes in NES +typedef unsigned char _8BYTECHEATMAP; +#define CHEATMAP_SIZE 0x10000 / 8 + +extern int FCEUI_FindCheatMapByte(uint16 address); +extern void FCEUI_SetCheatMapByte(uint16 address, bool cheat); +extern void FCEUI_CreateCheatMap(); +extern void FCEUI_RefreshCheatMap(); +extern void FCEUI_ReleaseCheatMap(); + int FCEU_CheatGetByte(uint32 A); void FCEU_CheatSetByte(uint32 A, uint8 V); @@ -44,11 +55,6 @@ struct SEARCHPOSSIBLE { bool update; }; -// Trying to find a more efficient way for determining if an address has a cheat -// 1 byte represents to 8 bytes in NES, -int IsByteCheat(uint8 address); -void SetByteCheat(uint8 address, bool cheat); - #define FCEU_SEARCH_SPECIFIC_CHANGE 0 #define FCEU_SEARCH_RELATIVE_CHANGE 1 #define FCEU_SEARCH_PUERLY_RELATIVE_CHANGE 2 diff --git a/src/drivers/win/cheat.cpp b/src/drivers/win/cheat.cpp index 576737e9..7ba4779f 100644 --- a/src/drivers/win/cheat.cpp +++ b/src/drivers/win/cheat.cpp @@ -41,6 +41,7 @@ extern bool wasPausedByCheats; int CheatWindow; int CheatStyle = 1; +int CheatMapUsers = 0; // how many windows using cheatmap #define GGLISTSIZE 128 //hopefully this is enough for all cases @@ -1541,3 +1542,19 @@ void DeleteCheatFont() hNewFont = NULL; } } + +void CreateCheatMap() +{ + if (!CheatMapUsers) + FCEUI_CreateCheatMap(); + ++CheatMapUsers; +} + +void ReleaseCheatMap() +{ + --CheatMapUsers; + printf("CheatMapUsers: %d\n", CheatMapUsers); + if (!CheatMapUsers) + FCEUI_ReleaseCheatMap(); +} + diff --git a/src/drivers/win/cheat.h b/src/drivers/win/cheat.h index a10af805..7b45a5c5 100644 --- a/src/drivers/win/cheat.h +++ b/src/drivers/win/cheat.h @@ -40,6 +40,10 @@ void SetupCheatFont(HWND hDlg); void DeleteCheatFont(); extern POINT CalcSubWindowPos(HWND hDlg, POINT* conf); +void CreateCheatMap(); +void ReleaseCheatMap(); +extern int CheatMapUsers; + extern INT_PTR CALLBACK GGConvCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); extern LRESULT APIENTRY FilterEditCtrlProc(HWND hDlg, UINT msg, WPARAM wP, LPARAM lP); extern WNDPROC DefaultEditCtrlProc; diff --git a/src/drivers/win/memview.cpp b/src/drivers/win/memview.cpp index 682ba7cf..81030e70 100644 --- a/src/drivers/win/memview.cpp +++ b/src/drivers/win/memview.cpp @@ -669,37 +669,30 @@ void UpdateCaption() int GetMemViewData(uint32 i) { - if (EditingMode == MODE_NES_MEMORY) - return GetMem(i); - - if (EditingMode == MODE_NES_PPU) + switch (EditingMode) { - i &= 0x3FFF; - if(i < 0x2000)return VPage[(i)>>10][(i)]; - //NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') - if (GameInfo->type==GIT_NSF) - { - return (0); - } - else - { - if(i < 0x3F00) - return vnapage[(i >> 10) & 0x3][i & 0x3FF]; - return READPAL_MOTHEROFALL(i & 0x1F); - } - } - - if (EditingMode == MODE_NES_OAM) - { - return SPRAM[i & 0xFF]; - } - - if (EditingMode == MODE_NES_FILE) - { - //todo: use getfiledata() here - if(i < 16) return *((unsigned char *)&head+i); - if(i < 16+PRGsize[0])return PRGptr[0][i-16]; - if(i < 16+PRGsize[0]+CHRsize[0])return CHRptr[0][i-16-PRGsize[0]]; + case MODE_NES_MEMORY: + return GetMem(i); + case MODE_NES_PPU: + i &= 0x3FFF; + if (i < 0x2000)return VPage[(i) >> 10][(i)]; + //NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') + if (GameInfo->type == GIT_NSF) + return (0); + else + { + if (i < 0x3F00) + return vnapage[(i >> 10) & 0x3][i & 0x3FF]; + return READPAL_MOTHEROFALL(i & 0x1F); + } + break; + case MODE_NES_OAM: + return SPRAM[i & 0xFF]; + case MODE_NES_FILE: + //todo: use getfiledata() here + if (i < 16) return *((unsigned char *)&head + i); + if (i < 16 + PRGsize[0])return PRGptr[0][i - 16]; + if (i < 16 + PRGsize[0] + CHRsize[0])return CHRptr[0][i - 16 - PRGsize[0]]; } return 0; } @@ -729,89 +722,88 @@ void UpdateColorTable() TextColorList[hexBookmarks[j].address - CurOffset] = RGB(0,0xCC,0); // Green for Bookmarks } - //mbg merge 6/29/06 - added argument - if (EditingMode == MODE_NES_MEMORY) - FCEUI_ListCheats(UpdateCheatColorCallB, 0); - - if(EditingMode == MODE_NES_FILE) + switch (EditingMode) { - if (cdloggerdataSize) - { - for (i = 0; i < DataAmount; i++) + case MODE_NES_MEMORY: + for (uint32 a = CurOffset; a < CurOffset + DataAmount; ++a) + if (FCEUI_FindCheatMapByte(a)) + TextColorList[a - CurOffset] = RGB(HexFreezeColorR, HexFreezeColorG, HexFreezeColorB); + break; + case MODE_NES_FILE: + if (cdloggerdataSize) { - temp_offset = CurOffset + i - 16; // (minus iNES header) - if (temp_offset >= 0) + for (i = 0; i < DataAmount; i++) { - if ((unsigned int)temp_offset < cdloggerdataSize) + temp_offset = CurOffset + i - 16; // (minus iNES header) + if (temp_offset >= 0) { - // PRG - if ((cdloggerdata[temp_offset] & 3) == 3) + if ((unsigned int)temp_offset < cdloggerdataSize) { - // the byte is both Code and Data - green - TextColorList[i]=RGB(0,190,0); - } else if((cdloggerdata[temp_offset] & 3) == 1) - { - // the byte is Code - dark-yellow - TextColorList[i]=RGB(160,140,0); - } else if((cdloggerdata[temp_offset] & 3) == 2) - { - // the byte is Data - blue/cyan - if (cdloggerdata[temp_offset] & 0x40) - // PCM data - cyan - TextColorList[i]=RGB(0,130,160); - else - // non-PCM data - blue - TextColorList[i]=RGB(0,0,210); + // PRG + if ((cdloggerdata[temp_offset] & 3) == 3) + { + // the byte is both Code and Data - green + TextColorList[i] = RGB(0, 190, 0); + } + else if ((cdloggerdata[temp_offset] & 3) == 1) + { + // the byte is Code - dark-yellow + TextColorList[i] = RGB(160, 140, 0); + } + else if ((cdloggerdata[temp_offset] & 3) == 2) + { + // the byte is Data - blue/cyan + if (cdloggerdata[temp_offset] & 0x40) + // PCM data - cyan + TextColorList[i] = RGB(0, 130, 160); + else + // non-PCM data - blue + TextColorList[i] = RGB(0, 0, 210); + } } - } else - { - temp_offset -= cdloggerdataSize; - if (((unsigned int)temp_offset < cdloggerVideoDataSize)) + else { - // CHR - if ((cdloggervdata[temp_offset] & 3) == 3) + temp_offset -= cdloggerdataSize; + if (((unsigned int)temp_offset < cdloggerVideoDataSize)) { - // the byte was both rendered and read programmatically - light-green - TextColorList[i]=RGB(5,255,5); - } else if ((cdloggervdata[temp_offset] & 3) == 1) - { - // the byte was rendered - yellow - TextColorList[i]=RGB(210,190,0); - } else if ((cdloggervdata[temp_offset] & 3) == 2) - { - // the byte was read programmatically - light-blue - TextColorList[i]=RGB(15,15,255); + // CHR + if ((cdloggervdata[temp_offset] & 3) == 3) + { + // the byte was both rendered and read programmatically - light-green + TextColorList[i] = RGB(5, 255, 5); + } + else if ((cdloggervdata[temp_offset] & 3) == 1) + { + // the byte was rendered - yellow + TextColorList[i] = RGB(210, 190, 0); + } + else if ((cdloggervdata[temp_offset] & 3) == 2) + { + // the byte was read programmatically - light-blue + TextColorList[i] = RGB(15, 15, 255); + } } } } } } - } - tmp = undo_list; - while(tmp!= 0) - { - //if((tmp->addr < CurOffset+DataAmount) && (tmp->addr+tmp->size > CurOffset)) - for(i = tmp->addr;i < tmp->addr+tmp->size;i++){ - if((i > CurOffset) && (i < CurOffset+DataAmount)) - TextColorList[i-CurOffset] = RGB(RomFreezeColorR,RomFreezeColorG,RomFreezeColorB); + tmp = undo_list; + while (tmp != 0) + { + //if((tmp->addr < CurOffset+DataAmount) && (tmp->addr+tmp->size > CurOffset)) + for (i = tmp->addr; i < tmp->addr + tmp->size; i++) { + if ((i > CurOffset) && (i < CurOffset + DataAmount)) + TextColorList[i - CurOffset] = RGB(RomFreezeColorR, RomFreezeColorG, RomFreezeColorB); + } + tmp = tmp->last; } - tmp=tmp->last; - } + break; } UpdateMemoryView(1); //anytime the colors change, the memory viewer needs to be completely redrawn } -//mbg merge 6/29/06 - added argument -int UpdateCheatColorCallB(char *name, uint32 a, uint8 v, int compare,int s,int type, void *data) { - - if((a >= (uint32)CurOffset) && (a < (uint32)CurOffset+DataAmount)){ - if(s)TextColorList[a-CurOffset] = RGB(HexFreezeColorR,HexFreezeColorG,HexFreezeColorB); - } - return 1; -} - int addrtodelete; // This is a very ugly hackish method of doing this int cheatwasdeleted; // but it works and that is all that matters here. int DeleteCheatCallB(char *name, uint32 a, uint8 v, int compare,int s,int type, void *data){ //mbg merge 6/29/06 - added arg @@ -1001,29 +993,30 @@ void InputData(char *input){ if (addr >= MaxSize) continue; - if (EditingMode == MODE_NES_MEMORY) + switch(EditingMode) { - // RAM (system bus) - BWrite[addr](addr,data[i]); - } else if (EditingMode == MODE_NES_PPU) - { - // PPU - addr &= 0x3FFF; - if(addr < 0x2000) - VPage[addr>>10][addr] = data[i]; //todo: detect if this is vrom and turn it red if so - if((addr >= 0x2000) && (addr < 0x3F00)) - vnapage[(addr>>10)&0x3][addr&0x3FF] = data[i]; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? - if((addr >= 0x3F00) && (addr < 0x3FFF)) - PalettePoke(addr,data[i]); - } else if (EditingMode == MODE_NES_OAM) - { - addr &= 0xFF; - SPRAM[addr] = data[i]; - } else if (EditingMode == MODE_NES_FILE) - { - // ROM - ApplyPatch(addr,datasize,data); - break; + case MODE_NES_MEMORY: + // RAM (system bus) + BWrite[addr](addr, data[i]); + break; + case MODE_NES_PPU: + // PPU + addr &= 0x3FFF; + if (addr < 0x2000) + VPage[addr >> 10][addr] = data[i]; //todo: detect if this is vrom and turn it red if so + if ((addr >= 0x2000) && (addr < 0x3F00)) + vnapage[(addr >> 10) & 0x3][addr & 0x3FF] = data[i]; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? + if ((addr >= 0x3F00) && (addr < 0x3FFF)) + PalettePoke(addr, data[i]); + break; + case MODE_NES_OAM: + addr &= 0xFF; + SPRAM[addr] = data[i]; + break; + case MODE_NES_FILE: + // ROM + ApplyPatch(addr, datasize, data); + break; } } CursorStartAddy+=datasize; @@ -1194,6 +1187,8 @@ void KillMemView() UnregisterClass("MEMVIEW",fceu_hInstance); hMemView = 0; hMemFind = 0; + if (EditingMode == MODE_NES_MEMORY) + ReleaseCheatMap(); return; } @@ -1232,7 +1227,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa case WM_CREATE: SetWindowPos(hwnd,0,MemView_wndx,MemView_wndy,MemViewSizeX,MemViewSizeY,SWP_NOZORDER|SWP_NOOWNERZORDER); - + debuggerWasActive = 1; mDC = GetDC(hwnd); HDataDC = mDC;//deleteme @@ -1252,6 +1247,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa resetHighlightingActivityLog(); EditingText = CurOffset = 0; EditingMode = MODE_NES_MEMORY; + CreateCheatMap(); //set the default table UnloadTableFile(); @@ -1685,8 +1681,10 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa checkCondition(condition, numWPs); numWPs++; - { extern int myNumWPs; - myNumWPs++; } + { + extern int myNumWPs; + myNumWPs++; + } if (hDebug) AddBreakList(); else @@ -2034,24 +2032,34 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa case MENU_MV_VIEW_PPU: case MENU_MV_VIEW_OAM: case MENU_MV_VIEW_ROM: - EditingMode = wParam - MENU_MV_VIEW_RAM; + { + int _EditingMode = wParam - MENU_MV_VIEW_RAM; + // Leave NES Memory + if (_EditingMode == MODE_NES_MEMORY && EditingMode != MODE_NES_MEMORY) + CreateCheatMap(); + // Enter NES Memory + if (_EditingMode != MODE_NES_MEMORY && EditingMode == MODE_NES_MEMORY) + ReleaseCheatMap(); + EditingMode = _EditingMode; for (i = MODE_NES_MEMORY; i <= MODE_NES_FILE; i++) if(EditingMode == i) { CheckMenuRadioItem(GetMenu(hMemView), MENU_MV_VIEW_RAM, MENU_MV_VIEW_ROM, MENU_MV_VIEW_RAM + i, MF_BYCOMMAND); break; } - if (EditingMode == MODE_NES_MEMORY) - MaxSize = 0x10000; - if (EditingMode == MODE_NES_PPU) + + switch (EditingMode) { - if (GameInfo->type==GIT_NSF) {MaxSize = 0x2000;} //Also disabled under GetMemViewData - else {MaxSize = 0x4000;} + case MODE_NES_MEMORY: + MaxSize = 0x10000; break; + case MODE_NES_PPU: + MaxSize = (GameInfo->type == GIT_NSF ? 0x2000 : 0x4000); break; + case MODE_NES_OAM: + MaxSize = 0x100; break; + case MODE_NES_FILE: //todo: add trainer size + MaxSize = 16 + CHRsize[0] + PRGsize[0]; break; } - if (EditingMode == MODE_NES_OAM) - MaxSize = 0x100; - if (EditingMode == MODE_NES_FILE) - MaxSize = 16+CHRsize[0]+PRGsize[0]; //todo: add trainer size + if (CurOffset >= MaxSize - DataAmount) CurOffset = MaxSize - DataAmount; if (CurOffset < 0) CurOffset = 0; if(CursorEndAddy >= MaxSize) CursorEndAddy = -1; @@ -2070,7 +2078,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa UpdateColorTable(); UpdateCaption(); return 0; - + } case ID_HIGHLIGHTING_HIGHLIGHT_ACTIVITY: { MemView_HighlightActivity ^= 1; diff --git a/src/drivers/win/memwatch.cpp b/src/drivers/win/memwatch.cpp index e3b4fc16..48948ab2 100644 --- a/src/drivers/win/memwatch.cpp +++ b/src/drivers/win/memwatch.cpp @@ -318,8 +318,8 @@ void UpdateMemWatch() if (FrozenAddressCount) for (unsigned int x = 0; x < FrozenAddressCount; x++) { - extern int IsByteCheat(uint8); - if (IsByteCheat(mwrec.addr)) + extern int FCEUI_FindCheatMapByte(uint16); + if (FCEUI_FindCheatMapByte(mwrec.addr)) SetTextColor(hdc,GetSysColor(COLOR_HIGHLIGHT)); } @@ -812,6 +812,8 @@ static INT_PTR CALLBACK MemWatchCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LP editlast[x]= 0; } + CreateCheatMap(); + RamChangeInitialize = true; break; @@ -830,7 +832,9 @@ static INT_PTR CALLBACK MemWatchCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LP case WM_QUIT: CloseMemoryWatch(); break; - + case WM_DESTROY: + ReleaseCheatMap(); + break; case WM_DROPFILES: { unsigned int len; diff --git a/src/drivers/win/ram_search.cpp b/src/drivers/win/ram_search.cpp index 6a05e252..ac69a91a 100644 --- a/src/drivers/win/ram_search.cpp +++ b/src/drivers/win/ram_search.cpp @@ -1420,6 +1420,8 @@ INT_PTR CALLBACK RamSearchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara CalcSubWindowPos(hDlg, NULL); + CreateCheatMap(); + switch(rs_o) { case '<': @@ -2105,6 +2107,7 @@ INT_PTR CALLBACK RamSearchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara break; case WM_DESTROY: RamSearchHWnd = NULL; + ReleaseCheatMap(); // theApp.modelessCheatDialogIsOpen = false; break; } diff --git a/src/drivers/win/ramwatch.cpp b/src/drivers/win/ramwatch.cpp index 79d17ed8..e96ce86a 100644 --- a/src/drivers/win/ramwatch.cpp +++ b/src/drivers/win/ramwatch.cpp @@ -1059,6 +1059,7 @@ INT_PTR CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam rwrecentmenu=CreateMenu(); UpdateRW_RMenu(rwrecentmenu, RAMMENU_FILE_RECENT, RW_MENU_FIRST_RECENT_FILE); + CreateCheatMap(); const char* names[3] = {"Address","Value","Notes"}; int widths[3] = {78,64,160}; init_list_box(GetDlgItem(hDlg,IDC_WATCHLIST),names,3,widths); @@ -1506,6 +1507,8 @@ INT_PTR CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam // release the hdc related objects SeparatorCache::DeInit(); + // release cheatmap + ReleaseCheatMap(); break; case WM_DROPFILES: