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