some missing error handling
[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].Enabled = 0;
344         Cheats[NumCheats].WasEnabled = 0;
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
394         Cheats[NumCheats].Descr = strdup(descr[0] ? descr : _("(Untitled)"));
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         Cheats[index].Descr = NULL;
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 }