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