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