Cheats:
- 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:
parent
f13b137867
commit
0add4b34bf
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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.
Loading…
Reference in New Issue