- 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
@ -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<ARMCPU_ARM9,MMU_AT_DEBUG>(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<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo & 0x0000FFFF);
_MMU_write16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo);
break;
case 0x02:
case 0x02: // 2XXXXXXX 000000YY byte[XXXXXXX+offset] = YY
addr = hi + offset;
_MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo & 0x000000FF);
_MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo);
break;
case 0x03:
case 0x03: // 3XXXXXXX YYYYYYYY IF YYYYYYYY > word[XXXXXXX] ;unsigned
if (hi == 0) hi = offset; // V1.54+
val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(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<ARMCPU_ARM9,MMU_AT_DEBUG>(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<ARMCPU_ARM9,MMU_AT_DEBUG>(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<ARMCPU_ARM9,MMU_AT_DEBUG>(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<ARMCPU_ARM9,MMU_AT_DEBUG>(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<ARMCPU_ARM9,MMU_AT_DEBUG>(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<ARMCPU_ARM9,MMU_AT_DEBUG>(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<ARMCPU_ARM9,MMU_AT_DEBUG>(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<ARMCPU_ARM9,MMU_AT_DEBUG>(addr);
offset = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(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<ARMCPU_ARM9,MMU_AT_DEBUG>(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,59 +322,59 @@ 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<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, datareg);
offset += 4;
break;
case 0x7:
case 0x7: // D7000000 XXXXXXXX half[XXXXXXXX+offset]=datareg, offset=offset+2
addr = lo + offset;
_MMU_write16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr,datareg & 0x0000FFFF);
_MMU_write16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, datareg);
offset += 2;
break;
case 0x8:
case 0x8: // D8000000 XXXXXXXX byte[XXXXXXXX+offset]=datareg, offset=offset+1
addr = lo + offset;
_MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr,datareg & 0x000000FF);
_MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, datareg);
offset += 1;
break;
case 0x9:
case 0x9: // D9000000 XXXXXXXX datareg = word[XXXXXXXX+offset]
addr = lo + offset;
datareg = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr);
break;
case 0xA:
case 0xA: // DA000000 XXXXXXXX datareg = half[XXXXXXXX+offset]
addr = lo + offset;
datareg = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr);
break;
case 0xB:
case 0xB: // DB000000 XXXXXXXX datareg = byte[XXXXXXXX+offset] ;bugged on pre-v1.54
addr = lo + offset;
datareg = _MMU_read08<ARMCPU_ARM9,MMU_AT_DEBUG>(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;
@ -384,14 +389,14 @@ void CHEATS::ARparser(CHEATS_LIST& list)
}
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<ARMCPU_ARM9,MMU_AT_DEBUG>(offset+t);
_MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(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;
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;
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)
{
// TODO
dataSize = 0;
fseek(fp, 0, SEEK_SET);
fread(&buf[0], 1, 512, fp);
R4decrypt((u8 *)&buf[0], 512, 0);
memcpy(&date[0], &buf[0x10], 16);
}
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};
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];

View File

@ -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;
@ -127,32 +131,51 @@ 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;

View File

@ -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)

View File

@ -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;
return res;
}

View File

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

View File

@ -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

Binary file not shown.