/* 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(scrollindexscrollmax) 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); }