Commit | Line | Data |
---|---|---|
ef79bbde P |
1 | /* Cheat Support for PCSX-Reloaded |
2 | * Copyright (c) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA | |
17 | */ | |
18 | ||
19 | #include "psxcommon.h" | |
20 | #include "r3000a.h" | |
21 | #include "psxmem.h" | |
22 | ||
23 | #include "cheat.h" | |
24 | ||
25 | Cheat *Cheats = NULL; | |
26 | int NumCheats = 0; | |
9c27c205 | 27 | int NumCheatsAllocated = 0; |
ef79bbde P |
28 | |
29 | CheatCode *CheatCodes = NULL; | |
30 | int NumCodes = 0; | |
9c27c205 | 31 | int NumCodesAllocated = 0; |
ef79bbde P |
32 | |
33 | s8 *prevM = NULL; | |
34 | u32 *SearchResults = NULL; | |
35 | int NumSearchResults = 0; | |
36 | static int NumSearchResultsAllocated = 0; | |
37 | ||
38 | #define ALLOC_INCREMENT 100 | |
39 | ||
40 | void ClearAllCheats() { | |
41 | int i; | |
42 | ||
43 | if (Cheats != NULL) { | |
44 | for (i = 0; i < NumCheats; i++) { | |
45 | free(Cheats[i].Descr); | |
46 | } | |
47 | free(Cheats); | |
48 | } | |
49 | ||
50 | Cheats = NULL; | |
51 | NumCheats = 0; | |
52 | NumCheatsAllocated = 0; | |
53 | ||
54 | if (CheatCodes != NULL) { | |
55 | free(CheatCodes); | |
56 | } | |
57 | ||
58 | CheatCodes = NULL; | |
59 | NumCodes = 0; | |
60 | NumCodesAllocated = 0; | |
61 | } | |
62 | ||
63 | // load cheats from the specific filename | |
64 | void LoadCheats(const char *filename) { | |
65 | FILE *fp; | |
66 | char buf[256]; | |
67 | int count = 0; | |
68 | unsigned int t1, t2; | |
69 | ||
70 | fp = fopen(filename, "r"); | |
71 | if (fp == NULL) { | |
72 | return; | |
73 | } | |
74 | ||
75 | ClearAllCheats(); | |
76 | ||
77 | while (fgets(buf, 255, fp) != NULL) { | |
78 | buf[255] = '\0'; | |
79 | trim(buf); | |
80 | ||
81 | // Skip comment or blank lines | |
82 | if (buf[0] == '#' || buf[0] == ';' || buf[0] == '/' || buf[0] == '\"' || buf[0] == '\0') | |
83 | continue; | |
84 | ||
85 | if (buf[0] == '[' && buf[strlen(buf) - 1] == ']') { | |
86 | if (NumCheats > 0) | |
87 | Cheats[NumCheats - 1].n = count; | |
88 | ||
89 | if (NumCheats >= NumCheatsAllocated) { | |
90 | NumCheatsAllocated += ALLOC_INCREMENT; | |
91 | ||
92 | if (Cheats == NULL) { | |
93 | assert(NumCheats == 0); | |
94 | assert(NumCheatsAllocated == ALLOC_INCREMENT); | |
95 | Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated); | |
96 | } else { | |
97 | Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated); | |
98 | } | |
99 | } | |
100 | ||
101 | buf[strlen(buf) - 1] = '\0'; | |
102 | count = 0; | |
103 | ||
104 | if (buf[1] == '*') { | |
105 | Cheats[NumCheats].Descr = strdup(buf + 2); | |
106 | Cheats[NumCheats].Enabled = 1; | |
107 | } else { | |
108 | Cheats[NumCheats].Descr = strdup(buf + 1); | |
109 | Cheats[NumCheats].Enabled = 0; | |
110 | } | |
2c843d96 | 111 | Cheats[NumCheats].WasEnabled = 0; |
ef79bbde P |
112 | |
113 | Cheats[NumCheats].First = NumCodes; | |
114 | ||
115 | NumCheats++; | |
116 | continue; | |
117 | } | |
118 | ||
119 | if (NumCheats <= 0) | |
120 | continue; | |
121 | ||
122 | if (NumCodes >= NumCodesAllocated) { | |
123 | NumCodesAllocated += ALLOC_INCREMENT; | |
124 | ||
125 | if (CheatCodes == NULL) { | |
126 | assert(NumCodes == 0); | |
127 | assert(NumCodesAllocated == ALLOC_INCREMENT); | |
128 | CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated); | |
129 | } else { | |
130 | CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated); | |
131 | } | |
132 | } | |
133 | ||
134 | sscanf(buf, "%x %x", &t1, &t2); | |
135 | ||
136 | CheatCodes[NumCodes].Addr = t1; | |
137 | CheatCodes[NumCodes].Val = t2; | |
138 | ||
139 | NumCodes++; | |
140 | count++; | |
141 | } | |
142 | ||
143 | if (NumCheats > 0) | |
144 | Cheats[NumCheats - 1].n = count; | |
145 | ||
146 | fclose(fp); | |
147 | ||
148 | SysPrintf(_("Cheats loaded from: %s\n"), filename); | |
149 | } | |
150 | ||
151 | // save all cheats to the specified filename | |
152 | void SaveCheats(const char *filename) { | |
153 | FILE *fp; | |
154 | int i, j; | |
155 | ||
156 | fp = fopen(filename, "w"); | |
157 | if (fp == NULL) { | |
158 | return; | |
159 | } | |
160 | ||
161 | for (i = 0; i < NumCheats; i++) { | |
162 | // write the description | |
163 | if (Cheats[i].Enabled) | |
164 | fprintf(fp, "[*%s]\n", Cheats[i].Descr); | |
165 | else | |
166 | fprintf(fp, "[%s]\n", Cheats[i].Descr); | |
167 | ||
168 | // write all cheat codes | |
169 | for (j = 0; j < Cheats[i].n; j++) { | |
170 | fprintf(fp, "%.8X %.4X\n", | |
171 | CheatCodes[Cheats[i].First + j].Addr, | |
172 | CheatCodes[Cheats[i].First + j].Val); | |
173 | } | |
174 | ||
175 | fprintf(fp, "\n"); | |
176 | } | |
177 | ||
178 | fclose(fp); | |
179 | ||
180 | SysPrintf(_("Cheats saved to: %s\n"), filename); | |
181 | } | |
182 | ||
183 | // apply all enabled cheats | |
184 | void ApplyCheats() { | |
185 | int i, j, k, endindex; | |
2c843d96 | 186 | int was_enabled; |
ef79bbde P |
187 | |
188 | for (i = 0; i < NumCheats; i++) { | |
2c843d96 | 189 | was_enabled = Cheats[i].WasEnabled; |
ef79bbde | 190 | if (!Cheats[i].Enabled) { |
2c843d96 | 191 | if (!Cheats[i].WasEnabled) |
192 | continue; | |
ef79bbde | 193 | } |
2c843d96 | 194 | Cheats[i].WasEnabled = Cheats[i].Enabled; |
ef79bbde P |
195 | |
196 | // process all cheat codes | |
197 | endindex = Cheats[i].First + Cheats[i].n; | |
198 | ||
199 | for (j = Cheats[i].First; j < endindex; j++) { | |
200 | u8 type = (uint8_t)(CheatCodes[j].Addr >> 24); | |
201 | u32 addr = (CheatCodes[j].Addr & 0x001FFFFF); | |
202 | u16 val = CheatCodes[j].Val; | |
203 | u32 taddr; | |
204 | ||
2c843d96 | 205 | if (!was_enabled) { |
206 | switch (type) { | |
207 | case CHEAT_CONST16: | |
208 | CheatCodes[j].OldVal = psxMu16(addr); | |
209 | break; | |
210 | case CHEAT_CONST8: | |
211 | CheatCodes[j].OldVal = psxMu8(addr); | |
212 | break; | |
213 | } | |
214 | } | |
215 | else if (!Cheats[i].Enabled) { | |
216 | val = CheatCodes[j].OldVal; | |
217 | if (type != CHEAT_CONST16 && type != CHEAT_CONST8) | |
218 | continue; | |
219 | } | |
220 | ||
ef79bbde P |
221 | switch (type) { |
222 | case CHEAT_CONST8: | |
223 | psxMu8ref(addr) = (u8)val; | |
224 | break; | |
225 | ||
226 | case CHEAT_CONST16: | |
227 | psxMu16ref(addr) = SWAPu16(val); | |
228 | break; | |
229 | ||
230 | case CHEAT_INC16: | |
231 | psxMu16ref(addr) = SWAPu16(psxMu16(addr) + val); | |
232 | break; | |
233 | ||
234 | case CHEAT_DEC16: | |
235 | psxMu16ref(addr) = SWAPu16(psxMu16(addr) - val); | |
236 | break; | |
237 | ||
238 | case CHEAT_INC8: | |
239 | psxMu8ref(addr) += (u8)val; | |
240 | break; | |
241 | ||
242 | case CHEAT_DEC8: | |
243 | psxMu8ref(addr) -= (u8)val; | |
244 | break; | |
245 | ||
246 | case CHEAT_SLIDE: | |
247 | j++; | |
248 | if (j >= endindex) | |
249 | break; | |
250 | ||
251 | type = (uint8_t)(CheatCodes[j].Addr >> 24); | |
252 | taddr = (CheatCodes[j].Addr & 0x001FFFFF); | |
253 | val = CheatCodes[j].Val; | |
254 | ||
255 | if (type == CHEAT_CONST8) { | |
256 | for (k = 0; k < ((addr >> 8) & 0xFF); k++) { | |
257 | psxMu8ref(taddr) = (u8)val; | |
258 | taddr += (s8)(addr & 0xFF); | |
259 | val += (s8)(CheatCodes[j - 1].Val & 0xFF); | |
260 | } | |
261 | } | |
262 | else if (type == CHEAT_CONST16) { | |
263 | for (k = 0; k < ((addr >> 8) & 0xFF); k++) { | |
264 | psxMu16ref(taddr) = SWAPu16(val); | |
265 | taddr += (s8)(addr & 0xFF); | |
266 | val += (s8)(CheatCodes[j - 1].Val & 0xFF); | |
267 | } | |
268 | } | |
269 | break; | |
270 | ||
271 | case CHEAT_MEMCPY: | |
272 | j++; | |
273 | if (j >= endindex) | |
274 | break; | |
275 | ||
276 | taddr = (CheatCodes[j].Addr & 0x001FFFFF); | |
277 | for (k = 0; k < val; k++) { | |
278 | psxMu8ref(taddr + k) = PSXMu8(addr + k); | |
279 | } | |
280 | break; | |
281 | ||
282 | case CHEAT_EQU8: | |
283 | if (PSXMu8(addr) != (u8)val) | |
284 | j++; // skip the next code | |
285 | break; | |
286 | ||
287 | case CHEAT_NOTEQU8: | |
288 | if (PSXMu8(addr) == (u8)val) | |
289 | j++; // skip the next code | |
290 | break; | |
291 | ||
292 | case CHEAT_LESSTHAN8: | |
293 | if (PSXMu8(addr) >= (u8)val) | |
294 | j++; // skip the next code | |
295 | break; | |
296 | ||
297 | case CHEAT_GREATERTHAN8: | |
298 | if (PSXMu8(addr) <= (u8)val) | |
299 | j++; // skip the next code | |
300 | break; | |
301 | ||
302 | case CHEAT_EQU16: | |
303 | if (PSXMu16(addr) != val) | |
304 | j++; // skip the next code | |
305 | break; | |
306 | ||
307 | case CHEAT_NOTEQU16: | |
308 | if (PSXMu16(addr) == val) | |
309 | j++; // skip the next code | |
310 | break; | |
311 | ||
312 | case CHEAT_LESSTHAN16: | |
313 | if (PSXMu16(addr) >= val) | |
314 | j++; // skip the next code | |
315 | break; | |
316 | ||
317 | case CHEAT_GREATERTHAN16: | |
318 | if (PSXMu16(addr) <= val) | |
319 | j++; // skip the next code | |
320 | break; | |
321 | } | |
322 | } | |
323 | } | |
324 | } | |
325 | ||
326 | int AddCheat(const char *descr, char *code) { | |
327 | int c = 1; | |
328 | char *p1, *p2; | |
329 | ||
330 | if (NumCheats >= NumCheatsAllocated) { | |
331 | NumCheatsAllocated += ALLOC_INCREMENT; | |
332 | ||
333 | if (Cheats == NULL) { | |
334 | assert(NumCheats == 0); | |
335 | assert(NumCheatsAllocated == ALLOC_INCREMENT); | |
336 | Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated); | |
337 | } | |
338 | else { | |
339 | Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated); | |
340 | } | |
341 | } | |
342 | ||
ef79bbde | 343 | Cheats[NumCheats].Enabled = 0; |
2c843d96 | 344 | Cheats[NumCheats].WasEnabled = 0; |
ef79bbde P |
345 | Cheats[NumCheats].First = NumCodes; |
346 | Cheats[NumCheats].n = 0; | |
347 | ||
348 | p1 = code; | |
349 | p2 = code; | |
350 | ||
351 | while (c) { | |
352 | unsigned int t1, t2; | |
353 | ||
354 | while (*p2 != '\n' && *p2 != '\0') | |
355 | p2++; | |
356 | ||
357 | if (*p2 == '\0') | |
358 | c = 0; | |
359 | ||
360 | *p2 = '\0'; | |
361 | p2++; | |
362 | ||
363 | t1 = 0; | |
364 | t2 = 0; | |
365 | sscanf(p1, "%x %x", &t1, &t2); | |
366 | ||
367 | if (t1 > 0x10000000) { | |
368 | if (NumCodes >= NumCodesAllocated) { | |
369 | NumCodesAllocated += ALLOC_INCREMENT; | |
370 | ||
371 | if (CheatCodes == NULL) { | |
372 | assert(NumCodes == 0); | |
373 | assert(NumCodesAllocated == ALLOC_INCREMENT); | |
374 | CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated); | |
375 | } | |
376 | else { | |
377 | CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated); | |
378 | } | |
379 | } | |
380 | ||
381 | CheatCodes[NumCodes].Addr = t1; | |
382 | CheatCodes[NumCodes].Val = t2; | |
383 | NumCodes++; | |
384 | Cheats[NumCheats].n++; | |
385 | } | |
386 | ||
387 | p1 = p2; | |
388 | } | |
389 | ||
390 | if (Cheats[NumCheats].n == 0) { | |
391 | return -1; | |
392 | } | |
393 | ||
cfa5a2af | 394 | Cheats[NumCheats].Descr = strdup(descr[0] ? descr : _("(Untitled)")); |
ef79bbde P |
395 | NumCheats++; |
396 | return 0; | |
397 | } | |
398 | ||
399 | void RemoveCheat(int index) { | |
400 | assert(index >= 0 && index < NumCheats); | |
401 | ||
402 | free(Cheats[index].Descr); | |
cfa5a2af | 403 | Cheats[index].Descr = NULL; |
ef79bbde P |
404 | |
405 | while (index < NumCheats - 1) { | |
406 | Cheats[index] = Cheats[index + 1]; | |
407 | index++; | |
408 | } | |
409 | ||
410 | NumCheats--; | |
411 | } | |
412 | ||
413 | int EditCheat(int index, const char *descr, char *code) { | |
414 | int c = 1; | |
415 | int prev = NumCodes; | |
416 | char *p1, *p2; | |
417 | ||
418 | assert(index >= 0 && index < NumCheats); | |
419 | ||
420 | p1 = code; | |
421 | p2 = code; | |
422 | ||
423 | while (c) { | |
424 | unsigned int t1, t2; | |
425 | ||
426 | while (*p2 != '\n' && *p2 != '\0') | |
427 | p2++; | |
428 | ||
429 | if (*p2 == '\0') | |
430 | c = 0; | |
431 | ||
432 | *p2 = '\0'; | |
433 | p2++; | |
434 | ||
435 | t1 = 0; | |
436 | t2 = 0; | |
437 | sscanf(p1, "%x %x", &t1, &t2); | |
438 | ||
439 | if (t1 > 0x10000000) { | |
440 | if (NumCodes >= NumCodesAllocated) { | |
441 | NumCodesAllocated += ALLOC_INCREMENT; | |
442 | ||
443 | if (CheatCodes == NULL) { | |
444 | assert(NumCodes == 0); | |
445 | assert(NumCodesAllocated == ALLOC_INCREMENT); | |
446 | CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated); | |
447 | } | |
448 | else { | |
449 | CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated); | |
450 | } | |
451 | } | |
452 | ||
453 | CheatCodes[NumCodes].Addr = t1; | |
454 | CheatCodes[NumCodes].Val = t2; | |
455 | NumCodes++; | |
456 | } | |
457 | ||
458 | p1 = p2; | |
459 | } | |
460 | ||
461 | if (NumCodes == prev) { | |
462 | return -1; | |
463 | } | |
464 | ||
465 | free(Cheats[index].Descr); | |
466 | Cheats[index].Descr = strdup(descr[0] ? descr : _("(Untitled)")); | |
467 | Cheats[index].First = prev; | |
468 | Cheats[index].n = NumCodes - prev; | |
469 | ||
470 | return 0; | |
471 | } | |
472 | ||
473 | void FreeCheatSearchResults() { | |
474 | if (SearchResults != NULL) { | |
475 | free(SearchResults); | |
476 | } | |
477 | SearchResults = NULL; | |
478 | ||
479 | NumSearchResults = 0; | |
480 | NumSearchResultsAllocated = 0; | |
481 | } | |
482 | ||
483 | void FreeCheatSearchMem() { | |
484 | if (prevM != NULL) { | |
485 | free(prevM); | |
486 | } | |
487 | prevM = NULL; | |
488 | } | |
489 | ||
490 | void CheatSearchBackupMemory() { | |
491 | if (prevM != NULL) { | |
492 | memcpy(prevM, psxM, 0x200000); | |
493 | } | |
494 | } | |
495 | ||
496 | static void CheatSearchInitBackupMemory() { | |
497 | if (prevM == NULL) { | |
498 | prevM = (s8 *)malloc(0x200000); | |
499 | CheatSearchBackupMemory(); | |
500 | } | |
501 | } | |
502 | ||
503 | static void CheatSearchAddResult(u32 addr) { | |
504 | if (NumSearchResults >= NumSearchResultsAllocated) { | |
505 | NumSearchResultsAllocated += ALLOC_INCREMENT; | |
506 | ||
507 | if (SearchResults == NULL) { | |
508 | SearchResults = (u32 *)malloc(sizeof(u32) * NumSearchResultsAllocated); | |
509 | } | |
510 | else { | |
511 | SearchResults = (u32 *)realloc(SearchResults, sizeof(u32) * NumSearchResultsAllocated); | |
512 | } | |
513 | } | |
514 | ||
515 | SearchResults[NumSearchResults++] = addr; | |
516 | } | |
517 | ||
518 | void CheatSearchEqual8(u8 val) { | |
519 | u32 i, j; | |
520 | ||
521 | CheatSearchInitBackupMemory(); | |
522 | ||
523 | if (SearchResults == NULL) { | |
524 | // search the whole memory | |
525 | for (i = 0; i < 0x200000; i++) { | |
526 | if (PSXMu8(i) == val) { | |
527 | CheatSearchAddResult(i); | |
528 | } | |
529 | } | |
530 | } | |
531 | else { | |
532 | // only search within the previous results | |
533 | j = 0; | |
534 | ||
535 | for (i = 0; i < NumSearchResults; i++) { | |
536 | if (PSXMu8(SearchResults[i]) == val) { | |
537 | SearchResults[j++] = SearchResults[i]; | |
538 | } | |
539 | } | |
540 | ||
541 | NumSearchResults = j; | |
542 | } | |
543 | } | |
544 | ||
545 | void CheatSearchEqual16(u16 val) { | |
546 | u32 i, j; | |
547 | ||
548 | CheatSearchInitBackupMemory(); | |
549 | ||
550 | if (SearchResults == NULL) { | |
551 | // search the whole memory | |
552 | for (i = 0; i < 0x200000; i += 2) { | |
553 | if (PSXMu16(i) == val) { | |
554 | CheatSearchAddResult(i); | |
555 | } | |
556 | } | |
557 | } | |
558 | else { | |
559 | // only search within the previous results | |
560 | j = 0; | |
561 | ||
562 | for (i = 0; i < NumSearchResults; i++) { | |
563 | if (PSXMu16(SearchResults[i]) == val) { | |
564 | SearchResults[j++] = SearchResults[i]; | |
565 | } | |
566 | } | |
567 | ||
568 | NumSearchResults = j; | |
569 | } | |
570 | } | |
571 | ||
572 | void CheatSearchEqual32(u32 val) { | |
573 | u32 i, j; | |
574 | ||
575 | CheatSearchInitBackupMemory(); | |
576 | ||
577 | if (SearchResults == NULL) { | |
578 | // search the whole memory | |
579 | for (i = 0; i < 0x200000; i += 4) { | |
580 | if (PSXMu32(i) == val) { | |
581 | CheatSearchAddResult(i); | |
582 | } | |
583 | } | |
584 | } | |
585 | else { | |
586 | // only search within the previous results | |
587 | j = 0; | |
588 | ||
589 | for (i = 0; i < NumSearchResults; i++) { | |
590 | if (PSXMu32(SearchResults[i]) == val) { | |
591 | SearchResults[j++] = SearchResults[i]; | |
592 | } | |
593 | } | |
594 | ||
595 | NumSearchResults = j; | |
596 | } | |
597 | } | |
598 | ||
599 | void CheatSearchNotEqual8(u8 val) { | |
600 | u32 i, j; | |
601 | ||
602 | CheatSearchInitBackupMemory(); | |
603 | ||
604 | if (SearchResults == NULL) { | |
605 | // search the whole memory | |
606 | for (i = 0; i < 0x200000; i++) { | |
607 | if (PSXMu8(i) != val) { | |
608 | CheatSearchAddResult(i); | |
609 | } | |
610 | } | |
611 | } | |
612 | else { | |
613 | // only search within the previous results | |
614 | j = 0; | |
615 | ||
616 | for (i = 0; i < NumSearchResults; i++) { | |
617 | if (PSXMu8(SearchResults[i]) != val) { | |
618 | SearchResults[j++] = SearchResults[i]; | |
619 | } | |
620 | } | |
621 | ||
622 | NumSearchResults = j; | |
623 | } | |
624 | } | |
625 | ||
626 | void CheatSearchNotEqual16(u16 val) { | |
627 | u32 i, j; | |
628 | ||
629 | CheatSearchInitBackupMemory(); | |
630 | ||
631 | if (SearchResults == NULL) { | |
632 | // search the whole memory | |
633 | for (i = 0; i < 0x200000; i += 2) { | |
634 | if (PSXMu16(i) != val) { | |
635 | CheatSearchAddResult(i); | |
636 | } | |
637 | } | |
638 | } | |
639 | else { | |
640 | // only search within the previous results | |
641 | j = 0; | |
642 | ||
643 | for (i = 0; i < NumSearchResults; i++) { | |
644 | if (PSXMu16(SearchResults[i]) != val) { | |
645 | SearchResults[j++] = SearchResults[i]; | |
646 | } | |
647 | } | |
648 | ||
649 | NumSearchResults = j; | |
650 | } | |
651 | } | |
652 | ||
653 | void CheatSearchNotEqual32(u32 val) { | |
654 | u32 i, j; | |
655 | ||
656 | CheatSearchInitBackupMemory(); | |
657 | ||
658 | if (SearchResults == NULL) { | |
659 | // search the whole memory | |
660 | for (i = 0; i < 0x200000; i += 4) { | |
661 | if (PSXMu32(i) != val) { | |
662 | CheatSearchAddResult(i); | |
663 | } | |
664 | } | |
665 | } | |
666 | else { | |
667 | // only search within the previous results | |
668 | j = 0; | |
669 | ||
670 | for (i = 0; i < NumSearchResults; i++) { | |
671 | if (PSXMu32(SearchResults[i]) != val) { | |
672 | SearchResults[j++] = SearchResults[i]; | |
673 | } | |
674 | } | |
675 | ||
676 | NumSearchResults = j; | |
677 | } | |
678 | } | |
679 | ||
680 | void CheatSearchRange8(u8 min, u8 max) { | |
681 | u32 i, j; | |
682 | ||
683 | CheatSearchInitBackupMemory(); | |
684 | ||
685 | if (SearchResults == NULL) { | |
686 | // search the whole memory | |
687 | for (i = 0; i < 0x200000; i++) { | |
688 | if (PSXMu8(i) >= min && PSXMu8(i) <= max) { | |
689 | CheatSearchAddResult(i); | |
690 | } | |
691 | } | |
692 | } | |
693 | else { | |
694 | // only search within the previous results | |
695 | j = 0; | |
696 | ||
697 | for (i = 0; i < NumSearchResults; i++) { | |
698 | if (PSXMu8(SearchResults[i]) >= min && PSXMu8(SearchResults[i]) <= max) { | |
699 | SearchResults[j++] = SearchResults[i]; | |
700 | } | |
701 | } | |
702 | ||
703 | NumSearchResults = j; | |
704 | } | |
705 | } | |
706 | ||
707 | void CheatSearchRange16(u16 min, u16 max) { | |
708 | u32 i, j; | |
709 | ||
710 | CheatSearchInitBackupMemory(); | |
711 | ||
712 | if (SearchResults == NULL) { | |
713 | // search the whole memory | |
714 | for (i = 0; i < 0x200000; i += 2) { | |
715 | if (PSXMu16(i) >= min && PSXMu16(i) <= max) { | |
716 | CheatSearchAddResult(i); | |
717 | } | |
718 | } | |
719 | } | |
720 | else { | |
721 | // only search within the previous results | |
722 | j = 0; | |
723 | ||
724 | for (i = 0; i < NumSearchResults; i++) { | |
725 | if (PSXMu16(SearchResults[i]) >= min && PSXMu16(SearchResults[i]) <= max) { | |
726 | SearchResults[j++] = SearchResults[i]; | |
727 | } | |
728 | } | |
729 | ||
730 | NumSearchResults = j; | |
731 | } | |
732 | } | |
733 | ||
734 | void CheatSearchRange32(u32 min, u32 max) { | |
735 | u32 i, j; | |
736 | ||
737 | CheatSearchInitBackupMemory(); | |
738 | ||
739 | if (SearchResults == NULL) { | |
740 | // search the whole memory | |
741 | for (i = 0; i < 0x200000; i += 4) { | |
742 | if (PSXMu32(i) >= min && PSXMu32(i) <= max) { | |
743 | CheatSearchAddResult(i); | |
744 | } | |
745 | } | |
746 | } | |
747 | else { | |
748 | // only search within the previous results | |
749 | j = 0; | |
750 | ||
751 | for (i = 0; i < NumSearchResults; i++) { | |
752 | if (PSXMu32(SearchResults[i]) >= min && PSXMu32(SearchResults[i]) <= max) { | |
753 | SearchResults[j++] = SearchResults[i]; | |
754 | } | |
755 | } | |
756 | ||
757 | NumSearchResults = j; | |
758 | } | |
759 | } | |
760 | ||
761 | void CheatSearchIncreasedBy8(u8 val) { | |
762 | u32 i, j; | |
763 | ||
764 | assert(prevM != NULL); // not possible for the first search | |
765 | ||
766 | j = 0; | |
767 | ||
768 | for (i = 0; i < NumSearchResults; i++) { | |
769 | if (PSXMu8(SearchResults[i]) - PrevMu8(SearchResults[i]) == val) { | |
770 | SearchResults[j++] = SearchResults[i]; | |
771 | } | |
772 | } | |
773 | ||
774 | NumSearchResults = j; | |
775 | } | |
776 | ||
777 | void CheatSearchIncreasedBy16(u16 val) { | |
778 | u32 i, j; | |
779 | ||
780 | assert(prevM != NULL); // not possible for the first search | |
781 | ||
782 | j = 0; | |
783 | ||
784 | for (i = 0; i < NumSearchResults; i++) { | |
785 | if (PSXMu16(SearchResults[i]) - PrevMu16(SearchResults[i]) == val) { | |
786 | SearchResults[j++] = SearchResults[i]; | |
787 | } | |
788 | } | |
789 | ||
790 | NumSearchResults = j; | |
791 | } | |
792 | ||
793 | void CheatSearchIncreasedBy32(u32 val) { | |
794 | u32 i, j; | |
795 | ||
796 | assert(prevM != NULL); // not possible for the first search | |
797 | ||
798 | j = 0; | |
799 | ||
800 | for (i = 0; i < NumSearchResults; i++) { | |
801 | if (PSXMu32(SearchResults[i]) - PrevMu32(SearchResults[i]) == val) { | |
802 | SearchResults[j++] = SearchResults[i]; | |
803 | } | |
804 | } | |
805 | ||
806 | NumSearchResults = j; | |
807 | } | |
808 | ||
809 | void CheatSearchDecreasedBy8(u8 val) { | |
810 | u32 i, j; | |
811 | ||
812 | assert(prevM != NULL); // not possible for the first search | |
813 | ||
814 | j = 0; | |
815 | ||
816 | for (i = 0; i < NumSearchResults; i++) { | |
817 | if (PrevMu8(SearchResults[i]) - PSXMu8(SearchResults[i]) == val) { | |
818 | SearchResults[j++] = SearchResults[i]; | |
819 | } | |
820 | } | |
821 | ||
822 | NumSearchResults = j; | |
823 | } | |
824 | ||
825 | void CheatSearchDecreasedBy16(u16 val) { | |
826 | u32 i, j; | |
827 | ||
828 | assert(prevM != NULL); // not possible for the first search | |
829 | ||
830 | j = 0; | |
831 | ||
832 | for (i = 0; i < NumSearchResults; i++) { | |
833 | if (PrevMu16(SearchResults[i]) - PSXMu16(SearchResults[i]) == val) { | |
834 | SearchResults[j++] = SearchResults[i]; | |
835 | } | |
836 | } | |
837 | ||
838 | NumSearchResults = j; | |
839 | } | |
840 | ||
841 | void CheatSearchDecreasedBy32(u32 val) { | |
842 | u32 i, j; | |
843 | ||
844 | assert(prevM != NULL); // not possible for the first search | |
845 | ||
846 | j = 0; | |
847 | ||
848 | for (i = 0; i < NumSearchResults; i++) { | |
849 | if (PrevMu32(SearchResults[i]) - PSXMu32(SearchResults[i]) == val) { | |
850 | SearchResults[j++] = SearchResults[i]; | |
851 | } | |
852 | } | |
853 | ||
854 | NumSearchResults = j; | |
855 | } | |
856 | ||
857 | void CheatSearchIncreased8() { | |
858 | u32 i, j; | |
859 | ||
860 | assert(prevM != NULL); // not possible for the first search | |
861 | ||
862 | j = 0; | |
863 | ||
864 | for (i = 0; i < NumSearchResults; i++) { | |
865 | if (PrevMu8(SearchResults[i]) < PSXMu8(SearchResults[i])) { | |
866 | SearchResults[j++] = SearchResults[i]; | |
867 | } | |
868 | } | |
869 | ||
870 | NumSearchResults = j; | |
871 | } | |
872 | ||
873 | void CheatSearchIncreased16() { | |
874 | u32 i, j; | |
875 | ||
876 | assert(prevM != NULL); // not possible for the first search | |
877 | ||
878 | j = 0; | |
879 | ||
880 | for (i = 0; i < NumSearchResults; i++) { | |
881 | if (PrevMu16(SearchResults[i]) < PSXMu16(SearchResults[i])) { | |
882 | SearchResults[j++] = SearchResults[i]; | |
883 | } | |
884 | } | |
885 | ||
886 | NumSearchResults = j; | |
887 | } | |
888 | ||
889 | void CheatSearchIncreased32() { | |
890 | u32 i, j; | |
891 | ||
892 | assert(prevM != NULL); // not possible for the first search | |
893 | ||
894 | j = 0; | |
895 | ||
896 | for (i = 0; i < NumSearchResults; i++) { | |
897 | if (PrevMu32(SearchResults[i]) < PSXMu32(SearchResults[i])) { | |
898 | SearchResults[j++] = SearchResults[i]; | |
899 | } | |
900 | } | |
901 | ||
902 | NumSearchResults = j; | |
903 | } | |
904 | ||
905 | void CheatSearchDecreased8() { | |
906 | u32 i, j; | |
907 | ||
908 | assert(prevM != NULL); // not possible for the first search | |
909 | ||
910 | j = 0; | |
911 | ||
912 | for (i = 0; i < NumSearchResults; i++) { | |
913 | if (PrevMu8(SearchResults[i]) > PSXMu8(SearchResults[i])) { | |
914 | SearchResults[j++] = SearchResults[i]; | |
915 | } | |
916 | } | |
917 | ||
918 | NumSearchResults = j; | |
919 | } | |
920 | ||
921 | void CheatSearchDecreased16() { | |
922 | u32 i, j; | |
923 | ||
924 | assert(prevM != NULL); // not possible for the first search | |
925 | ||
926 | j = 0; | |
927 | ||
928 | for (i = 0; i < NumSearchResults; i++) { | |
929 | if (PrevMu16(SearchResults[i]) > PSXMu16(SearchResults[i])) { | |
930 | SearchResults[j++] = SearchResults[i]; | |
931 | } | |
932 | } | |
933 | ||
934 | NumSearchResults = j; | |
935 | } | |
936 | ||
937 | void CheatSearchDecreased32() { | |
938 | u32 i, j; | |
939 | ||
940 | assert(prevM != NULL); // not possible for the first search | |
941 | ||
942 | j = 0; | |
943 | ||
944 | for (i = 0; i < NumSearchResults; i++) { | |
945 | if (PrevMu32(SearchResults[i]) > PSXMu32(SearchResults[i])) { | |
946 | SearchResults[j++] = SearchResults[i]; | |
947 | } | |
948 | } | |
949 | ||
950 | NumSearchResults = j; | |
951 | } | |
952 | ||
953 | void CheatSearchDifferent8() { | |
954 | u32 i, j; | |
955 | ||
956 | assert(prevM != NULL); // not possible for the first search | |
957 | ||
958 | j = 0; | |
959 | ||
960 | for (i = 0; i < NumSearchResults; i++) { | |
961 | if (PrevMu8(SearchResults[i]) != PSXMu8(SearchResults[i])) { | |
962 | SearchResults[j++] = SearchResults[i]; | |
963 | } | |
964 | } | |
965 | ||
966 | NumSearchResults = j; | |
967 | } | |
968 | ||
969 | void CheatSearchDifferent16() { | |
970 | u32 i, j; | |
971 | ||
972 | assert(prevM != NULL); // not possible for the first search | |
973 | ||
974 | j = 0; | |
975 | ||
976 | for (i = 0; i < NumSearchResults; i++) { | |
977 | if (PrevMu16(SearchResults[i]) != PSXMu16(SearchResults[i])) { | |
978 | SearchResults[j++] = SearchResults[i]; | |
979 | } | |
980 | } | |
981 | ||
982 | NumSearchResults = j; | |
983 | } | |
984 | ||
985 | void CheatSearchDifferent32() { | |
986 | u32 i, j; | |
987 | ||
988 | assert(prevM != NULL); // not possible for the first search | |
989 | ||
990 | j = 0; | |
991 | ||
992 | for (i = 0; i < NumSearchResults; i++) { | |
993 | if (PrevMu32(SearchResults[i]) != PSXMu32(SearchResults[i])) { | |
994 | SearchResults[j++] = SearchResults[i]; | |
995 | } | |
996 | } | |
997 | ||
998 | NumSearchResults = j; | |
999 | } | |
1000 | ||
1001 | void CheatSearchNoChange8() { | |
1002 | u32 i, j; | |
1003 | ||
1004 | assert(prevM != NULL); // not possible for the first search | |
1005 | ||
1006 | j = 0; | |
1007 | ||
1008 | for (i = 0; i < NumSearchResults; i++) { | |
1009 | if (PrevMu8(SearchResults[i]) == PSXMu8(SearchResults[i])) { | |
1010 | SearchResults[j++] = SearchResults[i]; | |
1011 | } | |
1012 | } | |
1013 | ||
1014 | NumSearchResults = j; | |
1015 | } | |
1016 | ||
1017 | void CheatSearchNoChange16() { | |
1018 | u32 i, j; | |
1019 | ||
1020 | assert(prevM != NULL); // not possible for the first search | |
1021 | ||
1022 | j = 0; | |
1023 | ||
1024 | for (i = 0; i < NumSearchResults; i++) { | |
1025 | if (PrevMu16(SearchResults[i]) == PSXMu16(SearchResults[i])) { | |
1026 | SearchResults[j++] = SearchResults[i]; | |
1027 | } | |
1028 | } | |
1029 | ||
1030 | NumSearchResults = j; | |
1031 | } | |
1032 | ||
1033 | void CheatSearchNoChange32() { | |
1034 | u32 i, j; | |
1035 | ||
1036 | assert(prevM != NULL); // not possible for the first search | |
1037 | ||
1038 | j = 0; | |
1039 | ||
1040 | for (i = 0; i < NumSearchResults; i++) { | |
1041 | if (PrevMu32(SearchResults[i]) == PSXMu32(SearchResults[i])) { | |
1042 | SearchResults[j++] = SearchResults[i]; | |
1043 | } | |
1044 | } | |
1045 | ||
1046 | NumSearchResults = j; | |
1047 | } |