fceux/drivers/win/cheat.c

488 lines
18 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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;
}
//This is slow
static char *U16ToStr(uint16 a)
{
static char TempArray[16];
sprintf(TempArray,"%04X",a);
return TempArray;
}
//Rewritten to be fast for MemWatch (--Luke)
static char *U8ToStr(uint8 a)
{
static char TempArray[8];
TempArray[0] = '0' + a/100;
TempArray[1] = '0' + (a%100)/10;
TempArray[2] = '0' + (a%10);
TempArray[3] = 0;
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);
}