diff --git a/desmume/src/cheatSystem.cpp b/desmume/src/cheatSystem.cpp index 6c8dd14ab..2650c163b 100644 --- a/desmume/src/cheatSystem.cpp +++ b/desmume/src/cheatSystem.cpp @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 DeSmuME team +/* Copyright (C) 2009-2011 DeSmuME team This file is part of DeSmuME @@ -127,11 +127,11 @@ void CHEATS::ARparser(CHEATS_LIST& list) //manual hook } else - if ((hi==0x0000AA99) && (lo==0)) + if ((hi==0x0000AA99) && (lo==0)) // 0000AA99 00000000 parameter bytes 9..10 for above code (padded with 00s) { //parameter bytes 9..10 for above code (padded with 00s) } - else + else // 0XXXXXXX YYYYYYYY word[XXXXXXX+offset] = YYYYYYYY { addr = hi + offset; _MMU_write32(addr, lo); @@ -139,17 +139,17 @@ void CHEATS::ARparser(CHEATS_LIST& list) } break; - case 0x01: + case 0x01: // 1XXXXXXX 0000YYYY half[XXXXXXX+offset] = YYYY addr = hi + offset; - _MMU_write16(addr, lo & 0x0000FFFF); + _MMU_write16(addr, lo); break; - case 0x02: + case 0x02: // 2XXXXXXX 000000YY byte[XXXXXXX+offset] = YY addr = hi + offset; - _MMU_write08(addr, lo & 0x000000FF); + _MMU_write08(addr, lo); break; - case 0x03: + case 0x03: // 3XXXXXXX YYYYYYYY IF YYYYYYYY > word[XXXXXXX] ;unsigned if (hi == 0) hi = offset; // V1.54+ val = _MMU_read32(hi); if ( lo > val ) @@ -162,7 +162,11 @@ void CHEATS::ARparser(CHEATS_LIST& list) } break; - case 0x04: + case 0x04: // 4XXXXXXX YYYYYYYY IF YYYYYYYY < word[XXXXXXX] ;unsigned + if ((hi == 0x04332211) && (lo == 88776655)) //44332211 88776655 parameter bytes 1..8 for above code (example) + { + break; + } if (hi == 0) hi = offset; // V1.54+ val = _MMU_read32(hi); if ( lo < val ) @@ -175,7 +179,7 @@ void CHEATS::ARparser(CHEATS_LIST& list) } break; - case 0x05: + case 0x05: // 5XXXXXXX YYYYYYYY IF YYYYYYYY = word[XXXXXXX] if (hi == 0) hi = offset; // V1.54+ val = _MMU_read32(hi); if ( lo == val ) @@ -188,7 +192,7 @@ void CHEATS::ARparser(CHEATS_LIST& list) } break; - case 0x06: + case 0x06: // 6XXXXXXX YYYYYYYY IF YYYYYYYY <> word[XXXXXXX] if (hi == 0) hi = offset; // V1.54+ val = _MMU_read32(hi); if ( lo != val ) @@ -201,7 +205,7 @@ void CHEATS::ARparser(CHEATS_LIST& list) } break; - case 0x07: + case 0x07: // 7XXXXXXX ZZZZYYYY IF YYYY > ((not ZZZZ) AND half[XXXXXXX]) if (hi == 0) hi = offset; // V1.54+ val = _MMU_read16(hi); if ( (lo & 0xFFFF) > ( (~(lo >> 16)) & val) ) @@ -214,7 +218,7 @@ void CHEATS::ARparser(CHEATS_LIST& list) } break; - case 0x08: + case 0x08: // 8XXXXXXX ZZZZYYYY IF YYYY < ((not ZZZZ) AND half[XXXXXXX]) if (hi == 0) hi = offset; // V1.54+ val = _MMU_read16(hi); if ( (lo & 0xFFFF) < ( (~(lo >> 16)) & val) ) @@ -227,7 +231,7 @@ void CHEATS::ARparser(CHEATS_LIST& list) } break; - case 0x09: + case 0x09: // 9XXXXXXX ZZZZYYYY IF YYYY = ((not ZZZZ) AND half[XXXXXXX]) if (hi == 0) hi = offset; // V1.54+ val = _MMU_read16(hi); if ( (lo & 0xFFFF) == ( (~(lo >> 16)) & val) ) @@ -240,7 +244,7 @@ void CHEATS::ARparser(CHEATS_LIST& list) } break; - case 0x0A: + case 0x0A: // AXXXXXXX ZZZZYYYY IF YYYY <> ((not ZZZZ) AND half[XXXXXXX]) if (hi == 0) hi = offset; // V1.54+ val = _MMU_read16(hi); if ( (lo & 0xFFFF) != ( (~(lo >> 16)) & val) ) @@ -253,15 +257,15 @@ void CHEATS::ARparser(CHEATS_LIST& list) } break; - case 0x0B: + case 0x0B: // BXXXXXXX 00000000 offset = word[XXXXXXX+offset] addr = hi + offset; - offset = _MMU_read32(addr); + offset = _MMU_read32(addr);; break; case 0x0C: switch (subtype) { - case 0x0: + case 0x0: // C0000000 YYYYYYYY FOR loopcount=0 to YYYYYYYY ;execute Y+1 times if (loopcount < (lo+1)) loop_flag = 1; else @@ -270,10 +274,11 @@ void CHEATS::ARparser(CHEATS_LIST& list) loopbackline = i; break; - case 0x4: + case 0x4: // C4000000 00000000 offset = address of the C4000000 code ; V1.54 + printf("AR: untested code C4\n"); break; - case 0x5: + case 0x5: // C5000000 XXXXYYYY counter=counter+1, IF (counter AND YYYY) = XXXX ; V1.54 counter++; if ( (counter & (lo & 0xFFFF)) == ((lo >> 8) & 0xFFFF) ) { @@ -285,8 +290,8 @@ void CHEATS::ARparser(CHEATS_LIST& list) } break; - case 0x6: - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][lo>>20], lo & MMU.MMU_MASK[ARMCPU_ARM9][lo>>20], offset); + case 0x6: // C6000000 XXXXXXXX [XXXXXXXX]=offset ; V1.54 + _MMU_write32(lo, offset); break; } break; @@ -295,15 +300,15 @@ void CHEATS::ARparser(CHEATS_LIST& list) { switch (subtype) { - case 0x0: + case 0x0: // D0000000 00000000 ENDIF break; - case 0x1: + case 0x1: // D1000000 00000000 NEXT loopcount if (loop_flag) i = (loopbackline-1); break; - case 0x2: + case 0x2: // D2000000 00000000 NEXT loopcount, and then FLUSH everything if (loop_flag) i = (loopbackline-1); else @@ -317,81 +322,81 @@ void CHEATS::ARparser(CHEATS_LIST& list) } break; - case 0x3: + case 0x3: // D3000000 XXXXXXXX offset = XXXXXXXX offset = lo; break; - case 0x4: + case 0x4: // D4000000 XXXXXXXX datareg = datareg + XXXXXXXX datareg += lo; break; - case 0x5: + case 0x5: // D5000000 XXXXXXXX datareg = XXXXXXXX datareg = lo; break; - case 0x6: + case 0x6: // D6000000 XXXXXXXX word[XXXXXXXX+offset]=datareg, offset=offset+4 addr = lo + offset; - _MMU_write32(addr,datareg); + _MMU_write32(addr, datareg); offset += 4; break; - case 0x7: + case 0x7: // D7000000 XXXXXXXX half[XXXXXXXX+offset]=datareg, offset=offset+2 addr = lo + offset; - _MMU_write16(addr,datareg & 0x0000FFFF); + _MMU_write16(addr, datareg); offset += 2; break; - case 0x8: + case 0x8: // D8000000 XXXXXXXX byte[XXXXXXXX+offset]=datareg, offset=offset+1 addr = lo + offset; - _MMU_write08(addr,datareg & 0x000000FF); + _MMU_write08(addr, datareg); offset += 1; break; - case 0x9: + case 0x9: // D9000000 XXXXXXXX datareg = word[XXXXXXXX+offset] addr = lo + offset; datareg = _MMU_read32(addr); break; - case 0xA: + case 0xA: // DA000000 XXXXXXXX datareg = half[XXXXXXXX+offset] addr = lo + offset; datareg = _MMU_read16(addr); break; - case 0xB: + case 0xB: // DB000000 XXXXXXXX datareg = byte[XXXXXXXX+offset] ;bugged on pre-v1.54 addr = lo + offset; datareg = _MMU_read08(addr); break; - case 0xC: + case 0xC: // DC000000 XXXXXXXX offset = offset + XXXXXXXX offset += lo; break; } } break; - case 0xE: + case 0xE: // EXXXXXXX YYYYYYYY Copy YYYYYYYY parameter bytes to [XXXXXXXX+offset...] { u8 *tmp_code = (u8*)(list.code[i+1]); u32 addr = hi+offset; for (u32 t = 0; t < lo; t++) { - u8 tmp = tmp_code[t]; - _MMU_write08(addr,tmp); + u8 tmp = tmp_code[t]; + _MMU_write08(addr, tmp); addr++; } i += (lo / 8); } break; - case 0xF: + case 0xF: // FXXXXXXX YYYYYYYY Copy YYYYYYYY bytes from [offset..] to [XXXXXXX...] for (u32 t = 0; t < lo; t++) { u8 tmp = _MMU_read08(offset+t); - _MMU_write08(hi+t,tmp); + _MMU_write08(hi+t, tmp); } break; - //default: INFO("AR: ERROR uknown command 0x%2X at %08X:%08X\n", type, hi, lo); break; + default: PROGINFO("AR: ERROR uknown command 0x%2X at %08X:%08X\n", type, hi, lo); break; } } } @@ -727,7 +732,7 @@ void CHEATS::process() switch (list[i].type) { - case 0: // internal list system + case 0: // internal cheat system { //INFO("list at 0x02|%06X value %i (size %i)\n",list[i].code[0], list[i].lo[0], list[i].size); u32 addr = list[i].code[0][0] | 0x02000000; @@ -753,7 +758,7 @@ void CHEATS::process() break; } break; - } //end case 0 internal list system + } //end case 0 internal cheat system case 1: // Action Replay ARparser(list[i]); @@ -1066,28 +1071,97 @@ void CHEATSEARCH::getListReset() } // ========================================================================= Export +void CHEATSEXPORT::R4decrypt(u8 *buf, u32 len, u32 n) +{ + size_t r = 0; + while (r < len) + { + size_t i ; + u16 key = n ^ 0x484A; + for (i = 0 ; i < 512 && i < len - r ; i ++) + { + u8 _xor = 0; + if (key & 0x4000) _xor |= 0x80; + if (key & 0x1000) _xor |= 0x40; + if (key & 0x0800) _xor |= 0x20; + if (key & 0x0200) _xor |= 0x10; + if (key & 0x0080) _xor |= 0x08; + if (key & 0x0040) _xor |= 0x04; + if (key & 0x0002) _xor |= 0x02; + if (key & 0x0001) _xor |= 0x01; + + u32 k = ((buf[i] << 8) ^ key) << 16; + u32 x = k; + for (u8 j = 1; j < 32; j ++) + x ^= k >> j; + key = 0x0000; + if (BIT_N(x, 23)) key |= 0x8000; + if (BIT_N(k, 22)) key |= 0x4000; + if (BIT_N(k, 21)) key |= 0x2000; + if (BIT_N(k, 20)) key |= 0x1000; + if (BIT_N(k, 19)) key |= 0x0800; + if (BIT_N(k, 18)) key |= 0x0400; + if (BIT_N(k, 17) != BIT_N(x, 31)) key |= 0x0200; + if (BIT_N(k, 16) != BIT_N(x, 30)) key |= 0x0100; + if (BIT_N(k, 30) != BIT_N(k, 29)) key |= 0x0080; + if (BIT_N(k, 29) != BIT_N(k, 28)) key |= 0x0040; + if (BIT_N(k, 28) != BIT_N(k, 27)) key |= 0x0020; + if (BIT_N(k, 27) != BIT_N(k, 26)) key |= 0x0010; + if (BIT_N(k, 26) != BIT_N(k, 25)) key |= 0x0008; + if (BIT_N(k, 25) != BIT_N(k, 24)) key |= 0x0004; + if (BIT_N(k, 25) != BIT_N(x, 26)) key |= 0x0002; + if (BIT_N(k, 24) != BIT_N(x, 25)) key |= 0x0001; + buf[i] ^= _xor; + } + + buf+= 512; + r += 512; + n += 1; + } +} + bool CHEATSEXPORT::load(char *path) { + error = 0; + fp = fopen(path, "rb"); if (!fp) { printf("Error open database\n"); + error = 1; return false; } + char *headerID = "R4 CheatCode"; + char buf[255] = {0}; + fread(buf, 1, strlen(headerID), fp); + if (strncmp(buf, headerID, strlen(headerID)) != 0) + { + // check encrypted + R4decrypt((u8 *)buf, strlen(headerID), 0); + if (strcmp(buf, headerID) != 0) + { + error = 2; + return false; + } + encrypted = true; + } + fseek(fp, 0, SEEK_END); fsize = ftell(fp); fseek(fp, 0, SEEK_SET); if (!search()) { - printf("ERROR: cheat in database not founded\n"); + printf("ERROR: cheat in database not found\n"); + error = 3; return false; } if (!getCodes()) { printf("ERROR: export cheats failed\n"); + error = 4; return false; } @@ -1104,43 +1178,71 @@ void CHEATSEXPORT::close() } } -// TODO: decrypting database bool CHEATSEXPORT::search() { if (!fp) return false; - u32 pos = 0x0100; - FAT_R4 fat_empty; + u32 pos = 0x0100; + FAT_R4 fat_tmp = {0}; + u8 buf[512] = {0}; - memset(&fat, 0, sizeof(FAT_R4)); - memset(&fat_empty, 0, sizeof(FAT_R4)); - - fseek(fp, pos, SEEK_SET); - while (pos < fsize) + CRC = 0; + encOffset = 0; + u32 t = 0; + memset(date, 0, sizeof(date)); + if (encrypted) { - fread(&fat, sizeof(FAT_R4), 1, fp); - if (memcmp(&fat, &fat_empty, sizeof(FAT_R4)) == 0) break; + fseek(fp, 0, SEEK_SET); + fread(&buf[0], 1, 512, fp); + R4decrypt((u8 *)&buf[0], 512, 0); + memcpy(&date[0], &buf[0x10], 16); + } + else + { + fseek(fp, 0x10, SEEK_SET); + fread(&date, 16, 1, fp); + fseek(fp, pos, SEEK_SET); + fread(&fat_tmp, sizeof(fat), 1, fp); + } + + while (1) + { + if (encrypted) + { + memcpy(&fat, &buf[pos % 512], sizeof(fat)); + pos += sizeof(fat); + if ((pos>>9) > t) + { + t++; + fread(&buf[0], 1, 512, fp); + R4decrypt((u8 *)&buf[0], 512, t); + } + memcpy(&fat_tmp, &buf[pos % 512], sizeof(fat_tmp)); // next + } + else + { + memcpy(&fat, &fat_tmp, sizeof(fat)); + fread(&fat_tmp, sizeof(fat_tmp), 1, fp); + + } + //printf("serial: %s, offset %08X\n", fat.serial, fat.addr); if (memcmp(gameInfo.header.gameCode, &fat.serial[0], 4) == 0) { - FAT_R4 fat_tmp; - - memset(&fat_tmp, 0, sizeof(FAT_R4)); - fread(&fat_tmp, sizeof(FAT_R4), 1, fp); - if (memcmp(&fat_tmp, &fat_empty, sizeof(FAT_R4)) == 0) + dataSize = fat_tmp.addr?(fat_tmp.addr - fat.addr):0; + if (encrypted) { - // TODO - dataSize = 0; - } - else - { - dataSize = (fat_tmp.addr - fat.addr); + encOffset = fat.addr % 512; + dataSize += encOffset; } + if (!dataSize) return false; + CRC = fat.CRC; char buf[5] = {0}; memcpy(&buf, &fat.serial[0], 4); - printf("Found %s CRC %08X at 0x%08llX (size %i)\n", buf, fat.CRC, fat.addr, dataSize); + printf("Cheats: found %s CRC %08X at 0x%08llX, size %i byte(s)\n", buf, fat.CRC, fat.addr, dataSize - encOffset); return true; } - pos += sizeof(FAT_R4); + + if (fat.addr == 0) break; } memset(&fat, 0, sizeof(FAT_R4)); @@ -1158,7 +1260,7 @@ bool CHEATSEXPORT::getCodes() if (!data) return false; memset(data, 0, dataSize+8); - fseek(fp, fat.addr, SEEK_SET); + fseek(fp, fat.addr - encOffset, SEEK_SET); if (fread(data, 1, dataSize, fp) != dataSize) { @@ -1167,8 +1269,11 @@ bool CHEATSEXPORT::getCodes() return false; } - u8 *title = data; - u32 *cmd = (u32 *)(((intptr_t)title + strlen((char*)title) + 4) & 0xFFFFFFFC); + if (encrypted) + R4decrypt(data, dataSize, fat.addr >> 9); + + gametitle = data + encOffset; + u32 *cmd = (u32 *)(((intptr_t)gametitle + strlen((char*)gametitle) + 4) & 0xFFFFFFFC); numCheats = (*cmd) & (~0xF0000000); cmd += 9; cheats = new CHEATS_LIST[numCheats]; diff --git a/desmume/src/cheatSystem.h b/desmume/src/cheatSystem.h index 26561cfe3..530b807e4 100644 --- a/desmume/src/cheatSystem.h +++ b/desmume/src/cheatSystem.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2010 DeSmuME team +/* Copyright (C) 2009-2011 DeSmuME team This file is part of DeSmuME @@ -37,6 +37,10 @@ struct CHEATS_LIST // 1 - Action Replay // 2 - Codebreakers BOOL enabled; + // TODO + u8 freezeType; // 0 - normal freeze + // 1 - can decrease + // 2 - can increase u32 code[MAX_XX_CODE][2]; char description[255]; int num; @@ -115,44 +119,63 @@ enum CHEATS_DB_TYPE #pragma pack(push) #pragma pack(1) - typedef struct FAT_R4 - { - u8 serial[4]; - u32 CRC; - u64 addr; - } FAT_R4; +typedef struct FAT_R4 +{ + u8 serial[4]; + u32 CRC; + u64 addr; +} FAT_R4; #pragma pack(pop) class CHEATSEXPORT { private: CHEATS_DB_TYPE type; + bool encrypted; FILE *fp; u32 fsize; u32 dataSize; + u32 encOffset; FAT_R4 fat; bool search(); bool getCodes(); + void R4decrypt(u8 *buf, u32 len, u32 n); u32 numCheats; CHEATS_LIST *cheats; + u8 error; // 0 - no errors + // 1 - open failed/file not found + // 2 - file format is wrong (no valid header ID) + // 3 - cheat not found in database + // 4 - export error from database + public: CHEATSEXPORT() : fp(NULL), fsize(0), dataSize(0), + encOffset(0), type(CHEATS_DB_R4), + encrypted(false), numCheats(0), - cheats(0) - {} + cheats(0), + CRC(0), + error(0) + { + memset(date, 0, sizeof(date)); + } ~CHEATSEXPORT() {} + u8 *gametitle; + u8 date[17]; + u32 CRC; bool load(char *path); void close(); CHEATS_LIST *getCheats(); u32 getCheatsNum(); + u8 getErrorCode() { return error; } }; extern CHEATS *cheats; diff --git a/desmume/src/path.h b/desmume/src/path.h index 8b1ca4601..f21961510 100644 --- a/desmume/src/path.h +++ b/desmume/src/path.h @@ -95,6 +95,7 @@ public: #define SCREENSHOTKEY "Screenshots" #define AVIKEY "AviFiles" #define CHEATKEY "Cheats" + #define R4FORMATKEY "R4format" #define SOUNDKEY "SoundSamples" #define FIRMWAREKEY "Firmware" #define FORMATKEY "format" @@ -221,6 +222,7 @@ public: GetPrivateProfileString(SECTION, FORMATKEY, "%f_%s_%r", screenshotFormat, MAX_FORMAT, IniName); savelastromvisit = GetPrivateProfileBool(SECTION, LASTVISITKEY, true, IniName); currentimageformat = (ImageFormat)GetPrivateProfileInt(SECTION, DEFAULTFORMATKEY, PNG, IniName); + r4Format = (R4Format)GetPrivateProfileInt(SECTION, R4FORMATKEY, R4_CHEAT_DAT, IniName); #endif /* needsSaving = GetPrivateProfileInt(SECTION, NEEDSSAVINGKEY, TRUE, IniName); @@ -412,6 +414,18 @@ public: strncpy(output, file.c_str(), MAX_PATH); } + enum R4Format + { +#if defined(_WINDOWS) && !defined(WXPORT) + R4_CHEAT_DAT = IDC_R4TYPE1, + R4_USRCHEAT_DAT = IDC_R4TYPE2 +#else + R4_CHEAT_DAT, + R4_USRCHEAT_DAT +#endif + }; + R4Format r4Format; + enum ImageFormat { #if defined(_WINDOWS) && !defined(WXPORT) diff --git a/desmume/src/windows/cheatsWin.cpp b/desmume/src/windows/cheatsWin.cpp index 2369e0884..6a172f5bf 100644 --- a/desmume/src/windows/cheatsWin.cpp +++ b/desmume/src/windows/cheatsWin.cpp @@ -1,4 +1,4 @@ -/* Copyright 2009-2010 DeSmuME team +/* Copyright (C) 2009-2011 DeSmuME team This file is part of DeSmuME @@ -24,7 +24,13 @@ #include "../debug.h" #include "../utils/xstring.h" #include "../path.h" +#include "../NDSSystem.h" +#include "../version.h" +extern u8 CheatsR4Type = 0; + +static const char *HEX_Valid = "Oo0123456789ABCDEFabcdef"; +static const char *DEC_Valid = "Oo0123456789"; static u8 searchType = 0; static u8 searchSize = 0; static u8 searchSign = 0; @@ -80,7 +86,16 @@ u32 searchRange[4][2] = { //========================================= Export static CHEATSEXPORT *cheatsExport = NULL; -void CheatsExportDialog(HWND hwnd); +bool CheatsExportDialog(HWND hwnd); + +void generateAR(HWND dialog, u32 addr, u32 val, u8 size) +{ + // Action Replay code generate + if (size > 3) size = 3; + char buf[17] = {0}; + sprintf(buf, "%X%07X %08X", 3-size, addr | 0x02000000, val); + SetWindowText(GetDlgItem(dialog, IDC_AR_CODE), buf); +} LONG_PTR CALLBACK EditValueProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -88,21 +103,6 @@ LONG_PTR CALLBACK EditValueProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara { switch (wParam) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - break; - case 'o': - case 'O': - wParam = '0'; - break; case '-': { u32 pos = 0; @@ -120,6 +120,11 @@ LONG_PTR CALLBACK EditValueProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara cheatAddPasteCheck = true; break; default: + if (strchr(DEC_Valid, wParam)) + { + if(wParam=='o' || wParam=='O') wParam='0'; + break; + } wParam = 0; break; } @@ -135,35 +140,6 @@ LONG_PTR CALLBACK EditValueHEXProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP { switch (wParam) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - break; - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - wParam -= 32; - break; - case 'o': - case 'O': - wParam = '0'; - break; case VK_BACK: case 0x3: // ^C case 0x18: // ^X @@ -173,6 +149,11 @@ LONG_PTR CALLBACK EditValueHEXProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP cheatAddPasteCheck = true; break; default: + if (strchr(HEX_Valid, wParam)) + { + if(wParam=='o' || wParam=='O') wParam='0'; + break; + } wParam = 0; break; } @@ -190,6 +171,8 @@ INT_PTR CALLBACK CheatsAddProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam { case WM_INITDIALOG: { + memset(editBuf, 0, sizeof(editBuf)); + memset(&tempCheat, 0, sizeof(tempCheat)); saveOldEditProc = oldEditProc; SendMessage(GetDlgItem(dialog, IDC_EDIT1), EM_SETLIMITTEXT, 6, 0); SendMessage(GetDlgItem(dialog, IDC_EDIT2), EM_SETLIMITTEXT, 11, 0); @@ -241,6 +224,8 @@ INT_PTR CALLBACK CheatsAddProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam SetFocus(GetDlgItem(dialog, IDC_EDIT2)); SendMessage(GetDlgItem(dialog, IDC_EDIT2), EM_SETSEL, 0, -1); } + + CheatAddVerify(dialog,editBuf[0],editBuf[1],searchAddSize); } return searchAddMode != 2; @@ -380,6 +365,8 @@ INT_PTR CALLBACK CheatsEditProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lpara { case WM_INITDIALOG: { + memset(editBuf, 0, sizeof(editBuf)); + memset(&tempCheat, 0, sizeof(tempCheat)); saveOldEditProc = oldEditProc; SendMessage(GetDlgItem(dialog, IDC_EDIT1), EM_SETLIMITTEXT, 6, 0); SendMessage(GetDlgItem(dialog, IDC_EDIT2), EM_SETLIMITTEXT, 10, 0); @@ -406,6 +393,8 @@ INT_PTR CALLBACK CheatsEditProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lpara CheckDlgButton(dialog, IDC_CHECK1, tempCheat.enabled?BST_CHECKED:BST_UNCHECKED); CheckRadioButton(dialog, searchSizeIDDs[0], searchSizeIDDs[ARRAY_SIZE(searchSizeIDDs) - 1], searchSizeIDDs[tempCheat.size]); SetWindowText(GetDlgItem(dialog, IDOK), "Update"); + + generateAR(dialog, tempCheat.code[0][0], tempCheat.code[0][1], searchSizeIDDs[tempCheat.size]); } return TRUE; @@ -519,12 +508,14 @@ INT_PTR CALLBACK CheatsAdd_XX_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lp { case WM_INITDIALOG: { + memset(editBuf, 0, sizeof(editBuf)); SendMessage(GetDlgItem(dialog, IDC_EDIT2), EM_FMTLINES, (WPARAM)TRUE, (LPARAM)0); if (cheatXXtype == 0) { if (cheatXXaction == 0) // add { + memset(&tempCheat, 0, sizeof(tempCheat)); SetWindowText(dialog, "Add Action Replay code"); tempCheat.enabled = TRUE; } @@ -537,6 +528,7 @@ INT_PTR CALLBACK CheatsAdd_XX_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lp { if (cheatXXaction == 0) // add { + memset(&tempCheat, 0, sizeof(tempCheat)); SetWindowText(dialog, "Add Codebreaker code"); tempCheat.enabled = TRUE; } @@ -669,23 +661,23 @@ INT_PTR CALLBACK CheatsListBox_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM l { case WM_INITDIALOG: { + // TODO: Codebreaker + ShowWindow(GetDlgItem(dialog, IDC_BADD_CB), SW_HIDE);// hide button + LV_COLUMN lvColumn; u32 address = 0; u32 val = 0; cheatListView = GetDlgItem(dialog, IDC_LIST1); - //ListView_SetExtendedListViewStyle(GetDlgItem(hDlg, IDC_CHEAT_LIST), LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES); ListView_SetExtendedListViewStyle(cheatListView, LVS_EX_FULLROWSELECT | LVS_EX_TWOCLICKACTIVATE | LVS_EX_CHECKBOXES); memset(&lvColumn,0,sizeof(LV_COLUMN)); lvColumn.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT; - lvColumn.fmt=LVCFMT_CENTER; lvColumn.cx=20; lvColumn.pszText=""; ListView_InsertColumn(cheatListView, 0, &lvColumn); - lvColumn.fmt=LVCFMT_LEFT; lvColumn.cx=84; lvColumn.pszText="Address"; @@ -748,8 +740,8 @@ INT_PTR CALLBACK CheatsListBox_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM l EnableWindow(GetDlgItem(dialog, IDOK), FALSE); - ListView_SetItemState(searchListView,0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED); - SetFocus(searchListView); + ListView_SetItemState(cheatListView,0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED); + SetFocus(cheatListView); return TRUE; } @@ -759,6 +751,10 @@ INT_PTR CALLBACK CheatsListBox_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM l LPNMHDR tmp_msg = (LPNMHDR)lparam; switch (tmp_msg->code) { + case LVN_ITEMACTIVATE: + SendMessage(dialog, WM_COMMAND, IDC_BEDIT, 0); + break; + case LVN_ITEMCHANGED: { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lparam; @@ -813,9 +809,7 @@ INT_PTR CALLBACK CheatsListBox_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM l { case IDOK: if (cheats->save()) - { EndDialog(dialog, TRUE); - } else MessageBox(dialog, "Can't save cheats to file.\nCheck your path (Menu->Config->Path Settings->\"Cheats\")","Error",MB_OK); return TRUE; @@ -845,7 +839,6 @@ INT_PTR CALLBACK CheatsListBox_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM l ListView_SetItemText(cheatListView, row, 2, buf); ListView_SetItemText(cheatListView, row, 3, editBuf[2]); ListView_SetCheckState(cheatListView, row, searchAddFreeze); - EnableWindow(GetDlgItem(dialog, IDOK), TRUE); } } @@ -854,14 +847,10 @@ INT_PTR CALLBACK CheatsListBox_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM l case IDC_BADD_AR: { if (LOWORD(wparam) == IDC_BADD_AR) - { cheatXXtype = 0; - } else if (LOWORD(wparam) == IDC_BADD_CB) - { cheatXXtype = 1; - } else return TRUE; cheatXXaction = 0; // 0 = add @@ -899,7 +888,6 @@ INT_PTR CALLBACK CheatsListBox_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM l if (cheatEditPos > cheats->getSize()) return TRUE; cheats->get(&tempCheat, cheatEditPos); - switch (tempCheat.type) { case 0: // internal @@ -955,20 +943,18 @@ INT_PTR CALLBACK CheatsListBox_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM l { int tmp_pos = ListView_GetNextItem(cheatListView, -1, LVNI_ALL | LVNI_SELECTED); if (tmp_pos == -1) - { break; - } + if (cheats->remove(tmp_pos)) - { ListView_DeleteItem(cheatListView, tmp_pos); - } } EnableWindow(GetDlgItem(dialog, IDOK), TRUE); } return TRUE; case IDC_EXPORT: - CheatsExportDialog(dialog); + if (CheatsExportDialog(dialog)) + EnableWindow(GetDlgItem(dialog, IDOK), TRUE); return TRUE; } break; @@ -1039,7 +1025,7 @@ INT_PTR CALLBACK CheatsSearchExactWnd(HWND dialog, UINT msg,WPARAM wparam,LPARAM ltoa(searchNumberResults, buf, 10); SetWindowText(GetDlgItem(dialog, IDC_SNUMBER), buf); SetFocus(GetDlgItem(dialog, IDC_EVALUE)); - break; + return TRUE; } case WM_COMMAND: @@ -1382,6 +1368,8 @@ void CheatAddVerify(HWND dialog,char* addre, char* valu,u8 size) } else EnableWindow(GetDlgItem(dialog, IDOK), TRUE); + + generateAR(dialog, fix, fix2, size); } @@ -1392,9 +1380,18 @@ INT_PTR CALLBACK CheatsExportProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lpa { case WM_INITDIALOG: { + SetWindowText(GetDlgItem(dialog, IDC_CDATE), (LPCSTR)cheatsExport->date); + if ((char*)cheatsExport->gametitle != "") + { + char buf[512] = {0}; + GetWindowText(dialog, &buf[0], sizeof(buf)); + strcat(buf, ": "); + strcat(buf, (char*)cheatsExport->gametitle); + SetWindowText(dialog, (LPCSTR)buf); + } LV_COLUMN lvColumn; exportListView = GetDlgItem(dialog, IDC_LIST_CHEATS); - ListView_SetExtendedListViewStyle(exportListView, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); + ListView_SetExtendedListViewStyle(exportListView, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_CHECKBOXES); memset(&lvColumn,0,sizeof(LV_COLUMN)); lvColumn.mask=LVCF_FMT|LVCF_TEXT|LVCF_WIDTH; @@ -1415,6 +1412,10 @@ INT_PTR CALLBACK CheatsExportProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lpa lvi.pszText= tmp[i].description; SendMessage(exportListView, LVM_INSERTITEM, 0, (LPARAM)&lvi); } + if (gameInfo.crc != cheatsExport->CRC) + { + //MessageBox(dialog, "WARNING!\n Checksums not matching.",EMU_DESMUME_NAME_AND_VERSION(), MB_OK);// | MB_ICON_ERROR); + } SendMessage(exportListView, WM_SETREDRAW, (WPARAM)TRUE,0); ListView_SetItemState(exportListView,0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED); SetFocus(exportListView); @@ -1426,14 +1427,15 @@ INT_PTR CALLBACK CheatsExportProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lpa { case IDOK: { - u32 count = ListView_GetSelectedCount(exportListView); + u32 count = ListView_GetItemCount(exportListView); if (count > 0) { - u32 prev = ListView_GetNextItem(exportListView, -1, LVIS_SELECTED); + bool done = false; + CHEATS_LIST *tmp = (CHEATS_LIST*)cheatsExport->getCheats(); for (u32 i = 0; i < count; i++) { - CHEATS_LIST *tmp = (CHEATS_LIST*)cheatsExport->getCheats(); - cheats->add_AR_Direct(tmp[prev]); + if (!ListView_GetCheckState(exportListView, i)) continue; + cheats->add_AR_Direct(tmp[i]); LVITEM lvi; @@ -1444,11 +1446,10 @@ INT_PTR CALLBACK CheatsExportProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lpa u32 row = ListView_InsertItem(cheatListView, &lvi); ListView_SetItemText(cheatListView, row, 1, "Action"); ListView_SetItemText(cheatListView, row, 2, "Replay"); - ListView_SetItemText(cheatListView, row, 3, tmp[prev].description); - - prev = ListView_GetNextItem(exportListView, prev, LVIS_SELECTED); + ListView_SetItemText(cheatListView, row, 3, tmp[i].description); + done = true; } - EndDialog(dialog, TRUE); + if (done) EndDialog(dialog, TRUE); } } break; @@ -1463,32 +1464,50 @@ INT_PTR CALLBACK CheatsExportProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lpa return FALSE; } -void CheatsExportDialog(HWND hwnd) +bool CheatsExportDialog(HWND hwnd) { + bool res = false; cheatsExport = new CHEATSEXPORT(); - if (!cheatsExport) return; + if (!cheatsExport) return false; char buf[MAX_PATH] = {0}; - PathInfo path; - path.init("USRCHEAT.DAT"); - path.getpathnoext(path.MODULE, &buf[0]); - strcat(buf, ".DAT"); - // TODO: select file + strcpy(buf, path.getpath(path.CHEATS).c_str()); + if (path.r4Format == path.R4_CHEAT_DAT) + strcat(buf,"cheat.dat"); + else + if (path.r4Format == path.R4_USRCHEAT_DAT) + strcat(buf,"usrcheat.dat"); + else return false; if (cheatsExport->load(buf)) { if (cheatsExport->getCheatsNum() > 0) - { - DialogBoxW(hAppInst, MAKEINTRESOURCEW(IDD_CHEAT_EXPORT), hwnd, (DLGPROC) CheatsExportProc); - } + res = DialogBoxW(hAppInst, MAKEINTRESOURCEW(IDD_CHEAT_EXPORT), hwnd, (DLGPROC) CheatsExportProc); else - { MessageBox(hwnd, "Cheats for this game in database not founded.", "DeSmuME", MB_OK | MB_ICONERROR); - } } else - MessageBox(hwnd, "Error loading cheat database.", "DeSmuME", MB_OK | MB_ICONERROR); + { + char buf2[512] = {0}; + if (cheatsExport->getErrorCode() == 1) + sprintf(buf2, "Error loading cheats database. File not found\n\"%s\"\nCheck your path (Menu->Config->Path Settings->\"Cheats\")\n\nYou can download it from http://cheats.gbatemp.net/", buf); + else + if (cheatsExport->getErrorCode() == 2) + sprintf(buf2, "File \"%s\" is not R4 cheats database.\nWrong file format!", buf); + else + if (cheatsExport->getErrorCode() == 3) + sprintf(buf2, "Serial \"%s\" not found in database.", gameInfo.ROMserial); + else + if (cheatsExport->getErrorCode() == 4) + sprintf(buf2, "Error export from database"); + else + sprintf(buf2, "Unknown error!!!"); + MessageBox(hwnd, buf2, "DeSmuME", MB_OK | MB_ICONERROR); + } cheatsExport->close(); delete cheatsExport; cheatsExport = NULL; -} \ No newline at end of file + + return res; +} + diff --git a/desmume/src/windows/cheatsWin.h b/desmume/src/windows/cheatsWin.h index 3bd6e3da5..3fcdc6136 100644 --- a/desmume/src/windows/cheatsWin.h +++ b/desmume/src/windows/cheatsWin.h @@ -1,4 +1,4 @@ -/* Copyright 2009 DeSmuME team +/* Copyright (C) 2009-2011 DeSmuME team This file is part of DeSmuME diff --git a/desmume/src/windows/resource.h b/desmume/src/windows/resource.h index 8fc39f7f7..987121c38 100644 --- a/desmume/src/windows/resource.h +++ b/desmume/src/windows/resource.h @@ -389,12 +389,16 @@ #define IDC_EXPORT 1038 #define IDC_RFOLDER 1039 #define IDC_2012 1039 +#define IDC_EXPORT2 1039 #define IDC_BBROWSE2 1040 #define IDC_PATHDESMUME 1041 +#define IDC_CDATE 1041 #define IDC_BRESTART 1042 #define IDC_BVIEW 1043 +#define IDC_R4TYPE1 1043 #define IDC_BSEARCH 1044 #define IDC_PIANO_F 1044 +#define IDC_R4TYPE2 1044 #define IDC_RADIO1 1045 #define IDC_PIANO_FS 1045 #define IDC_RADIO2 1046 @@ -405,6 +409,7 @@ #define IDC_PIANO_A 1048 #define IDC_RADIO5 1049 #define IDC_PIANO_AS 1049 +#define IDC_AR_CODE 1049 #define IDC_RADIO6 1050 #define IDC_PIANO_G 1050 #define IDC_RADIO7 1051 @@ -972,7 +977,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 125 #define _APS_NEXT_COMMAND_VALUE 40094 -#define _APS_NEXT_CONTROL_VALUE 1041 +#define _APS_NEXT_CONTROL_VALUE 1050 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/desmume/src/windows/resources.rc b/desmume/src/windows/resources.rc index 7336ae7cb..025e80dc5 100644 Binary files a/desmume/src/windows/resources.rc and b/desmume/src/windows/resources.rc differ