drc: rm x86 stuff - it's unmaintained here
[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 static int NumCheatsAllocated = 0;
28
29 CheatCode *CheatCodes = NULL;
30 int NumCodes = 0;
31 static 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
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
186         for (i = 0; i < NumCheats; i++) {
187                 if (!Cheats[i].Enabled) {
188                         continue;
189                 }
190
191                 // process all cheat codes
192                 endindex = Cheats[i].First + Cheats[i].n;
193
194                 for (j = Cheats[i].First; j < endindex; j++) {
195                         u8              type = (uint8_t)(CheatCodes[j].Addr >> 24);
196                         u32             addr = (CheatCodes[j].Addr & 0x001FFFFF);
197                         u16             val = CheatCodes[j].Val;
198                         u32             taddr;
199
200                         switch (type) {
201                                 case CHEAT_CONST8:
202                                         psxMu8ref(addr) = (u8)val;
203                                         break;
204
205                                 case CHEAT_CONST16:
206                                         psxMu16ref(addr) = SWAPu16(val);
207                                         break;
208
209                                 case CHEAT_INC16:
210                                         psxMu16ref(addr) = SWAPu16(psxMu16(addr) + val);
211                                         break;
212
213                                 case CHEAT_DEC16:
214                                         psxMu16ref(addr) = SWAPu16(psxMu16(addr) - val);
215                                         break;
216
217                                 case CHEAT_INC8:
218                                         psxMu8ref(addr) += (u8)val;
219                                         break;
220
221                                 case CHEAT_DEC8:
222                                         psxMu8ref(addr) -= (u8)val;
223                                         break;
224
225                                 case CHEAT_SLIDE:
226                                         j++;
227                                         if (j >= endindex)
228                                                 break;
229
230                                         type = (uint8_t)(CheatCodes[j].Addr >> 24);
231                                         taddr = (CheatCodes[j].Addr & 0x001FFFFF);
232                                         val = CheatCodes[j].Val;
233
234                                         if (type == CHEAT_CONST8) {
235                                                 for (k = 0; k < ((addr >> 8) & 0xFF); k++) {
236                                                         psxMu8ref(taddr) = (u8)val;
237                                                         taddr += (s8)(addr & 0xFF);
238                                                         val += (s8)(CheatCodes[j - 1].Val & 0xFF);
239                                                 }
240                                         }
241                                         else if (type == CHEAT_CONST16) {
242                                                 for (k = 0; k < ((addr >> 8) & 0xFF); k++) {
243                                                         psxMu16ref(taddr) = SWAPu16(val);
244                                                         taddr += (s8)(addr & 0xFF);
245                                                         val += (s8)(CheatCodes[j - 1].Val & 0xFF);
246                                                 }
247                                         }
248                                         break;
249
250                                 case CHEAT_MEMCPY:
251                                         j++;
252                                         if (j >= endindex)
253                                                 break;
254
255                                         taddr = (CheatCodes[j].Addr & 0x001FFFFF);
256                                         for (k = 0; k < val; k++) {
257                                                 psxMu8ref(taddr + k) = PSXMu8(addr + k);
258                                         }
259                                         break;
260
261                                 case CHEAT_EQU8:
262                                         if (PSXMu8(addr) != (u8)val)
263                                                 j++; // skip the next code
264                                         break;
265
266                                 case CHEAT_NOTEQU8:
267                                         if (PSXMu8(addr) == (u8)val)
268                                                 j++; // skip the next code
269                                         break;
270
271                                 case CHEAT_LESSTHAN8:
272                                         if (PSXMu8(addr) >= (u8)val)
273                                                 j++; // skip the next code
274                                         break;
275
276                                 case CHEAT_GREATERTHAN8:
277                                         if (PSXMu8(addr) <= (u8)val)
278                                                 j++; // skip the next code
279                                         break;
280
281                                 case CHEAT_EQU16:
282                                         if (PSXMu16(addr) != val)
283                                                 j++; // skip the next code
284                                         break;
285
286                                 case CHEAT_NOTEQU16:
287                                         if (PSXMu16(addr) == val)
288                                                 j++; // skip the next code
289                                         break;
290
291                                 case CHEAT_LESSTHAN16:
292                                         if (PSXMu16(addr) >= val)
293                                                 j++; // skip the next code
294                                         break;
295
296                                 case CHEAT_GREATERTHAN16:
297                                         if (PSXMu16(addr) <= val)
298                                                 j++; // skip the next code
299                                         break;
300                         }
301                 }
302         }
303 }
304
305 int AddCheat(const char *descr, char *code) {
306         int c = 1;
307         char *p1, *p2;
308
309         if (NumCheats >= NumCheatsAllocated) {
310                 NumCheatsAllocated += ALLOC_INCREMENT;
311
312                 if (Cheats == NULL) {
313                         assert(NumCheats == 0);
314                         assert(NumCheatsAllocated == ALLOC_INCREMENT);
315                         Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated);
316                 }
317                 else {
318                         Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated);
319                 }
320         }
321
322         Cheats[NumCheats].Descr = strdup(descr[0] ? descr : _("(Untitled)"));
323         Cheats[NumCheats].Enabled = 0;
324         Cheats[NumCheats].First = NumCodes;
325         Cheats[NumCheats].n = 0;
326
327         p1 = code;
328         p2 = code;
329
330         while (c) {
331                 unsigned int t1, t2;
332
333                 while (*p2 != '\n' && *p2 != '\0')
334                         p2++;
335
336                 if (*p2 == '\0')
337                         c = 0;
338
339                 *p2 = '\0';
340                 p2++;
341
342                 t1 = 0;
343                 t2 = 0;
344                 sscanf(p1, "%x %x", &t1, &t2);
345
346                 if (t1 > 0x10000000) {
347                         if (NumCodes >= NumCodesAllocated) {
348                                 NumCodesAllocated += ALLOC_INCREMENT;
349
350                                 if (CheatCodes == NULL) {
351                                         assert(NumCodes == 0);
352                                         assert(NumCodesAllocated == ALLOC_INCREMENT);
353                                         CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
354                                 }
355                                 else {
356                                         CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
357                                 }
358                         }
359
360                         CheatCodes[NumCodes].Addr = t1;
361                         CheatCodes[NumCodes].Val = t2;
362                         NumCodes++;
363                         Cheats[NumCheats].n++;
364                 }
365
366                 p1 = p2;
367         }
368
369         if (Cheats[NumCheats].n == 0) {
370                 return -1;
371         }
372
373         NumCheats++;
374         return 0;
375 }
376
377 void RemoveCheat(int index) {
378         assert(index >= 0 && index < NumCheats);
379
380         free(Cheats[index].Descr);
381
382         while (index < NumCheats - 1) {
383                 Cheats[index] = Cheats[index + 1];
384                 index++;
385         }
386
387         NumCheats--;
388 }
389
390 int EditCheat(int index, const char *descr, char *code) {
391         int c = 1;
392         int prev = NumCodes;
393         char *p1, *p2;
394
395         assert(index >= 0 && index < NumCheats);
396
397         p1 = code;
398         p2 = code;
399
400         while (c) {
401                 unsigned int t1, t2;
402
403                 while (*p2 != '\n' && *p2 != '\0')
404                         p2++;
405
406                 if (*p2 == '\0')
407                         c = 0;
408
409                 *p2 = '\0';
410                 p2++;
411
412                 t1 = 0;
413                 t2 = 0;
414                 sscanf(p1, "%x %x", &t1, &t2);
415
416                 if (t1 > 0x10000000) {
417                         if (NumCodes >= NumCodesAllocated) {
418                                 NumCodesAllocated += ALLOC_INCREMENT;
419
420                                 if (CheatCodes == NULL) {
421                                         assert(NumCodes == 0);
422                                         assert(NumCodesAllocated == ALLOC_INCREMENT);
423                                         CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
424                                 }
425                                 else {
426                                         CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
427                                 }
428                         }
429
430                         CheatCodes[NumCodes].Addr = t1;
431                         CheatCodes[NumCodes].Val = t2;
432                         NumCodes++;
433                 }
434
435                 p1 = p2;
436         }
437
438         if (NumCodes == prev) {
439                 return -1;
440         }
441
442         free(Cheats[index].Descr);
443         Cheats[index].Descr = strdup(descr[0] ? descr : _("(Untitled)"));
444         Cheats[index].First = prev;
445         Cheats[index].n = NumCodes - prev;
446
447         return 0;
448 }
449
450 void FreeCheatSearchResults() {
451         if (SearchResults != NULL) {
452                 free(SearchResults);
453         }
454         SearchResults = NULL;
455
456         NumSearchResults = 0;
457         NumSearchResultsAllocated = 0;
458 }
459
460 void FreeCheatSearchMem() {
461         if (prevM != NULL) {
462                 free(prevM);
463         }
464         prevM = NULL;
465 }
466
467 void CheatSearchBackupMemory() {
468         if (prevM != NULL) {
469                 memcpy(prevM, psxM, 0x200000);
470         }
471 }
472
473 static void CheatSearchInitBackupMemory() {
474         if (prevM == NULL) {
475                 prevM = (s8 *)malloc(0x200000);
476                 CheatSearchBackupMemory();
477         }
478 }
479
480 static void CheatSearchAddResult(u32 addr) {
481         if (NumSearchResults >= NumSearchResultsAllocated) {
482                 NumSearchResultsAllocated += ALLOC_INCREMENT;
483
484                 if (SearchResults == NULL) {
485                         SearchResults = (u32 *)malloc(sizeof(u32) * NumSearchResultsAllocated);
486                 }
487                 else {
488                         SearchResults = (u32 *)realloc(SearchResults, sizeof(u32) * NumSearchResultsAllocated);
489                 }
490         }
491
492         SearchResults[NumSearchResults++] = addr;
493 }
494
495 void CheatSearchEqual8(u8 val) {
496         u32 i, j;
497
498         CheatSearchInitBackupMemory();
499
500         if (SearchResults == NULL) {
501                 // search the whole memory
502                 for (i = 0; i < 0x200000; i++) {
503                         if (PSXMu8(i) == val) {
504                                 CheatSearchAddResult(i);
505                         }
506                 }
507         }
508         else {
509                 // only search within the previous results
510                 j = 0;
511
512                 for (i = 0; i < NumSearchResults; i++) {
513                         if (PSXMu8(SearchResults[i]) == val) {
514                                 SearchResults[j++] = SearchResults[i];
515                         }
516                 }
517
518                 NumSearchResults = j;
519         }
520 }
521
522 void CheatSearchEqual16(u16 val) {
523         u32 i, j;
524
525         CheatSearchInitBackupMemory();
526
527         if (SearchResults == NULL) {
528                 // search the whole memory
529                 for (i = 0; i < 0x200000; i += 2) {
530                         if (PSXMu16(i) == val) {
531                                 CheatSearchAddResult(i);
532                         }
533                 }
534         }
535         else {
536                 // only search within the previous results
537                 j = 0;
538
539                 for (i = 0; i < NumSearchResults; i++) {
540                         if (PSXMu16(SearchResults[i]) == val) {
541                                 SearchResults[j++] = SearchResults[i];
542                         }
543                 }
544
545                 NumSearchResults = j;
546         }
547 }
548
549 void CheatSearchEqual32(u32 val) {
550         u32 i, j;
551
552         CheatSearchInitBackupMemory();
553
554         if (SearchResults == NULL) {
555                 // search the whole memory
556                 for (i = 0; i < 0x200000; i += 4) {
557                         if (PSXMu32(i) == val) {
558                                 CheatSearchAddResult(i);
559                         }
560                 }
561         }
562         else {
563                 // only search within the previous results
564                 j = 0;
565
566                 for (i = 0; i < NumSearchResults; i++) {
567                         if (PSXMu32(SearchResults[i]) == val) {
568                                 SearchResults[j++] = SearchResults[i];
569                         }
570                 }
571
572                 NumSearchResults = j;
573         }
574 }
575
576 void CheatSearchNotEqual8(u8 val) {
577         u32 i, j;
578
579         CheatSearchInitBackupMemory();
580
581         if (SearchResults == NULL) {
582                 // search the whole memory
583                 for (i = 0; i < 0x200000; i++) {
584                         if (PSXMu8(i) != val) {
585                                 CheatSearchAddResult(i);
586                         }
587                 }
588         }
589         else {
590                 // only search within the previous results
591                 j = 0;
592
593                 for (i = 0; i < NumSearchResults; i++) {
594                         if (PSXMu8(SearchResults[i]) != val) {
595                                 SearchResults[j++] = SearchResults[i];
596                         }
597                 }
598
599                 NumSearchResults = j;
600         }
601 }
602
603 void CheatSearchNotEqual16(u16 val) {
604         u32 i, j;
605
606         CheatSearchInitBackupMemory();
607
608         if (SearchResults == NULL) {
609                 // search the whole memory
610                 for (i = 0; i < 0x200000; i += 2) {
611                         if (PSXMu16(i) != val) {
612                                 CheatSearchAddResult(i);
613                         }
614                 }
615         }
616         else {
617                 // only search within the previous results
618                 j = 0;
619
620                 for (i = 0; i < NumSearchResults; i++) {
621                         if (PSXMu16(SearchResults[i]) != val) {
622                                 SearchResults[j++] = SearchResults[i];
623                         }
624                 }
625
626                 NumSearchResults = j;
627         }
628 }
629
630 void CheatSearchNotEqual32(u32 val) {
631         u32 i, j;
632
633         CheatSearchInitBackupMemory();
634
635         if (SearchResults == NULL) {
636                 // search the whole memory
637                 for (i = 0; i < 0x200000; i += 4) {
638                         if (PSXMu32(i) != val) {
639                                 CheatSearchAddResult(i);
640                         }
641                 }
642         }
643         else {
644                 // only search within the previous results
645                 j = 0;
646
647                 for (i = 0; i < NumSearchResults; i++) {
648                         if (PSXMu32(SearchResults[i]) != val) {
649                                 SearchResults[j++] = SearchResults[i];
650                         }
651                 }
652
653                 NumSearchResults = j;
654         }
655 }
656
657 void CheatSearchRange8(u8 min, u8 max) {
658         u32 i, j;
659
660         CheatSearchInitBackupMemory();
661
662         if (SearchResults == NULL) {
663                 // search the whole memory
664                 for (i = 0; i < 0x200000; i++) {
665                         if (PSXMu8(i) >= min && PSXMu8(i) <= max) {
666                                 CheatSearchAddResult(i);
667                         }
668                 }
669         }
670         else {
671                 // only search within the previous results
672                 j = 0;
673
674                 for (i = 0; i < NumSearchResults; i++) {
675                         if (PSXMu8(SearchResults[i]) >= min && PSXMu8(SearchResults[i]) <= max) {
676                                 SearchResults[j++] = SearchResults[i];
677                         }
678                 }
679
680                 NumSearchResults = j;
681         }
682 }
683
684 void CheatSearchRange16(u16 min, u16 max) {
685         u32 i, j;
686
687         CheatSearchInitBackupMemory();
688
689         if (SearchResults == NULL) {
690                 // search the whole memory
691                 for (i = 0; i < 0x200000; i += 2) {
692                         if (PSXMu16(i) >= min && PSXMu16(i) <= max) {
693                                 CheatSearchAddResult(i);
694                         }
695                 }
696         }
697         else {
698                 // only search within the previous results
699                 j = 0;
700
701                 for (i = 0; i < NumSearchResults; i++) {
702                         if (PSXMu16(SearchResults[i]) >= min && PSXMu16(SearchResults[i]) <= max) {
703                                 SearchResults[j++] = SearchResults[i];
704                         }
705                 }
706
707                 NumSearchResults = j;
708         }
709 }
710
711 void CheatSearchRange32(u32 min, u32 max) {
712         u32 i, j;
713
714         CheatSearchInitBackupMemory();
715
716         if (SearchResults == NULL) {
717                 // search the whole memory
718                 for (i = 0; i < 0x200000; i += 4) {
719                         if (PSXMu32(i) >= min && PSXMu32(i) <= max) {
720                                 CheatSearchAddResult(i);
721                         }
722                 }
723         }
724         else {
725                 // only search within the previous results
726                 j = 0;
727
728                 for (i = 0; i < NumSearchResults; i++) {
729                         if (PSXMu32(SearchResults[i]) >= min && PSXMu32(SearchResults[i]) <= max) {
730                                 SearchResults[j++] = SearchResults[i];
731                         }
732                 }
733
734                 NumSearchResults = j;
735         }
736 }
737
738 void CheatSearchIncreasedBy8(u8 val) {
739         u32 i, j;
740
741         assert(prevM != NULL); // not possible for the first search
742
743         j = 0;
744
745         for (i = 0; i < NumSearchResults; i++) {
746                 if (PSXMu8(SearchResults[i]) - PrevMu8(SearchResults[i]) == val) {
747                         SearchResults[j++] = SearchResults[i];
748                 }
749         }
750
751         NumSearchResults = j;
752 }
753
754 void CheatSearchIncreasedBy16(u16 val) {
755         u32 i, j;
756
757         assert(prevM != NULL); // not possible for the first search
758
759         j = 0;
760
761         for (i = 0; i < NumSearchResults; i++) {
762                 if (PSXMu16(SearchResults[i]) - PrevMu16(SearchResults[i]) == val) {
763                         SearchResults[j++] = SearchResults[i];
764                 }
765         }
766
767         NumSearchResults = j;
768 }
769
770 void CheatSearchIncreasedBy32(u32 val) {
771         u32 i, j;
772
773         assert(prevM != NULL); // not possible for the first search
774
775         j = 0;
776
777         for (i = 0; i < NumSearchResults; i++) {
778                 if (PSXMu32(SearchResults[i]) - PrevMu32(SearchResults[i]) == val) {
779                         SearchResults[j++] = SearchResults[i];
780                 }
781         }
782
783         NumSearchResults = j;
784 }
785
786 void CheatSearchDecreasedBy8(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 (PrevMu8(SearchResults[i]) - PSXMu8(SearchResults[i]) == val) {
795                         SearchResults[j++] = SearchResults[i];
796                 }
797         }
798
799         NumSearchResults = j;
800 }
801
802 void CheatSearchDecreasedBy16(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 (PrevMu16(SearchResults[i]) - PSXMu16(SearchResults[i]) == val) {
811                         SearchResults[j++] = SearchResults[i];
812                 }
813         }
814
815         NumSearchResults = j;
816 }
817
818 void CheatSearchDecreasedBy32(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 (PrevMu32(SearchResults[i]) - PSXMu32(SearchResults[i]) == val) {
827                         SearchResults[j++] = SearchResults[i];
828                 }
829         }
830
831         NumSearchResults = j;
832 }
833
834 void CheatSearchIncreased8() {
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])) {
843                         SearchResults[j++] = SearchResults[i];
844                 }
845         }
846
847         NumSearchResults = j;
848 }
849
850 void CheatSearchIncreased16() {
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])) {
859                         SearchResults[j++] = SearchResults[i];
860                 }
861         }
862
863         NumSearchResults = j;
864 }
865
866 void CheatSearchIncreased32() {
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])) {
875                         SearchResults[j++] = SearchResults[i];
876                 }
877         }
878
879         NumSearchResults = j;
880 }
881
882 void CheatSearchDecreased8() {
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 CheatSearchDecreased16() {
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 CheatSearchDecreased32() {
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 CheatSearchDifferent8() {
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 CheatSearchDifferent16() {
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 CheatSearchDifferent32() {
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 CheatSearchNoChange8() {
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 CheatSearchNoChange16() {
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 CheatSearchNoChange32() {
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 }