- add export cheats from R4 database (only from decrypted);
use: place USRCHEAT.DAT in DeSmuME folder, in Emulation->Cheats->List click on "Export..." button.
TODO: decrypting encrypted DB, add choose path for DB
This commit is contained in:
mtabachenko 2010-07-27 21:35:44 +00:00
parent f13b137867
commit 0add4b34bf
5 changed files with 355 additions and 3 deletions

View File

@ -420,6 +420,14 @@ BOOL CHEATS::XXcodePreParser(CHEATS_LIST *list, char *code)
return TRUE;
}
BOOL CHEATS::add_AR_Direct(CHEATS_LIST cheat)
{
size_t num = list.size();
list.push_back(cheat);
list[num].type = 1;
return TRUE;
}
BOOL CHEATS::add_AR(char *code, char *description, BOOL enabled)
{
//if (num == MAX_CHEAT_LIST) return FALSE;
@ -1028,3 +1036,183 @@ void CHEATSEARCH::getListReset()
{
lastRecord = 0;
}
// ========================================================================= Export
bool CHEATSEXPORT::load(char *path)
{
fp = fopen(path, "rb");
if (!fp)
{
printf("Error open database\n");
return false;
}
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
if (!search())
{
printf("ERROR: cheat in database not founded\n");
return false;
}
if (!getCodes())
{
printf("ERROR: export cheats failed\n");
return false;
}
return true;
}
void CHEATSEXPORT::close()
{
if (fp)
fclose(fp);
if (cheats)
{
delete [] cheats;
cheats = NULL;
}
}
// TODO: decrypting database
bool CHEATSEXPORT::search()
{
if (!fp) return false;
u32 pos = 0x0100;
FAT_R4 fat_empty = {0};
memset(&fat, 0, sizeof(FAT_R4));
fseek(fp, pos, SEEK_SET);
while (pos < fsize)
{
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 = {0};
fread(&fat_tmp, sizeof(FAT_R4), 1, fp);
if (memcmp(&fat_tmp, &fat_empty, sizeof(FAT_R4)) == 0)
{
// TODO
dataSize = 0;
}
else
{
dataSize = (fat_tmp.addr - fat.addr);
}
char buf[5] = {0};
memcpy(&buf, &fat.serial[0], 4);
printf("Founded %s CRC %08X at 0x%08X (size %i)\n", buf, fat.CRC, fat.addr, dataSize);
return true;
}
pos += sizeof(FAT_R4);
}
memset(&fat, 0, sizeof(FAT_R4));
return false;
}
bool CHEATSEXPORT::getCodes()
{
if (!fp) return false;
u32 pos = 0;
u32 pos_cht = 0;
u8 *data = new u8 [dataSize+8];
if (!data) return false;
memset(data, 0, dataSize+8);
fseek(fp, fat.addr, SEEK_SET);
if (fread(data, 1, dataSize, fp) != dataSize)
{
delete [] data;
data = NULL;
return false;
}
u8 *title = data;
u32 *cmd = (u32 *)(((u32 )title + strlen((char*)title) + 4) & 0xFFFFFFFC);
numCheats = (*cmd) & (~0xF0000000);
cmd += 9;
cheats = new CHEATS_LIST[numCheats];
memset(cheats, 0, sizeof(CHEATS_LIST) * numCheats);
while (pos < numCheats)
{
u32 folderNum = 1;
u8 *folderName = NULL;
u8 *folderNote = NULL;
if ((*cmd & 0xF0000000) == 0x10000000) // Folder
{
folderNum = (*cmd & 0x00FFFFFF);
folderName = (u8*)((u32)cmd + 4);
folderNote = (u8*)((u32)folderName + strlen((char*)folderName) + 1);
pos++;
numCheats--;
cmd = (u32 *)(((u32)folderName + strlen((char*)folderName) + 1 + strlen((char*)folderNote) + 1 + 3) & 0xFFFFFFFC);
}
for (int i = 0; i < folderNum; i++) // in folder
{
u8 *cheatName = (u8 *)((u32)cmd + 4);
u8 *cheatNote = (u8 *)((u32)cheatName + strlen((char*)cheatName) + 1);
u32 *cheatData = (u32 *)(((u32)cheatNote + strlen((char*)cheatNote) + 1 + 3) & 0xFFFFFFFC);
u32 cheatDataLen = *cheatData++;
if (cheatDataLen)
{
char buf[2048];
memset(buf, 0, 2048);
cheats[pos_cht].num = cheatDataLen/2;
cheats[pos_cht].type = 1;
if ( folderName && *folderName )
{
sprintf(cheats[pos_cht].description, "%s: ", folderName);
}
strcat(cheats[pos_cht].description, (char*)cheatName);
if ( cheatNote && *cheatNote )
{
strcat(cheats[pos_cht].description, "| ");
strcat(cheats[pos_cht].description, (char*)cheatNote);
}
for(u32 j = 0, t = 0; j < (cheatDataLen/2); j++, t+=2 )
{
cheats[pos_cht].code[j][0] = (u32)*(cheatData+t);
//printf("%i: %08X ", j, cheats[pos_cht].code[j][0]);
cheats[pos_cht].code[j][1] = (u32)*(cheatData+t+1);
//printf("%08X\n", cheats[pos_cht].code[j][1]);
}
}
pos++; pos_cht++;
cmd = (u32 *)((u32)cmd + ((*cmd + 1)*4));
}
};
delete [] data;
//for (int i = 0; i < numCheats; i++)
// printf("%i: %s\n", i, cheats[i].description);
return true;
}
CHEATS_LIST *CHEATSEXPORT::getCheats()
{
return cheats;
}
u32 CHEATSEXPORT::getCheatsNum()
{
return numCheats;
}

