view src/gba/GBACheats.cpp @ 83:95cb2152d7cd

fleshing out functional gb interface
author Robert McIntyre <rlm@mit.edu>
date Fri, 09 Mar 2012 19:18:00 -0600
parents f9f4f1b99eed
children
line wrap: on
line source
1 #include <cstdio>
2 #include <cctype>
3 #include <cstring>
5 #include "../common/System.h"
6 #include "../common/Util.h"
7 #include "../NLS.h"
8 #include "GBACheats.h"
9 #include "GBA.h"
10 #include "GBAinline.h"
11 #include "GBAGlobals.h"
13 /**
14 * Gameshark code types:
15 *
16 * NNNNNNNN 001DC0DE - ID code for the game (game 4 character name) from ROM
17 * DEADFACE XXXXXXXX - changes decryption seeds
18 * 0AAAAAAA 000000YY - 8-bit constant write
19 * 1AAAAAAA 0000YYYY - 16-bit constant write
20 * 2AAAAAAA YYYYYYYY - 32-bit constant write
21 * 3AAAAAAA YYYYYYYY - ??
22 * 6AAAAAAA 0000YYYY - 16-bit ROM Patch (address >> 1)
23 * 6AAAAAAA 1000YYYY - 16-bit ROM Patch ? (address >> 1)
24 * 6AAAAAAA 2000YYYY - 16-bit ROM Patch ? (address >> 1)
25 * 8A1AAAAA 000000YY - 8-bit button write
26 * 8A2AAAAA 0000YYYY - 16-bit button write
27 * 8A3AAAAA YYYYYYYY - 32-bit button write
28 * 80F00000 0000YYYY - button slow motion
29 * DAAAAAAA 0000YYYY - if address contains 16-bit value enable next code
30 * FAAAAAAA 0000YYYY - Master code function
31 *
32 * CodeBreaker codes types:
33 *
34 * 0000AAAA 000Y - Game CRC (Y are flags: 8 - CRC, 2 - DI)
35 * 1AAAAAAA YYYY - Master Code function (store address at ((YYYY << 0x16)
36 * + 0x08000100))
37 * 2AAAAAAA YYYY - 16-bit or
38 * 3AAAAAAA YYYY - 8-bit constant write
39 * 4AAAAAAA YYYY - Slide code
40 * XXXXCCCC IIII (C is count and I is address increment, X is value incr.)
41 * 5AAAAAAA CCCC - Super code (Write bytes to address, CCCC is count)
42 * BBBBBBBB BBBB
43 * 6AAAAAAA YYYY - 16-bit and
44 * 7AAAAAAA YYYY - if address contains 16-bit value enable next code
45 * 8AAAAAAA YYYY - 16-bit constant write
46 * 9AAAAAAA YYYY - change decryption (when first code only?)
47 * AAAAAAAA YYYY - if address does not contain 16-bit value enable next code
48 * BAAAAAAA YYYY - if 16-bit < YYYY
49 * CAAAAAAA YYYY - if 16-bit > YYYY
50 * D0000020 YYYY - if button keys equal value enable next code
51 * EAAAAAAA YYYY - increase value stored in address
52 */
53 #define UNKNOWN_CODE -1
54 #define INT_8_BIT_WRITE 0
55 #define INT_16_BIT_WRITE 1
56 #define INT_32_BIT_WRITE 2
57 #define GSA_16_BIT_ROM_PATCH 3
58 #define GSA_8_BIT_GS_WRITE 4
59 #define GSA_16_BIT_GS_WRITE 5
60 #define GSA_32_BIT_GS_WRITE 6
61 #define CBA_IF_KEYS_PRESSED 7
62 #define CBA_IF_TRUE 8
63 #define CBA_SLIDE_CODE 9
64 #define CBA_IF_FALSE 10
65 #define CBA_AND 11
66 #define GSA_8_BIT_GS_WRITE2 12
67 #define GSA_16_BIT_GS_WRITE2 13
68 #define GSA_32_BIT_GS_WRITE2 14
69 #define GSA_16_BIT_ROM_PATCH2 15
70 #define GSA_8_BIT_SLIDE 16
71 #define GSA_16_BIT_SLIDE 17
72 #define GSA_32_BIT_SLIDE 18
73 #define GSA_8_BIT_IF_TRUE 19
74 #define GSA_32_BIT_IF_TRUE 20
75 #define GSA_8_BIT_IF_FALSE 21
76 #define GSA_32_BIT_IF_FALSE 22
77 #define GSA_8_BIT_FILL 23
78 #define GSA_16_BIT_FILL 24
79 #define GSA_8_BIT_IF_TRUE2 25
80 #define GSA_16_BIT_IF_TRUE2 26
81 #define GSA_32_BIT_IF_TRUE2 27
82 #define GSA_8_BIT_IF_FALSE2 28
83 #define GSA_16_BIT_IF_FALSE2 29
84 #define GSA_32_BIT_IF_FALSE2 30
85 #define GSA_SLOWDOWN 31
86 #define CBA_ADD 32
87 #define CBA_OR 33
88 #define CBA_LT 34
89 #define CBA_GT 35
90 #define CBA_SUPER 36
92 CheatsData cheatsList[100];
93 int cheatsNumber = 0;
95 u8 cheatsCBASeedBuffer[0x30];
96 u32 cheatsCBASeed[4];
97 u32 cheatsCBATemporaryValue = 0;
98 u16 cheatsCBATable[256];
99 bool cheatsCBATableGenerated = false;
101 u8 cheatsCBACurrentSeed[12] = {
102 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00,
104 0x00, 0x00, 0x00, 0x00
105 };
107 #define CHEAT_IS_HEX(a) (((a) >= 'A' && (a) <= 'F') || ((a) >= '0' && (a) <= '9'))
109 #define CHEAT_PATCH_ROM_16BIT(a, v) \
110 WRITE16LE(((u16 *)&rom[(a) & 0x1ffffff]), v);
112 static bool isMultilineWithData(int i)
113 {
114 // we consider it a multiline code if it has more than one line of data
115 // otherwise, it can still be considered a single code
116 if (i < cheatsNumber && i >= 0)
117 switch (cheatsList[i].size)
118 {
119 case INT_8_BIT_WRITE:
120 case INT_16_BIT_WRITE:
121 case INT_32_BIT_WRITE:
122 case GSA_16_BIT_ROM_PATCH:
123 case GSA_8_BIT_GS_WRITE:
124 case GSA_16_BIT_GS_WRITE:
125 case GSA_32_BIT_GS_WRITE:
126 case CBA_AND:
127 case CBA_IF_KEYS_PRESSED:
128 case CBA_IF_TRUE:
129 case CBA_IF_FALSE:
130 case GSA_8_BIT_IF_TRUE:
131 case GSA_32_BIT_IF_TRUE:
132 case GSA_8_BIT_IF_FALSE:
133 case GSA_32_BIT_IF_FALSE:
134 case GSA_8_BIT_FILL:
135 case GSA_16_BIT_FILL:
136 case GSA_8_BIT_IF_TRUE2:
137 case GSA_16_BIT_IF_TRUE2:
138 case GSA_32_BIT_IF_TRUE2:
139 case GSA_8_BIT_IF_FALSE2:
140 case GSA_16_BIT_IF_FALSE2:
141 case GSA_32_BIT_IF_FALSE2:
142 case GSA_SLOWDOWN:
143 case CBA_ADD:
144 case CBA_OR:
145 return false;
146 // the codes below have two lines of data
147 case CBA_SLIDE_CODE:
148 case GSA_8_BIT_GS_WRITE2:
149 case GSA_16_BIT_GS_WRITE2:
150 case GSA_32_BIT_GS_WRITE2:
151 case GSA_16_BIT_ROM_PATCH2:
152 case GSA_8_BIT_SLIDE:
153 case GSA_16_BIT_SLIDE:
154 case GSA_32_BIT_SLIDE:
155 case CBA_LT:
156 case CBA_GT:
157 case CBA_SUPER:
158 return true;
159 }
160 return false;
161 }
163 static int getCodeLength(int num)
164 {
165 if (num >= cheatsNumber || num < 0)
166 return 1;
168 // this is for all the codes that are true multiline
169 switch (cheatsList[num].size)
170 {
171 case INT_8_BIT_WRITE:
172 case INT_16_BIT_WRITE:
173 case INT_32_BIT_WRITE:
174 case GSA_16_BIT_ROM_PATCH:
175 case GSA_8_BIT_GS_WRITE:
176 case GSA_16_BIT_GS_WRITE:
177 case GSA_32_BIT_GS_WRITE:
178 case CBA_AND:
179 case GSA_8_BIT_FILL:
180 case GSA_16_BIT_FILL:
181 case GSA_SLOWDOWN:
182 case CBA_ADD:
183 case CBA_OR:
184 return 1;
185 case CBA_IF_KEYS_PRESSED:
186 case CBA_IF_TRUE:
187 case CBA_IF_FALSE:
188 case CBA_SLIDE_CODE:
189 case GSA_8_BIT_GS_WRITE2:
190 case GSA_16_BIT_GS_WRITE2:
191 case GSA_32_BIT_GS_WRITE2:
192 case GSA_16_BIT_ROM_PATCH2:
193 case GSA_8_BIT_SLIDE:
194 case GSA_16_BIT_SLIDE:
195 case GSA_32_BIT_SLIDE:
196 case GSA_8_BIT_IF_TRUE:
197 case GSA_32_BIT_IF_TRUE:
198 case GSA_8_BIT_IF_FALSE:
199 case GSA_32_BIT_IF_FALSE:
200 case CBA_LT:
201 case CBA_GT:
202 return 2;
203 case GSA_8_BIT_IF_TRUE2:
204 case GSA_16_BIT_IF_TRUE2:
205 case GSA_32_BIT_IF_TRUE2:
206 case GSA_8_BIT_IF_FALSE2:
207 case GSA_16_BIT_IF_FALSE2:
208 case GSA_32_BIT_IF_FALSE2:
209 return 3;
210 case CBA_SUPER:
211 return (cheatsList[num].value+5)/6;
212 }
213 return 1;
214 }
216 int cheatsCheckKeys(u32 keys, u32 extended)
217 {
218 int ticks = 0;
219 for (int i = 0; i < cheatsNumber; i++)
220 {
221 if (!cheatsList[i].enabled)
222 {
223 // make sure we skip other lines in this code
224 i += getCodeLength(i)-1;
225 continue;
226 }
227 switch (cheatsList[i].size)
228 {
229 case INT_8_BIT_WRITE:
230 CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
231 break;
232 case INT_16_BIT_WRITE:
233 CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
234 break;
235 case INT_32_BIT_WRITE:
236 CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
237 break;
238 case GSA_16_BIT_ROM_PATCH:
239 if ((cheatsList[i].status & 1) == 0)
240 {
241 if (CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value)
242 {
243 cheatsList[i].oldValue = CPUReadHalfWord(cheatsList[i].address);
244 cheatsList[i].status |= 1;
245 CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value);
246 }
247 }
248 break;
249 case GSA_8_BIT_GS_WRITE:
250 if (extended & 4)
251 {
252 CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
253 }
254 break;
255 case GSA_16_BIT_GS_WRITE:
256 if (extended & 4)
257 {
258 CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
259 }
260 break;
261 case GSA_32_BIT_GS_WRITE:
262 if (extended & 4)
263 {
264 CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
265 }
266 break;
267 case CBA_IF_KEYS_PRESSED:
268 {
269 u16 value = cheatsList[i].value;
270 u32 addr = cheatsList[i].address;
271 if ((addr & 0x30) == 0x20)
272 {
273 if ((keys & value) != value)
274 {
275 i++;
276 }
277 }
278 else if ((addr & 0x30) == 0x10)
279 {
280 if ((keys & value) == value)
281 {
282 i++;
283 }
284 }
285 break;
286 }
287 case CBA_IF_TRUE:
288 if (CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value)
289 {
290 i++;
291 }
292 break;
293 case CBA_SLIDE_CODE:
294 {
295 u32 address = cheatsList[i].address;
296 u16 value = cheatsList[i].value;
297 i++;
298 if (i < cheatsNumber)
299 {
300 int count = (cheatsList[i].address & 0xFFFF);
301 u16 vinc = (cheatsList[i].address >> 16) & 0xFFFF;
302 int inc = cheatsList[i].value;
304 for (int x = 0; x < count; x++)
305 {
306 CPUWriteHalfWord(address, value);
307 address += inc;
308 value += vinc;
309 }
310 }
311 break;
312 }
313 case CBA_IF_FALSE:
314 if (CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value)
315 {
316 i++;
317 }
318 break;
319 case CBA_AND:
320 CPUWriteHalfWord(cheatsList[i].address,
321 CPUReadHalfWord(cheatsList[i].address) &
322 cheatsList[i].value);
323 break;
324 case GSA_8_BIT_GS_WRITE2:
325 i++;
326 if (i < cheatsNumber)
327 {
328 if (extended & 4)
329 {
330 CPUWriteByte(cheatsList[i-1].value, cheatsList[i].address);
331 }
332 }
333 break;
334 case GSA_16_BIT_GS_WRITE2:
335 i++;
336 if (i < cheatsNumber)
337 {
338 if (extended & 4)
339 {
340 CPUWriteHalfWord(cheatsList[i-1].value, cheatsList[i].address);
341 }
342 }
343 break;
344 case GSA_32_BIT_GS_WRITE2:
345 i++;
346 if (i < cheatsNumber)
347 {
348 if (extended & 4)
349 {
350 CPUWriteMemory(cheatsList[i-1].value, cheatsList[i].address);
351 }
352 }
353 break;
354 case GSA_16_BIT_ROM_PATCH2:
355 i++;
356 if (i < cheatsNumber)
357 {
358 if ((cheatsList[i-1].status & 1) == 0)
359 {
360 u32 addr = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
361 if (CPUReadHalfWord(addr) != (cheatsList[i].address & 0xFFFF))
362 {
363 cheatsList[i-1].oldValue = CPUReadHalfWord(addr);
364 cheatsList[i-1].status |= 1;
365 CHEAT_PATCH_ROM_16BIT(addr, cheatsList[i].address & 0xFFFF);
366 }
367 }
368 }
369 break;
370 case GSA_8_BIT_SLIDE:
371 i++;
372 if (i < cheatsNumber)
373 {
374 u32 addr = cheatsList[i-1].value;
375 u8 value = cheatsList[i].address;
376 int vinc = (cheatsList[i].value >> 24) & 255;
377 int count = (cheatsList[i].value >> 16) & 255;
378 int ainc = (cheatsList[i].value & 0xffff);
379 while (count > 0)
380 {
381 CPUWriteByte(addr, value);
382 value += vinc;
383 addr += ainc;
384 count--;
385 }
386 }
387 break;
388 case GSA_16_BIT_SLIDE:
389 i++;
390 if (i < cheatsNumber)
391 {
392 u32 addr = cheatsList[i-1].value;
393 u16 value = cheatsList[i].address;
394 int vinc = (cheatsList[i].value >> 24) & 255;
395 int count = (cheatsList[i].value >> 16) & 255;
396 int ainc = (cheatsList[i].value & 0xffff)*2;
397 while (count > 0)
398 {
399 CPUWriteHalfWord(addr, value);
400 value += vinc;
401 addr += ainc;
402 count--;
403 }
404 }
405 break;
406 case GSA_32_BIT_SLIDE:
407 i++;
408 if (i < cheatsNumber)
409 {
410 u32 addr = cheatsList[i-1].value;
411 u32 value = cheatsList[i].address;
412 int vinc = (cheatsList[i].value >> 24) & 255;
413 int count = (cheatsList[i].value >> 16) & 255;
414 int ainc = (cheatsList[i].value & 0xffff)*4;
415 while (count > 0)
416 {
417 CPUWriteMemory(addr, value);
418 value += vinc;
419 addr += ainc;
420 count--;
421 }
422 }
423 break;
424 case GSA_8_BIT_IF_TRUE:
425 if (CPUReadByte(cheatsList[i].address) != cheatsList[i].value)
426 {
427 i++;
428 }
429 break;
430 case GSA_32_BIT_IF_TRUE:
431 if (CPUReadMemory(cheatsList[i].address) != cheatsList[i].value)
432 {
433 i++;
434 }
435 break;
436 case GSA_8_BIT_IF_FALSE:
437 if (CPUReadByte(cheatsList[i].address) == cheatsList[i].value)
438 {
439 i++;
440 }
441 break;
442 case GSA_32_BIT_IF_FALSE:
443 if (CPUReadMemory(cheatsList[i].address) == cheatsList[i].value)
444 {
445 i++;
446 }
447 break;
448 case GSA_8_BIT_FILL:
449 {
450 u32 addr = cheatsList[i].address;
451 u8 v = cheatsList[i].value & 0xff;
452 u32 end = addr + (cheatsList[i].value >> 8);
453 do
454 {
455 CPUWriteByte(addr, v);
456 addr++;
457 }
458 while (addr <= end);
459 break;
460 }
461 case GSA_16_BIT_FILL:
462 {
463 u32 addr = cheatsList[i].address;
464 u16 v = cheatsList[i].value & 0xffff;
465 u32 end = addr + ((cheatsList[i].value >> 16) << 1);
466 do
467 {
468 CPUWriteHalfWord(addr, v);
469 addr += 2;
470 }
471 while (addr <= end);
472 break;
473 }
474 case GSA_8_BIT_IF_TRUE2:
475 if (CPUReadByte(cheatsList[i].address) != cheatsList[i].value)
476 {
477 i += 2;
478 }
479 break;
480 case GSA_16_BIT_IF_TRUE2:
481 if (CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value)
482 {
483 i += 2;
484 }
485 break;
486 case GSA_32_BIT_IF_TRUE2:
487 if (CPUReadMemory(cheatsList[i].address) != cheatsList[i].value)
488 {
489 i += 2;
490 }
491 break;
492 case GSA_8_BIT_IF_FALSE2:
493 if (CPUReadByte(cheatsList[i].address) == cheatsList[i].value)
494 {
495 i += 2;
496 }
497 break;
498 case GSA_16_BIT_IF_FALSE2:
499 if (CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value)
500 {
501 i += 2;
502 }
503 break;
504 case GSA_32_BIT_IF_FALSE2:
505 if (CPUReadMemory(cheatsList[i].address) == cheatsList[i].value)
506 {
507 i += 2;
508 }
509 break;
510 case GSA_SLOWDOWN:
511 // check if button was pressed and released, if so toggle our state
512 if ((cheatsList[i].status & 4) && !(extended & 4))
513 cheatsList[i].status ^= 1;
514 if (extended & 4)
515 cheatsList[i].status |= 4;
516 else
517 cheatsList[i].status &= ~4;
519 if (cheatsList[i].status & 1)
520 ticks += 2*256*((cheatsList[i].value >> 8) & 255);
521 break;
522 case CBA_ADD:
523 CPUWriteHalfWord(cheatsList[i].address,
524 CPUReadHalfWord(cheatsList[i].address) +
525 (u16)cheatsList[i].value);
526 break;
527 case CBA_OR:
528 CPUWriteHalfWord(cheatsList[i].address,
529 CPUReadHalfWord(cheatsList[i].address) |
530 cheatsList[i].value);
531 break;
532 case CBA_LT:
533 if (CPUReadHalfWord(cheatsList[i].address) >= cheatsList[i].value)
534 i++;
535 break;
536 case CBA_GT:
537 if (CPUReadHalfWord(cheatsList[i].address) <= cheatsList[i].value)
538 i++;
539 break;
540 case CBA_SUPER:
541 {
542 int count = 2*cheatsList[i].value;
543 u32 address = cheatsList[i].address;
544 for (int x = 0; x < count; x++)
545 {
546 u8 b;
547 int res = x % 6;
548 if (res < 4)
549 b = (cheatsList[i].address >> (24-8*res)) & 0xFF;
550 else
551 b = (cheatsList[i].value >> (8 - 8*(res-4))) & 0x0FF;
552 CPUWriteByte(address, b);
553 address++;
554 if (x && !res)
555 i++;
556 }
557 if (count % 6)
558 i++;
559 break;
560 }
561 }
562 }
563 return ticks;
564 }
566 void cheatsAdd(const char *codeStr,
567 const char *desc,
568 u32 address,
569 u32 value,
570 int code,
571 int size)
572 {
573 if (cheatsNumber < 100)
574 {
575 int x = cheatsNumber;
576 cheatsList[x].code = code;
577 cheatsList[x].size = size;
578 cheatsList[x].address = address;
579 cheatsList[x].value = value;
580 strcpy(cheatsList[x].codestring, codeStr);
581 strcpy(cheatsList[x].desc, desc);
582 cheatsList[x].enabled = true;
583 cheatsList[x].status = 0;
585 // we only store the old value for this simple codes. ROM patching
586 // is taken care when it actually patches the ROM
587 switch (cheatsList[x].size)
588 {
589 case INT_8_BIT_WRITE:
590 cheatsList[x].oldValue = CPUReadByte(address);
591 break;
592 case INT_16_BIT_WRITE:
593 cheatsList[x].oldValue = CPUReadHalfWord(address);
594 break;
595 case INT_32_BIT_WRITE:
596 cheatsList[x].oldValue = CPUReadMemory(address);
597 break;
598 }
599 cheatsNumber++;
600 }
601 }
603 void cheatsDelete(int number, bool restore)
604 {
605 if (number < cheatsNumber && number >= 0)
606 {
607 int x = number;
609 if (restore)
610 {
611 switch (cheatsList[x].size)
612 {
613 case INT_8_BIT_WRITE:
614 CPUWriteByte(cheatsList[x].address, (u8)cheatsList[x].oldValue);
615 break;
616 case INT_16_BIT_WRITE:
617 CPUWriteHalfWord(cheatsList[x].address, (u16)cheatsList[x].oldValue);
618 break;
619 case INT_32_BIT_WRITE:
620 CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue);
621 break;
622 case GSA_16_BIT_ROM_PATCH:
623 if (cheatsList[x].status & 1)
624 {
625 cheatsList[x].status &= ~1;
626 CHEAT_PATCH_ROM_16BIT(cheatsList[x].address,
627 cheatsList[x].oldValue);
628 }
629 break;
630 case GSA_16_BIT_ROM_PATCH2:
631 if (cheatsList[x].status & 1)
632 {
633 cheatsList[x].status &= ~1;
634 CHEAT_PATCH_ROM_16BIT(((cheatsList[x].value & 0x00FFFFFF) << 1)+
635 0x8000000,
636 cheatsList[x].oldValue);
637 }
638 break;
639 }
640 }
641 if ((x+1) < cheatsNumber)
642 {
643 memcpy(&cheatsList[x], &cheatsList[x+1], sizeof(CheatsData)*
644 (cheatsNumber-x-1));
645 }
646 cheatsNumber--;
647 }
648 }
650 void cheatsDeleteAll(bool restore)
651 {
652 for (int i = cheatsNumber-1; i >= 0; i--)
653 {
654 cheatsDelete(i, restore);
655 }
656 }
658 void cheatsEnable(int i)
659 {
660 if (i >= 0 && i < cheatsNumber)
661 {
662 cheatsList[i].enabled = true;
663 }
664 }
666 void cheatsDisable(int i)
667 {
668 if (i >= 0 && i < cheatsNumber)
669 {
670 switch (cheatsList[i].size)
671 {
672 case GSA_16_BIT_ROM_PATCH:
673 if (cheatsList[i].status & 1)
674 {
675 cheatsList[i].status &= ~1;
676 CHEAT_PATCH_ROM_16BIT(cheatsList[i].address,
677 cheatsList[i].oldValue);
678 }
679 break;
680 case GSA_16_BIT_ROM_PATCH2:
681 if (cheatsList[i].status & 1)
682 {
683 cheatsList[i].status &= ~1;
684 CHEAT_PATCH_ROM_16BIT(((cheatsList[i].value & 0x00FFFFFF) << 1)+
685 0x8000000,
686 cheatsList[i].oldValue);
687 }
688 break;
689 }
690 cheatsList[i].enabled = false;
691 }
692 }
694 bool cheatsVerifyCheatCode(const char *code, const char *desc)
695 {
696 int len = strlen(code);
697 if (len != 11 && len != 13 && len != 17)
698 {
699 systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code);
700 return false;
701 }
703 if (code[8] != ':')
704 {
705 systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code);
706 return false;
707 }
709 int i;
710 for (i = 0; i < 8; i++)
711 {
712 if (!CHEAT_IS_HEX(code[i]))
713 {
714 // wrong cheat
715 systemMessage(MSG_INVALID_CHEAT_CODE,
716 N_("Invalid cheat code '%s'"), code);
717 return false;
718 }
719 }
720 for (i = 9; i < len; i++)
721 {
722 if (!CHEAT_IS_HEX(code[i]))
723 {
724 // wrong cheat
725 systemMessage(MSG_INVALID_CHEAT_CODE,
726 N_("Invalid cheat code '%s'"), code);
727 return false;
728 }
729 }
731 u32 address = 0;
732 u32 value = 0;
734 char buffer[10];
735 strncpy(buffer, code, 8);
736 buffer[8] = 0;
737 sscanf(buffer, "%x", &address);
739 switch (address >> 24)
740 {
741 case 2:
742 case 3:
743 break;
744 default:
745 systemMessage(MSG_INVALID_CHEAT_CODE_ADDRESS,
746 N_("Invalid cheat code address: %08x"),
747 address);
748 return false;
749 }
751 strncpy(buffer, &code[9], 8);
752 sscanf(buffer, "%x", &value);
753 int type = 0;
754 if (len == 13)
755 type = 1;
756 if (len == 17)
757 type = 2;
758 cheatsAdd(code, desc, address, value, type, type);
759 return true;
760 }
762 void cheatsAddCheatCode(const char *code, const char *desc)
763 {
764 cheatsVerifyCheatCode(code, desc);
765 }
767 void cheatsDecryptGSACode(u32& address, u32& value, bool v3)
768 {
769 u32 rollingseed = 0xC6EF3720;
770 u32 seeds_v1[] = { 0x09F4FBBD, 0x9681884A, 0x352027E9, 0xF3DEE5A7 };
771 u32 seeds_v3[] = { 0x7AA9648F, 0x7FAE6994, 0xC0EFAAD5, 0x42712C57 };
772 u32 *seeds = v3 ? seeds_v3 : seeds_v1;
774 int bitsleft = 32;
775 while (bitsleft > 0)
776 {
777 value -= ((((address << 4) + seeds[2]) ^ (address + rollingseed)) ^
778 ((address >> 5) + seeds[3]));
779 address -= ((((value << 4) + seeds[0]) ^ (value + rollingseed)) ^
780 ((value >> 5) + seeds[1]));
781 rollingseed -= 0x9E3779B9;
782 bitsleft--;
783 }
784 }
786 void cheatsAddGSACode(const char *code, const char *desc, bool v3)
787 {
788 if (strlen(code) != 16)
789 {
790 // wrong cheat
791 systemMessage(MSG_INVALID_GSA_CODE,
792 N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY"));
793 return;
794 }
796 int i;
797 for (i = 0; i < 16; i++)
798 {
799 if (!CHEAT_IS_HEX(code[i]))
800 {
801 // wrong cheat
802 systemMessage(MSG_INVALID_GSA_CODE,
803 N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY"));
804 return;
805 }
806 }
808 char buffer[10];
809 strncpy(buffer, code, 8);
810 buffer[8] = 0;
811 u32 address;
812 sscanf(buffer, "%x", &address);
813 strncpy(buffer, &code[8], 8);
814 buffer[8] = 0;
815 u32 value;
816 sscanf(buffer, "%x", &value);
818 cheatsDecryptGSACode(address, value, v3);
820 if (value == 0x1DC0DE)
821 {
822 u32 gamecode = READ32LE(((u32 *)&rom[0xac]));
823 if (gamecode != address)
824 {
825 char buffer[5];
826 *((u32 *)buffer) = address;
827 buffer[4] = 0;
828 char buffer2[5];
829 *((u32 *)buffer2) = READ32LE(((u32 *)&rom[0xac]));
830 buffer2[4] = 0;
831 systemMessage(MSG_GBA_CODE_WARNING,
832 N_("Warning: cheats are for game %s. Current game is %s.\nCodes may not work correctly."),
833 buffer, buffer2);
834 }
835 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, v3 ? 257 : 256,
836 UNKNOWN_CODE);
837 return;
838 }
839 if (isMultilineWithData(cheatsNumber-1))
840 {
841 cheatsAdd(code, desc, address, value, v3 ? 257 : 256, UNKNOWN_CODE);
842 return;
843 }
844 if (v3)
845 {
846 int type = (address >> 25) & 127;
847 u32 addr = (address & 0x00F00000) << 4 | (address & 0x0003FFFF);
848 switch (type)
849 {
850 case 0x00:
851 if (address == 0)
852 {
853 type = (value >> 25) & 127;
854 addr = (value & 0x00F00000) << 4 | (value & 0x0003FFFF);
855 switch (type)
856 {
857 case 0x04:
858 cheatsAdd(code, desc, 0, value & 0x00FFFFFF, 257, GSA_SLOWDOWN);
859 break;
860 case 0x08:
861 cheatsAdd(code, desc, 0, addr, 257, GSA_8_BIT_GS_WRITE2);
862 break;
863 case 0x09:
864 cheatsAdd(code, desc, 0, addr, 257, GSA_16_BIT_GS_WRITE2);
865 break;
866 case 0x0a:
867 cheatsAdd(code, desc, 0, addr, 257, GSA_32_BIT_GS_WRITE2);
868 break;
869 case 0x0c:
870 case 0x0d:
871 case 0x0e:
872 case 0x0f:
873 cheatsAdd(code, desc, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2);
874 break;
875 case 0x40:
876 cheatsAdd(code, desc, 0, addr, 257, GSA_8_BIT_SLIDE);
877 break;
878 case 0x41:
879 cheatsAdd(code, desc, 0, addr, 257, GSA_16_BIT_SLIDE);
880 break;
881 case 0x42:
882 cheatsAdd(code, desc, 0, addr, 257, GSA_32_BIT_SLIDE);
883 break;
884 default:
885 cheatsAdd(code, desc, address, value, 257, UNKNOWN_CODE);
886 break;
887 }
888 }
889 else
890 cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_FILL);
891 break;
892 case 0x01:
893 cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_FILL);
894 break;
895 case 0x02:
896 cheatsAdd(code, desc, addr, value, 257, INT_32_BIT_WRITE);
897 break;
898 case 0x04:
899 cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_TRUE);
900 break;
901 case 0x05:
902 cheatsAdd(code, desc, addr, value, 257, CBA_IF_TRUE);
903 break;
904 case 0x06:
905 cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_TRUE);
906 break;
907 case 0x08:
908 cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_FALSE);
909 break;
910 case 0x09:
911 cheatsAdd(code, desc, addr, value, 257, CBA_IF_FALSE);
912 break;
913 case 0x0a:
914 cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_FALSE);
915 break;
916 case 0x24:
917 cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_TRUE2);
918 break;
919 case 0x25:
920 cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_IF_TRUE2);
921 break;
922 case 0x26:
923 cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_TRUE2);
924 break;
925 case 0x28:
926 cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_FALSE2);
927 break;
928 case 0x29:
929 cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_IF_FALSE2);
930 break;
931 case 0x2a:
932 cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_FALSE2);
933 break;
934 default:
935 cheatsAdd(code, desc, address, value, 257, UNKNOWN_CODE);
936 break;
937 }
938 }
939 else
940 {
941 int type = (address >> 28) & 15;
942 switch (type)
943 {
944 case 0:
945 case 1:
946 case 2:
947 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256, type);
948 break;
949 case 6:
950 address <<= 1;
951 type = (address >> 28) & 15;
952 if (type == 0x0c)
953 {
954 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256,
955 GSA_16_BIT_ROM_PATCH);
956 break;
957 }
958 // unsupported code
959 cheatsAdd(code, desc, address, value, 256,
960 UNKNOWN_CODE);
961 break;
962 case 8:
963 switch ((address >> 20) & 15)
964 {
965 case 1:
966 cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256,
967 GSA_8_BIT_GS_WRITE);
968 break;
969 case 2:
970 cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256,
971 GSA_16_BIT_GS_WRITE);
972 break;
973 case 3:
974 cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256,
975 GSA_32_BIT_GS_WRITE);
976 case 15:
977 cheatsAdd(code, desc, 0, value & 0xFF00, 256, GSA_SLOWDOWN);
978 break;
979 default:
980 // unsupported code
981 cheatsAdd(code, desc, address, value, 256,
982 UNKNOWN_CODE);
983 break;
984 }
985 break;
986 case 0x0d:
987 if (address != 0xDEADFACE)
988 {
989 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256,
990 CBA_IF_TRUE);
991 }
992 else
993 cheatsAdd(code, desc, address, value, 256,
994 UNKNOWN_CODE);
995 break;
996 default:
997 // unsupported code
998 cheatsAdd(code, desc, address, value, 256,
999 UNKNOWN_CODE);
1000 break;
1005 bool cheatsImportGSACodeFile(const char *name, int game, bool v3)
1007 FILE *f = fopen(name, "rb");
1008 if (!f)
1009 return false;
1011 int games = 0;
1012 int len = 0;
1013 fseek(f, 0x1e, SEEK_CUR);
1014 fread(&games, 1, 4, f);
1015 bool found = false;
1016 int g = 0;
1017 while (games > 0)
1019 if (g == game)
1021 found = true;
1022 break;
1024 fread(&len, 1, 4, f);
1025 fseek(f, len, SEEK_CUR);
1026 int codes = 0;
1027 fread(&codes, 1, 4, f);
1028 while (codes > 0)
1030 fread(&len, 1, 4, f);
1031 fseek(f, len, SEEK_CUR);
1032 fseek(f, 8, SEEK_CUR);
1033 fread(&len, 1, 4, f);
1034 fseek(f, len*12, SEEK_CUR);
1035 codes--;
1037 games--;
1038 g++;
1040 if (found)
1042 char desc[256];
1043 char code[17];
1044 fread(&len, 1, 4, f);
1045 fseek(f, len, SEEK_CUR);
1046 int codes = 0;
1047 fread(&codes, 1, 4, f);
1048 while (codes > 0)
1050 fread(&len, 1, 4, f);
1051 fread(desc, 1, len, f);
1052 desc[len] = 0;
1053 desc[31] = 0;
1054 fread(&len, 1, 4, f);
1055 fseek(f, len, SEEK_CUR);
1056 fseek(f, 4, SEEK_CUR);
1057 fread(&len, 1, 4, f);
1058 while (len)
1060 fseek(f, 4, SEEK_CUR);
1061 fread(code, 1, 8, f);
1062 fseek(f, 4, SEEK_CUR);
1063 fread(&code[8], 1, 8, f);
1064 code[16] = 0;
1065 cheatsAddGSACode(code, desc, v3);
1066 len -= 2;
1068 codes--;
1071 fclose(f);
1072 return false;
1075 void cheatsCBAReverseArray(u8 *array, u8 *dest)
1077 dest[0] = array[3];
1078 dest[1] = array[2];
1079 dest[2] = array[1];
1080 dest[3] = array[0];
1081 dest[4] = array[5];
1082 dest[5] = array[4];
1085 void chatsCBAScramble(u8 *array, int count, u8 b)
1087 u8 *x = array + (count >> 3);
1088 u8 *y = array + (b >> 3);
1089 u32 z = *x & (1 << (count & 7));
1090 u32 x0 = (*x & (~(1 << (count & 7))));
1091 if (z != 0)
1092 z = 1;
1093 if ((*y & (1 << (b & 7))) != 0)
1094 x0 |= (1 << (count & 7));
1095 *x = x0;
1096 u32 temp = *y & (~(1 << (b & 7)));
1097 if (z != 0)
1098 temp |= (1 << (b & 7));
1099 *y = temp;
1102 u32 cheatsCBAGetValue(u8 *array)
1104 return array[0] | array[1]<<8 | array[2] << 16 | array[3]<<24;
1107 u16 cheatsCBAGetData(u8 *array)
1109 return array[4] | array[5]<<8;
1112 void cheatsCBAArrayToValue(u8 *array, u8 *dest)
1114 dest[0] = array[3];
1115 dest[1] = array[2];
1116 dest[2] = array[1];
1117 dest[3] = array[0];
1118 dest[4] = array[5];
1119 dest[5] = array[4];
1122 void cheatsCBAParseSeedCode(u32 address, u32 value, u32 *array)
1124 array[0] = 1;
1125 array[1] = value & 0xFF;
1126 array[2] = (address >> 0x10) & 0xFF;
1127 array[3] = (value >> 8) & 0xFF;
1128 array[4] = (address >> 0x18) & 0x0F;
1129 array[5] = address & 0xFFFF;
1130 array[6] = address;
1131 array[7] = value;
1134 u32 cheatsCBAEncWorker()
1136 u32 x = (cheatsCBATemporaryValue * 0x41c64e6d) + 0x3039;
1137 u32 y = (x * 0x41c64e6d) + 0x3039;
1138 u32 z = x >> 0x10;
1139 x = ((y >> 0x10) & 0x7fff) << 0x0f;
1140 z = (z << 0x1e) | x;
1141 x = (y * 0x41c64e6d) + 0x3039;
1142 cheatsCBATemporaryValue = x;
1143 return z | ((x >> 0x10) & 0x7fff);
1146 #define ROR(v, s) \
1147 (((v) >> (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
1149 u32 cheatsCBACalcIndex(u32 x, u32 y)
1151 if (y != 0)
1153 if (y == 1)
1154 x = 0;
1155 else if (x == y)
1156 x = 0;
1157 if (y < 1)
1158 return x;
1159 else if (x < y)
1160 return x;
1161 u32 x0 = 1;
1163 while (y < 0x10000000)
1165 if (y < x)
1167 y = y << 4;
1168 x0 = x0 << 4;
1170 else
1171 break;
1174 while (y < 0x80000000)
1176 if (y < x)
1178 y = y << 1;
1179 x0 = x0 << 1;
1181 else
1182 break;
1185 loop:
1186 u32 z = 0;
1187 if (x >= y)
1188 x -= y;
1189 if (x >= (y >> 1))
1191 x -= (y >> 1);
1192 z |= ROR(x0, 1);
1194 if (x >= (y >> 2))
1196 x -= (y >> 2);
1197 z |= ROR(x0, 2);
1199 if (x >= (y >> 3))
1201 x -= (y >> 3);
1202 z |= ROR(x0, 3);
1205 u32 temp = x0;
1207 if (x != 0)
1209 x0 = x0 >> 4;
1210 if (x0 != 0)
1212 y = y >> 4;
1213 goto loop;
1217 z = z & 0xe0000000;
1219 if (z != 0)
1221 if ((temp & 7) == 0)
1222 return x;
1224 else
1225 return x;
1227 if ((z & ROR(temp, 3)) != 0)
1228 x += y >> 3;
1229 if ((z & ROR(temp, 2)) != 0)
1230 x += y >> 2;
1231 if ((z & ROR(temp, 1)) != 0)
1232 x += y >> 1;
1233 return x;
1235 else
1236 {}
1237 // should not happen in the current code
1238 return 0;
1241 void cheatsCBAUpdateSeedBuffer(u32 a, u8 *buffer, int count)
1243 int i;
1244 for (i = 0; i < count; i++)
1245 buffer[i] = i;
1246 for (i = 0; (u32)i < a; i++)
1248 u32 a = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
1249 u32 b = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
1250 u32 t = buffer[a];
1251 buffer[a] = buffer[b];
1252 buffer[b] = t;
1256 void cheatsCBAChangeEncryption(u32 *seed)
1258 int i;
1260 cheatsCBATemporaryValue = (seed[1] ^ 0x1111);
1261 cheatsCBAUpdateSeedBuffer(0x50, cheatsCBASeedBuffer, 0x30);
1262 cheatsCBATemporaryValue = 0x4efad1c3;
1264 for (i = 0; (u32)i < seed[4]; i++)
1266 cheatsCBATemporaryValue = cheatsCBAEncWorker();
1268 cheatsCBASeed[2] = cheatsCBAEncWorker();
1269 cheatsCBASeed[3] = cheatsCBAEncWorker();
1271 cheatsCBATemporaryValue = seed[3] ^ 0xf254;
1273 for (i = 0; (u32)i < seed[3]; i++)
1275 cheatsCBATemporaryValue = cheatsCBAEncWorker();
1278 cheatsCBASeed[0] = cheatsCBAEncWorker();
1279 cheatsCBASeed[1] = cheatsCBAEncWorker();
1281 *((u32 *)&cheatsCBACurrentSeed[0]) = seed[6];
1282 *((u32 *)&cheatsCBACurrentSeed[4]) = seed[7];
1283 *((u32 *)&cheatsCBACurrentSeed[8]) = 0;
1286 u16 cheatsCBAGenValue(u32 x, u32 y, u32 z)
1288 y <<= 0x10;
1289 z <<= 0x10;
1290 x <<= 0x18;
1291 u32 x0 = (int)y >> 0x10;
1292 z = (int)z >> 0x10;
1293 x = (int)x >> 0x10;
1294 for (int i = 0; i < 8; i++)
1296 u32 temp = z ^ x;
1297 if ((int)temp >= 0)
1299 temp = z << 0x11;
1301 else
1303 temp = z << 0x01;
1304 temp ^= x0;
1305 temp = temp << 0x10;
1307 z = (int)temp >> 0x10;
1308 temp = x << 0x11;
1309 x = (int)temp >> 0x10;
1311 return z & 0xffff;
1314 void cheatsCBAGenTable()
1316 for (int i = 0; i < 0x100; i++)
1318 cheatsCBATable[i] = cheatsCBAGenValue(i, 0x1021, 0);
1320 cheatsCBATableGenerated = true;
1323 u16 cheatsCBACalcCRC(u8 *rom, int count)
1325 u32 crc = 0xffffffff;
1327 if (count & 3)
1329 // 0x08000EAE
1331 else
1333 count = (count >> 2) - 1;
1334 if (count != -1)
1336 while (count != -1)
1338 crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
1339 ^ *rom++]) << 0x10) >> 0x10;
1340 crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
1341 ^ *rom++]) << 0x10) >> 0x10;
1342 crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
1343 ^ *rom++]) << 0x10) >> 0x10;
1344 crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
1345 ^ *rom++]) << 0x10) >> 0x10;
1346 count--;
1350 return crc & 0xffff;
1353 void cheatsCBADecrypt(u8 *decrypt)
1355 u8 buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
1356 u8 *array = &buffer[1];
1358 cheatsCBAReverseArray(decrypt, array);
1360 for (int count = 0x2f; count >= 0; count--)
1362 chatsCBAScramble(array, count, cheatsCBASeedBuffer[count]);
1364 cheatsCBAArrayToValue(array, decrypt);
1365 *((u32 *)decrypt) = cheatsCBAGetValue(decrypt) ^
1366 cheatsCBASeed[0];
1367 *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt) ^
1368 cheatsCBASeed[1]) & 0xffff;
1370 cheatsCBAReverseArray(decrypt, array);
1372 u32 cs = cheatsCBAGetValue(cheatsCBACurrentSeed);
1373 for (int i = 0; i <= 4; i++)
1375 array[i] = ((cs >> 8) ^ array[i+1]) ^ array[i] ;
1378 array[5] = (cs >> 8) ^ array[5];
1380 for (int j = 5; j >= 0; j--)
1382 array[j] = (cs ^ array[j-1]) ^ array[j];
1385 cheatsCBAArrayToValue(array, decrypt);
1387 *((u32 *)decrypt) = cheatsCBAGetValue(decrypt)
1388 ^ cheatsCBASeed[2];
1389 *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt)
1390 ^ cheatsCBASeed[3]) & 0xffff;
1393 int cheatsCBAGetCount()
1395 int count = 0;
1396 for (int i = 0; i < cheatsNumber; i++)
1398 if (cheatsList[i].code == 512)
1399 count++;
1401 return count;
1404 bool cheatsCBAShouldDecrypt()
1406 for (int i = 0; i < cheatsNumber; i++)
1408 if (cheatsList[i].code == 512)
1410 return (cheatsList[i].codestring[0] == '9');
1413 return false;
1416 void cheatsAddCBACode(const char *code, const char *desc)
1418 if (strlen(code) != 13)
1420 // wrong cheat
1421 systemMessage(MSG_INVALID_CBA_CODE,
1422 N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
1423 return;
1426 int i;
1427 for (i = 0; i < 8; i++)
1429 if (!CHEAT_IS_HEX(code[i]))
1431 // wrong cheat
1432 systemMessage(MSG_INVALID_CBA_CODE,
1433 N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
1434 return;
1438 if (code[8] != ' ')
1440 systemMessage(MSG_INVALID_CBA_CODE,
1441 N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
1442 return;
1445 for (i = 9; i < 13; i++)
1447 if (!CHEAT_IS_HEX(code[i]))
1449 // wrong cheat
1450 systemMessage(MSG_INVALID_CBA_CODE,
1451 N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
1452 return;
1456 char buffer[10];
1457 strncpy(buffer, code, 8);
1458 buffer[8] = 0;
1459 u32 address;
1460 sscanf(buffer, "%x", &address);
1461 strncpy(buffer, &code[9], 4);
1462 buffer[4] = 0;
1463 u32 value;
1464 sscanf(buffer, "%x", &value);
1466 u8 array[8] = {
1467 address &255,
1468 (address >> 8) & 255,
1469 (address >> 16) & 255,
1470 (address >> 24) & 255,
1471 (value & 255),
1472 (value >> 8) & 255,
1473 0,
1475 };
1477 if (cheatsCBAGetCount() == 0 &&
1478 (address >> 28) == 9)
1480 u32 seed[8];
1481 cheatsCBAParseSeedCode(address, value, seed);
1482 cheatsCBAChangeEncryption(seed);
1483 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, UNKNOWN_CODE);
1485 else
1487 if (cheatsCBAShouldDecrypt())
1488 cheatsCBADecrypt(array);
1490 address = READ32LE(((u32 *)array));
1491 value = READ16LE(((u16 *)&array[4]));
1493 int type = (address >> 28) & 15;
1495 if (isMultilineWithData(cheatsNumber-1))
1497 cheatsAdd(code, desc, address, value, 512, UNKNOWN_CODE);
1498 return;
1501 switch (type)
1503 case 0x00:
1505 if (!cheatsCBATableGenerated)
1506 cheatsCBAGenTable();
1507 u32 crc = cheatsCBACalcCRC(rom, 0x10000);
1508 if (crc != address)
1510 systemMessage(MSG_CBA_CODE_WARNING,
1511 N_("Warning: Codes seem to be for a different game.\nCodes may not work correctly."));
1513 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1514 UNKNOWN_CODE);
1515 break;
1517 case 0x02:
1518 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1519 CBA_OR);
1520 break;
1521 case 0x03:
1522 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1523 INT_8_BIT_WRITE);
1524 break;
1525 case 0x04:
1526 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1527 CBA_SLIDE_CODE);
1528 break;
1529 case 0x05:
1530 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1531 CBA_SUPER);
1532 break;
1533 case 0x06:
1534 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1535 CBA_AND);
1536 break;
1537 case 0x07:
1538 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1539 CBA_IF_TRUE);
1540 break;
1541 case 0x08:
1542 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1543 INT_16_BIT_WRITE);
1544 break;
1545 case 0x0a:
1546 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1547 CBA_IF_FALSE);
1548 break;
1549 case 0x0b:
1550 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1551 CBA_LT);
1552 break;
1553 case 0x0c:
1554 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1555 CBA_GT);
1556 break;
1557 case 0x0d:
1558 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1559 CBA_IF_KEYS_PRESSED);
1560 break;
1561 case 0x0e:
1562 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
1563 CBA_ADD);
1564 break;
1565 default:
1566 // unsupported code
1567 cheatsAdd(code, desc, address & 0xFFFFFFFF, value, 512,
1568 UNKNOWN_CODE);
1569 break;
1574 void cheatsSaveGame(gzFile file)
1576 utilWriteInt(file, cheatsNumber);
1578 utilGzWrite(file, cheatsList, sizeof(cheatsList));
1581 void cheatsReadGame(gzFile file)
1583 cheatsNumber = 0;
1585 cheatsNumber = utilReadInt(file);
1587 utilGzRead(file, cheatsList, sizeof(cheatsList));
1589 bool firstCodeBreaker = true;
1591 for (int i = 0; i < cheatsNumber; i++)
1593 cheatsList[i].status = 0;
1594 if (!cheatsList[i].codestring[0])
1596 switch (cheatsList[i].size)
1598 case 0:
1599 sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
1600 cheatsList[i].value);
1601 break;
1602 case 1:
1603 sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
1604 cheatsList[i].value);
1605 break;
1606 case 2:
1607 sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
1608 cheatsList[i].value);
1609 break;
1613 if (cheatsList[i].enabled)
1615 cheatsEnable(i);
1618 if (cheatsList[i].code == 512 && firstCodeBreaker)
1620 firstCodeBreaker = false;
1621 char buffer[10];
1622 strncpy(buffer, cheatsList[i].codestring, 8);
1623 buffer[8] = 0;
1624 u32 address;
1625 sscanf(buffer, "%x", &address);
1626 if ((address >> 28) == 9)
1628 strncpy(buffer, &cheatsList[i].codestring[9], 4);
1629 buffer[4] = 0;
1630 u32 value;
1631 sscanf(buffer, "%x", &value);
1633 u32 seed[8];
1634 cheatsCBAParseSeedCode(address, value, seed);
1635 cheatsCBAChangeEncryption(seed);
1641 void cheatsSaveCheatList(const char *file)
1643 if (cheatsNumber == 0)
1644 return;
1645 FILE *f = fopen(file, "wb");
1646 if (f == NULL)
1647 return;
1648 int version = 1;
1649 fwrite(&version, 1, sizeof(version), f);
1650 int type = 0;
1651 fwrite(&type, 1, sizeof(type), f);
1652 fwrite(&cheatsNumber, 1, sizeof(cheatsNumber), f);
1653 fwrite(cheatsList, 1, sizeof(cheatsList), f);
1654 fclose(f);
1657 bool cheatsLoadCheatList(const char *file)
1659 cheatsNumber = 0;
1661 int count = 0;
1663 FILE *f = fopen(file, "rb");
1665 if (f == NULL)
1666 return false;
1668 int version = 0;
1670 if (fread(&version, 1, sizeof(version), f) != sizeof(version))
1672 fclose(f);
1673 return false;
1676 if (version != 1)
1678 systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION,
1679 N_("Unsupported cheat list version %d"), version);
1680 fclose(f);
1681 return false;
1684 int type = 0;
1685 if (fread(&type, 1, sizeof(type), f) != sizeof(type))
1687 fclose(f);
1688 return false;
1691 if (type != 0)
1693 systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE,
1694 N_("Unsupported cheat list type %d"), type);
1695 fclose(f);
1696 return false;
1699 if (fread(&count, 1, sizeof(count), f) != sizeof(count))
1701 fclose(f);
1702 return false;
1705 if (fread(cheatsList, 1, sizeof(cheatsList), f) != sizeof(cheatsList))
1707 fclose(f);
1708 return false;
1711 bool firstCodeBreaker = true;
1713 for (int i = 0; i < count; i++)
1715 cheatsList[i].status = 0; // remove old status as it is not used
1716 if (!cheatsList[i].codestring[0])
1718 switch (cheatsList[i].size)
1720 case 0:
1721 sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
1722 cheatsList[i].value);
1723 break;
1724 case 1:
1725 sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
1726 cheatsList[i].value);
1727 break;
1728 case 2:
1729 sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
1730 cheatsList[i].value);
1731 break;
1735 if (cheatsList[i].code == 512 && firstCodeBreaker)
1737 firstCodeBreaker = false;
1738 char buffer[10];
1739 strncpy(buffer, cheatsList[i].codestring, 8);
1740 buffer[8] = 0;
1741 u32 address;
1742 sscanf(buffer, "%x", &address);
1743 if ((address >> 28) == 9)
1745 strncpy(buffer, &cheatsList[i].codestring[9], 4);
1746 buffer[4] = 0;
1747 u32 value;
1748 sscanf(buffer, "%x", &value);
1750 u32 seed[8];
1751 cheatsCBAParseSeedCode(address, value, seed);
1752 cheatsCBAChangeEncryption(seed);
1756 cheatsNumber = count;
1757 fclose(f);
1758 return true;
1761 extern int *extCpuLoopTicks;
1762 extern int *extClockTicks;
1763 extern int *extTicks;
1764 extern int cpuSavedTicks;
1766 extern void debuggerBreakOnWrite(u32 *, u32, u32, int);
1768 #define CPU_BREAK_LOOP2 \
1769 cpuSavedTicks = cpuSavedTicks - *extCpuLoopTicks; \
1770 *extCpuLoopTicks = *extClockTicks; \
1771 *extTicks = *extClockTicks;
1773 void cheatsWriteMemory(u32 *address, u32 value, u32 mask)
1775 #ifdef BKPT_SUPPORT
1776 #ifdef SDL
1777 if (cheatsNumber == 0)
1779 debuggerBreakOnWrite(address, *address, value, 2);
1780 CPU_BREAK_LOOP2;
1781 *address = value;
1782 return;
1784 #endif
1785 #endif
1788 void cheatsWriteHalfWord(u16 *address, u16 value, u16 mask)
1790 #ifdef BKPT_SUPPORT
1791 #ifdef SDL
1792 if (cheatsNumber == 0)
1794 debuggerBreakOnWrite((u32 *)address, *address, value, 1);
1795 CPU_BREAK_LOOP2;
1796 *address = value;
1797 return;
1799 #endif
1800 #endif
1803 #if defined BKPT_SUPPORT && defined SDL
1804 void cheatsWriteByte(u8 *address, u8 value)
1805 #else
1806 void cheatsWriteByte(u8 *, u8)
1807 #endif
1809 #ifdef BKPT_SUPPORT
1810 #ifdef SDL
1811 if (cheatsNumber == 0)
1813 debuggerBreakOnWrite((u32 *)address, *address, value, 0);
1814 CPU_BREAK_LOOP2;
1815 *address = value;
1816 return;
1818 #endif
1819 #endif
1822 #undef CPU_BREAK_LOOP2