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