View File

@ -38,7 +38,7 @@ struct CHEATS_LIST
// 2 - Codebreakers
BOOL enabled;
u32 code[MAX_XX_CODE][2];
char description[75];
char description[255];
int num;
u8 size;
};
@ -68,6 +68,7 @@ public:
BOOL update(u8 size, u32 address, u32 val, char *description, BOOL enabled, u32 pos);
BOOL add_AR(char *code, char *description, BOOL enabled);
BOOL update_AR(char *code, char *description, BOOL enabled, u32 pos);
BOOL add_AR_Direct(CHEATS_LIST cheat);
BOOL add_CB(char *code, char *description, BOOL enabled);
BOOL update_CB(char *code, char *description, BOOL enabled, u32 pos);
BOOL remove(u32 pos);
@ -107,6 +108,53 @@ public:
void getListReset();
};
enum CHEATS_DB_TYPE
{
CHEATS_DB_R4 = 0
};
#pragma pack(push)
#pragma pack(1)
struct FAT_R4
{
u8 serial[4];
u32 CRC;
u64 addr;
};
#pragma pack(pop)
class CHEATSEXPORT
{
private:
CHEATS_DB_TYPE type;
FILE *fp;
u32 fsize;
u32 dataSize;
FAT_R4 fat;
bool search();
bool getCodes();
u32 numCheats;
CHEATS_LIST *cheats;
public:
CHEATSEXPORT() :
fp(NULL),
fsize(0),
dataSize(0),
type(CHEATS_DB_R4),
numCheats(0),
cheats(0)
{}
~CHEATSEXPORT()
{}
bool load(char *path);
void close();
CHEATS_LIST *getCheats();
u32 getCheatsNum();
};
extern CHEATS *cheats;
extern CHEATSEARCH *cheatSearch;

View File

