| 1 | /* FCE Ultra - NES/Famicom Emulator\r |
| 2 | *\r |
| 3 | * Copyright notice for this file:\r |
| 4 | * Copyright (C) 2002 Ben Parnell\r |
| 5 | *\r |
| 6 | * This program is free software; you can redistribute it and/or modify\r |
| 7 | * it under the terms of the GNU General Public License as published by\r |
| 8 | * the Free Software Foundation; either version 2 of the License, or\r |
| 9 | * (at your option) any later version.\r |
| 10 | *\r |
| 11 | * This program is distributed in the hope that it will be useful,\r |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of\r |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r |
| 14 | * GNU General Public License for more details.\r |
| 15 | *\r |
| 16 | * You should have received a copy of the GNU General Public License\r |
| 17 | * along with this program; if not, write to the Free Software\r |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r |
| 19 | */\r |
| 20 | \r |
| 21 | #include "common.h"\r |
| 22 | \r |
| 23 | #include "cheat.h"\r |
| 24 | \r |
| 25 | static int selcheat;\r |
| 26 | static int scheatmethod=0;\r |
| 27 | static uint8 cheatval1=0;\r |
| 28 | static uint8 cheatval2=0;\r |
| 29 | \r |
| 30 | static void ConfigAddCheat(HWND wnd);\r |
| 31 | \r |
| 32 | \r |
| 33 | static uint16 StrToU16(char *s)\r |
| 34 | {\r |
| 35 | unsigned int ret=0;\r |
| 36 | sscanf(s,"%4x",&ret);\r |
| 37 | return ret;\r |
| 38 | }\r |
| 39 | \r |
| 40 | static uint8 StrToU8(char *s)\r |
| 41 | {\r |
| 42 | unsigned int ret=0;\r |
| 43 | sscanf(s,"%d",&ret);\r |
| 44 | return ret;\r |
| 45 | }\r |
| 46 | \r |
| 47 | \r |
| 48 | /* Need to be careful where these functions are used. */\r |
| 49 | static char *U16ToStr(uint16 a)\r |
| 50 | {\r |
| 51 | static char TempArray[16];\r |
| 52 | sprintf(TempArray,"%04X",a);\r |
| 53 | return TempArray;\r |
| 54 | }\r |
| 55 | \r |
| 56 | static char *U8ToStr(uint8 a)\r |
| 57 | {\r |
| 58 | static char TempArray[16];\r |
| 59 | sprintf(TempArray,"%03d",a);\r |
| 60 | return TempArray;\r |
| 61 | }\r |
| 62 | \r |
| 63 | \r |
| 64 | static HWND RedoCheatsWND;\r |
| 65 | static int RedoCheatsCallB(char *name, uint32 a, uint8 v, int s)\r |
| 66 | {\r |
| 67 | SendDlgItemMessage(RedoCheatsWND,101,LB_ADDSTRING,0,(LPARAM)(LPSTR)name);\r |
| 68 | return(1);\r |
| 69 | }\r |
| 70 | \r |
| 71 | static void RedoCheatsLB(HWND hwndDlg)\r |
| 72 | {\r |
| 73 | SendDlgItemMessage(hwndDlg,101,LB_RESETCONTENT,0,0);\r |
| 74 | RedoCheatsWND=hwndDlg;\r |
| 75 | FCEUI_ListCheats(RedoCheatsCallB);\r |
| 76 | }\r |
| 77 | \r |
| 78 | \r |
| 79 | BOOL CALLBACK CheatsConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)\r |
| 80 | {\r |
| 81 | switch(uMsg)\r |
| 82 | {\r |
| 83 | case WM_INITDIALOG: \r |
| 84 | RedoCheatsLB(hwndDlg);\r |
| 85 | break;\r |
| 86 | case WM_CLOSE:\r |
| 87 | case WM_QUIT: goto gornk;\r |
| 88 | case WM_COMMAND:\r |
| 89 | switch(HIWORD(wParam))\r |
| 90 | {\r |
| 91 | case BN_CLICKED:\r |
| 92 | if(selcheat>=0)\r |
| 93 | {\r |
| 94 | if(LOWORD(wParam)==107)\r |
| 95 | FCEUI_SetCheat(selcheat,0,-1,-1,1);\r |
| 96 | else if(LOWORD(wParam)==108)\r |
| 97 | FCEUI_SetCheat(selcheat,0,-1,-1,0);\r |
| 98 | }\r |
| 99 | break;\r |
| 100 | case EN_KILLFOCUS:\r |
| 101 | if(selcheat>=0)\r |
| 102 | {\r |
| 103 | char TempArray[256];\r |
| 104 | int32 t;\r |
| 105 | \r |
| 106 | GetDlgItemText(hwndDlg,LOWORD(wParam),TempArray,256);\r |
| 107 | switch(LOWORD(wParam))\r |
| 108 | {\r |
| 109 | case 102:FCEUI_SetCheat(selcheat,TempArray,-1,-1,-1);\r |
| 110 | SendDlgItemMessage(hwndDlg,101,LB_INSERTSTRING,selcheat,(LPARAM)(LPCTSTR)TempArray);\r |
| 111 | SendDlgItemMessage(hwndDlg,101,LB_DELETESTRING,selcheat+1,0);\r |
| 112 | SendDlgItemMessage(hwndDlg,101,LB_SETCURSEL,selcheat,0);\r |
| 113 | break;\r |
| 114 | case 103:t=StrToU16(TempArray);\r |
| 115 | FCEUI_SetCheat(selcheat,0,t,-1,-1);\r |
| 116 | break;\r |
| 117 | case 104:t=StrToU8(TempArray);\r |
| 118 | FCEUI_SetCheat(selcheat,0,-1,t,-1);\r |
| 119 | break;\r |
| 120 | }\r |
| 121 | }\r |
| 122 | break;\r |
| 123 | }\r |
| 124 | \r |
| 125 | switch(LOWORD(wParam))\r |
| 126 | {\r |
| 127 | case 101:\r |
| 128 | if(HIWORD(wParam)==LBN_SELCHANGE)\r |
| 129 | {\r |
| 130 | char *s;\r |
| 131 | uint32 a;\r |
| 132 | uint8 b;\r |
| 133 | int status;\r |
| 134 | \r |
| 135 | selcheat=SendDlgItemMessage(hwndDlg,101,LB_GETCURSEL,0,(LPARAM)(LPSTR)0);\r |
| 136 | if(selcheat<0) break;\r |
| 137 | \r |
| 138 | FCEUI_GetCheat(selcheat,&s,&a,&b,&status);\r |
| 139 | SetDlgItemText(hwndDlg,102,(LPTSTR)s);\r |
| 140 | SetDlgItemText(hwndDlg,103,(LPTSTR)U16ToStr(a));\r |
| 141 | SetDlgItemText(hwndDlg,104,(LPTSTR)U8ToStr(b));\r |
| 142 | \r |
| 143 | CheckRadioButton(hwndDlg,107,108,status?107:108);\r |
| 144 | }\r |
| 145 | break;\r |
| 146 | }\r |
| 147 | \r |
| 148 | if(!(wParam>>16))\r |
| 149 | switch(wParam&0xFFFF)\r |
| 150 | {\r |
| 151 | case 106:\r |
| 152 | if(selcheat>=0)\r |
| 153 | {\r |
| 154 | FCEUI_DelCheat(selcheat);\r |
| 155 | SendDlgItemMessage(hwndDlg,101,LB_DELETESTRING,selcheat,0);\r |
| 156 | selcheat=-1;\r |
| 157 | SetDlgItemText(hwndDlg,102,(LPTSTR)"");\r |
| 158 | SetDlgItemText(hwndDlg,103,(LPTSTR)"");\r |
| 159 | SetDlgItemText(hwndDlg,104,(LPTSTR)"");\r |
| 160 | CheckRadioButton(hwndDlg,107,108,0); // Is this correct?\r |
| 161 | }\r |
| 162 | break;\r |
| 163 | case 105:\r |
| 164 | ConfigAddCheat(hwndDlg);\r |
| 165 | RedoCheatsLB(hwndDlg);\r |
| 166 | break;\r |
| 167 | case 1:\r |
| 168 | gornk:\r |
| 169 | EndDialog(hwndDlg,0);\r |
| 170 | break;\r |
| 171 | }\r |
| 172 | }\r |
| 173 | return 0;\r |
| 174 | }\r |
| 175 | \r |
| 176 | \r |
| 177 | void ConfigCheats(HWND hParent)\r |
| 178 | {\r |
| 179 | if(!GI)\r |
| 180 | {\r |
| 181 | FCEUD_PrintError("You must have a game loaded before you can manipulate cheats.");\r |
| 182 | return;\r |
| 183 | }\r |
| 184 | \r |
| 185 | if(GI->type==GIT_NSF)\r |
| 186 | {\r |
| 187 | FCEUD_PrintError("Sorry, you can't cheat with NSFs.");\r |
| 188 | return;\r |
| 189 | }\r |
| 190 | \r |
| 191 | selcheat=-1;\r |
| 192 | DialogBox(fceu_hInstance,"CHEATS",hParent,CheatsConCallB);\r |
| 193 | }\r |
| 194 | \r |
| 195 | \r |
| 196 | \r |
| 197 | \r |
| 198 | \r |
| 199 | \r |
| 200 | HWND cfcallbw;\r |
| 201 | \r |
| 202 | int cfcallb(uint32 a, uint8 last, uint8 current)\r |
| 203 | {\r |
| 204 | char temp[16];\r |
| 205 | \r |
| 206 | sprintf(temp,"%04X:%03d:%03d",(unsigned int)a,last,current);\r |
| 207 | SendDlgItemMessage(cfcallbw,108,LB_ADDSTRING,0,(LPARAM)(LPSTR)temp);\r |
| 208 | return(1);\r |
| 209 | }\r |
| 210 | \r |
| 211 | static int scrollindex;\r |
| 212 | static int scrollnum;\r |
| 213 | static int scrollmax;\r |
| 214 | \r |
| 215 | int cfcallbinsert(uint32 a, uint8 last, uint8 current)\r |
| 216 | {\r |
| 217 | char temp[16];\r |
| 218 | \r |
| 219 | sprintf(temp,"%04X:%03d:%03d",(unsigned int)a,last,current);\r |
| 220 | SendDlgItemMessage(cfcallbw,108,LB_INSERTSTRING,13,(LPARAM)(LPSTR)temp);\r |
| 221 | return(1);\r |
| 222 | }\r |
| 223 | \r |
| 224 | int cfcallbinsertt(uint32 a, uint8 last, uint8 current)\r |
| 225 | {\r |
| 226 | char temp[16];\r |
| 227 | \r |
| 228 | sprintf(temp,"%04X:%03d:%03d",(unsigned int)a,last,current);\r |
| 229 | SendDlgItemMessage(cfcallbw,108,LB_INSERTSTRING,0,(LPARAM)(LPSTR)temp);\r |
| 230 | return(1);\r |
| 231 | }\r |
| 232 | \r |
| 233 | \r |
| 234 | void AddTheThing(HWND hwndDlg, char *s, int a, int v)\r |
| 235 | {\r |
| 236 | if(FCEUI_AddCheat(s,a,v))\r |
| 237 | MessageBox(hwndDlg,"Cheat Added","Cheat Added",MB_OK);\r |
| 238 | }\r |
| 239 | \r |
| 240 | \r |
| 241 | static void DoGet(void)\r |
| 242 | {\r |
| 243 | int n=FCEUI_CheatSearchGetCount();\r |
| 244 | int t;\r |
| 245 | scrollnum=n;\r |
| 246 | scrollindex=-32768;\r |
| 247 | \r |
| 248 | SendDlgItemMessage(cfcallbw,108,LB_RESETCONTENT,0,0);\r |
| 249 | FCEUI_CheatSearchGetRange(0,13,cfcallb);\r |
| 250 | \r |
| 251 | t=-32768+n-1-13;\r |
| 252 | if(t<-32768)\r |
| 253 | t=-32768;\r |
| 254 | scrollmax=t;\r |
| 255 | SendDlgItemMessage(cfcallbw,120,SBM_SETRANGE,-32768,t);\r |
| 256 | SendDlgItemMessage(cfcallbw,120,SBM_SETPOS,-32768,1);\r |
| 257 | }\r |
| 258 | \r |
| 259 | \r |
| 260 | BOOL CALLBACK AddCheatCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)\r |
| 261 | {\r |
| 262 | static int lbfocus;\r |
| 263 | static HWND hwndLB;\r |
| 264 | cfcallbw=hwndDlg;\r |
| 265 | \r |
| 266 | \r |
| 267 | switch(uMsg)\r |
| 268 | { \r |
| 269 | case WM_VSCROLL:\r |
| 270 | if(scrollnum>13)\r |
| 271 | {\r |
| 272 | switch((int)LOWORD(wParam))\r |
| 273 | {\r |
| 274 | case SB_TOP:\r |
| 275 | scrollindex=-32768;\r |
| 276 | SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);\r |
| 277 | SendDlgItemMessage(hwndDlg,108,LB_RESETCONTENT,13,0);\r |
| 278 | FCEUI_CheatSearchGetRange(scrollindex+32768,scrollindex+32768+13,cfcallb);\r |
| 279 | break;\r |
| 280 | case SB_BOTTOM:\r |
| 281 | scrollindex=scrollmax;\r |
| 282 | SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);\r |
| 283 | SendDlgItemMessage(hwndDlg,108,LB_RESETCONTENT,13,0);\r |
| 284 | FCEUI_CheatSearchGetRange(scrollindex+32768,scrollindex+32768+13,cfcallb);\r |
| 285 | break;\r |
| 286 | case SB_LINEUP:\r |
| 287 | if(scrollindex>-32768)\r |
| 288 | {\r |
| 289 | scrollindex--;\r |
| 290 | SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);\r |
| 291 | SendDlgItemMessage(hwndDlg,108,LB_DELETESTRING,13,0);\r |
| 292 | FCEUI_CheatSearchGetRange(scrollindex+32768,scrollindex+32768,cfcallbinsertt);\r |
| 293 | }\r |
| 294 | break;\r |
| 295 | \r |
| 296 | case SB_PAGEUP:\r |
| 297 | scrollindex-=14;\r |
| 298 | if(scrollindex<-32768) scrollindex=-32768;\r |
| 299 | SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);\r |
| 300 | SendDlgItemMessage(hwndDlg,108,LB_RESETCONTENT,13,0);\r |
| 301 | FCEUI_CheatSearchGetRange(scrollindex+32768,scrollindex+32768+13,cfcallb);\r |
| 302 | break;\r |
| 303 | \r |
| 304 | case SB_LINEDOWN:\r |
| 305 | if(scrollindex<scrollmax)\r |
| 306 | {\r |
| 307 | scrollindex++;\r |
| 308 | SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);\r |
| 309 | SendDlgItemMessage(hwndDlg,108,LB_DELETESTRING,0,0);\r |
| 310 | FCEUI_CheatSearchGetRange(scrollindex+32768+13,scrollindex+32768+13,cfcallbinsert);\r |
| 311 | }\r |
| 312 | break;\r |
| 313 | \r |
| 314 | case SB_PAGEDOWN:\r |
| 315 | scrollindex+=14;\r |
| 316 | if(scrollindex>scrollmax)\r |
| 317 | scrollindex=scrollmax;\r |
| 318 | SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);\r |
| 319 | SendDlgItemMessage(hwndDlg,108,LB_RESETCONTENT,0,0);\r |
| 320 | FCEUI_CheatSearchGetRange(scrollindex+32768,scrollindex+32768+13,cfcallb);\r |
| 321 | break;\r |
| 322 | \r |
| 323 | case SB_THUMBPOSITION:\r |
| 324 | case SB_THUMBTRACK:\r |
| 325 | scrollindex=(short int)HIWORD(wParam);\r |
| 326 | SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);\r |
| 327 | SendDlgItemMessage(hwndDlg,108,LB_RESETCONTENT,0,0);\r |
| 328 | FCEUI_CheatSearchGetRange(32768+scrollindex,32768+scrollindex+13,cfcallb);\r |
| 329 | break;\r |
| 330 | }\r |
| 331 | \r |
| 332 | } \r |
| 333 | break;\r |
| 334 | \r |
| 335 | case WM_INITDIALOG:\r |
| 336 | SetDlgItemText(hwndDlg,110,(LPTSTR)U8ToStr(cheatval1));\r |
| 337 | SetDlgItemText(hwndDlg,111,(LPTSTR)U8ToStr(cheatval2));\r |
| 338 | DoGet();\r |
| 339 | CheckRadioButton(hwndDlg,115,118,scheatmethod+115);\r |
| 340 | lbfocus=0;\r |
| 341 | hwndLB=0;\r |
| 342 | break;\r |
| 343 | \r |
| 344 | case WM_VKEYTOITEM:\r |
| 345 | if(lbfocus)\r |
| 346 | {\r |
| 347 | int real;\r |
| 348 | \r |
| 349 | real=SendDlgItemMessage(hwndDlg,108,LB_GETCURSEL,0,(LPARAM)(LPSTR)0);\r |
| 350 | switch((int)LOWORD(wParam))\r |
| 351 | {\r |
| 352 | case VK_UP: \r |
| 353 | /* mmmm....recursive goodness */\r |
| 354 | if(!real)\r |
| 355 | SendMessage(hwndDlg,WM_VSCROLL,SB_LINEUP,0);\r |
| 356 | return(-1);\r |
| 357 | break;\r |
| 358 | case VK_DOWN:\r |
| 359 | if(real==13)\r |
| 360 | SendMessage(hwndDlg,WM_VSCROLL,SB_LINEDOWN,0);\r |
| 361 | return(-1);\r |
| 362 | break;\r |
| 363 | case VK_PRIOR:\r |
| 364 | SendMessage(hwndDlg,WM_VSCROLL,SB_PAGEUP,0);\r |
| 365 | break;\r |
| 366 | case VK_NEXT:\r |
| 367 | SendMessage(hwndDlg,WM_VSCROLL,SB_PAGEDOWN,0);\r |
| 368 | break;\r |
| 369 | case VK_HOME:\r |
| 370 | SendMessage(hwndDlg,WM_VSCROLL,SB_TOP,0);\r |
| 371 | break;\r |
| 372 | case VK_END:\r |
| 373 | SendMessage(hwndDlg,WM_VSCROLL,SB_BOTTOM,0);\r |
| 374 | break;\r |
| 375 | }\r |
| 376 | return(-2);\r |
| 377 | }\r |
| 378 | break;\r |
| 379 | \r |
| 380 | case WM_CLOSE:\r |
| 381 | case WM_QUIT: goto gornk;\r |
| 382 | case WM_COMMAND:\r |
| 383 | switch(LOWORD(wParam))\r |
| 384 | {\r |
| 385 | case 108:\r |
| 386 | switch(HIWORD(wParam))\r |
| 387 | {\r |
| 388 | case LBN_SELCHANGE:\r |
| 389 | {\r |
| 390 | char TempArray[32];\r |
| 391 | SendDlgItemMessage(hwndDlg,108,LB_GETTEXT,SendDlgItemMessage(hwndDlg,108,LB_GETCURSEL,0,(LPARAM)(LPSTR)0),(LPARAM)(LPCTSTR)TempArray);\r |
| 392 | TempArray[4]=0;\r |
| 393 | SetDlgItemText(hwndDlg,201,(LPTSTR)TempArray); \r |
| 394 | }\r |
| 395 | break;\r |
| 396 | case LBN_SETFOCUS:\r |
| 397 | lbfocus=1;\r |
| 398 | break;\r |
| 399 | case LBN_KILLFOCUS:\r |
| 400 | lbfocus=0;\r |
| 401 | break;\r |
| 402 | }\r |
| 403 | break;\r |
| 404 | }\r |
| 405 | \r |
| 406 | switch(HIWORD(wParam))\r |
| 407 | {\r |
| 408 | case BN_CLICKED:\r |
| 409 | if(LOWORD(wParam)>=115 && LOWORD(wParam)<=118)\r |
| 410 | scheatmethod=LOWORD(wParam)-115;\r |
| 411 | break;\r |
| 412 | case EN_CHANGE:\r |
| 413 | {\r |
| 414 | char TempArray[256];\r |
| 415 | GetDlgItemText(hwndDlg,LOWORD(wParam),TempArray,256);\r |
| 416 | switch(LOWORD(wParam))\r |
| 417 | {\r |
| 418 | case 110:cheatval1=StrToU8(TempArray);break;\r |
| 419 | case 111:cheatval2=StrToU8(TempArray);break;\r |
| 420 | }\r |
| 421 | }\r |
| 422 | break;\r |
| 423 | }\r |
| 424 | \r |
| 425 | \r |
| 426 | if(!(wParam>>16))\r |
| 427 | switch(wParam&0xFFFF)\r |
| 428 | {\r |
| 429 | case 112:\r |
| 430 | FCEUI_CheatSearchBegin();\r |
| 431 | DoGet();\r |
| 432 | break;\r |
| 433 | case 113:\r |
| 434 | FCEUI_CheatSearchEnd(scheatmethod,cheatval1,cheatval2);\r |
| 435 | DoGet();\r |
| 436 | break;\r |
| 437 | case 114:\r |
| 438 | FCEUI_CheatSearchSetCurrentAsOriginal();\r |
| 439 | DoGet();\r |
| 440 | break;\r |
| 441 | case 107:\r |
| 442 | FCEUI_CheatSearchShowExcluded();\r |
| 443 | DoGet();\r |
| 444 | break;\r |
| 445 | case 105:\r |
| 446 | {\r |
| 447 | int a,v;\r |
| 448 | char temp[256];\r |
| 449 | \r |
| 450 | GetDlgItemText(hwndDlg,201,temp,4+1);\r |
| 451 | a=StrToU16(temp);\r |
| 452 | GetDlgItemText(hwndDlg,202,temp,3+1);\r |
| 453 | v=StrToU8(temp);\r |
| 454 | \r |
| 455 | GetDlgItemText(hwndDlg,200,temp,256);\r |
| 456 | AddTheThing(hwndDlg,temp,a,v);\r |
| 457 | }\r |
| 458 | break;\r |
| 459 | case 106:\r |
| 460 | gornk:\r |
| 461 | EndDialog(hwndDlg,0);\r |
| 462 | break;\r |
| 463 | }\r |
| 464 | }\r |
| 465 | return 0;\r |
| 466 | }\r |
| 467 | \r |
| 468 | static void ConfigAddCheat(HWND wnd)\r |
| 469 | {\r |
| 470 | DialogBox(fceu_hInstance,"ADDCHEAT",wnd,AddCheatCallB);\r |
| 471 | }\r |