frontend: pandora: work around r20a vs r21 versioning
[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
23 #include "cheat.h"
24
25 Cheat *Cheats = NULL;
26 int NumCheats = 0;
27 int NumCheatsAllocated = 0;
28
29 CheatCode *CheatCodes = NULL;
30 int NumCodes = 0;
31 int NumCodesAllocated = 0;
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                         }
111                         Cheats[NumCheats].WasEnabled = 0;
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;
186         int             was_enabled;
187
188         for (i = 0; i < NumCheats; i++) {
189                 was_enabled = Cheats[i].WasEnabled;
190                 if (!Cheats[i].Enabled) {
191                         if (!Cheats[i].WasEnabled)
192                                 continue;
193                 }
194                 Cheats[i].WasEnabled = Cheats[i].Enabled;
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
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
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
343         Cheats[NumCheats].Descr = strdup(descr[0] ? descr : _("(Untitled)"));
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         NumCheats++;
396         return 0;
397 }
398
399 void RemoveCheat(int index) {
400         assert(index >= 0 && index < NumCheats);
401
402         free(Cheats[index].Descr);
403
404         while (index < NumCheats - 1) {
405                 Cheats[index] = Cheats[index + 1];
406                 index++;
407         }
408
409         NumCheats--;
410 }
411
412 int EditCheat(int index, const char *descr, char *code) {
413         int c = 1;
414         int prev = NumCodes;
415         char *p1, *p2;
416
417         assert(index >= 0 && index < NumCheats);
418
419         p1 = code;
420         p2 = code;
421
422         while (c) {
423                 unsigned int t1, t2;
424
425                 while (*p2 != '\n' && *p2 != '\0')
426                         p2++;
427
428                 if (*p2 == '\0')
429                         c = 0;
430
431                 *p2 = '\0';
432                 p2++;
433
434                 t1 = 0;
435                 t2 = 0;
436                 sscanf(p1, "%x %x", &t1, &t2);
437
438                 if (t1 > 0x10000000) {
439                         if (NumCodes >= NumCodesAllocated) {
440                                 NumCodesAllocated += ALLOC_INCREMENT;
441
442                                 if (CheatCodes == NULL) {
443                                         assert(NumCodes == 0);
444                                         assert(NumCodesAllocated == ALLOC_INCREMENT);
445                                         CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
446                                 }
447                                 else {
448                                         CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
449                                 }
450                         }
451
452                         CheatCodes[NumCodes].Addr = t1;
453                         CheatCodes[NumCodes].Val = t2;
454                         NumCodes++;
455                 }
456
457                 p1 = p2;
458         }
459
460         if (NumCodes == prev) {
461                 return -1;
462         }
463
464         free(Cheats[index].Descr);
465         Cheats[index].Descr = strdup(descr[0] ? descr : _("(Untitled)"));
466         Cheats[index].First = prev;
467         Cheats[index].n = NumCodes - prev;
468
469         return 0;
470 }
471
472 void FreeCheatSearchResults() {
473         if (SearchResults != NULL) {
474                 free(SearchResults);
475         }
476         SearchResults = NULL;
477
478         NumSearchResults = 0;
479         NumSearchResultsAllocated = 0;
480 }
481
482 void FreeCheatSearchMem() {
483         if (prevM != NULL) {
484                 free(prevM);
485         }
486         prevM = NULL;
487 }
488
489 void CheatSearchBackupMemory() {
490         if (prevM != NULL) {
491                 memcpy(prevM, psxM, 0x200000);
492         }
493 }
494
495 static void CheatSearchInitBackupMemory() {
496         if (prevM == NULL) {
497                 prevM = (s8 *)malloc(0x200000);
498                 CheatSearchBackupMemory();
499         }
500 }
501
502 static void CheatSearchAddResult(u32 addr) {
503         if (NumSearchResults >= NumSearchResultsAllocated) {
504                 NumSearchResultsAllocated += ALLOC_INCREMENT;
505
506                 if (SearchResults == NULL) {
507                         SearchResults = (u32 *)malloc(sizeof(u32) * NumSearchResultsAllocated);
508                 }
509                 else {
510                         SearchResults = (u32 *)realloc(SearchResults, sizeof(u32) * NumSearchResultsAllocated);
511                 }
512         }
513
514         SearchResults[NumSearchResults++] = addr;
515 }
516
517 void CheatSearchEqual8(u8 val) {
518         u32 i, j;
519
520         CheatSearchInitBackupMemory();
521
522         if (SearchResults == NULL) {
523                 // search the whole memory
524                 for (i = 0; i < 0x200000; i++) {
525                         if (PSXMu8(i) == val) {
526                                 CheatSearchAddResult(i);
527                         }
528                 }
529         }
530         else {
531                 // only search within the previous results
532                 j = 0;
533
534                 for (i = 0; i < NumSearchResults; i++) {
535                         if (PSXMu8(SearchResults[i]) == val) {
536                                 SearchResults[j++] = SearchResults[i];
537                         }
538                 }
539
540                 NumSearchResults = j;
541         }
542 }
543
544 void CheatSearchEqual16(u16 val) {
545         u32 i, j;
546
547         CheatSearchInitBackupMemory();
548
549         if (SearchResults == NULL) {
550                 // search the whole memory
551                 for (i = 0; i < 0x200000; i += 2) {
552                         if (PSXMu16(i) == val) {
553                                 CheatSearchAddResult(i);
554                         }
555                 }
556         }
557         else {
558                 // only search within the previous results
559                 j = 0;
560
561                 for (i = 0; i < NumSearchResults; i++) {
562                         if (PSXMu16(SearchResults[i]) == val) {
563                                 SearchResults[j++] = SearchResults[i];
564                         }
565                 }
566
567                 NumSearchResults = j;
568         }
569 }
570
571 void CheatSearchEqual32(u32 val) {
572         u32 i, j;
573
574         CheatSearchInitBackupMemory();
575
576         if (SearchResults == NULL) {
577                 // search the whole memory
578                 for (i = 0; i < 0x200000; i += 4) {
579                         if (PSXMu32(i) == val) {
580                                 CheatSearchAddResult(i);
581                         }
582                 }
583         }
584         else {
585                 // only search within the previous results
586                 j = 0;
587
588                 for (i = 0; i < NumSearchResults; i++) {
589                         if (PSXMu32(SearchResults[i]) == val) {
590                                 SearchResults[j++] = SearchResults[i];
591                         }
592                 }
593
594                 NumSearchResults = j;
595         }
596 }
597
598 void CheatSearchNotEqual8(u8 val) {
599         u32 i, j;
600
601         CheatSearchInitBackupMemory();
602
603         if (SearchResults == NULL) {
604                 // search the whole memory
605                 for (i = 0; i < 0x200000; i++) {
606                         if (PSXMu8(i) != val) {
607                                 CheatSearchAddResult(i);
608                         }
609                 }
610         }
611         else {
612                 // only search within the previous results
613                 j = 0;
614
615                 for (i = 0; i < NumSearchResults; i++) {
616                         if (PSXMu8(SearchResults[i]) != val) {
617                                 SearchResults[j++] = SearchResults[i];
618                         }
619                 }
620
621                 NumSearchResults = j;
622         }
623 }
624
625 void CheatSearchNotEqual16(u16 val) {
626         u32 i, j;
627
628         CheatSearchInitBackupMemory();
629
630         if (SearchResults == NULL) {
631                 // search the whole memory
632                 for (i = 0; i < 0x200000; i += 2) {
633                         if (PSXMu16(i) != val) {
634                                 CheatSearchAddResult(i);
635                         }
636                 }
637         }
638         else {
639                 // only search within the previous results
640                 j = 0;
641
642                 for (i = 0; i < NumSearchResults; i++) {
643                         if (PSXMu16(SearchResults[i]) != val) {
644                                 SearchResults[j++] = SearchResults[i];
645                         }
646                 }
647
648                 NumSearchResults = j;
649         }
650 }
651
652 void CheatSearchNotEqual32(u32 val) {
653         u32 i, j;
654
655         CheatSearchInitBackupMemory();
656
657         if (SearchResults == NULL) {
658                 // search the whole memory
659                 for (i = 0; i < 0x200000; i += 4) {
660                         if (PSXMu32(i) != val) {
661                                 CheatSearchAddResult(i);
662                         }
663                 }
664         }
665         else {
666                 // only search within the previous results
667                 j = 0;
668
669                 for (i = 0; i < NumSearchResults; i++) {
670                         if (PSXMu32(SearchResults[i]) != val) {
671                                 SearchResults[j++] = SearchResults[i];
672                         }
673                 }
674
675                 NumSearchResults = j;
676         }
677 }
678
679 void CheatSearchRange8(u8 min, u8 max) {
680         u32 i, j;
681
682         CheatSearchInitBackupMemory();
683
684         if (SearchResults == NULL) {
685                 // search the whole memory
686                 for (i = 0; i < 0x200000; i++) {
687                         if (PSXMu8(i) >= min && PSXMu8(i) <= max) {
688                                 CheatSearchAddResult(i);
689                         }
690                 }
691         }
692         else {
693                 // only search within the previous results
694                 j = 0;
695
696                 for (i = 0; i < NumSearchResults; i++) {
697                         if (PSXMu8(SearchResults[i]) >= min && PSXMu8(SearchResults[i]) <= max) {
698                                 SearchResults[j++] = SearchResults[i];
699                         }
700                 }
701
702                 NumSearchResults = j;
703         }
704 }
705
706 void CheatSearchRange16(u16 min, u16 max) {
707         u32 i, j;
708
709         CheatSearchInitBackupMemory();
710
711         if (SearchResults == NULL) {
712                 // search the whole memory
713                 for (i = 0; i < 0x200000; i += 2) {
714                         if (PSXMu16(i) >= min && PSXMu16(i) <= max) {
715                                 CheatSearchAddResult(i);
716                         }
717                 }
718         }
719         else {
720                 // only search within the previous results
721                 j = 0;
722
723                 for (i = 0; i < NumSearchResults; i++) {
724                         if (PSXMu16(SearchResults[i]) >= min && PSXMu16(SearchResults[i]) <= max) {
725                                 SearchResults[j++] = SearchResults[i];
726                         }
727                 }
728
729                 NumSearchResults = j;
730         }
731 }
732
733 void CheatSearchRange32(u32 min, u32 max) {
734         u32 i, j;
735
736         CheatSearchInitBackupMemory();
737
738         if (SearchResults == NULL) {
739                 // search the whole memory
740                 for (i = 0; i < 0x200000; i += 4) {
741                         if (PSXMu32(i) >= min && PSXMu32(i) <= max) {
742                                 CheatSearchAddResult(i);
743                         }
744                 }
745         }
746         else {
747                 // only search within the previous results
748                 j = 0;
749
750                 for (i = 0; i < NumSearchResults; i++) {
751                         if (PSXMu32(SearchResults[i]) >= min && PSXMu32(SearchResults[i]) <= max) {
752                                 SearchResults[j++] = SearchResults[i];
753                         }
754                 }
755
756                 NumSearchResults = j;
757         }
758 }
759
760 void CheatSearchIncreasedBy8(u8 val) {
761         u32 i, j;
762
763         assert(prevM != NULL); // not possible for the first search
764
765         j = 0;
766
767         for (i = 0; i < NumSearchResults; i++) {
768                 if (PSXMu8(SearchResults[i]) - PrevMu8(SearchResults[i]) == val) {
769                         SearchResults[j++] = SearchResults[i];
770                 }
771         }
772
773         NumSearchResults = j;
774 }
775
776 void CheatSearchIncreasedBy16(u16 val) {
777         u32 i, j;
778
779         assert(prevM != NULL); // not possible for the first search
780
781         j = 0;
782
783         for (i = 0; i < NumSearchResults; i++) {
784                 if (PSXMu16(SearchResults[i]) - PrevMu16(SearchResults[i]) == val) {
785                         SearchResults[j++] = SearchResults[i];
786                 }
787         }
788
789         NumSearchResults = j;
790 }
791
792 void CheatSearchIncreasedBy32(u32 val) {
793         u32 i, j;
794
795         assert(prevM != NULL); // not possible for the first search
796
797         j = 0;
798
799         for (i = 0; i < NumSearchResults; i++) {
800                 if (PSXMu32(SearchResults[i]) - PrevMu32(SearchResults[i]) == val) {
801                         SearchResults[j++] = SearchResults[i];
802                 }
803         }
804
805         NumSearchResults = j;
806 }
807
808 void CheatSearchDecreasedBy8(u8 val) {
809         u32 i, j;
810
811         assert(prevM != NULL); // not possible for the first search
812
813         j = 0;
814
815         for (i = 0; i < NumSearchResults; i++) {
816                 if (PrevMu8(SearchResults[i]) - PSXMu8(SearchResults[i]) == val) {
817                         SearchResults[j++] = SearchResults[i];
818                 }
819         }
820
821         NumSearchResults = j;
822 }
823
824 void CheatSearchDecreasedBy16(u16 val) {
825         u32 i, j;
826
827         assert(prevM != NULL); // not possible for the first search
828
829         j = 0;
830
831         for (i = 0; i < NumSearchResults; i++) {
832                 if (PrevMu16(SearchResults[i]) - PSXMu16(SearchResults[i]) == val) {
833                         SearchResults[j++] = SearchResults[i];
834                 }
835         }
836
837         NumSearchResults = j;
838 }
839
840 void CheatSearchDecreasedBy32(u32 val) {
841         u32 i, j;
842
843         assert(prevM != NULL); // not possible for the first search
844
845         j = 0;
846
847         for (i = 0; i < NumSearchResults; i++) {
848                 if (PrevMu32(SearchResults[i]) - PSXMu32(SearchResults[i]) == val) {
849                         SearchResults[j++] = SearchResults[i];
850                 }
851         }
852
853         NumSearchResults = j;
854 }
855
856 void CheatSearchIncreased8() {
857         u32 i, j;
858
859         assert(prevM != NULL); // not possible for the first search
860
861         j = 0;
862
863         for (i = 0; i < NumSearchResults; i++) {
864                 if (PrevMu8(SearchResults[i]) < PSXMu8(SearchResults[i])) {
865                         SearchResults[j++] = SearchResults[i];
866                 }
867         }
868
869         NumSearchResults = j;
870 }
871
872 void CheatSearchIncreased16() {
873         u32 i, j;
874
875         assert(prevM != NULL); // not possible for the first search
876
877         j = 0;
878
879         for (i = 0; i < NumSearchResults; i++) {
880                 if (PrevMu16(SearchResults[i]) < PSXMu16(SearchResults[i])) {
881                         SearchResults[j++] = SearchResults[i];
882                 }
883         }
884
885         NumSearchResults = j;
886 }
887
888 void CheatSearchIncreased32() {
889         u32 i, j;
890
891         assert(prevM != NULL); // not possible for the first search
892
893         j = 0;
894
895         for (i = 0; i < NumSearchResults; i++) {
896                 if (PrevMu32(SearchResults[i]) < PSXMu32(SearchResults[i])) {
897                         SearchResults[j++] = SearchResults[i];
898                 }
899         }
900
901         NumSearchResults = j;
902 }
903
904 void CheatSearchDecreased8() {
905         u32 i, j;
906
907         assert(prevM != NULL); // not possible for the first search
908
909         j = 0;
910
911         for (i = 0; i < NumSearchResults; i++) {
912                 if (PrevMu8(SearchResults[i]) > PSXMu8(SearchResults[i])) {
913                         SearchResults[j++] = SearchResults[i];
914                 }
915         }
916
917         NumSearchResults = j;
918 }
919
920 void CheatSearchDecreased16() {
921         u32 i, j;
922
923         assert(prevM != NULL); // not possible for the first search
924
925         j = 0;
926
927         for (i = 0; i < NumSearchResults; i++) {
928                 if (PrevMu16(SearchResults[i]) > PSXMu16(SearchResults[i])) {
929                         SearchResults[j++] = SearchResults[i];
930                 }
931         }
932
933         NumSearchResults = j;
934 }
935
936 void CheatSearchDecreased32() {
937         u32 i, j;
938
939         assert(prevM != NULL); // not possible for the first search
940
941         j = 0;
942
943         for (i = 0; i < NumSearchResults; i++) {
944                 if (PrevMu32(SearchResults[i]) > PSXMu32(SearchResults[i])) {
945                         SearchResults[j++] = SearchResults[i];
946                 }
947         }
948
949         NumSearchResults = j;
950 }
951
952 void CheatSearchDifferent8() {
953         u32 i, j;
954
955         assert(prevM != NULL); // not possible for the first search
956
957         j = 0;
958
959         for (i = 0; i < NumSearchResults; i++) {
960                 if (PrevMu8(SearchResults[i]) != PSXMu8(SearchResults[i])) {
961                         SearchResults[j++] = SearchResults[i];
962                 }
963         }
964
965         NumSearchResults = j;
966 }
967
968 void CheatSearchDifferent16() {
969         u32 i, j;
970
971         assert(prevM != NULL); // not possible for the first search
972
973         j = 0;
974
975         for (i = 0; i < NumSearchResults; i++) {
976                 if (PrevMu16(SearchResults[i]) != PSXMu16(SearchResults[i])) {
977                         SearchResults[j++] = SearchResults[i];
978                 }
979         }
980
981         NumSearchResults = j;
982 }
983
984 void CheatSearchDifferent32() {
985         u32 i, j;
986
987         assert(prevM != NULL); // not possible for the first search
988
989         j = 0;
990
991         for (i = 0; i < NumSearchResults; i++) {
992                 if (PrevMu32(SearchResults[i]) != PSXMu32(SearchResults[i])) {
993                         SearchResults[j++] = SearchResults[i];
994                 }
995         }
996
997         NumSearchResults = j;
998 }
999
1000 void CheatSearchNoChange8() {
1001         u32 i, j;
1002
1003         assert(prevM != NULL); // not possible for the first search
1004
1005         j = 0;
1006
1007         for (i = 0; i < NumSearchResults; i++) {
1008                 if (PrevMu8(SearchResults[i]) == PSXMu8(SearchResults[i])) {
1009                         SearchResults[j++] = SearchResults[i];
1010                 }
1011         }
1012
1013         NumSearchResults = j;
1014 }
1015
1016 void CheatSearchNoChange16() {
1017         u32 i, j;
1018
1019         assert(prevM != NULL); // not possible for the first search
1020
1021         j = 0;
1022
1023         for (i = 0; i < NumSearchResults; i++) {
1024                 if (PrevMu16(SearchResults[i]) == PSXMu16(SearchResults[i])) {
1025                         SearchResults[j++] = SearchResults[i];
1026                 }
1027         }
1028
1029         NumSearchResults = j;
1030 }
1031
1032 void CheatSearchNoChange32() {
1033         u32 i, j;
1034
1035         assert(prevM != NULL); // not possible for the first search
1036
1037         j = 0;
1038
1039         for (i = 0; i < NumSearchResults; i++) {
1040                 if (PrevMu32(SearchResults[i]) == PSXMu32(SearchResults[i])) {
1041                         SearchResults[j++] = SearchResults[i];
1042                 }
1043         }
1044
1045         NumSearchResults = j;
1046 }