1 /* Cheat Support for PCSX-Reloaded
2 * Copyright (c) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>.
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.
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.
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
21 #include "psxcommon.h"
25 #include "../frontend/plugin_lib.h" // in_keystate for D4
31 int NumCheatsAllocated = 0;
33 CheatCode *CheatCodes = NULL;
35 int NumCodesAllocated = 0;
37 #define ALLOC_INCREMENT 16
39 void ClearAllCheats() {
43 for (i = 0; i < NumCheats; i++) {
44 free(Cheats[i].Descr);
51 NumCheatsAllocated = 0;
53 if (CheatCodes != NULL) {
59 NumCodesAllocated = 0;
62 // load cheats from the specific filename
63 void LoadCheats(const char *filename) {
69 fp = fopen(filename, "r");
76 while (fgets(buf, 255, fp) != NULL) {
80 // Skip comment or blank lines
81 if (buf[0] == '#' || buf[0] == ';' || buf[0] == '/' || buf[0] == '\"' || buf[0] == '\0')
84 if (buf[0] == '[' && buf[strlen(buf) - 1] == ']') {
86 Cheats[NumCheats - 1].n = count;
88 if (NumCheats >= NumCheatsAllocated) {
89 NumCheatsAllocated += ALLOC_INCREMENT;
92 assert(NumCheats == 0);
93 assert(NumCheatsAllocated == ALLOC_INCREMENT);
94 Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated);
96 Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated);
100 buf[strlen(buf) - 1] = '\0';
104 Cheats[NumCheats].Descr = strdup(buf + 2);
105 Cheats[NumCheats].Enabled = 1;
107 Cheats[NumCheats].Descr = strdup(buf + 1);
108 Cheats[NumCheats].Enabled = 0;
110 Cheats[NumCheats].WasEnabled = 0;
112 Cheats[NumCheats].First = NumCodes;
121 if (NumCodes >= NumCodesAllocated) {
122 NumCodesAllocated += ALLOC_INCREMENT;
124 if (CheatCodes == NULL) {
125 assert(NumCodes == 0);
126 assert(NumCodesAllocated == ALLOC_INCREMENT);
127 CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
129 CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
133 sscanf(buf, "%x %x", &t1, &t2);
135 CheatCodes[NumCodes].Addr = t1;
136 CheatCodes[NumCodes].Val = t2;
143 Cheats[NumCheats - 1].n = count;
147 SysPrintf(_("Cheats loaded from: %s\n"), filename);
150 // save all cheats to the specified filename
151 void SaveCheats(const char *filename) {
155 fp = fopen(filename, "w");
160 for (i = 0; i < NumCheats; i++) {
161 // write the description
162 if (Cheats[i].Enabled)
163 fprintf(fp, "[*%s]\n", Cheats[i].Descr);
165 fprintf(fp, "[%s]\n", Cheats[i].Descr);
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);
179 SysPrintf(_("Cheats saved to: %s\n"), filename);
182 // apply all enabled cheats
184 int i, j, k, endindex;
187 for (i = 0; i < NumCheats; i++) {
188 was_enabled = Cheats[i].WasEnabled;
189 if (!Cheats[i].Enabled) {
190 if (!Cheats[i].WasEnabled)
193 Cheats[i].WasEnabled = Cheats[i].Enabled;
195 // process all cheat codes
196 endindex = Cheats[i].First + Cheats[i].n;
198 for (j = Cheats[i].First; j < endindex; j++) {
199 u8 type = (uint8_t)(CheatCodes[j].Addr >> 24);
200 u32 addr = (CheatCodes[j].Addr & 0x001FFFFF);
201 u16 val = CheatCodes[j].Val;
207 CheatCodes[j].OldVal = psxMu16(addr);
210 CheatCodes[j].OldVal = psxMu8(addr);
214 else if (!Cheats[i].Enabled) {
215 val = CheatCodes[j].OldVal;
216 if (type != CHEAT_CONST16 && type != CHEAT_CONST8)
222 psxMu8ref(addr) = (u8)val;
226 psxMu16ref(addr) = SWAPu16(val);
229 case CHEAT_SCRATCHPAD16: // 1F
230 psxHu16ref(addr) = SWAPu16(val);
234 psxMu16ref(addr) = SWAPu16(psxMu16(addr) + val);
238 psxMu16ref(addr) = SWAPu16(psxMu16(addr) - val);
242 psxMu8ref(addr) += (u8)val;
246 psxMu8ref(addr) -= (u8)val;
254 type = (uint8_t)(CheatCodes[j].Addr >> 24);
255 taddr = (CheatCodes[j].Addr & 0x001FFFFF);
256 val = CheatCodes[j].Val;
258 if (type == CHEAT_CONST8) {
259 for (k = 0; k < ((addr >> 8) & 0xFF); k++) {
260 psxMu8ref(taddr) = (u8)val;
261 taddr += (s8)(addr & 0xFF);
262 val += (s8)(CheatCodes[j - 1].Val & 0xFF);
265 else if (type == CHEAT_CONST16) {
266 for (k = 0; k < ((addr >> 8) & 0xFF); k++) {
267 psxMu16ref(taddr) = SWAPu16(val);
268 taddr += (s8)(addr & 0xFF);
269 val += (s8)(CheatCodes[j - 1].Val & 0xFF);
279 taddr = (CheatCodes[j].Addr & 0x001FFFFF);
280 for (k = 0; k < val; k++) {
281 psxMu8ref(taddr + k) = PSXMu8(addr + k);
286 if (PSXMu8(addr) != (u8)val)
287 j++; // skip the next code
291 if (PSXMu8(addr) == (u8)val)
292 j++; // skip the next code
295 case CHEAT_LESSTHAN8:
296 if (PSXMu8(addr) >= (u8)val)
297 j++; // skip the next code
300 case CHEAT_GREATERTHAN8:
301 if (PSXMu8(addr) <= (u8)val)
302 j++; // skip the next code
306 if (PSXMu16(addr) != val)
307 j++; // skip the next code
311 if (PSXMu16(addr) == val)
312 j++; // skip the next code
315 case CHEAT_LESSTHAN16:
316 if (PSXMu16(addr) >= val)
317 j++; // skip the next code
320 case CHEAT_GREATERTHAN16:
321 if (PSXMu16(addr) <= val)
322 j++; // skip the next code
325 case CHEAT_BUTTONS1_16: { // D4
326 u16 keys = in_keystate[0];
327 keys = (keys << 8) | (keys >> 8);
329 j++; // skip the next code
334 SysPrintf("unhandled cheat %d,%d code %08X\n",
335 i, j, CheatCodes[j].Addr);
336 Cheats[i].WasEnabled = Cheats[i].Enabled = 0;
343 int AddCheat(const char *descr, char *code) {
347 if (NumCheats >= NumCheatsAllocated) {
348 NumCheatsAllocated += ALLOC_INCREMENT;
350 if (Cheats == NULL) {
351 assert(NumCheats == 0);
352 assert(NumCheatsAllocated == ALLOC_INCREMENT);
353 Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated);
356 Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated);
360 Cheats[NumCheats].Enabled = 0;
361 Cheats[NumCheats].WasEnabled = 0;
362 Cheats[NumCheats].First = NumCodes;
363 Cheats[NumCheats].n = 0;
369 unsigned int t1, t2, r;
371 while (*p2 != '\n' && *p2 != '\0')
382 r = sscanf(p1, "%x %x", &t1, &t2);
385 SysPrintf("cheat %d: couldn't parse '%s'\n", NumCodes, p1);
386 else if (t1 >= 0x10000000) {
387 if (NumCodes >= NumCodesAllocated) {
388 NumCodesAllocated += ALLOC_INCREMENT;
390 if (CheatCodes == NULL) {
391 assert(NumCodes == 0);
392 assert(NumCodesAllocated == ALLOC_INCREMENT);
393 CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
396 CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
400 CheatCodes[NumCodes].Addr = t1;
401 CheatCodes[NumCodes].Val = t2;
403 Cheats[NumCheats].n++;
409 if (Cheats[NumCheats].n == 0) {
413 Cheats[NumCheats].Descr = strdup(descr[0] ? descr : _("(Untitled)"));
418 void RemoveCheat(int index) {
419 assert(index >= 0 && index < NumCheats);
421 free(Cheats[index].Descr);
422 Cheats[index].Descr = NULL;
424 while (index < NumCheats - 1) {
425 Cheats[index] = Cheats[index + 1];
432 int EditCheat(int index, const char *descr, char *code) {
437 assert(index >= 0 && index < NumCheats);
445 while (*p2 != '\n' && *p2 != '\0')
456 sscanf(p1, "%x %x", &t1, &t2);
458 if (t1 > 0x10000000) {
459 if (NumCodes >= NumCodesAllocated) {
460 NumCodesAllocated += ALLOC_INCREMENT;
462 if (CheatCodes == NULL) {
463 assert(NumCodes == 0);
464 assert(NumCodesAllocated == ALLOC_INCREMENT);
465 CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
468 CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
472 CheatCodes[NumCodes].Addr = t1;
473 CheatCodes[NumCodes].Val = t2;
480 if (NumCodes == prev) {
484 free(Cheats[index].Descr);
485 Cheats[index].Descr = strdup(descr[0] ? descr : _("(Untitled)"));
486 Cheats[index].First = prev;
487 Cheats[index].n = NumCodes - prev;
493 static int NumSearchResultsAllocated = 0;
494 int NumSearchResults = 0;
495 u32 *SearchResults = NULL;
498 void FreeCheatSearchResults() {
499 if (SearchResults != NULL) {
502 SearchResults = NULL;
504 NumSearchResults = 0;
505 NumSearchResultsAllocated = 0;
508 void FreeCheatSearchMem() {
515 void CheatSearchBackupMemory() {
517 memcpy(prevM, psxRegs.ptrs.psxM, 0x200000);
521 static void CheatSearchInitBackupMemory() {
523 prevM = (s8 *)malloc(0x200000);
524 CheatSearchBackupMemory();
528 static void CheatSearchAddResult(u32 addr) {
529 if (NumSearchResults >= NumSearchResultsAllocated) {
530 NumSearchResultsAllocated += ALLOC_INCREMENT;
532 if (SearchResults == NULL) {
533 SearchResults = (u32 *)malloc(sizeof(u32) * NumSearchResultsAllocated);
536 SearchResults = (u32 *)realloc(SearchResults, sizeof(u32) * NumSearchResultsAllocated);
540 SearchResults[NumSearchResults++] = addr;
543 void CheatSearchEqual8(u8 val) {
546 CheatSearchInitBackupMemory();
548 if (SearchResults == NULL) {
549 // search the whole memory
550 for (i = 0; i < 0x200000; i++) {
551 if (PSXMu8(i) == val) {
552 CheatSearchAddResult(i);
557 // only search within the previous results
560 for (i = 0; i < NumSearchResults; i++) {
561 if (PSXMu8(SearchResults[i]) == val) {
562 SearchResults[j++] = SearchResults[i];
566 NumSearchResults = j;
570 void CheatSearchEqual16(u16 val) {
573 CheatSearchInitBackupMemory();
575 if (SearchResults == NULL) {
576 // search the whole memory
577 for (i = 0; i < 0x200000; i += 2) {
578 if (PSXMu16(i) == val) {
579 CheatSearchAddResult(i);
584 // only search within the previous results
587 for (i = 0; i < NumSearchResults; i++) {
588 if (PSXMu16(SearchResults[i]) == val) {
589 SearchResults[j++] = SearchResults[i];
593 NumSearchResults = j;
597 void CheatSearchEqual32(u32 val) {
600 CheatSearchInitBackupMemory();
602 if (SearchResults == NULL) {
603 // search the whole memory
604 for (i = 0; i < 0x200000; i += 4) {
605 if (PSXMu32(i) == val) {
606 CheatSearchAddResult(i);
611 // only search within the previous results
614 for (i = 0; i < NumSearchResults; i++) {
615 if (PSXMu32(SearchResults[i]) == val) {
616 SearchResults[j++] = SearchResults[i];
620 NumSearchResults = j;
624 void CheatSearchNotEqual8(u8 val) {
627 CheatSearchInitBackupMemory();
629 if (SearchResults == NULL) {
630 // search the whole memory
631 for (i = 0; i < 0x200000; i++) {
632 if (PSXMu8(i) != val) {
633 CheatSearchAddResult(i);
638 // only search within the previous results
641 for (i = 0; i < NumSearchResults; i++) {
642 if (PSXMu8(SearchResults[i]) != val) {
643 SearchResults[j++] = SearchResults[i];
647 NumSearchResults = j;
651 void CheatSearchNotEqual16(u16 val) {
654 CheatSearchInitBackupMemory();
656 if (SearchResults == NULL) {
657 // search the whole memory
658 for (i = 0; i < 0x200000; i += 2) {
659 if (PSXMu16(i) != val) {
660 CheatSearchAddResult(i);
665 // only search within the previous results
668 for (i = 0; i < NumSearchResults; i++) {
669 if (PSXMu16(SearchResults[i]) != val) {
670 SearchResults[j++] = SearchResults[i];
674 NumSearchResults = j;
678 void CheatSearchNotEqual32(u32 val) {
681 CheatSearchInitBackupMemory();
683 if (SearchResults == NULL) {
684 // search the whole memory
685 for (i = 0; i < 0x200000; i += 4) {
686 if (PSXMu32(i) != val) {
687 CheatSearchAddResult(i);
692 // only search within the previous results
695 for (i = 0; i < NumSearchResults; i++) {
696 if (PSXMu32(SearchResults[i]) != val) {
697 SearchResults[j++] = SearchResults[i];
701 NumSearchResults = j;
705 void CheatSearchRange8(u8 min, u8 max) {
708 CheatSearchInitBackupMemory();
710 if (SearchResults == NULL) {
711 // search the whole memory
712 for (i = 0; i < 0x200000; i++) {
713 if (PSXMu8(i) >= min && PSXMu8(i) <= max) {
714 CheatSearchAddResult(i);
719 // only search within the previous results
722 for (i = 0; i < NumSearchResults; i++) {
723 if (PSXMu8(SearchResults[i]) >= min && PSXMu8(SearchResults[i]) <= max) {
724 SearchResults[j++] = SearchResults[i];
728 NumSearchResults = j;
732 void CheatSearchRange16(u16 min, u16 max) {
735 CheatSearchInitBackupMemory();
737 if (SearchResults == NULL) {
738 // search the whole memory
739 for (i = 0; i < 0x200000; i += 2) {
740 if (PSXMu16(i) >= min && PSXMu16(i) <= max) {
741 CheatSearchAddResult(i);
746 // only search within the previous results
749 for (i = 0; i < NumSearchResults; i++) {
750 if (PSXMu16(SearchResults[i]) >= min && PSXMu16(SearchResults[i]) <= max) {
751 SearchResults[j++] = SearchResults[i];
755 NumSearchResults = j;
759 void CheatSearchRange32(u32 min, u32 max) {
762 CheatSearchInitBackupMemory();
764 if (SearchResults == NULL) {
765 // search the whole memory
766 for (i = 0; i < 0x200000; i += 4) {
767 if (PSXMu32(i) >= min && PSXMu32(i) <= max) {
768 CheatSearchAddResult(i);
773 // only search within the previous results
776 for (i = 0; i < NumSearchResults; i++) {
777 if (PSXMu32(SearchResults[i]) >= min && PSXMu32(SearchResults[i]) <= max) {
778 SearchResults[j++] = SearchResults[i];
782 NumSearchResults = j;
786 void CheatSearchIncreasedBy8(u8 val) {
789 assert(prevM != NULL); // not possible for the first search
793 for (i = 0; i < NumSearchResults; i++) {
794 if (PSXMu8(SearchResults[i]) - PrevMu8(SearchResults[i]) == val) {
795 SearchResults[j++] = SearchResults[i];
799 NumSearchResults = j;
802 void CheatSearchIncreasedBy16(u16 val) {
805 assert(prevM != NULL); // not possible for the first search
809 for (i = 0; i < NumSearchResults; i++) {
810 if (PSXMu16(SearchResults[i]) - PrevMu16(SearchResults[i]) == val) {
811 SearchResults[j++] = SearchResults[i];
815 NumSearchResults = j;
818 void CheatSearchIncreasedBy32(u32 val) {
821 assert(prevM != NULL); // not possible for the first search
825 for (i = 0; i < NumSearchResults; i++) {
826 if (PSXMu32(SearchResults[i]) - PrevMu32(SearchResults[i]) == val) {
827 SearchResults[j++] = SearchResults[i];
831 NumSearchResults = j;
834 void CheatSearchDecreasedBy8(u8 val) {
837 assert(prevM != NULL); // not possible for the first search
841 for (i = 0; i < NumSearchResults; i++) {
842 if (PrevMu8(SearchResults[i]) - PSXMu8(SearchResults[i]) == val) {
843 SearchResults[j++] = SearchResults[i];
847 NumSearchResults = j;
850 void CheatSearchDecreasedBy16(u16 val) {
853 assert(prevM != NULL); // not possible for the first search
857 for (i = 0; i < NumSearchResults; i++) {
858 if (PrevMu16(SearchResults[i]) - PSXMu16(SearchResults[i]) == val) {
859 SearchResults[j++] = SearchResults[i];
863 NumSearchResults = j;
866 void CheatSearchDecreasedBy32(u32 val) {
869 assert(prevM != NULL); // not possible for the first search
873 for (i = 0; i < NumSearchResults; i++) {
874 if (PrevMu32(SearchResults[i]) - PSXMu32(SearchResults[i]) == val) {
875 SearchResults[j++] = SearchResults[i];
879 NumSearchResults = j;
882 void CheatSearchIncreased8() {
885 assert(prevM != NULL); // not possible for the first search
889 for (i = 0; i < NumSearchResults; i++) {
890 if (PrevMu8(SearchResults[i]) < PSXMu8(SearchResults[i])) {
891 SearchResults[j++] = SearchResults[i];
895 NumSearchResults = j;
898 void CheatSearchIncreased16() {
901 assert(prevM != NULL); // not possible for the first search
905 for (i = 0; i < NumSearchResults; i++) {
906 if (PrevMu16(SearchResults[i]) < PSXMu16(SearchResults[i])) {
907 SearchResults[j++] = SearchResults[i];
911 NumSearchResults = j;
914 void CheatSearchIncreased32() {
917 assert(prevM != NULL); // not possible for the first search
921 for (i = 0; i < NumSearchResults; i++) {
922 if (PrevMu32(SearchResults[i]) < PSXMu32(SearchResults[i])) {
923 SearchResults[j++] = SearchResults[i];
927 NumSearchResults = j;
930 void CheatSearchDecreased8() {
933 assert(prevM != NULL); // not possible for the first search
937 for (i = 0; i < NumSearchResults; i++) {
938 if (PrevMu8(SearchResults[i]) > PSXMu8(SearchResults[i])) {
939 SearchResults[j++] = SearchResults[i];
943 NumSearchResults = j;
946 void CheatSearchDecreased16() {
949 assert(prevM != NULL); // not possible for the first search
953 for (i = 0; i < NumSearchResults; i++) {
954 if (PrevMu16(SearchResults[i]) > PSXMu16(SearchResults[i])) {
955 SearchResults[j++] = SearchResults[i];
959 NumSearchResults = j;
962 void CheatSearchDecreased32() {
965 assert(prevM != NULL); // not possible for the first search
969 for (i = 0; i < NumSearchResults; i++) {
970 if (PrevMu32(SearchResults[i]) > PSXMu32(SearchResults[i])) {
971 SearchResults[j++] = SearchResults[i];
975 NumSearchResults = j;
978 void CheatSearchDifferent8() {
981 assert(prevM != NULL); // not possible for the first search
985 for (i = 0; i < NumSearchResults; i++) {
986 if (PrevMu8(SearchResults[i]) != PSXMu8(SearchResults[i])) {
987 SearchResults[j++] = SearchResults[i];
991 NumSearchResults = j;
994 void CheatSearchDifferent16() {
997 assert(prevM != NULL); // not possible for the first search
1001 for (i = 0; i < NumSearchResults; i++) {
1002 if (PrevMu16(SearchResults[i]) != PSXMu16(SearchResults[i])) {
1003 SearchResults[j++] = SearchResults[i];
1007 NumSearchResults = j;
1010 void CheatSearchDifferent32() {
1013 assert(prevM != NULL); // not possible for the first search
1017 for (i = 0; i < NumSearchResults; i++) {
1018 if (PrevMu32(SearchResults[i]) != PSXMu32(SearchResults[i])) {
1019 SearchResults[j++] = SearchResults[i];
1023 NumSearchResults = j;
1026 void CheatSearchNoChange8() {
1029 assert(prevM != NULL); // not possible for the first search
1033 for (i = 0; i < NumSearchResults; i++) {
1034 if (PrevMu8(SearchResults[i]) == PSXMu8(SearchResults[i])) {
1035 SearchResults[j++] = SearchResults[i];
1039 NumSearchResults = j;
1042 void CheatSearchNoChange16() {
1045 assert(prevM != NULL); // not possible for the first search
1049 for (i = 0; i < NumSearchResults; i++) {
1050 if (PrevMu16(SearchResults[i]) == PSXMu16(SearchResults[i])) {
1051 SearchResults[j++] = SearchResults[i];
1055 NumSearchResults = j;
1058 void CheatSearchNoChange32() {
1061 assert(prevM != NULL); // not possible for the first search
1065 for (i = 0; i < NumSearchResults; i++) {
1066 if (PrevMu32(SearchResults[i]) == PSXMu32(SearchResults[i])) {
1067 SearchResults[j++] = SearchResults[i];
1071 NumSearchResults = j;