446 lines
12 KiB
C
446 lines
12 KiB
C
|
|
/* FCE Ultra - NES/Famicom Emulator
|
||
|
|
*
|
||
|
|
* Copyright notice for this file:
|
||
|
|
* Copyright (C) 2002 Xodnizel
|
||
|
|
*
|
||
|
|
* This program is free software; you can redistribute it and/or modify
|
||
|
|
* it under the terms of the GNU General Public License as published by
|
||
|
|
* the Free Software Foundation; either version 2 of the License, or
|
||
|
|
* (at your option) any later version.
|
||
|
|
*
|
||
|
|
* This program is distributed in the hope that it will be useful,
|
||
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
* GNU General Public License for more details.
|
||
|
|
*
|
||
|
|
* You should have received a copy of the GNU General Public License
|
||
|
|
* along with this program; if not, write to the Free Software
|
||
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "common.h"
|
||
|
|
|
||
|
|
#include "cheat.h"
|
||
|
|
|
||
|
|
static HWND acwin = 0;
|
||
|
|
|
||
|
|
static int selcheat;
|
||
|
|
static int scheatmethod = 0;
|
||
|
|
static uint8 cheatval1 = 0;
|
||
|
|
static uint8 cheatval2 = 0;
|
||
|
|
|
||
|
|
#define CSTOD 24
|
||
|
|
|
||
|
|
static uint16 StrToU16(char *s) {
|
||
|
|
unsigned int ret = 0;
|
||
|
|
sscanf(s, "%4x", &ret);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint8 StrToU8(char *s) {
|
||
|
|
unsigned int ret = 0;
|
||
|
|
sscanf(s, "%d", &ret);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int StrToI(char *s) {
|
||
|
|
int ret = 0;
|
||
|
|
sscanf(s, "%d", &ret);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/* Need to be careful where these functions are used. */
|
||
|
|
static char *U16ToStr(uint16 a) {
|
||
|
|
static char TempArray[16];
|
||
|
|
sprintf(TempArray, "%04X", a);
|
||
|
|
return TempArray;
|
||
|
|
}
|
||
|
|
|
||
|
|
static char *U8ToStr(uint8 a) {
|
||
|
|
static char TempArray[16];
|
||
|
|
sprintf(TempArray, "%03d", a);
|
||
|
|
return TempArray;
|
||
|
|
}
|
||
|
|
|
||
|
|
static char *IToStr(int a) {
|
||
|
|
static char TempArray[32];
|
||
|
|
sprintf(TempArray, "%d", a);
|
||
|
|
return TempArray;
|
||
|
|
}
|
||
|
|
|
||
|
|
static HWND RedoCheatsWND;
|
||
|
|
static int RedoCheatsCallB(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data) {
|
||
|
|
char tmp[512];
|
||
|
|
sprintf(tmp, "%s %s", s ? "+" : "-", name);
|
||
|
|
SendDlgItemMessage(RedoCheatsWND, 300, LB_ADDSTRING, 0, (LPARAM)(LPSTR)tmp);
|
||
|
|
return(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void RedoCheatsLB(HWND hwndDlg) {
|
||
|
|
SendDlgItemMessage(hwndDlg, 300, LB_RESETCONTENT, 0, 0);
|
||
|
|
RedoCheatsWND = hwndDlg;
|
||
|
|
FCEUI_ListCheats(RedoCheatsCallB, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
int cfcallb(uint32 a, uint8 last, uint8 current) {
|
||
|
|
char temp[16];
|
||
|
|
|
||
|
|
sprintf(temp, "%04X:%03d:%03d", (unsigned int)a, last, current);
|
||
|
|
SendDlgItemMessage(acwin, 108, LB_ADDSTRING, 0, (LPARAM)(LPSTR)temp);
|
||
|
|
return(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
static int scrollindex;
|
||
|
|
static int scrollnum;
|
||
|
|
static int scrollmax;
|
||
|
|
|
||
|
|
int cfcallbinsert(uint32 a, uint8 last, uint8 current) {
|
||
|
|
char temp[16];
|
||
|
|
|
||
|
|
sprintf(temp, "%04X:%03d:%03d", (unsigned int)a, last, current);
|
||
|
|
SendDlgItemMessage(acwin, 108, LB_INSERTSTRING, (CSTOD - 1), (LPARAM)(LPSTR)temp);
|
||
|
|
return(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
int cfcallbinsertt(uint32 a, uint8 last, uint8 current) {
|
||
|
|
char temp[16];
|
||
|
|
|
||
|
|
sprintf(temp, "%04X:%03d:%03d", (unsigned int)a, last, current);
|
||
|
|
SendDlgItemMessage(acwin, 108, LB_INSERTSTRING, 0, (LPARAM)(LPSTR)temp);
|
||
|
|
return(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void AddTheThing(HWND hwndDlg, char *s, int a, int v) {
|
||
|
|
if (FCEUI_AddCheat(s, a, v, -1, 0))
|
||
|
|
MessageBox(hwndDlg, "Cheat Added", "Cheat Added", MB_OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
static void DoGet(void) {
|
||
|
|
int n = FCEUI_CheatSearchGetCount();
|
||
|
|
int t;
|
||
|
|
scrollnum = n;
|
||
|
|
scrollindex = -32768;
|
||
|
|
|
||
|
|
SendDlgItemMessage(acwin, 108, LB_RESETCONTENT, 0, 0);
|
||
|
|
FCEUI_CheatSearchGetRange(0, (CSTOD - 1), cfcallb);
|
||
|
|
|
||
|
|
t = -32768 + n - 1 - (CSTOD - 1);
|
||
|
|
if (t < -32768)
|
||
|
|
t = -32768;
|
||
|
|
scrollmax = t;
|
||
|
|
SendDlgItemMessage(acwin, 120, SBM_SETRANGE, -32768, t);
|
||
|
|
SendDlgItemMessage(acwin, 120, SBM_SETPOS, -32768, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void FixCheatSelButtons(HWND hwndDlg, int how) {
|
||
|
|
/* Update Cheat Button */
|
||
|
|
EnableWindow(GetDlgItem(hwndDlg, 251), how);
|
||
|
|
|
||
|
|
/* Delete Cheat Button */
|
||
|
|
EnableWindow(GetDlgItem(hwndDlg, 252), how);
|
||
|
|
}
|
||
|
|
|
||
|
|
static BOOL CALLBACK AddCheatCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||
|
|
static int lbfocus;
|
||
|
|
static HWND hwndLB;
|
||
|
|
|
||
|
|
switch (uMsg) {
|
||
|
|
case WM_VSCROLL:
|
||
|
|
if (scrollnum > (CSTOD - 1)) {
|
||
|
|
switch ((int)LOWORD(wParam)) {
|
||
|
|
case SB_TOP:
|
||
|
|
scrollindex = -32768;
|
||
|
|
SendDlgItemMessage(hwndDlg, 120, SBM_SETPOS, scrollindex, 1);
|
||
|
|
SendDlgItemMessage(hwndDlg, 108, LB_RESETCONTENT, (CSTOD - 1), 0);
|
||
|
|
FCEUI_CheatSearchGetRange(scrollindex + 32768, scrollindex + 32768 + (CSTOD - 1), cfcallb);
|
||
|
|
break;
|
||
|
|
case SB_BOTTOM:
|
||
|
|
scrollindex = scrollmax;
|
||
|
|
SendDlgItemMessage(hwndDlg, 120, SBM_SETPOS, scrollindex, 1);
|
||
|
|
SendDlgItemMessage(hwndDlg, 108, LB_RESETCONTENT, (CSTOD - 1), 0);
|
||
|
|
FCEUI_CheatSearchGetRange(scrollindex + 32768, scrollindex + 32768 + (CSTOD - 1), cfcallb);
|
||
|
|
break;
|
||
|
|
case SB_LINEUP:
|
||
|
|
if (scrollindex > -32768) {
|
||
|
|
scrollindex--;
|
||
|
|
SendDlgItemMessage(hwndDlg, 120, SBM_SETPOS, scrollindex, 1);
|
||
|
|
SendDlgItemMessage(hwndDlg, 108, LB_DELETESTRING, (CSTOD - 1), 0);
|
||
|
|
FCEUI_CheatSearchGetRange(scrollindex + 32768, scrollindex + 32768, cfcallbinsertt);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case SB_PAGEUP:
|
||
|
|
scrollindex -= CSTOD;
|
||
|
|
if (scrollindex < -32768) scrollindex = -32768;
|
||
|
|
SendDlgItemMessage(hwndDlg, 120, SBM_SETPOS, scrollindex, 1);
|
||
|
|
SendDlgItemMessage(hwndDlg, 108, LB_RESETCONTENT, (CSTOD - 1), 0);
|
||
|
|
FCEUI_CheatSearchGetRange(scrollindex + 32768, scrollindex + 32768 + (CSTOD - 1), cfcallb);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case SB_LINEDOWN:
|
||
|
|
if (scrollindex < scrollmax) {
|
||
|
|
scrollindex++;
|
||
|
|
SendDlgItemMessage(hwndDlg, 120, SBM_SETPOS, scrollindex, 1);
|
||
|
|
SendDlgItemMessage(hwndDlg, 108, LB_DELETESTRING, 0, 0);
|
||
|
|
FCEUI_CheatSearchGetRange(scrollindex + 32768 + (CSTOD - 1), scrollindex + 32768 + (CSTOD - 1), cfcallbinsert);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case SB_PAGEDOWN:
|
||
|
|
scrollindex += CSTOD;
|
||
|
|
if (scrollindex > scrollmax)
|
||
|
|
scrollindex = scrollmax;
|
||
|
|
SendDlgItemMessage(hwndDlg, 120, SBM_SETPOS, scrollindex, 1);
|
||
|
|
SendDlgItemMessage(hwndDlg, 108, LB_RESETCONTENT, 0, 0);
|
||
|
|
FCEUI_CheatSearchGetRange(scrollindex + 32768, scrollindex + 32768 + (CSTOD - 1), cfcallb);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case SB_THUMBPOSITION:
|
||
|
|
case SB_THUMBTRACK:
|
||
|
|
scrollindex = (short int)HIWORD(wParam);
|
||
|
|
SendDlgItemMessage(hwndDlg, 120, SBM_SETPOS, scrollindex, 1);
|
||
|
|
SendDlgItemMessage(hwndDlg, 108, LB_RESETCONTENT, 0, 0);
|
||
|
|
FCEUI_CheatSearchGetRange(32768 + scrollindex, 32768 + scrollindex + (CSTOD - 1), cfcallb);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case WM_INITDIALOG:
|
||
|
|
selcheat = -1;
|
||
|
|
FixCheatSelButtons(hwndDlg, 0);
|
||
|
|
acwin = hwndDlg;
|
||
|
|
SetDlgItemText(hwndDlg, 110, (LPTSTR)U8ToStr(cheatval1));
|
||
|
|
SetDlgItemText(hwndDlg, 111, (LPTSTR)U8ToStr(cheatval2));
|
||
|
|
DoGet();
|
||
|
|
CheckRadioButton(hwndDlg, 115, 120, scheatmethod + 115);
|
||
|
|
lbfocus = 0;
|
||
|
|
hwndLB = 0;
|
||
|
|
|
||
|
|
RedoCheatsLB(hwndDlg);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case WM_VKEYTOITEM:
|
||
|
|
if (lbfocus) {
|
||
|
|
int real;
|
||
|
|
|
||
|
|
real = SendDlgItemMessage(hwndDlg, 108, LB_GETCURSEL, 0, (LPARAM)(LPSTR)0);
|
||
|
|
switch ((int)LOWORD(wParam)) {
|
||
|
|
case VK_UP:
|
||
|
|
/* mmmm....recursive goodness */
|
||
|
|
if (!real)
|
||
|
|
SendMessage(hwndDlg, WM_VSCROLL, SB_LINEUP, 0);
|
||
|
|
return(-1);
|
||
|
|
break;
|
||
|
|
case VK_DOWN:
|
||
|
|
if (real == (CSTOD - 1))
|
||
|
|
SendMessage(hwndDlg, WM_VSCROLL, SB_LINEDOWN, 0);
|
||
|
|
return(-1);
|
||
|
|
break;
|
||
|
|
case VK_PRIOR:
|
||
|
|
SendMessage(hwndDlg, WM_VSCROLL, SB_PAGEUP, 0);
|
||
|
|
break;
|
||
|
|
case VK_NEXT:
|
||
|
|
SendMessage(hwndDlg, WM_VSCROLL, SB_PAGEDOWN, 0);
|
||
|
|
break;
|
||
|
|
case VK_HOME:
|
||
|
|
SendMessage(hwndDlg, WM_VSCROLL, SB_TOP, 0);
|
||
|
|
break;
|
||
|
|
case VK_END:
|
||
|
|
SendMessage(hwndDlg, WM_VSCROLL, SB_BOTTOM, 0);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
return(-2);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case WM_CLOSE:
|
||
|
|
case WM_QUIT: goto gornk;
|
||
|
|
case WM_COMMAND:
|
||
|
|
switch (LOWORD(wParam)) {
|
||
|
|
case 300: /* List box selection changed. */
|
||
|
|
if (HIWORD(wParam) == LBN_SELCHANGE) {
|
||
|
|
char *s;
|
||
|
|
uint32 a;
|
||
|
|
uint8 v;
|
||
|
|
int status;
|
||
|
|
int c, type;
|
||
|
|
|
||
|
|
selcheat = SendDlgItemMessage(hwndDlg, 300, LB_GETCURSEL, 0, (LPARAM)(LPSTR)0);
|
||
|
|
if (selcheat < 0) {
|
||
|
|
FixCheatSelButtons(hwndDlg, 0);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
FixCheatSelButtons(hwndDlg, 1);
|
||
|
|
|
||
|
|
FCEUI_GetCheat(selcheat, &s, &a, &v, &c, &status, &type);
|
||
|
|
SetDlgItemText(hwndDlg, 200, (LPTSTR)s);
|
||
|
|
SetDlgItemText(hwndDlg, 201, (LPTSTR)U16ToStr(a));
|
||
|
|
SetDlgItemText(hwndDlg, 202, (LPTSTR)U8ToStr(v));
|
||
|
|
SetDlgItemText(hwndDlg, 203, (c == -1) ? (LPTSTR)"" : (LPTSTR)IToStr(c));
|
||
|
|
CheckDlgButton(hwndDlg, 204, type ? BST_CHECKED : BST_UNCHECKED);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case 108:
|
||
|
|
switch (HIWORD(wParam)) {
|
||
|
|
case LBN_SELCHANGE:
|
||
|
|
{
|
||
|
|
char TempArray[32];
|
||
|
|
SendDlgItemMessage(hwndDlg, 108, LB_GETTEXT, SendDlgItemMessage(hwndDlg, 108, LB_GETCURSEL, 0, (LPARAM)(LPSTR)0), (LPARAM)(LPCTSTR)TempArray);
|
||
|
|
TempArray[4] = 0;
|
||
|
|
SetDlgItemText(hwndDlg, 201, (LPTSTR)TempArray);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case LBN_SETFOCUS:
|
||
|
|
lbfocus = 1;
|
||
|
|
break;
|
||
|
|
case LBN_KILLFOCUS:
|
||
|
|
lbfocus = 0;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
switch (HIWORD(wParam)) {
|
||
|
|
case LBN_DBLCLK:
|
||
|
|
if (selcheat >= 0) {
|
||
|
|
if (LOWORD(wParam) == 300)
|
||
|
|
FCEUI_ToggleCheat(selcheat);
|
||
|
|
RedoCheatsLB(hwndDlg);
|
||
|
|
SendDlgItemMessage(hwndDlg, 300, LB_SETCURSEL, selcheat, 0);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case BN_CLICKED:
|
||
|
|
if (LOWORD(wParam) >= 115 && LOWORD(wParam) <= 120)
|
||
|
|
scheatmethod = LOWORD(wParam) - 115;
|
||
|
|
else switch (LOWORD(wParam)) {
|
||
|
|
case 112:
|
||
|
|
FCEUI_CheatSearchBegin();
|
||
|
|
DoGet();
|
||
|
|
break;
|
||
|
|
case 113:
|
||
|
|
FCEUI_CheatSearchEnd(scheatmethod, cheatval1, cheatval2);
|
||
|
|
DoGet();
|
||
|
|
break;
|
||
|
|
case 114:
|
||
|
|
FCEUI_CheatSearchSetCurrentAsOriginal();
|
||
|
|
DoGet();
|
||
|
|
break;
|
||
|
|
case 107:
|
||
|
|
FCEUI_CheatSearchShowExcluded();
|
||
|
|
DoGet();
|
||
|
|
break;
|
||
|
|
case 250: /* Add Cheat Button */
|
||
|
|
{
|
||
|
|
int a, v, c, t;
|
||
|
|
char name[257];
|
||
|
|
char temp[16];
|
||
|
|
|
||
|
|
GetDlgItemText(hwndDlg, 200, name, 256 + 1);
|
||
|
|
GetDlgItemText(hwndDlg, 201, temp, 4 + 1);
|
||
|
|
a = StrToU16(temp);
|
||
|
|
GetDlgItemText(hwndDlg, 202, temp, 3 + 1);
|
||
|
|
v = StrToU8(temp);
|
||
|
|
GetDlgItemText(hwndDlg, 203, temp, 3 + 1);
|
||
|
|
if (temp[0] == 0)
|
||
|
|
c = -1;
|
||
|
|
else
|
||
|
|
c = StrToI(temp);
|
||
|
|
t = (IsDlgButtonChecked(hwndDlg, 204) == BST_CHECKED) ? 1 : 0;
|
||
|
|
FCEUI_AddCheat(name, a, v, c, t);
|
||
|
|
RedoCheatsLB(hwndDlg);
|
||
|
|
SendDlgItemMessage(hwndDlg, 300, LB_SETCURSEL, selcheat, 0);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case 253: /* Add GG Cheat Button */
|
||
|
|
{
|
||
|
|
uint16 a;
|
||
|
|
int c;
|
||
|
|
uint8 v;
|
||
|
|
char name[257];
|
||
|
|
|
||
|
|
GetDlgItemText(hwndDlg, 200, name, 256 + 1);
|
||
|
|
|
||
|
|
if (FCEUI_DecodeGG(name, &a, &v, &c)) {
|
||
|
|
FCEUI_AddCheat(name, a, v, c, 1);
|
||
|
|
RedoCheatsLB(hwndDlg);
|
||
|
|
SendDlgItemMessage(hwndDlg, 300, LB_SETCURSEL, selcheat, 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 251: /* Update Cheat Button */
|
||
|
|
if (selcheat >= 0) {
|
||
|
|
int a, v, c, t;
|
||
|
|
char name[257];
|
||
|
|
char temp[16];
|
||
|
|
|
||
|
|
GetDlgItemText(hwndDlg, 200, name, 256 + 1);
|
||
|
|
GetDlgItemText(hwndDlg, 201, temp, 4 + 1);
|
||
|
|
a = StrToU16(temp);
|
||
|
|
GetDlgItemText(hwndDlg, 202, temp, 3 + 1);
|
||
|
|
v = StrToU8(temp);
|
||
|
|
GetDlgItemText(hwndDlg, 203, temp, 3 + 1);
|
||
|
|
if (temp[0] == 0)
|
||
|
|
c = -1;
|
||
|
|
else
|
||
|
|
c = StrToI(temp);
|
||
|
|
t = (IsDlgButtonChecked(hwndDlg, 204) == BST_CHECKED) ? 1 : 0;
|
||
|
|
FCEUI_SetCheat(selcheat, name, a, v, c, -1, t);
|
||
|
|
RedoCheatsLB(hwndDlg);
|
||
|
|
SendDlgItemMessage(hwndDlg, 300, LB_SETCURSEL, selcheat, 0);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case 252: /* Delete cheat button */
|
||
|
|
if (selcheat >= 0) {
|
||
|
|
FCEUI_DelCheat(selcheat);
|
||
|
|
SendDlgItemMessage(hwndDlg, 300, LB_DELETESTRING, selcheat, 0);
|
||
|
|
FixCheatSelButtons(hwndDlg, 0);
|
||
|
|
selcheat = -1;
|
||
|
|
SetDlgItemText(hwndDlg, 200, (LPTSTR)"");
|
||
|
|
SetDlgItemText(hwndDlg, 201, (LPTSTR)"");
|
||
|
|
SetDlgItemText(hwndDlg, 202, (LPTSTR)"");
|
||
|
|
SetDlgItemText(hwndDlg, 203, (LPTSTR)"");
|
||
|
|
CheckDlgButton(hwndDlg, 204, BST_UNCHECKED);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case 106:
|
||
|
|
gornk:
|
||
|
|
EndDialog(hwndDlg, 0);
|
||
|
|
acwin = 0;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case EN_CHANGE:
|
||
|
|
{
|
||
|
|
char TempArray[256];
|
||
|
|
GetDlgItemText(hwndDlg, LOWORD(wParam), TempArray, 256);
|
||
|
|
switch (LOWORD(wParam)) {
|
||
|
|
case 110: cheatval1 = StrToU8(TempArray); break;
|
||
|
|
case 111: cheatval2 = StrToU8(TempArray); break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void ConfigAddCheat(HWND wnd) {
|
||
|
|
if (!GI) {
|
||
|
|
FCEUD_PrintError("You must have a game loaded before you can manipulate cheats.");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (GI->type == GIT_NSF) {
|
||
|
|
FCEUD_PrintError("Sorry, you can't cheat with NSFs.");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
DialogBox(fceu_hInstance, "ADDCHEAT", wnd, AddCheatCallB);
|
||
|
|
}
|