gamegenie.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. /*
  2. * Code Breaker plugin - The TI-NESulator Project
  3. * gamegenie.c: Hack your games with unlimited lives of add new powers!
  4. *
  5. * Created by Manoel Trapier.
  6. * Copyright 2003-2008 986 Corp. All rights reserved.
  7. *
  8. * $LastChangedDate$
  9. * $Author$
  10. * $HeadURL$
  11. * $Revision$
  12. *
  13. */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <os_dependent.h>
  17. #define __TINES_PLUGINS__
  18. #include <plugins/manager.h>
  19. #undef __TINES_PLUGINS_
  20. #include <memory/manager.h>
  21. #include <types.h>
  22. /* Allegro includes */
  23. #ifdef __APPLE__
  24. #define USE_CONSOLE
  25. #include <Allegro/allegro.h>
  26. #else
  27. #define USE_CONSOLE
  28. #include <allegro.h>
  29. #endif
  30. typedef enum gg_States_
  31. {
  32. GG_S00_MAIN_STATE = 0,
  33. GG_S01_SEARCH_VALUE,
  34. GG_S02_SEARCH_BAR
  35. } gg_States;
  36. /* Actual State Machine state */
  37. gg_States gg_state = GG_S00_MAIN_STATE;
  38. /* Own representation of memory */
  39. byte gg_MainRAM[0x800];
  40. byte gg_OldMainRAM[0x800];
  41. byte gg_SRAM[0x2000];
  42. /* Field used to now which byte are currently marked as pertinent or not */
  43. byte gg_use_MainRAM[0x800];
  44. byte gg_use_SRAM[0x2000];
  45. int gg_ResultNumber;
  46. byte gg_PatchUsed[10];
  47. byte gg_PatchedPage[10];
  48. byte gg_PatchedAddr[10];
  49. byte gg_PatchedValue[10];
  50. func_rdhook gg_rdhookPtr[10];
  51. #define GG_RDHOOKPATCH(d) \
  52. byte gg_RdHookPatch##d(byte addr) \
  53. { \
  54. if (addr == gg_PatchedAddr[d]) \
  55. { \
  56. return gg_PatchedValue[d]; \
  57. } \
  58. else \
  59. { \
  60. if (gg_rdhookPtr[d] != NULL) \
  61. return gg_rdhookPtr[d](addr); \
  62. else \
  63. return (get_page_ptr(gg_PatchedPage[d])[addr]); \
  64. } \
  65. }
  66. #define GG_MAX_PATCH 10
  67. /* Defines the rdhook patches */
  68. GG_RDHOOKPATCH(0)
  69. GG_RDHOOKPATCH(1)
  70. GG_RDHOOKPATCH(2)
  71. GG_RDHOOKPATCH(3)
  72. GG_RDHOOKPATCH(4)
  73. GG_RDHOOKPATCH(5)
  74. GG_RDHOOKPATCH(6)
  75. GG_RDHOOKPATCH(7)
  76. GG_RDHOOKPATCH(8)
  77. GG_RDHOOKPATCH(9)
  78. void gg_SetPatch(int id, byte page, byte addr, byte value)
  79. {
  80. func_rdhook fptr;
  81. if (id >= GG_MAX_PATCH)
  82. return;
  83. /* Set parameters for the patch */
  84. if (gg_PatchUsed[id] == 0x00)
  85. {
  86. gg_rdhookPtr[id] = get_page_rdhook(page);
  87. }
  88. gg_PatchedPage[id] = page;
  89. gg_PatchedAddr[id] = addr;
  90. gg_PatchedValue[id] = value;
  91. gg_PatchUsed[id] = 0xFF;
  92. /* Set a ReadHook on the page */
  93. switch(id)
  94. {
  95. default:
  96. case 0:
  97. fptr = gg_RdHookPatch0;
  98. break;
  99. case 1:
  100. fptr = gg_RdHookPatch1;
  101. break;
  102. case 2:
  103. fptr = gg_RdHookPatch2;
  104. break;
  105. case 3:
  106. fptr = gg_RdHookPatch3;
  107. break;
  108. case 4:
  109. fptr = gg_RdHookPatch4;
  110. break;
  111. case 5:
  112. fptr = gg_RdHookPatch5;
  113. break;
  114. case 6:
  115. fptr = gg_RdHookPatch6;
  116. break;
  117. case 7:
  118. fptr = gg_RdHookPatch7;
  119. break;
  120. case 8:
  121. fptr = gg_RdHookPatch8;
  122. break;
  123. case 9:
  124. fptr = gg_RdHookPatch9;
  125. break;
  126. }
  127. set_page_rd_hook(page, fptr);
  128. }
  129. /* Access to the bitmap Buffer */
  130. extern BITMAP *Buffer;
  131. BITMAP *gg_Buffer;
  132. void MessageBox(char *title, char *msg)
  133. {
  134. int sc_w, sc_h;
  135. int box_h, box_t, box_l, box_w;
  136. sc_w = screen->w;
  137. sc_h = screen->h;
  138. gg_Buffer = create_bitmap(sc_w, sc_h);
  139. blit(Buffer, gg_Buffer, 0, 0, 0, 0, 512 + 256, 480);
  140. box_w = text_length(font, title) + 10;
  141. box_w = (box_w>text_length(font, msg))?box_w:text_length(font, msg);
  142. box_w += 15 * 2; /*sc_w/2;*/
  143. box_h = 15*2 + 10;
  144. /* Set the box center */
  145. box_t = (sc_h - box_h) / 2;
  146. box_l = (sc_w - box_w) / 2;
  147. rectfill(gg_Buffer, box_l, box_t, box_l + box_w, box_t + box_h, 60);
  148. rect(gg_Buffer, box_l + 5, box_t + 5, box_l + box_w - 5, box_t + box_h - 5, 34);
  149. /* Display the title */
  150. textout_centre_ex(gg_Buffer, font, title, box_w / 2 + box_l, box_t + 2, 34, 60);
  151. /* Display the message */
  152. textout_centre_ex(gg_Buffer, font, msg, box_w / 2 + box_l, 15 + box_t + 2, 34, 60);
  153. blit(gg_Buffer, screen, 0, 0, 0, 0, 512 + 256, 480);
  154. sleep(1);
  155. release_bitmap(gg_Buffer);
  156. }
  157. unsigned short SelectNumber(char *title, char *msg, byte size)
  158. {
  159. int sc_w, sc_h;
  160. int box_h, box_t, box_l, box_w;
  161. char valueText[10];
  162. unsigned short value;
  163. byte digit = 0;
  164. sc_w = screen->w;
  165. sc_h = screen->h;
  166. gg_Buffer = create_bitmap(sc_w, sc_h);
  167. blit(Buffer, gg_Buffer, 0, 0, 0, 0, 512 + 256, 480);
  168. box_w = text_length(font, title) + 10;
  169. box_w = (box_w>text_length(font, msg))?box_w:text_length(font, msg);
  170. sprintf(valueText, "0000");
  171. box_w = (box_w>text_length(font, valueText))?box_w:text_length(font, msg);
  172. box_w += 15 * 2; /*sc_w/2;*/
  173. box_h = 15*2 + 30;
  174. /* Set the box center */
  175. box_t = (sc_h - box_h) / 2;
  176. box_l = (sc_w - box_w) / 2;
  177. value = 0;
  178. while(!key[KEY_ENTER])
  179. {
  180. rectfill(gg_Buffer, box_l, box_t, box_l + box_w, box_t + box_h, 60);
  181. rect(gg_Buffer, box_l + 5, box_t + 5, box_l + box_w - 5, box_t + box_h - 5, 34);
  182. /* Display the title */
  183. textout_centre_ex(gg_Buffer, font, title, box_w / 2 + box_l, box_t + 2, 34, 60);
  184. /* Display the message */
  185. textout_centre_ex(gg_Buffer, font, msg, box_w / 2 + box_l, 15 + box_t + 2, 34, 60);
  186. if (size == 2)
  187. sprintf(valueText, " %02X", value&0xFF);
  188. else
  189. sprintf(valueText, "%04X", value);
  190. textout_centre_ex(gg_Buffer, font, valueText, box_w / 2 + box_l , 15 + box_t + 2 + 10, 34, 60);
  191. switch(digit)
  192. {
  193. default:
  194. case 0:
  195. textout_centre_ex(gg_Buffer, font, " ^", box_w / 2 + box_l , 15 + box_t + 2 + 20, 34, 60);
  196. break;
  197. case 1:
  198. textout_centre_ex(gg_Buffer, font, " ^ ", box_w / 2 + box_l , 15 + box_t + 2 + 20, 34, 60);
  199. break;
  200. case 2:
  201. textout_centre_ex(gg_Buffer, font, " ^ ", box_w / 2 + box_l , 15 + box_t + 2 + 20, 34, 60);
  202. break;
  203. case 3:
  204. textout_centre_ex(gg_Buffer, font, "^ ", box_w / 2 + box_l , 15 + box_t + 2 + 20, 34, 60);
  205. break;
  206. }
  207. blit(gg_Buffer, screen, 0, 0, 0, 0, 512 + 256, 480);
  208. if (key[KEY_UP])
  209. {
  210. usleep(100000);
  211. value += ((digit==0)?0x0001:((digit==1)?0x0010:((digit==2)?0x0100:0x1000)));
  212. value &= (size==2)?0xFF:0xFFFF;
  213. }
  214. if (key[KEY_DOWN])
  215. {
  216. usleep(100000);
  217. value -= ((digit==0)?0x0001:((digit==1)?0x0010:((digit==2)?0x0100:0x1000)));
  218. value &= (size==2)?0xFF:0xFFFF;
  219. }
  220. if (key[KEY_RIGHT])
  221. {
  222. usleep(100000);
  223. if (digit <= 0)
  224. digit = size-1;
  225. else
  226. digit --;
  227. }
  228. if (key[KEY_LEFT])
  229. {
  230. usleep(100000);
  231. if (digit >= size-1)
  232. digit = 0;
  233. else
  234. digit ++;
  235. }
  236. }
  237. release_bitmap(gg_Buffer);
  238. while(key[KEY_ENTER]);
  239. return value;
  240. }
  241. int DispMenu(int itemc, char *itemv[], char *title)
  242. {
  243. //console_printf(Console_Default, "%s(%d, %p, \"%s\");\n", __func__, itemc, itemv, title);
  244. int selection = 0;
  245. int i;
  246. int sc_w, sc_h;
  247. int box_h, box_t, box_l, box_w;
  248. sc_w = screen->w;
  249. sc_h = screen->h;
  250. gg_Buffer = create_bitmap(sc_w, sc_h);
  251. blit(Buffer, gg_Buffer, 0, 0, 0, 0, 512 + 256, 480);
  252. box_w = text_length(font, title) + 10;
  253. for (i = 0; i < itemc; i ++)
  254. box_w = (box_w>text_length(font, itemv[i]))?box_w:text_length(font, itemv[i]);
  255. box_w += 15 * 2; /*sc_w/2;*/
  256. box_h = 15*2 + itemc*10;
  257. /* Set the box center */
  258. box_t = (sc_h - box_h) / 2;
  259. box_l = (sc_w - box_w) / 2;
  260. while(!key[KEY_ENTER])
  261. {
  262. /* Draw the box and highlight the selected item */
  263. rectfill(gg_Buffer, box_l, box_t, box_l + box_w, box_t + box_h, 60);
  264. rect(gg_Buffer, box_l + 5, box_t + 5, box_l + box_w - 5, box_t + box_h - 5, 34);
  265. /* Display the title */
  266. textout_centre_ex(gg_Buffer, font, title, box_w / 2 + box_l, box_t + 2, 34, 60);
  267. /* Display the highlight item */
  268. rectfill(gg_Buffer, box_l+15, 15 + box_t + (selection * 10) , box_l + box_w - 15, 15 + box_t + (selection * 10) + 10, 34);
  269. textout_centre_ex(gg_Buffer, font, itemv[selection], box_w / 2 + box_l, 15 + box_t + (selection * 10) + 2, 60, 34);
  270. /* Display other items */
  271. for (i = 0; i < itemc; i ++)
  272. {
  273. if (i != selection)
  274. textout_centre_ex(gg_Buffer, font, itemv[i], box_w / 2 + box_l, 15 + box_t + (i * 10) + 2, 34, 60);
  275. }
  276. /* Blit the screen buffer */
  277. blit(gg_Buffer, screen, 0, 0, 0, 0, 512 + 256, 480);
  278. /* Now get the keyboard state */
  279. if (key[KEY_UP])
  280. {
  281. usleep(100000);
  282. if (selection <= 0)
  283. selection = itemc - 1;
  284. else
  285. selection --;
  286. }
  287. if (key[KEY_DOWN])
  288. {
  289. usleep(100000);
  290. if (selection >= (itemc - 1))
  291. selection = 0;
  292. else
  293. selection ++;
  294. }
  295. }
  296. release_bitmap(gg_Buffer);
  297. while(key[KEY_ENTER]);
  298. return selection;
  299. }
  300. byte AskYesNo(char *title)
  301. {
  302. char *YesNo[] = { "No", "Yes" };
  303. return DispMenu(2, YesNo, title);
  304. }
  305. byte gg_CalcChk(unsigned short addr, byte value)
  306. {
  307. int chk = 0x42;
  308. chk += (addr & 0xFF00) >> 8;
  309. chk -= (addr & 0x00FF);
  310. chk += (value & 0x00FF);
  311. return chk;
  312. }
  313. /*
  314. Code is AAAAVVCC where
  315. AAAA = address,
  316. VV = value,
  317. CC = cheksum
  318. */
  319. unsigned long gg_MakeCode(unsigned addr, byte value)
  320. {
  321. unsigned long code = addr << 16;
  322. code |= (value << 8);
  323. code |= (gg_CalcChk(addr, value) & 0x00FF);
  324. return code ^ 0x246FF53A;
  325. }
  326. byte gg_SelectPatch()
  327. {
  328. char *Items[GG_MAX_PATCH + 1];
  329. char *tmp;
  330. int i;
  331. byte ret;
  332. for (i = 0; i < GG_MAX_PATCH; i++)
  333. {
  334. tmp = (char*) malloc(0x100);
  335. console_printf(Console_Default, "Items[%d]: %p\n", i, tmp);
  336. if (gg_PatchUsed[i] == 0x00)
  337. sprintf(tmp, "Patch %d: Not used", i);
  338. else
  339. sprintf(tmp, "Patch %d: Put 0x%02X on address 0x%02X%02X (Code: %08lX)",
  340. i, gg_PatchedValue[i], gg_PatchedPage[i], gg_PatchedAddr[i],
  341. gg_MakeCode((gg_PatchedPage[i]<<8) | gg_PatchedAddr[i], gg_PatchedValue[i]));
  342. Items[i] = tmp;
  343. }
  344. tmp = (char*) malloc(0x100);
  345. sprintf(tmp, "Return");
  346. Items[GG_MAX_PATCH] = tmp;
  347. ret = DispMenu(GG_MAX_PATCH + 1, Items, "Code Breaker - Select a patch");
  348. for(i = 0; i < GG_MAX_PATCH; i++)
  349. free(Items[i]);
  350. if (ret == GG_MAX_PATCH)
  351. return 0xFF;
  352. return ret;
  353. }
  354. void gg_PatchManager()
  355. {
  356. console_printf(Console_Default, "DTC!\n");
  357. }
  358. void gg_InitSearch()
  359. {
  360. unsigned short addr;
  361. for(addr = 0x000; addr < 0x800; addr ++)
  362. {
  363. gg_MainRAM[addr] = ReadMemory((addr&0xFF00)>>8,addr&0x00FF);
  364. gg_use_MainRAM[addr] = 0xFF;
  365. }
  366. gg_ResultNumber = 0x800;
  367. }
  368. typedef enum gg_SearchForMode_
  369. {
  370. GG_SEARCHFOR_LOWER = 0,
  371. GG_SEARCHFOR_HIGHER,
  372. GG_SEARCHFOR_IDENTIC,
  373. GG_SEARCHFOR_DIFFERENT
  374. } gg_SearchForMode;
  375. void gg_SearchForValue(byte value)
  376. {
  377. unsigned short addr;
  378. //byte oldValue;
  379. byte currentValue;
  380. gg_ResultNumber = 0x00;
  381. for(addr = 0x000; addr < 0x800; addr ++)
  382. {
  383. if (gg_use_MainRAM[addr] == 0xFF)
  384. {
  385. /* "Backup" the old ram */
  386. memcpy(gg_OldMainRAM, gg_MainRAM, 0x800);
  387. //oldValue = gg_MainRAM[addr];
  388. currentValue = ReadMemory((addr&0xFF00)>>8,addr&0x00FF);
  389. if (currentValue != value)
  390. { /* This is not the good one ! */
  391. gg_use_MainRAM[addr] = 0x00;
  392. }
  393. else
  394. { /* This can be the good one ! */
  395. gg_ResultNumber++;
  396. gg_MainRAM[addr] = currentValue;
  397. }
  398. }
  399. }
  400. }
  401. void gg_SearchFor(gg_SearchForMode mode)
  402. {
  403. unsigned short addr;
  404. byte oldValue;
  405. byte currentValue;
  406. gg_ResultNumber = 0x00;
  407. for(addr = 0x000; addr < 0x800; addr ++)
  408. {
  409. if (gg_use_MainRAM[addr] == 0xFF)
  410. {
  411. /* "Backup" the old ram */
  412. memcpy(gg_OldMainRAM, gg_MainRAM, 0x800);
  413. oldValue = gg_MainRAM[addr];
  414. currentValue = ReadMemory((addr&0xFF00)>>8,addr&0x00FF);
  415. switch(mode)
  416. {
  417. case GG_SEARCHFOR_LOWER:
  418. if (currentValue >= oldValue)
  419. { /* This is not the good one ! */
  420. gg_use_MainRAM[addr] = 0x00;
  421. }
  422. else
  423. { /* This can be the good one ! */
  424. gg_ResultNumber++;
  425. gg_MainRAM[addr] = currentValue;
  426. }
  427. break;
  428. case GG_SEARCHFOR_HIGHER:
  429. if (currentValue <= oldValue)
  430. { /* This is not the good one ! */
  431. gg_use_MainRAM[addr] = 0x00;
  432. }
  433. else
  434. { /* This can be the good one ! */
  435. gg_ResultNumber++;
  436. gg_MainRAM[addr] = currentValue;
  437. }
  438. break;
  439. case GG_SEARCHFOR_IDENTIC:
  440. if (currentValue != oldValue)
  441. { /* This is not the good one ! */
  442. gg_use_MainRAM[addr] = 0x00;
  443. }
  444. else
  445. { /* This can be the good one ! */
  446. gg_ResultNumber++;
  447. gg_MainRAM[addr] = currentValue;
  448. }
  449. break;
  450. case GG_SEARCHFOR_DIFFERENT:
  451. if (currentValue == oldValue)
  452. { /* This is not the good one ! */
  453. gg_use_MainRAM[addr] = 0x00;
  454. }
  455. else
  456. { /* This can be the good one ! */
  457. gg_ResultNumber++;
  458. gg_MainRAM[addr] = currentValue;
  459. }
  460. break;
  461. }
  462. }
  463. }
  464. }
  465. byte gg_DisplayResults()
  466. {
  467. char *Items[100];
  468. char *tmp;
  469. int i, addr = 0x0000;
  470. byte ret = 0;
  471. unsigned short AddrList[21];
  472. if (gg_ResultNumber > 20)
  473. {
  474. MessageBox("Code Breaker", "Too many results for displaying them!");
  475. }
  476. else
  477. {
  478. for (i = 0; i < gg_ResultNumber; i++)
  479. {
  480. while(gg_use_MainRAM[addr] != 0xFF)
  481. addr ++;
  482. console_printf(Console_Default, "0x%04X [%d]\n", addr, i);
  483. tmp = (char*) malloc(0x100);
  484. sprintf(tmp,"Patch: %08XAddress 0x%04X - Was: 0x%02X - Actual: 0x%02X",
  485. i,
  486. addr,
  487. gg_OldMainRAM[addr],
  488. gg_MainRAM[addr]);
  489. Items[i] = tmp;
  490. AddrList[i] = addr;
  491. addr++;
  492. }
  493. tmp = (char*) malloc(0x100);
  494. sprintf(tmp, "Return");
  495. Items[i] = tmp;
  496. ret = DispMenu(gg_ResultNumber + 1, Items, "Code Breaker - Search");
  497. if (ret < i)
  498. {
  499. if (AskYesNo("Code Breaker: Apply this patch?"))
  500. {
  501. /* Now patch it ! */
  502. gg_SetPatch(gg_SelectPatch(), (AddrList[ret]&0xFF00)>>8, (AddrList[ret]&0x00FF),
  503. SelectNumber("Code Breaker", "Value to apply:", 2) & 0x00FF);
  504. ret = 1;
  505. }
  506. }
  507. for(i=0 ; i<gg_ResultNumber+1; i++)
  508. free(Items[i]);
  509. }
  510. return ret;
  511. }
  512. void gg_Start()
  513. {
  514. char *S00_MenuList[] = { "Search a specific Value", "Search for an Unknown Value", "Enter code",
  515. "Manage Patches", "Exit" };
  516. char *S01_MenuList[] = { "Value is identical", "New Value...", "Value is different",
  517. "Value is greater", "Value is lower", "Result", "Restart", "Exit" };
  518. char *S02_MenuList[] = { "Value is identical", "Value is different", "Value is greater",
  519. "Value is lower", "Result", "Restart", "Exit" };
  520. char Buffer[100];
  521. int ret;
  522. byte value;
  523. unsigned short addr;
  524. switch(gg_state)
  525. {
  526. default:
  527. case GG_S00_MAIN_STATE:
  528. ret = DispMenu(5, S00_MenuList, "Code Breaker - Main");
  529. switch (ret)
  530. {
  531. case 0:
  532. gg_InitSearch();
  533. gg_state = GG_S01_SEARCH_VALUE;
  534. value = SelectNumber("Code Breaker", "Select the value:", 2) & 0x00FF;
  535. gg_SearchForValue(value);
  536. MessageBox("Code Breaker", "Search initialized !");
  537. break;
  538. case 1:
  539. gg_InitSearch();
  540. gg_state = GG_S02_SEARCH_BAR;
  541. MessageBox("Code Breaker", "Search initialized !");
  542. break;
  543. case 2: /* Enter code */
  544. addr = SelectNumber("Code Breaker", "Select the address", 4);
  545. value = SelectNumber("Code Breaker", "Select the value:", 2) & 0x00FF;
  546. if (AskYesNo("Code Breaker: Apply this patch?"))
  547. {
  548. /* Now patch it ! */
  549. gg_SetPatch(gg_SelectPatch(),
  550. (addr&0xFF00)>>8, (addr&0x00FF),
  551. value);
  552. }
  553. break;
  554. case 3: /* Patch manager */
  555. gg_PatchManager();
  556. break;
  557. }
  558. break;
  559. case GG_S01_SEARCH_VALUE:
  560. S01_MENU:
  561. ret = DispMenu(8, S01_MenuList, "Code Breaker - Search");
  562. switch(ret)
  563. {
  564. case 0:
  565. gg_SearchFor(GG_SEARCHFOR_IDENTIC);
  566. //goto S02_MENU;
  567. break;
  568. case 1:
  569. value = SelectNumber("Code Breaker", "Select the value:", 2) & 0x00FF;
  570. gg_SearchForValue(value);
  571. break;
  572. case 2:
  573. gg_SearchFor(GG_SEARCHFOR_DIFFERENT);
  574. //goto S02_MENU;
  575. break;
  576. case 3:
  577. gg_SearchFor(GG_SEARCHFOR_HIGHER);
  578. //goto S02_MENU;
  579. break;
  580. case 4:
  581. gg_SearchFor(GG_SEARCHFOR_LOWER);
  582. //goto S02_MENU;
  583. break;
  584. case 5: /* Results */
  585. if (gg_DisplayResults() == 1)
  586. gg_state = GG_S00_MAIN_STATE;
  587. else
  588. goto S01_MENU;
  589. break;
  590. case 6:
  591. if (AskYesNo("Code Breaker: Restart?"))
  592. {
  593. gg_state = GG_S00_MAIN_STATE;
  594. gg_Start();
  595. }
  596. else
  597. goto S01_MENU;
  598. break;
  599. }
  600. sprintf(Buffer,"Results found: %d", gg_ResultNumber);
  601. MessageBox("Code Breaker", Buffer);
  602. break;
  603. case GG_S02_SEARCH_BAR:
  604. S02_MENU:
  605. ret = DispMenu(7, S02_MenuList, "Code Breaker - Search");
  606. switch(ret)
  607. {
  608. case 0:
  609. gg_SearchFor(GG_SEARCHFOR_IDENTIC);
  610. //goto S02_MENU;
  611. break;
  612. case 1:
  613. gg_SearchFor(GG_SEARCHFOR_DIFFERENT);
  614. //goto S02_MENU;
  615. break;
  616. case 2:
  617. gg_SearchFor(GG_SEARCHFOR_HIGHER);
  618. //goto S02_MENU;
  619. break;
  620. case 3:
  621. gg_SearchFor(GG_SEARCHFOR_LOWER);
  622. //goto S02_MENU;
  623. break;
  624. case 4: /* Results */
  625. if (gg_DisplayResults() == 1)
  626. gg_state = GG_S00_MAIN_STATE;
  627. else
  628. goto S02_MENU;
  629. break;
  630. case 5:
  631. if (AskYesNo("Code Breaker: Restart?"))
  632. {
  633. gg_state = GG_S00_MAIN_STATE;
  634. gg_Start();
  635. }
  636. else
  637. goto S02_MENU;
  638. break;
  639. }
  640. sprintf(Buffer,"Results found: %d", gg_ResultNumber);
  641. MessageBox("Code Breaker", Buffer);
  642. break;
  643. }
  644. }
  645. int gg_Init()
  646. {
  647. int i;
  648. console_printf(Console_Default, "Initializing GG plugin...\n");
  649. plugin_install_keypressHandler('g', gg_Start);
  650. for ( i = 0; i < GG_MAX_PATCH; i++)
  651. gg_PatchUsed[i] = 0x00;
  652. return 0;
  653. }
  654. int gg_Deinit()
  655. {
  656. return 0;
  657. }