@ -50,6 +50,7 @@ static u8 cheatXXaction = 0;
static HWND searchWnd = NULL;
static HWND searchListView = NULL;
static HWND cheatListView = NULL;
static HWND exportListView = NULL;
static LONG_PTR oldEditProc = NULL;
static LONG_PTR oldEditProcHEX = NULL;
@ -76,6 +77,10 @@ u32 searchRange[4][2] = {
{ 0, 4294967295 }
};
//========================================= Export
static CHEATSEXPORT *cheatsExport = NULL;
void CheatsExportDialog(HWND hwnd);
LONG_PTR CALLBACK EditValueProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_CHAR)
@ -958,6 +963,10 @@ INT_PTR CALLBACK CheatsListBox_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM l
}
return TRUE;
case IDC_EXPORT:
CheatsExportDialog(dialog);
return TRUE;
}
break;
}
@ -1372,3 +1381,107 @@ void CheatAddVerify(HWND dialog,char* addre, char* valu,u8 size)
else
EnableWindow(GetDlgItem(dialog, IDOK), TRUE);
}
// ============================================================= Export
INT_PTR CALLBACK CheatsExportProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam)
{
switch (msg)
{
case WM_INITDIALOG:
{
LV_COLUMN lvColumn;
exportListView = GetDlgItem(dialog, IDC_LIST_CHEATS);
ListView_SetExtendedListViewStyle(exportListView, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
memset(&lvColumn,0,sizeof(LV_COLUMN));
lvColumn.mask=LVCF_FMT|LVCF_TEXT|LVCF_WIDTH;
lvColumn.fmt=LVCFMT_LEFT;
lvColumn.cx=1000;
lvColumn.pszText="Cheats";
ListView_InsertColumn(exportListView, 0, &lvColumn);
LVITEM lvi;
memset(&lvi,0,sizeof(LVITEM));
lvi.mask = LVIF_TEXT|LVIF_STATE;
lvi.iItem = INT_MAX;
SendMessage(exportListView, WM_SETREDRAW, (WPARAM)FALSE,0);
for (int i = 0; i < cheatsExport->getCheatsNum(); i++)
{
CHEATS_LIST *tmp = (CHEATS_LIST*)cheatsExport->getCheats();
lvi.pszText= tmp[i].description;
SendMessage(exportListView, LVM_INSERTITEM, 0, (LPARAM)&lvi);
}
SendMessage(exportListView, WM_SETREDRAW, (WPARAM)TRUE,0);
ListView_SetItemState(exportListView,0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
SetFocus(exportListView);
break;
}
case WM_COMMAND:
{
switch (LOWORD(wparam))
{
case IDOK:
{
u32 count = ListView_GetSelectedCount(exportListView);
if (count > 0)
{
u32 prev = ListView_GetNextItem(exportListView, -1, LVIS_SELECTED);
for (int i = 0; i < count; i++)
{
CHEATS_LIST *tmp = (CHEATS_LIST*)cheatsExport->getCheats();
cheats->add_AR_Direct(tmp[prev]);
LVITEM lvi;
memset(&lvi,0,sizeof(LVITEM));
lvi.mask = LVIF_TEXT|LVIF_STATE;
lvi.iItem = INT_MAX;
lvi.pszText= " ";
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);
}
EndDialog(dialog, TRUE);
}
}
break;
case IDCANCEL:
EndDialog(dialog, FALSE);
break;
}
break;
}
}
return FALSE;
}
void CheatsExportDialog(HWND hwnd)
{
cheatsExport = new CHEATSEXPORT();
if (!cheatsExport) return;
// TODO: select file
if (cheatsExport->load("USRCHEAT.DAT"))
{
if (cheatsExport->getCheatsNum() > 0)
{
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);
cheatsExport->close();
delete cheatsExport;
cheatsExport = NULL;
}

View File

@ -41,6 +41,7 @@
#define IDB_ROTATECW 120
#define IDM_MBG1 121
#define IDM_MBG2 122
#define IDD_CHEAT_EXPORT 122
#define IDM_MBG3 123
#define IDM_SBG0 124
#define IDM_SBG1 125
@ -378,7 +379,9 @@
#define IDC_PATH 1037
#define IDC_PATHGAME 1037
#define IDC_PIANO_E 1037
#define IDC_LIST_CHEATS 1037
#define IDC_RFILE 1038
#define IDC_EXPORT 1038
#define IDC_RFOLDER 1039
#define IDC_BBROWSE2 1040
#define IDC_PATHDESMUME 1041
@ -932,9 +935,9 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 122
#define _APS_NEXT_RESOURCE_VALUE 123
#define _APS_NEXT_COMMAND_VALUE 40079
#define _APS_NEXT_CONTROL_VALUE 1037
#define _APS_NEXT_CONTROL_VALUE 1039
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

Binary file not shown.