- add support R4 encrypted cheats base;
cheats (winport):
- fix GUI bugs;
- add boxcheck in export dialog;
- add convert internal cheats to AR;
- add select R4 cheats base format (Path Settings);
- cheats base file moved to cheat folder (CHEAT.DAT/USRCHEAT.DAT);
This commit is contained in:
mtabachenko 2011-05-19 12:54:00 +00:00
parent 10f649e843
commit 13ae3664ab
7 changed files with 338 additions and 172 deletions

View File

@ -1,4 +1,4 @@
/* Copyright 2009-2011 DeSmuME team /* Copyright (C) 2009-2011 DeSmuME team
This file is part of DeSmuME This file is part of DeSmuME
@ -127,11 +127,11 @@ void CHEATS::ARparser(CHEATS_LIST& list)
//manual hook //manual hook
} }
else 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) //parameter bytes 9..10 for above code (padded with 00s)
} }
else else // 0XXXXXXX YYYYYYYY word[XXXXXXX+offset] = YYYYYYYY
{ {
addr = hi + offset; addr = hi + offset;
_MMU_write32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo); _MMU_write32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo);
@ -139,17 +139,17 @@ void CHEATS::ARparser(CHEATS_LIST& list)
} }
break; break;
case 0x01: case 0x01: // 1XXXXXXX 0000YYYY half[XXXXXXX+offset] = YYYY
addr = hi + offset; addr = hi + offset;
_MMU_write16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo & 0x0000FFFF); _MMU_write16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo);
break; break;
case 0x02: case 0x02: // 2XXXXXXX 000000YY byte[XXXXXXX+offset] = YY
addr = hi + offset; addr = hi + offset;
_MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo & 0x000000FF); _MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo);
break; break;
case 0x03: case 0x03: // 3XXXXXXX YYYYYYYY IF YYYYYYYY > word[XXXXXXX] ;unsigned
if (hi == 0) hi = offset; // V1.54+ if (hi == 0) hi = offset; // V1.54+
val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(hi);
if ( lo > val ) if ( lo > val )
@ -162,7 +162,11 @@ void CHEATS::ARparser(CHEATS_LIST& list)
} }
break; 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+ if (hi == 0) hi = offset; // V1.54+
val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(hi);
if ( lo < val ) if ( lo < val )
@ -175,7 +179,7 @@ void CHEATS::ARparser(CHEATS_LIST& list)
} }
break; break;
case 0x05: case 0x05: // 5XXXXXXX YYYYYYYY IF YYYYYYYY = word[XXXXXXX]
if (hi == 0) hi = offset; // V1.54+ if (hi == 0) hi = offset; // V1.54+
val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(hi);
if ( lo == val ) if ( lo == val )
@ -188,7 +192,7 @@ void CHEATS::ARparser(CHEATS_LIST& list)
} }
break; break;
case 0x06: case 0x06: // 6XXXXXXX YYYYYYYY IF YYYYYYYY <> word[XXXXXXX]
if (hi == 0) hi = offset; // V1.54+ if (hi == 0) hi = offset; // V1.54+
val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(hi);
if ( lo != val ) if ( lo != val )
@ -201,7 +205,7 @@ void CHEATS::ARparser(CHEATS_LIST& list)
} }
break; break;
case 0x07: case 0x07: // 7XXXXXXX ZZZZYYYY IF YYYY > ((not ZZZZ) AND half[XXXXXXX])
if (hi == 0) hi = offset; // V1.54+ if (hi == 0) hi = offset; // V1.54+
val = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); val = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(hi);
if ( (lo & 0xFFFF) > ( (~(lo >> 16)) & val) ) if ( (lo & 0xFFFF) > ( (~(lo >> 16)) & val) )
@ -214,7 +218,7 @@ void CHEATS::ARparser(CHEATS_LIST& list)
} }
break; break;
case 0x08: case 0x08: // 8XXXXXXX ZZZZYYYY IF YYYY < ((not ZZZZ) AND half[XXXXXXX])
if (hi == 0) hi = offset; // V1.54+ if (hi == 0) hi = offset; // V1.54+
val = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); val = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(hi);
if ( (lo & 0xFFFF) < ( (~(lo >> 16)) & val) ) if ( (lo & 0xFFFF) < ( (~(lo >> 16)) & val) )
@ -227,7 +231,7 @@ void CHEATS::ARparser(CHEATS_LIST& list)
} }
break; break;
case 0x09: case 0x09: // 9XXXXXXX ZZZZYYYY IF YYYY = ((not ZZZZ) AND half[XXXXXXX])
if (hi == 0) hi = offset; // V1.54+ if (hi == 0) hi = offset; // V1.54+
val = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); val = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(hi);
if ( (lo & 0xFFFF) == ( (~(lo >> 16)) & val) ) if ( (lo & 0xFFFF) == ( (~(lo >> 16)) & val) )
@ -240,7 +244,7 @@ void CHEATS::ARparser(CHEATS_LIST& list)
} }
break; break;
case 0x0A: case 0x0A: // AXXXXXXX ZZZZYYYY IF YYYY <> ((not ZZZZ) AND half[XXXXXXX])
if (hi == 0) hi = offset; // V1.54+ if (hi == 0) hi = offset; // V1.54+
val = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); val = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(hi);
if ( (lo & 0xFFFF) != ( (~(lo >> 16)) & val) ) if ( (lo & 0xFFFF) != ( (~(lo >> 16)) & val) )
@ -253,15 +257,15 @@ void CHEATS::ARparser(CHEATS_LIST& list)
} }
break; break;
case 0x0B: case 0x0B: // BXXXXXXX 00000000 offset = word[XXXXXXX+offset]
addr = hi + offset; addr = hi + offset;
offset = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr); offset = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr);;
break; break;
case 0x0C: case 0x0C:
switch (subtype) switch (subtype)
{ {
case 0x0: case 0x0: // C0000000 YYYYYYYY FOR loopcount=0 to YYYYYYYY ;execute Y+1 times
if (loopcount < (lo+1)) if (loopcount < (lo+1))
loop_flag = 1; loop_flag = 1;
else else
@ -270,10 +274,11 @@ void CHEATS::ARparser(CHEATS_LIST& list)
loopbackline = i; loopbackline = i;
break; break;
case 0x4: case 0x4: // C4000000 00000000 offset = address of the C4000000 code ; V1.54
printf("AR: untested code C4\n");
break; break;
case 0x5: case 0x5: // C5000000 XXXXYYYY counter=counter+1, IF (counter AND YYYY) = XXXX ; V1.54
counter++; counter++;
if ( (counter & (lo & 0xFFFF)) == ((lo >> 8) & 0xFFFF) ) if ( (counter & (lo & 0xFFFF)) == ((lo >> 8) & 0xFFFF) )
{ {
@ -285,8 +290,8 @@ void CHEATS::ARparser(CHEATS_LIST& list)
} }
break; break;
case 0x6: case 0x6: // C6000000 XXXXXXXX [XXXXXXXX]=offset ; V1.54
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][lo>>20], lo & MMU.MMU_MASK[ARMCPU_ARM9][lo>>20], offset); _MMU_write32<ARMCPU_ARM9,MMU_AT_DEBUG>(lo, offset);
break; break;
} }
break; break;
@ -295,15 +300,15 @@ void CHEATS::ARparser(CHEATS_LIST& list)
{ {
switch (subtype) switch (subtype)
{ {
case 0x0: case 0x0: // D0000000 00000000 ENDIF
break; break;
case 0x1: case 0x1: // D1000000 00000000 NEXT loopcount
if (loop_flag) if (loop_flag)
i = (loopbackline-1); i = (loopbackline-1);
break; break;
case 0x2: case 0x2: // D2000000 00000000 NEXT loopcount, and then FLUSH everything
if (loop_flag) if (loop_flag)
i = (loopbackline-1); i = (loopbackline-1);
else else
@ -317,59 +322,59 @@ void CHEATS::ARparser(CHEATS_LIST& list)
} }
break; break;
case 0x3: case 0x3: // D3000000 XXXXXXXX offset = XXXXXXXX
offset = lo; offset = lo;
break; break;
case 0x4: case 0x4: // D4000000 XXXXXXXX datareg = datareg + XXXXXXXX
datareg += lo; datareg += lo;
break; break;
case 0x5: case 0x5: // D5000000 XXXXXXXX datareg = XXXXXXXX
datareg = lo; datareg = lo;
break; break;
case 0x6: case 0x6: // D6000000 XXXXXXXX word[XXXXXXXX+offset]=datareg, offset=offset+4
addr = lo + offset; addr = lo + offset;
_MMU_write32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, datareg); _MMU_write32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, datareg);
offset += 4; offset += 4;
break; break;
case 0x7: case 0x7: // D7000000 XXXXXXXX half[XXXXXXXX+offset]=datareg, offset=offset+2
addr = lo + offset; addr = lo + offset;
_MMU_write16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr,datareg & 0x0000FFFF); _MMU_write16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, datareg);
offset += 2; offset += 2;
break; break;
case 0x8: case 0x8: // D8000000 XXXXXXXX byte[XXXXXXXX+offset]=datareg, offset=offset+1
addr = lo + offset; addr = lo + offset;
_MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr,datareg & 0x000000FF); _MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, datareg);
offset += 1; offset += 1;
break; break;
case 0x9: case 0x9: // D9000000 XXXXXXXX datareg = word[XXXXXXXX+offset]
addr = lo + offset; addr = lo + offset;
datareg = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr); datareg = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr);
break; break;
case 0xA: case 0xA: // DA000000 XXXXXXXX datareg = half[XXXXXXXX+offset]
addr = lo + offset; addr = lo + offset;
datareg = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr); datareg = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr);
break; break;
case 0xB: case 0xB: // DB000000 XXXXXXXX datareg = byte[XXXXXXXX+offset] ;bugged on pre-v1.54
addr = lo + offset; addr = lo + offset;
datareg = _MMU_read08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr); datareg = _MMU_read08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr);
break; break;
case 0xC: case 0xC: // DC000000 XXXXXXXX offset = offset + XXXXXXXX
offset += lo; offset += lo;
break; break;
} }
} }
break; break;
case 0xE: case 0xE: // EXXXXXXX YYYYYYYY Copy YYYYYYYY parameter bytes to [XXXXXXXX+offset...]
{ {
u8 *tmp_code = (u8*)(list.code[i+1]); u8 *tmp_code = (u8*)(list.code[i+1]);
u32 addr = hi+offset; u32 addr = hi+offset;
@ -384,14 +389,14 @@ void CHEATS::ARparser(CHEATS_LIST& list)
} }
break; break;
case 0xF: case 0xF: // FXXXXXXX YYYYYYYY Copy YYYYYYYY bytes from [offset..] to [XXXXXXX...]
for (u32 t = 0; t < lo; t++) for (u32 t = 0; t < lo; t++)
{ {
u8 tmp = _MMU_read08<ARMCPU_ARM9,MMU_AT_DEBUG>(offset+t); u8 tmp = _MMU_read08<ARMCPU_ARM9,MMU_AT_DEBUG>(offset+t);
_MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(hi+t, tmp); _MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(hi+t, tmp);
} }
break; 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) 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); //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; u32 addr = list[i].code[0][0] | 0x02000000;
@ -753,7 +758,7 @@ void CHEATS::process()
break; break;
} }
break; break;
} //end case 0 internal list system } //end case 0 internal cheat system
case 1: // Action Replay case 1: // Action Replay
ARparser(list[i]); ARparser(list[i]);
@ -1066,28 +1071,97 @@ void CHEATSEARCH::getListReset()
} }
// ========================================================================= Export // ========================================================================= 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) bool CHEATSEXPORT::load(char *path)
{ {
error = 0;
fp = fopen(path, "rb"); fp = fopen(path, "rb");
if (!fp) if (!fp)
{ {
printf("Error open database\n"); printf("Error open database\n");
error = 1;
return false; 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); fseek(fp, 0, SEEK_END);
fsize = ftell(fp); fsize = ftell(fp);
fseek(fp, 0, SEEK_SET); fseek(fp, 0, SEEK_SET);
if (!search()) if (!search())
{ {
printf("ERROR: cheat in database not founded\n"); printf("ERROR: cheat in database not found\n");
error = 3;
return false; return false;
} }
if (!getCodes()) if (!getCodes())
{ {
printf("ERROR: export cheats failed\n"); printf("ERROR: export cheats failed\n");
error = 4;
return false; return false;
} }
@ -1104,43 +1178,71 @@ void CHEATSEXPORT::close()
} }
} }
// TODO: decrypting database
bool CHEATSEXPORT::search() bool CHEATSEXPORT::search()
{ {
if (!fp) return false; if (!fp) return false;
u32 pos = 0x0100; u32 pos = 0x0100;
FAT_R4 fat_empty; FAT_R4 fat_tmp = {0};
u8 buf[512] = {0};
memset(&fat, 0, sizeof(FAT_R4)); CRC = 0;
memset(&fat_empty, 0, sizeof(FAT_R4)); encOffset = 0;
u32 t = 0;
fseek(fp, pos, SEEK_SET); memset(date, 0, sizeof(date));
while (pos < fsize) if (encrypted)
{ {
fread(&fat, sizeof(FAT_R4), 1, fp); fseek(fp, 0, SEEK_SET);
if (memcmp(&fat, &fat_empty, sizeof(FAT_R4)) == 0) break; fread(&buf[0], 1, 512, fp);
if (memcmp(gameInfo.header.gameCode, &fat.serial[0], 4) == 0) R4decrypt((u8 *)&buf[0], 512, 0);
{ memcpy(&date[0], &buf[0x10], 16);
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)
{
// TODO
dataSize = 0;
} }
else else
{ {
dataSize = (fat_tmp.addr - fat.addr); 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)
{
dataSize = fat_tmp.addr?(fat_tmp.addr - fat.addr):0;
if (encrypted)
{
encOffset = fat.addr % 512;
dataSize += encOffset;
}
if (!dataSize) return false;
CRC = fat.CRC;
char buf[5] = {0}; char buf[5] = {0};
memcpy(&buf, &fat.serial[0], 4); 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; return true;
} }
pos += sizeof(FAT_R4);
if (fat.addr == 0) break;
} }
memset(&fat, 0, sizeof(FAT_R4)); memset(&fat, 0, sizeof(FAT_R4));
@ -1158,7 +1260,7 @@ bool CHEATSEXPORT::getCodes()
if (!data) return false; if (!data) return false;
memset(data, 0, dataSize+8); 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) if (fread(data, 1, dataSize, fp) != dataSize)
{ {
@ -1167,8 +1269,11 @@ bool CHEATSEXPORT::getCodes()
return false; return false;
} }
u8 *title = data; if (encrypted)
u32 *cmd = (u32 *)(((intptr_t)title + strlen((char*)title) + 4) & 0xFFFFFFFC); R4decrypt(data, dataSize, fat.addr >> 9);
gametitle = data + encOffset;
u32 *cmd = (u32 *)(((intptr_t)gametitle + strlen((char*)gametitle) + 4) & 0xFFFFFFFC);
numCheats = (*cmd) & (~0xF0000000); numCheats = (*cmd) & (~0xF0000000);
cmd += 9; cmd += 9;
cheats = new CHEATS_LIST[numCheats]; cheats = new CHEATS_LIST[numCheats];

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009-2010 DeSmuME team /* Copyright (C) 2009-2011 DeSmuME team
This file is part of DeSmuME This file is part of DeSmuME
@ -37,6 +37,10 @@ struct CHEATS_LIST
// 1 - Action Replay // 1 - Action Replay
// 2 - Codebreakers // 2 - Codebreakers
BOOL enabled; BOOL enabled;
// TODO
u8 freezeType; // 0 - normal freeze
// 1 - can decrease
// 2 - can increase
u32 code[MAX_XX_CODE][2]; u32 code[MAX_XX_CODE][2];
char description[255]; char description[255];
int num; int num;
@ -127,32 +131,51 @@ class CHEATSEXPORT
{ {
private: private:
CHEATS_DB_TYPE type; CHEATS_DB_TYPE type;
bool encrypted;
FILE *fp; FILE *fp;
u32 fsize; u32 fsize;
u32 dataSize; u32 dataSize;
u32 encOffset;
FAT_R4 fat; FAT_R4 fat;
bool search(); bool search();
bool getCodes(); bool getCodes();
void R4decrypt(u8 *buf, u32 len, u32 n);
u32 numCheats; u32 numCheats;
CHEATS_LIST *cheats; 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: public:
CHEATSEXPORT() : CHEATSEXPORT() :
fp(NULL), fp(NULL),
fsize(0), fsize(0),
dataSize(0), dataSize(0),
encOffset(0),
type(CHEATS_DB_R4), type(CHEATS_DB_R4),
encrypted(false),
numCheats(0), numCheats(0),
cheats(0) cheats(0),
{} CRC(0),
error(0)
{
memset(date, 0, sizeof(date));
}
~CHEATSEXPORT() ~CHEATSEXPORT()
{} {}
u8 *gametitle;
u8 date[17];
u32 CRC;
bool load(char *path); bool load(char *path);
void close(); void close();
CHEATS_LIST *getCheats(); CHEATS_LIST *getCheats();
u32 getCheatsNum(); u32 getCheatsNum();
u8 getErrorCode() { return error; }
}; };
extern CHEATS *cheats; extern CHEATS *cheats;

View File

@ -95,6 +95,7 @@ public:
#define SCREENSHOTKEY "Screenshots" #define SCREENSHOTKEY "Screenshots"
#define AVIKEY "AviFiles" #define AVIKEY "AviFiles"
#define CHEATKEY "Cheats" #define CHEATKEY "Cheats"
#define R4FORMATKEY "R4format"
#define SOUNDKEY "SoundSamples" #define SOUNDKEY "SoundSamples"
#define FIRMWAREKEY "Firmware" #define FIRMWAREKEY "Firmware"
#define FORMATKEY "format" #define FORMATKEY "format"
@ -221,6 +222,7 @@ public:
GetPrivateProfileString(SECTION, FORMATKEY, "%f_%s_%r", screenshotFormat, MAX_FORMAT, IniName); GetPrivateProfileString(SECTION, FORMATKEY, "%f_%s_%r", screenshotFormat, MAX_FORMAT, IniName);
savelastromvisit = GetPrivateProfileBool(SECTION, LASTVISITKEY, true, IniName); savelastromvisit = GetPrivateProfileBool(SECTION, LASTVISITKEY, true, IniName);
currentimageformat = (ImageFormat)GetPrivateProfileInt(SECTION, DEFAULTFORMATKEY, PNG, IniName); currentimageformat = (ImageFormat)GetPrivateProfileInt(SECTION, DEFAULTFORMATKEY, PNG, IniName);
r4Format = (R4Format)GetPrivateProfileInt(SECTION, R4FORMATKEY, R4_CHEAT_DAT, IniName);
#endif #endif
/* /*
needsSaving = GetPrivateProfileInt(SECTION, NEEDSSAVINGKEY, TRUE, IniName); needsSaving = GetPrivateProfileInt(SECTION, NEEDSSAVINGKEY, TRUE, IniName);
@ -412,6 +414,18 @@ public:
strncpy(output, file.c_str(), MAX_PATH); 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 enum ImageFormat
{ {
#if defined(_WINDOWS) && !defined(WXPORT) #if defined(_WINDOWS) && !defined(WXPORT)

View File

@ -1,4 +1,4 @@
/* Copyright 2009-2010 DeSmuME team /* Copyright (C) 2009-2011 DeSmuME team
This file is part of DeSmuME This file is part of DeSmuME
@ -24,7 +24,13 @@
#include "../debug.h" #include "../debug.h"
#include "../utils/xstring.h" #include "../utils/xstring.h"
#include "../path.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 searchType = 0;
static u8 searchSize = 0; static u8 searchSize = 0;
static u8 searchSign = 0; static u8 searchSign = 0;
@ -80,7 +86,16 @@ u32 searchRange[4][2] = {
//========================================= Export //========================================= Export
static CHEATSEXPORT *cheatsExport = NULL; 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) 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) 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 '-': case '-':
{ {
u32 pos = 0; u32 pos = 0;
@ -120,6 +120,11 @@ LONG_PTR CALLBACK EditValueProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
cheatAddPasteCheck = true; cheatAddPasteCheck = true;
break; break;
default: default:
if (strchr(DEC_Valid, wParam))
{
if(wParam=='o' || wParam=='O') wParam='0';
break;
}
wParam = 0; wParam = 0;
break; break;
} }
@ -135,35 +140,6 @@ LONG_PTR CALLBACK EditValueHEXProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
{ {
switch (wParam) 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 VK_BACK:
case 0x3: // ^C case 0x3: // ^C
case 0x18: // ^X case 0x18: // ^X
@ -173,6 +149,11 @@ LONG_PTR CALLBACK EditValueHEXProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
cheatAddPasteCheck = true; cheatAddPasteCheck = true;
break; break;
default: default:
if (strchr(HEX_Valid, wParam))
{
if(wParam=='o' || wParam=='O') wParam='0';
break;
}
wParam = 0; wParam = 0;
break; break;
} }
@ -190,6 +171,8 @@ INT_PTR CALLBACK CheatsAddProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
{ {
memset(editBuf, 0, sizeof(editBuf));
memset(&tempCheat, 0, sizeof(tempCheat));
saveOldEditProc = oldEditProc; saveOldEditProc = oldEditProc;
SendMessage(GetDlgItem(dialog, IDC_EDIT1), EM_SETLIMITTEXT, 6, 0); SendMessage(GetDlgItem(dialog, IDC_EDIT1), EM_SETLIMITTEXT, 6, 0);
SendMessage(GetDlgItem(dialog, IDC_EDIT2), EM_SETLIMITTEXT, 11, 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)); SetFocus(GetDlgItem(dialog, IDC_EDIT2));
SendMessage(GetDlgItem(dialog, IDC_EDIT2), EM_SETSEL, 0, -1); SendMessage(GetDlgItem(dialog, IDC_EDIT2), EM_SETSEL, 0, -1);
} }
CheatAddVerify(dialog,editBuf[0],editBuf[1],searchAddSize);
} }
return searchAddMode != 2; return searchAddMode != 2;
@ -380,6 +365,8 @@ INT_PTR CALLBACK CheatsEditProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lpara
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
{ {
memset(editBuf, 0, sizeof(editBuf));
memset(&tempCheat, 0, sizeof(tempCheat));
saveOldEditProc = oldEditProc; saveOldEditProc = oldEditProc;
SendMessage(GetDlgItem(dialog, IDC_EDIT1), EM_SETLIMITTEXT, 6, 0); SendMessage(GetDlgItem(dialog, IDC_EDIT1), EM_SETLIMITTEXT, 6, 0);
SendMessage(GetDlgItem(dialog, IDC_EDIT2), EM_SETLIMITTEXT, 10, 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); CheckDlgButton(dialog, IDC_CHECK1, tempCheat.enabled?BST_CHECKED:BST_UNCHECKED);
CheckRadioButton(dialog, searchSizeIDDs[0], searchSizeIDDs[ARRAY_SIZE(searchSizeIDDs) - 1], searchSizeIDDs[tempCheat.size]); CheckRadioButton(dialog, searchSizeIDDs[0], searchSizeIDDs[ARRAY_SIZE(searchSizeIDDs) - 1], searchSizeIDDs[tempCheat.size]);
SetWindowText(GetDlgItem(dialog, IDOK), "Update"); SetWindowText(GetDlgItem(dialog, IDOK), "Update");
generateAR(dialog, tempCheat.code[0][0], tempCheat.code[0][1], searchSizeIDDs[tempCheat.size]);
} }
return TRUE; return TRUE;
@ -519,12 +508,14 @@ INT_PTR CALLBACK CheatsAdd_XX_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lp
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
{ {
memset(editBuf, 0, sizeof(editBuf));
SendMessage(GetDlgItem(dialog, IDC_EDIT2), EM_FMTLINES, (WPARAM)TRUE, (LPARAM)0); SendMessage(GetDlgItem(dialog, IDC_EDIT2), EM_FMTLINES, (WPARAM)TRUE, (LPARAM)0);
if (cheatXXtype == 0) if (cheatXXtype == 0)
{ {
if (cheatXXaction == 0) // add if (cheatXXaction == 0) // add
{ {
memset(&tempCheat, 0, sizeof(tempCheat));
SetWindowText(dialog, "Add Action Replay code"); SetWindowText(dialog, "Add Action Replay code");
tempCheat.enabled = TRUE; 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 if (cheatXXaction == 0) // add
{ {
memset(&tempCheat, 0, sizeof(tempCheat));
SetWindowText(dialog, "Add Codebreaker code"); SetWindowText(dialog, "Add Codebreaker code");
tempCheat.enabled = TRUE; tempCheat.enabled = TRUE;
} }
@ -669,23 +661,23 @@ INT_PTR CALLBACK CheatsListBox_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM l
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
{ {
// TODO: Codebreaker
ShowWindow(GetDlgItem(dialog, IDC_BADD_CB), SW_HIDE);// hide button
LV_COLUMN lvColumn; LV_COLUMN lvColumn;
u32 address = 0; u32 address = 0;
u32 val = 0; u32 val = 0;
cheatListView = GetDlgItem(dialog, IDC_LIST1); 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); ListView_SetExtendedListViewStyle(cheatListView, LVS_EX_FULLROWSELECT | LVS_EX_TWOCLICKACTIVATE | LVS_EX_CHECKBOXES);
memset(&lvColumn,0,sizeof(LV_COLUMN)); memset(&lvColumn,0,sizeof(LV_COLUMN));
lvColumn.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT; lvColumn.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT;
lvColumn.fmt=LVCFMT_CENTER; lvColumn.fmt=LVCFMT_CENTER;
lvColumn.cx=20; lvColumn.cx=20;
lvColumn.pszText=""; lvColumn.pszText="";
ListView_InsertColumn(cheatListView, 0, &lvColumn); ListView_InsertColumn(cheatListView, 0, &lvColumn);
lvColumn.fmt=LVCFMT_LEFT; lvColumn.fmt=LVCFMT_LEFT;
lvColumn.cx=84; lvColumn.cx=84;
lvColumn.pszText="Address"; 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); EnableWindow(GetDlgItem(dialog, IDOK), FALSE);
ListView_SetItemState(searchListView,0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED); ListView_SetItemState(cheatListView,0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
SetFocus(searchListView); SetFocus(cheatListView);
return TRUE; return TRUE;
} }
@ -759,6 +751,10 @@ INT_PTR CALLBACK CheatsListBox_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM l
LPNMHDR tmp_msg = (LPNMHDR)lparam; LPNMHDR tmp_msg = (LPNMHDR)lparam;
switch (tmp_msg->code) switch (tmp_msg->code)
{ {
case LVN_ITEMACTIVATE:
SendMessage(dialog, WM_COMMAND, IDC_BEDIT, 0);
break;
case LVN_ITEMCHANGED: case LVN_ITEMCHANGED:
{ {
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lparam; 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: case IDOK:
if (cheats->save()) if (cheats->save())
{
EndDialog(dialog, TRUE); EndDialog(dialog, TRUE);
}
else else
MessageBox(dialog, "Can't save cheats to file.\nCheck your path (Menu->Config->Path Settings->\"Cheats\")","Error",MB_OK); MessageBox(dialog, "Can't save cheats to file.\nCheck your path (Menu->Config->Path Settings->\"Cheats\")","Error",MB_OK);
return TRUE; 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, 2, buf);
ListView_SetItemText(cheatListView, row, 3, editBuf[2]); ListView_SetItemText(cheatListView, row, 3, editBuf[2]);
ListView_SetCheckState(cheatListView, row, searchAddFreeze); ListView_SetCheckState(cheatListView, row, searchAddFreeze);
EnableWindow(GetDlgItem(dialog, IDOK), TRUE); 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: case IDC_BADD_AR:
{ {
if (LOWORD(wparam) == IDC_BADD_AR) if (LOWORD(wparam) == IDC_BADD_AR)
{
cheatXXtype = 0; cheatXXtype = 0;
}
else else
if (LOWORD(wparam) == IDC_BADD_CB) if (LOWORD(wparam) == IDC_BADD_CB)
{
cheatXXtype = 1; cheatXXtype = 1;
}
else else
return TRUE; return TRUE;
cheatXXaction = 0; // 0 = add 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; if (cheatEditPos > cheats->getSize()) return TRUE;
cheats->get(&tempCheat, cheatEditPos); cheats->get(&tempCheat, cheatEditPos);
switch (tempCheat.type) switch (tempCheat.type)
{ {
case 0: // internal 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); int tmp_pos = ListView_GetNextItem(cheatListView, -1, LVNI_ALL | LVNI_SELECTED);
if (tmp_pos == -1) if (tmp_pos == -1)
{
break; break;
}
if (cheats->remove(tmp_pos)) if (cheats->remove(tmp_pos))
{
ListView_DeleteItem(cheatListView, tmp_pos); ListView_DeleteItem(cheatListView, tmp_pos);
} }
}
EnableWindow(GetDlgItem(dialog, IDOK), TRUE); EnableWindow(GetDlgItem(dialog, IDOK), TRUE);
} }
return TRUE; return TRUE;
case IDC_EXPORT: case IDC_EXPORT:
CheatsExportDialog(dialog); if (CheatsExportDialog(dialog))
EnableWindow(GetDlgItem(dialog, IDOK), TRUE);
return TRUE; return TRUE;
} }
break; break;
@ -1039,7 +1025,7 @@ INT_PTR CALLBACK CheatsSearchExactWnd(HWND dialog, UINT msg,WPARAM wparam,LPARAM
ltoa(searchNumberResults, buf, 10); ltoa(searchNumberResults, buf, 10);
SetWindowText(GetDlgItem(dialog, IDC_SNUMBER), buf); SetWindowText(GetDlgItem(dialog, IDC_SNUMBER), buf);
SetFocus(GetDlgItem(dialog, IDC_EVALUE)); SetFocus(GetDlgItem(dialog, IDC_EVALUE));
break; return TRUE;
} }
case WM_COMMAND: case WM_COMMAND:
@ -1382,6 +1368,8 @@ void CheatAddVerify(HWND dialog,char* addre, char* valu,u8 size)
} }
else else
EnableWindow(GetDlgItem(dialog, IDOK), TRUE); 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: 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; LV_COLUMN lvColumn;
exportListView = GetDlgItem(dialog, IDC_LIST_CHEATS); 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)); memset(&lvColumn,0,sizeof(LV_COLUMN));
lvColumn.mask=LVCF_FMT|LVCF_TEXT|LVCF_WIDTH; 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; lvi.pszText= tmp[i].description;
SendMessage(exportListView, LVM_INSERTITEM, 0, (LPARAM)&lvi); 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); SendMessage(exportListView, WM_SETREDRAW, (WPARAM)TRUE,0);
ListView_SetItemState(exportListView,0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED); ListView_SetItemState(exportListView,0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
SetFocus(exportListView); SetFocus(exportListView);
@ -1426,14 +1427,15 @@ INT_PTR CALLBACK CheatsExportProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lpa
{ {
case IDOK: case IDOK:
{ {
u32 count = ListView_GetSelectedCount(exportListView); u32 count = ListView_GetItemCount(exportListView);
if (count > 0) 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++) for (u32 i = 0; i < count; i++)
{ {
CHEATS_LIST *tmp = (CHEATS_LIST*)cheatsExport->getCheats(); if (!ListView_GetCheckState(exportListView, i)) continue;
cheats->add_AR_Direct(tmp[prev]); cheats->add_AR_Direct(tmp[i]);
LVITEM lvi; LVITEM lvi;
@ -1444,11 +1446,10 @@ INT_PTR CALLBACK CheatsExportProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lpa
u32 row = ListView_InsertItem(cheatListView, &lvi); u32 row = ListView_InsertItem(cheatListView, &lvi);
ListView_SetItemText(cheatListView, row, 1, "Action"); ListView_SetItemText(cheatListView, row, 1, "Action");
ListView_SetItemText(cheatListView, row, 2, "Replay"); ListView_SetItemText(cheatListView, row, 2, "Replay");
ListView_SetItemText(cheatListView, row, 3, tmp[prev].description); ListView_SetItemText(cheatListView, row, 3, tmp[i].description);
done = true;
prev = ListView_GetNextItem(exportListView, prev, LVIS_SELECTED);
} }
EndDialog(dialog, TRUE); if (done) EndDialog(dialog, TRUE);
} }
} }
break; break;
@ -1463,32 +1464,50 @@ INT_PTR CALLBACK CheatsExportProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lpa
return FALSE; return FALSE;
} }
void CheatsExportDialog(HWND hwnd) bool CheatsExportDialog(HWND hwnd)
{ {
bool res = false;
cheatsExport = new CHEATSEXPORT(); cheatsExport = new CHEATSEXPORT();
if (!cheatsExport) return; if (!cheatsExport) return false;
char buf[MAX_PATH] = {0}; char buf[MAX_PATH] = {0};
PathInfo path; strcpy(buf, path.getpath(path.CHEATS).c_str());
path.init("USRCHEAT.DAT"); if (path.r4Format == path.R4_CHEAT_DAT)
path.getpathnoext(path.MODULE, &buf[0]); strcat(buf,"cheat.dat");
strcat(buf, ".DAT"); else
// TODO: select file if (path.r4Format == path.R4_USRCHEAT_DAT)
strcat(buf,"usrcheat.dat");
else return false;
if (cheatsExport->load(buf)) if (cheatsExport->load(buf))
{ {
if (cheatsExport->getCheatsNum() > 0) if (cheatsExport->getCheatsNum() > 0)
{ res = DialogBoxW(hAppInst, MAKEINTRESOURCEW(IDD_CHEAT_EXPORT), hwnd, (DLGPROC) CheatsExportProc);
DialogBoxW(hAppInst, MAKEINTRESOURCEW(IDD_CHEAT_EXPORT), hwnd, (DLGPROC) CheatsExportProc);
}
else else
{
MessageBox(hwnd, "Cheats for this game in database not founded.", "DeSmuME", MB_OK | MB_ICONERROR); MessageBox(hwnd, "Cheats for this game in database not founded.", "DeSmuME", MB_OK | MB_ICONERROR);
} }
}
else 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(); cheatsExport->close();
delete cheatsExport; delete cheatsExport;
cheatsExport = NULL; cheatsExport = NULL;
return res;
} }

View File

@ -1,4 +1,4 @@
/* Copyright 2009 DeSmuME team /* Copyright (C) 2009-2011 DeSmuME team
This file is part of DeSmuME This file is part of DeSmuME

View File

@ -389,12 +389,16 @@
#define IDC_EXPORT 1038 #define IDC_EXPORT 1038
#define IDC_RFOLDER 1039 #define IDC_RFOLDER 1039
#define IDC_2012 1039 #define IDC_2012 1039
#define IDC_EXPORT2 1039
#define IDC_BBROWSE2 1040 #define IDC_BBROWSE2 1040
#define IDC_PATHDESMUME 1041 #define IDC_PATHDESMUME 1041
#define IDC_CDATE 1041
#define IDC_BRESTART 1042 #define IDC_BRESTART 1042
#define IDC_BVIEW 1043 #define IDC_BVIEW 1043
#define IDC_R4TYPE1 1043
#define IDC_BSEARCH 1044 #define IDC_BSEARCH 1044
#define IDC_PIANO_F 1044 #define IDC_PIANO_F 1044
#define IDC_R4TYPE2 1044
#define IDC_RADIO1 1045 #define IDC_RADIO1 1045
#define IDC_PIANO_FS 1045 #define IDC_PIANO_FS 1045
#define IDC_RADIO2 1046 #define IDC_RADIO2 1046
@ -405,6 +409,7 @@
#define IDC_PIANO_A 1048 #define IDC_PIANO_A 1048
#define IDC_RADIO5 1049 #define IDC_RADIO5 1049
#define IDC_PIANO_AS 1049 #define IDC_PIANO_AS 1049
#define IDC_AR_CODE 1049
#define IDC_RADIO6 1050 #define IDC_RADIO6 1050
#define IDC_PIANO_G 1050 #define IDC_PIANO_G 1050
#define IDC_RADIO7 1051 #define IDC_RADIO7 1051
@ -972,7 +977,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 125 #define _APS_NEXT_RESOURCE_VALUE 125
#define _APS_NEXT_COMMAND_VALUE 40094 #define _APS_NEXT_COMMAND_VALUE 40094
#define _APS_NEXT_CONTROL_VALUE 1041 #define _APS_NEXT_CONTROL_VALUE 1050
#define _APS_NEXT_SYMED_VALUE 101 #define _APS_NEXT_SYMED_VALUE 101
#endif #endif
#endif #endif

Binary file not shown.