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