Mercurial > vba-linux
comparison src/gba/GBACheats.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 #include <cstdio> | |
2 #include <cctype> | |
3 #include <cstring> | |
4 | |
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" | |
12 | |
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 | |
91 | |
92 CheatsData cheatsList[100]; | |
93 int cheatsNumber = 0; | |
94 | |
95 u8 cheatsCBASeedBuffer[0x30]; | |
96 u32 cheatsCBASeed[4]; | |
97 u32 cheatsCBATemporaryValue = 0; | |
98 u16 cheatsCBATable[256]; | |
99 bool cheatsCBATableGenerated = false; | |
100 | |
101 u8 cheatsCBACurrentSeed[12] = { | |
102 0x00, 0x00, 0x00, 0x00, | |
103 0x00, 0x00, 0x00, 0x00, | |
104 0x00, 0x00, 0x00, 0x00 | |
105 }; | |
106 | |
107 #define CHEAT_IS_HEX(a) (((a) >= 'A' && (a) <= 'F') || ((a) >= '0' && (a) <= '9')) | |
108 | |
109 #define CHEAT_PATCH_ROM_16BIT(a, v) \ | |
110 WRITE16LE(((u16 *)&rom[(a) & 0x1ffffff]), v); | |
111 | |
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 } | |
162 | |
163 static int getCodeLength(int num) | |
164 { | |
165 if (num >= cheatsNumber || num < 0) | |
166 return 1; | |
167 | |
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 } | |
215 | |
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; | |
303 | |
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; | |
518 | |
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 } | |
565 | |
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; | |
584 | |
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 } | |
602 | |
603 void cheatsDelete(int number, bool restore) | |
604 { | |
605 if (number < cheatsNumber && number >= 0) | |
606 { | |
607 int x = number; | |
608 | |
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 } | |
649 | |
650 void cheatsDeleteAll(bool restore) | |
651 { | |
652 for (int i = cheatsNumber-1; i >= 0; i--) | |
653 { | |
654 cheatsDelete(i, restore); | |
655 } | |
656 } | |
657 | |
658 void cheatsEnable(int i) | |
659 { | |
660 if (i >= 0 && i < cheatsNumber) | |
661 { | |
662 cheatsList[i].enabled = true; | |
663 } | |
664 } | |
665 | |
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 } | |
693 | |
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 } | |
702 | |
703 if (code[8] != ':') | |
704 { | |
705 systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code); | |
706 return false; | |
707 } | |
708 | |
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 } | |
730 | |
731 u32 address = 0; | |
732 u32 value = 0; | |
733 | |
734 char buffer[10]; | |
735 strncpy(buffer, code, 8); | |
736 buffer[8] = 0; | |
737 sscanf(buffer, "%x", &address); | |
738 | |
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 } | |
750 | |
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 } | |
761 | |
762 void cheatsAddCheatCode(const char *code, const char *desc) | |
763 { | |
764 cheatsVerifyCheatCode(code, desc); | |
765 } | |
766 | |
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; | |
773 | |
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 } | |
785 | |
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 } | |
795 | |
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 } | |
807 | |
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); | |
817 | |
818 cheatsDecryptGSACode(address, value, v3); | |
819 | |
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; | |
1001 } | |
1002 } | |
1003 } | |
1004 | |
1005 bool cheatsImportGSACodeFile(const char *name, int game, bool v3) | |
1006 { | |
1007 FILE *f = fopen(name, "rb"); | |
1008 if (!f) | |
1009 return false; | |
1010 | |
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) | |
1018 { | |
1019 if (g == game) | |
1020 { | |
1021 found = true; | |
1022 break; | |
1023 } | |
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) | |
1029 { | |
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--; | |
1036 } | |
1037 games--; | |
1038 g++; | |
1039 } | |
1040 if (found) | |
1041 { | |
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) | |
1049 { | |
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) | |
1059 { | |
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; | |
1067 } | |
1068 codes--; | |
1069 } | |
1070 } | |
1071 fclose(f); | |
1072 return false; | |
1073 } | |
1074 | |
1075 void cheatsCBAReverseArray(u8 *array, u8 *dest) | |
1076 { | |
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]; | |
1083 } | |
1084 | |
1085 void chatsCBAScramble(u8 *array, int count, u8 b) | |
1086 { | |
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; | |
1100 } | |
1101 | |
1102 u32 cheatsCBAGetValue(u8 *array) | |
1103 { | |
1104 return array[0] | array[1]<<8 | array[2] << 16 | array[3]<<24; | |
1105 } | |
1106 | |
1107 u16 cheatsCBAGetData(u8 *array) | |
1108 { | |
1109 return array[4] | array[5]<<8; | |
1110 } | |
1111 | |
1112 void cheatsCBAArrayToValue(u8 *array, u8 *dest) | |
1113 { | |
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]; | |
1120 } | |
1121 | |
1122 void cheatsCBAParseSeedCode(u32 address, u32 value, u32 *array) | |
1123 { | |
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; | |
1132 } | |
1133 | |
1134 u32 cheatsCBAEncWorker() | |
1135 { | |
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); | |
1144 } | |
1145 | |
1146 #define ROR(v, s) \ | |
1147 (((v) >> (s)) | (((v) & ((1 << (s))-1)) << (32 - (s)))) | |
1148 | |
1149 u32 cheatsCBACalcIndex(u32 x, u32 y) | |
1150 { | |
1151 if (y != 0) | |
1152 { | |
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; | |
1162 | |
1163 while (y < 0x10000000) | |
1164 { | |
1165 if (y < x) | |
1166 { | |
1167 y = y << 4; | |
1168 x0 = x0 << 4; | |
1169 } | |
1170 else | |
1171 break; | |
1172 } | |
1173 | |
1174 while (y < 0x80000000) | |
1175 { | |
1176 if (y < x) | |
1177 { | |
1178 y = y << 1; | |
1179 x0 = x0 << 1; | |
1180 } | |
1181 else | |
1182 break; | |
1183 } | |
1184 | |
1185 loop: | |
1186 u32 z = 0; | |
1187 if (x >= y) | |
1188 x -= y; | |
1189 if (x >= (y >> 1)) | |
1190 { | |
1191 x -= (y >> 1); | |
1192 z |= ROR(x0, 1); | |
1193 } | |
1194 if (x >= (y >> 2)) | |
1195 { | |
1196 x -= (y >> 2); | |
1197 z |= ROR(x0, 2); | |
1198 } | |
1199 if (x >= (y >> 3)) | |
1200 { | |
1201 x -= (y >> 3); | |
1202 z |= ROR(x0, 3); | |
1203 } | |
1204 | |
1205 u32 temp = x0; | |
1206 | |
1207 if (x != 0) | |
1208 { | |
1209 x0 = x0 >> 4; | |
1210 if (x0 != 0) | |
1211 { | |
1212 y = y >> 4; | |
1213 goto loop; | |
1214 } | |
1215 } | |
1216 | |
1217 z = z & 0xe0000000; | |
1218 | |
1219 if (z != 0) | |
1220 { | |
1221 if ((temp & 7) == 0) | |
1222 return x; | |
1223 } | |
1224 else | |
1225 return x; | |
1226 | |
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; | |
1234 } | |
1235 else | |
1236 {} | |
1237 // should not happen in the current code | |
1238 return 0; | |
1239 } | |
1240 | |
1241 void cheatsCBAUpdateSeedBuffer(u32 a, u8 *buffer, int count) | |
1242 { | |
1243 int i; | |
1244 for (i = 0; i < count; i++) | |
1245 buffer[i] = i; | |
1246 for (i = 0; (u32)i < a; i++) | |
1247 { | |
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; | |
1253 } | |
1254 } | |
1255 | |
1256 void cheatsCBAChangeEncryption(u32 *seed) | |
1257 { | |
1258 int i; | |
1259 | |
1260 cheatsCBATemporaryValue = (seed[1] ^ 0x1111); | |
1261 cheatsCBAUpdateSeedBuffer(0x50, cheatsCBASeedBuffer, 0x30); | |
1262 cheatsCBATemporaryValue = 0x4efad1c3; | |
1263 | |
1264 for (i = 0; (u32)i < seed[4]; i++) | |
1265 { | |
1266 cheatsCBATemporaryValue = cheatsCBAEncWorker(); | |
1267 } | |
1268 cheatsCBASeed[2] = cheatsCBAEncWorker(); | |
1269 cheatsCBASeed[3] = cheatsCBAEncWorker(); | |
1270 | |
1271 cheatsCBATemporaryValue = seed[3] ^ 0xf254; | |
1272 | |
1273 for (i = 0; (u32)i < seed[3]; i++) | |
1274 { | |
1275 cheatsCBATemporaryValue = cheatsCBAEncWorker(); | |
1276 } | |
1277 | |
1278 cheatsCBASeed[0] = cheatsCBAEncWorker(); | |
1279 cheatsCBASeed[1] = cheatsCBAEncWorker(); | |
1280 | |
1281 *((u32 *)&cheatsCBACurrentSeed[0]) = seed[6]; | |
1282 *((u32 *)&cheatsCBACurrentSeed[4]) = seed[7]; | |
1283 *((u32 *)&cheatsCBACurrentSeed[8]) = 0; | |
1284 } | |
1285 | |
1286 u16 cheatsCBAGenValue(u32 x, u32 y, u32 z) | |
1287 { | |
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++) | |
1295 { | |
1296 u32 temp = z ^ x; | |
1297 if ((int)temp >= 0) | |
1298 { | |
1299 temp = z << 0x11; | |
1300 } | |
1301 else | |
1302 { | |
1303 temp = z << 0x01; | |
1304 temp ^= x0; | |
1305 temp = temp << 0x10; | |
1306 } | |
1307 z = (int)temp >> 0x10; | |
1308 temp = x << 0x11; | |
1309 x = (int)temp >> 0x10; | |
1310 } | |
1311 return z & 0xffff; | |
1312 } | |
1313 | |
1314 void cheatsCBAGenTable() | |
1315 { | |
1316 for (int i = 0; i < 0x100; i++) | |
1317 { | |
1318 cheatsCBATable[i] = cheatsCBAGenValue(i, 0x1021, 0); | |
1319 } | |
1320 cheatsCBATableGenerated = true; | |
1321 } | |
1322 | |
1323 u16 cheatsCBACalcCRC(u8 *rom, int count) | |
1324 { | |
1325 u32 crc = 0xffffffff; | |
1326 | |
1327 if (count & 3) | |
1328 { | |
1329 // 0x08000EAE | |
1330 } | |
1331 else | |
1332 { | |
1333 count = (count >> 2) - 1; | |
1334 if (count != -1) | |
1335 { | |
1336 while (count != -1) | |
1337 { | |
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--; | |
1347 } | |
1348 } | |
1349 } | |
1350 return crc & 0xffff; | |
1351 } | |
1352 | |
1353 void cheatsCBADecrypt(u8 *decrypt) | |
1354 { | |
1355 u8 buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | |
1356 u8 *array = &buffer[1]; | |
1357 | |
1358 cheatsCBAReverseArray(decrypt, array); | |
1359 | |
1360 for (int count = 0x2f; count >= 0; count--) | |
1361 { | |
1362 chatsCBAScramble(array, count, cheatsCBASeedBuffer[count]); | |
1363 } | |
1364 cheatsCBAArrayToValue(array, decrypt); | |
1365 *((u32 *)decrypt) = cheatsCBAGetValue(decrypt) ^ | |
1366 cheatsCBASeed[0]; | |
1367 *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt) ^ | |
1368 cheatsCBASeed[1]) & 0xffff; | |
1369 | |
1370 cheatsCBAReverseArray(decrypt, array); | |
1371 | |
1372 u32 cs = cheatsCBAGetValue(cheatsCBACurrentSeed); | |
1373 for (int i = 0; i <= 4; i++) | |
1374 { | |
1375 array[i] = ((cs >> 8) ^ array[i+1]) ^ array[i] ; | |
1376 } | |
1377 | |
1378 array[5] = (cs >> 8) ^ array[5]; | |
1379 | |
1380 for (int j = 5; j >= 0; j--) | |
1381 { | |
1382 array[j] = (cs ^ array[j-1]) ^ array[j]; | |
1383 } | |
1384 | |
1385 cheatsCBAArrayToValue(array, decrypt); | |
1386 | |
1387 *((u32 *)decrypt) = cheatsCBAGetValue(decrypt) | |
1388 ^ cheatsCBASeed[2]; | |
1389 *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt) | |
1390 ^ cheatsCBASeed[3]) & 0xffff; | |
1391 } | |
1392 | |
1393 int cheatsCBAGetCount() | |
1394 { | |
1395 int count = 0; | |
1396 for (int i = 0; i < cheatsNumber; i++) | |
1397 { | |
1398 if (cheatsList[i].code == 512) | |
1399 count++; | |
1400 } | |
1401 return count; | |
1402 } | |
1403 | |
1404 bool cheatsCBAShouldDecrypt() | |
1405 { | |
1406 for (int i = 0; i < cheatsNumber; i++) | |
1407 { | |
1408 if (cheatsList[i].code == 512) | |
1409 { | |
1410 return (cheatsList[i].codestring[0] == '9'); | |
1411 } | |
1412 } | |
1413 return false; | |
1414 } | |
1415 | |
1416 void cheatsAddCBACode(const char *code, const char *desc) | |
1417 { | |
1418 if (strlen(code) != 13) | |
1419 { | |
1420 // wrong cheat | |
1421 systemMessage(MSG_INVALID_CBA_CODE, | |
1422 N_("Invalid CBA code. Format is XXXXXXXX YYYY.")); | |
1423 return; | |
1424 } | |
1425 | |
1426 int i; | |
1427 for (i = 0; i < 8; i++) | |
1428 { | |
1429 if (!CHEAT_IS_HEX(code[i])) | |
1430 { | |
1431 // wrong cheat | |
1432 systemMessage(MSG_INVALID_CBA_CODE, | |
1433 N_("Invalid CBA code. Format is XXXXXXXX YYYY.")); | |
1434 return; | |
1435 } | |
1436 } | |
1437 | |
1438 if (code[8] != ' ') | |
1439 { | |
1440 systemMessage(MSG_INVALID_CBA_CODE, | |
1441 N_("Invalid CBA code. Format is XXXXXXXX YYYY.")); | |
1442 return; | |
1443 } | |
1444 | |
1445 for (i = 9; i < 13; i++) | |
1446 { | |
1447 if (!CHEAT_IS_HEX(code[i])) | |
1448 { | |
1449 // wrong cheat | |
1450 systemMessage(MSG_INVALID_CBA_CODE, | |
1451 N_("Invalid CBA code. Format is XXXXXXXX YYYY.")); | |
1452 return; | |
1453 } | |
1454 } | |
1455 | |
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); | |
1465 | |
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, | |
1474 0 | |
1475 }; | |
1476 | |
1477 if (cheatsCBAGetCount() == 0 && | |
1478 (address >> 28) == 9) | |
1479 { | |
1480 u32 seed[8]; | |
1481 cheatsCBAParseSeedCode(address, value, seed); | |
1482 cheatsCBAChangeEncryption(seed); | |
1483 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, UNKNOWN_CODE); | |
1484 } | |
1485 else | |
1486 { | |
1487 if (cheatsCBAShouldDecrypt()) | |
1488 cheatsCBADecrypt(array); | |
1489 | |
1490 address = READ32LE(((u32 *)array)); | |
1491 value = READ16LE(((u16 *)&array[4])); | |
1492 | |
1493 int type = (address >> 28) & 15; | |
1494 | |
1495 if (isMultilineWithData(cheatsNumber-1)) | |
1496 { | |
1497 cheatsAdd(code, desc, address, value, 512, UNKNOWN_CODE); | |
1498 return; | |
1499 } | |
1500 | |
1501 switch (type) | |
1502 { | |
1503 case 0x00: | |
1504 { | |
1505 if (!cheatsCBATableGenerated) | |
1506 cheatsCBAGenTable(); | |
1507 u32 crc = cheatsCBACalcCRC(rom, 0x10000); | |
1508 if (crc != address) | |
1509 { | |
1510 systemMessage(MSG_CBA_CODE_WARNING, | |
1511 N_("Warning: Codes seem to be for a different game.\nCodes may not work correctly.")); | |
1512 } | |
1513 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, | |
1514 UNKNOWN_CODE); | |
1515 break; | |
1516 } | |
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; | |
1570 } | |
1571 } | |
1572 } | |
1573 | |
1574 void cheatsSaveGame(gzFile file) | |
1575 { | |
1576 utilWriteInt(file, cheatsNumber); | |
1577 | |
1578 utilGzWrite(file, cheatsList, sizeof(cheatsList)); | |
1579 } | |
1580 | |
1581 void cheatsReadGame(gzFile file) | |
1582 { | |
1583 cheatsNumber = 0; | |
1584 | |
1585 cheatsNumber = utilReadInt(file); | |
1586 | |
1587 utilGzRead(file, cheatsList, sizeof(cheatsList)); | |
1588 | |
1589 bool firstCodeBreaker = true; | |
1590 | |
1591 for (int i = 0; i < cheatsNumber; i++) | |
1592 { | |
1593 cheatsList[i].status = 0; | |
1594 if (!cheatsList[i].codestring[0]) | |
1595 { | |
1596 switch (cheatsList[i].size) | |
1597 { | |
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; | |
1610 } | |
1611 } | |
1612 | |
1613 if (cheatsList[i].enabled) | |
1614 { | |
1615 cheatsEnable(i); | |
1616 } | |
1617 | |
1618 if (cheatsList[i].code == 512 && firstCodeBreaker) | |
1619 { | |
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) | |
1627 { | |
1628 strncpy(buffer, &cheatsList[i].codestring[9], 4); | |
1629 buffer[4] = 0; | |
1630 u32 value; | |
1631 sscanf(buffer, "%x", &value); | |
1632 | |
1633 u32 seed[8]; | |
1634 cheatsCBAParseSeedCode(address, value, seed); | |
1635 cheatsCBAChangeEncryption(seed); | |
1636 } | |
1637 } | |
1638 } | |
1639 } | |
1640 | |
1641 void cheatsSaveCheatList(const char *file) | |
1642 { | |
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); | |
1655 } | |
1656 | |
1657 bool cheatsLoadCheatList(const char *file) | |
1658 { | |
1659 cheatsNumber = 0; | |
1660 | |
1661 int count = 0; | |
1662 | |
1663 FILE *f = fopen(file, "rb"); | |
1664 | |
1665 if (f == NULL) | |
1666 return false; | |
1667 | |
1668 int version = 0; | |
1669 | |
1670 if (fread(&version, 1, sizeof(version), f) != sizeof(version)) | |
1671 { | |
1672 fclose(f); | |
1673 return false; | |
1674 } | |
1675 | |
1676 if (version != 1) | |
1677 { | |
1678 systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION, | |
1679 N_("Unsupported cheat list version %d"), version); | |
1680 fclose(f); | |
1681 return false; | |
1682 } | |
1683 | |
1684 int type = 0; | |
1685 if (fread(&type, 1, sizeof(type), f) != sizeof(type)) | |
1686 { | |
1687 fclose(f); | |
1688 return false; | |
1689 } | |
1690 | |
1691 if (type != 0) | |
1692 { | |
1693 systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE, | |
1694 N_("Unsupported cheat list type %d"), type); | |
1695 fclose(f); | |
1696 return false; | |
1697 } | |
1698 | |
1699 if (fread(&count, 1, sizeof(count), f) != sizeof(count)) | |
1700 { | |
1701 fclose(f); | |
1702 return false; | |
1703 } | |
1704 | |
1705 if (fread(cheatsList, 1, sizeof(cheatsList), f) != sizeof(cheatsList)) | |
1706 { | |
1707 fclose(f); | |
1708 return false; | |
1709 } | |
1710 | |
1711 bool firstCodeBreaker = true; | |
1712 | |
1713 for (int i = 0; i < count; i++) | |
1714 { | |
1715 cheatsList[i].status = 0; // remove old status as it is not used | |
1716 if (!cheatsList[i].codestring[0]) | |
1717 { | |
1718 switch (cheatsList[i].size) | |
1719 { | |
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; | |
1732 } | |
1733 } | |
1734 | |
1735 if (cheatsList[i].code == 512 && firstCodeBreaker) | |
1736 { | |
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) | |
1744 { | |
1745 strncpy(buffer, &cheatsList[i].codestring[9], 4); | |
1746 buffer[4] = 0; | |
1747 u32 value; | |
1748 sscanf(buffer, "%x", &value); | |
1749 | |
1750 u32 seed[8]; | |
1751 cheatsCBAParseSeedCode(address, value, seed); | |
1752 cheatsCBAChangeEncryption(seed); | |
1753 } | |
1754 } | |
1755 } | |
1756 cheatsNumber = count; | |
1757 fclose(f); | |
1758 return true; | |
1759 } | |
1760 | |
1761 extern int *extCpuLoopTicks; | |
1762 extern int *extClockTicks; | |
1763 extern int *extTicks; | |
1764 extern int cpuSavedTicks; | |
1765 | |
1766 extern void debuggerBreakOnWrite(u32 *, u32, u32, int); | |
1767 | |
1768 #define CPU_BREAK_LOOP2 \ | |
1769 cpuSavedTicks = cpuSavedTicks - *extCpuLoopTicks; \ | |
1770 *extCpuLoopTicks = *extClockTicks; \ | |
1771 *extTicks = *extClockTicks; | |
1772 | |
1773 void cheatsWriteMemory(u32 *address, u32 value, u32 mask) | |
1774 { | |
1775 #ifdef BKPT_SUPPORT | |
1776 #ifdef SDL | |
1777 if (cheatsNumber == 0) | |
1778 { | |
1779 debuggerBreakOnWrite(address, *address, value, 2); | |
1780 CPU_BREAK_LOOP2; | |
1781 *address = value; | |
1782 return; | |
1783 } | |
1784 #endif | |
1785 #endif | |
1786 } | |
1787 | |
1788 void cheatsWriteHalfWord(u16 *address, u16 value, u16 mask) | |
1789 { | |
1790 #ifdef BKPT_SUPPORT | |
1791 #ifdef SDL | |
1792 if (cheatsNumber == 0) | |
1793 { | |
1794 debuggerBreakOnWrite((u32 *)address, *address, value, 1); | |
1795 CPU_BREAK_LOOP2; | |
1796 *address = value; | |
1797 return; | |
1798 } | |
1799 #endif | |
1800 #endif | |
1801 } | |
1802 | |
1803 #if defined BKPT_SUPPORT && defined SDL | |
1804 void cheatsWriteByte(u8 *address, u8 value) | |
1805 #else | |
1806 void cheatsWriteByte(u8 *, u8) | |
1807 #endif | |
1808 { | |
1809 #ifdef BKPT_SUPPORT | |
1810 #ifdef SDL | |
1811 if (cheatsNumber == 0) | |
1812 { | |
1813 debuggerBreakOnWrite((u32 *)address, *address, value, 0); | |
1814 CPU_BREAK_LOOP2; | |
1815 *address = value; | |
1816 return; | |
1817 } | |
1818 #endif | |
1819 #endif | |
1820 } | |
1821 | |
1822 #undef CPU_BREAK_LOOP2 |