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
19 #include "psxcommon.h"
27 int NumCheatsAllocated = 0;
29 CheatCode *CheatCodes = NULL;
31 int NumCodesAllocated = 0;
34 u32 *SearchResults = NULL;
35 int NumSearchResults = 0;
36 static int NumSearchResultsAllocated = 0;
38 #define ALLOC_INCREMENT 100
40 void ClearAllCheats() {
44 for (i = 0; i < NumCheats; i++) {
45 free(Cheats[i].Descr);
52 NumCheatsAllocated = 0;
54 if (CheatCodes != NULL) {
60 NumCodesAllocated = 0;
63 // load cheats from the specific filename
64 void LoadCheats(const char *filename) {
70 fp = fopen(filename, "r");
77 while (fgets(buf, 255, fp) != NULL) {
81 // Skip comment or blank lines
82 if (buf[0] == '#' || buf[0] == ';' || buf[0] == '/' || buf[0] == '\"' || buf[0] == '\0')
85 if (buf[0] == '[' && buf[strlen(buf) - 1] == ']') {
87 Cheats[NumCheats - 1].n = count;
89 if (NumCheats >= NumCheatsAllocated) {
90 NumCheatsAllocated += ALLOC_INCREMENT;
93 assert(NumCheats == 0);
94 assert(NumCheatsAllocated == ALLOC_INCREMENT);
95 Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated);
97 Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated);
101 buf[strlen(buf) - 1] = '\0';
105 Cheats[NumCheats].Descr = strdup(buf + 2);
106 Cheats[NumCheats].Enabled = 1;
108 Cheats[NumCheats].Descr = strdup(buf + 1);
109 Cheats[NumCheats].Enabled = 0;
111 Cheats[NumCheats].WasEnabled = 0;
113 Cheats[NumCheats].First = NumCodes;
122 if (NumCodes >= NumCodesAllocated) {
123 NumCodesAllocated += ALLOC_INCREMENT;
125 if (CheatCodes == NULL) {
126 assert(NumCodes == 0);
127 assert(NumCodesAllocated == ALLOC_INCREMENT);
128 CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
130 CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
134 sscanf(buf, "%x %x", &t1, &t2);
136 CheatCodes[NumCodes].Addr = t1;
137 CheatCodes[NumCodes].Val = t2;
144 Cheats[NumCheats - 1].n = count;
148 SysPrintf(_("Cheats loaded from: %s\n"), filename);
151 // save all cheats to the specified filename
152 void SaveCheats(const char *filename) {
156 fp = fopen(filename, "w");
161 for (i = 0; i < NumCheats; i++) {
162 // write the description
163 if (Cheats[i].Enabled)
164 fprintf(fp, "[*%s]\n", Cheats[i].Descr);
166 fprintf(fp, "[%s]\n", Cheats[i].Descr);
168 // write all cheat codes
169 for (j = 0; j < Cheats[i].n; j++) {
170 fprintf(fp, "%.8X %.4X\n",
171 CheatCodes[Cheats[i].First + j].Addr,
172 CheatCodes[Cheats[i].First + j].Val);
180 SysPrintf(_("Cheats saved to: %s\n"), filename);
183 // apply all enabled cheats
185 int i, j, k, endindex;
188 for (i = 0; i < NumCheats; i++) {
189 was_enabled = Cheats[i].WasEnabled;
190 if (!Cheats[i].Enabled) {
191 if (!Cheats[i].WasEnabled)
194 Cheats[i].WasEnabled = Cheats[i].Enabled;
196 // process all cheat codes
197 endindex = Cheats[i].First + Cheats[i].n;
199 for (j = Cheats[i].First; j < endindex; j++) {
200 u8 type = (uint8_t)(CheatCodes[j].Addr >> 24);
201 u32 addr = (CheatCodes[j].Addr & 0x001FFFFF);
202 u16 val = CheatCodes[j].Val;
208 CheatCodes[j].OldVal = psxMu16(addr);
211 CheatCodes[j].OldVal = psxMu8(addr);
215 else if (!Cheats[i].Enabled) {
216 val = CheatCodes[j].OldVal;
217 if (type != CHEAT_CONST16 && type != CHEAT_CONST8)
223 psxMu8ref(addr) = (u8)val;
227 psxMu16ref(addr) = SWAPu16(val);
231 psxMu16ref(addr) = SWAPu16(psxMu16(addr) + val);
235 psxMu16ref(addr) = SWAPu16(psxMu16(addr) - val);
239 psxMu8ref(addr) += (u8)val;
243 psxMu8ref(addr) -= (u8)val;
251 type = (uint8_t)(CheatCodes[j].Addr >> 24);
252 taddr = (CheatCodes[j].Addr & 0x001FFFFF);
253 val = CheatCodes[j].Val;
255 if (type == CHEAT_CONST8) {
256 for (k = 0; k < ((addr >> 8) & 0xFF); k++) {
257 psxMu8ref(taddr) = (u8)val;
258 taddr += (s8)(addr & 0xFF);
259 val += (s8)(CheatCodes[j - 1].Val & 0xFF);
262 else if (type == CHEAT_CONST16) {
263 for (k = 0; k < ((addr >> 8) & 0xFF); k++) {
264 psxMu16ref(taddr) = SWAPu16(val);
265 taddr += (s8)(addr & 0xFF);
266 val += (s8)(CheatCodes[j - 1].Val & 0xFF);
276 taddr = (CheatCodes[j].Addr & 0x001FFFFF);
277 for (k = 0; k < val; k++) {
278 psxMu8ref(taddr + k) = PSXMu8(addr + k);
283 if (PSXMu8(addr) != (u8)val)
284 j++; // skip the next code
288 if (PSXMu8(addr) == (u8)val)
289 j++; // skip the next code
292 case CHEAT_LESSTHAN8:
293 if (PSXMu8(addr) >= (u8)val)
294 j++; // skip the next code
297 case CHEAT_GREATERTHAN8:
298 if (PSXMu8(addr) <= (u8)val)
299 j++; // skip the next code
303 if (PSXMu16(addr) != val)
304 j++; // skip the next code
308 if (PSXMu16(addr) == val)
309 j++; // skip the next code
312 case CHEAT_LESSTHAN16:
313 if (PSXMu16(addr) >= val)
314 j++; // skip the next code
317 case CHEAT_GREATERTHAN16:
318 if (PSXMu16(addr) <= val)
319 j++; // skip the next code
326 int AddCheat(const char *descr, char *code) {
330 if (NumCheats >= NumCheatsAllocated) {
331 NumCheatsAllocated += ALLOC_INCREMENT;
333 if (Cheats == NULL) {
334 assert(NumCheats == 0);
335 assert(NumCheatsAllocated == ALLOC_INCREMENT);
336 Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated);
339 Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated);
343 Cheats[NumCheats].Enabled = 0;
344 Cheats[NumCheats].WasEnabled = 0;
345 Cheats[NumCheats].First = NumCodes;
346 Cheats[NumCheats].n = 0;
354 while (*p2 != '\n' && *p2 != '\0')
365 sscanf(p1, "%x %x", &t1, &t2);
367 if (t1 > 0x10000000) {
368 if (NumCodes >= NumCodesAllocated) {
369 NumCodesAllocated += ALLOC_INCREMENT;
371 if (CheatCodes == NULL) {
372 assert(NumCodes == 0);
373 assert(NumCodesAllocated == ALLOC_INCREMENT);
374 CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
377 CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
381 CheatCodes[NumCodes].Addr = t1;
382 CheatCodes[NumCodes].Val = t2;
384 Cheats[NumCheats].n++;
390 if (Cheats[NumCheats].n == 0) {
394 Cheats[NumCheats].Descr = strdup(descr[0] ? descr : _("(Untitled)"));
399 void RemoveCheat(int index) {
400 assert(index >= 0 && index < NumCheats);
402 free(Cheats[index].Descr);
403 Cheats[index].Descr = NULL;
405 while (index < NumCheats - 1) {
406 Cheats[index] = Cheats[index + 1];
413 int EditCheat(int index, const char *descr, char *code) {
418 assert(index >= 0 && index < NumCheats);
426 while (*p2 != '\n' && *p2 != '\0')
437 sscanf(p1, "%x %x", &t1, &t2);
439 if (t1 > 0x10000000) {
440 if (NumCodes >= NumCodesAllocated) {
441 NumCodesAllocated += ALLOC_INCREMENT;
443 if (CheatCodes == NULL) {
444 assert(NumCodes == 0);
445 assert(NumCodesAllocated == ALLOC_INCREMENT);
446 CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
449 CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
453 CheatCodes[NumCodes].Addr = t1;
454 CheatCodes[NumCodes].Val = t2;
461 if (NumCodes == prev) {
465 free(Cheats[index].Descr);
466 Cheats[index].Descr = strdup(descr[0] ? descr : _("(Untitled)"));
467 Cheats[index].First = prev;
468 Cheats[index].n = NumCodes - prev;
473 void FreeCheatSearchResults() {
474 if (SearchResults != NULL) {
477 SearchResults = NULL;
479 NumSearchResults = 0;
480 NumSearchResultsAllocated = 0;
483 void FreeCheatSearchMem() {
490 void CheatSearchBackupMemory() {
492 memcpy(prevM, psxM, 0x200000);
496 static void CheatSearchInitBackupMemory() {
498 prevM = (s8 *)malloc(0x200000);
499 CheatSearchBackupMemory();
503 static void CheatSearchAddResult(u32 addr) {
504 if (NumSearchResults >= NumSearchResultsAllocated) {
505 NumSearchResultsAllocated += ALLOC_INCREMENT;
507 if (SearchResults == NULL) {
508 SearchResults = (u32 *)malloc(sizeof(u32) * NumSearchResultsAllocated);
511 SearchResults = (u32 *)realloc(SearchResults, sizeof(u32) * NumSearchResultsAllocated);
515 SearchResults[NumSearchResults++] = addr;
518 void CheatSearchEqual8(u8 val) {
521 CheatSearchInitBackupMemory();
523 if (SearchResults == NULL) {
524 // search the whole memory
525 for (i = 0; i < 0x200000; i++) {
526 if (PSXMu8(i) == val) {
527 CheatSearchAddResult(i);
532 // only search within the previous results
535 for (i = 0; i < NumSearchResults; i++) {
536 if (PSXMu8(SearchResults[i]) == val) {
537 SearchResults[j++] = SearchResults[i];
541 NumSearchResults = j;
545 void CheatSearchEqual16(u16 val) {
548 CheatSearchInitBackupMemory();
550 if (SearchResults == NULL) {
551 // search the whole memory
552 for (i = 0; i < 0x200000; i += 2) {
553 if (PSXMu16(i) == val) {
554 CheatSearchAddResult(i);
559 // only search within the previous results
562 for (i = 0; i < NumSearchResults; i++) {
563 if (PSXMu16(SearchResults[i]) == val) {
564 SearchResults[j++] = SearchResults[i];
568 NumSearchResults = j;
572 void CheatSearchEqual32(u32 val) {
575 CheatSearchInitBackupMemory();
577 if (SearchResults == NULL) {
578 // search the whole memory
579 for (i = 0; i < 0x200000; i += 4) {
580 if (PSXMu32(i) == val) {
581 CheatSearchAddResult(i);
586 // only search within the previous results
589 for (i = 0; i < NumSearchResults; i++) {
590 if (PSXMu32(SearchResults[i]) == val) {
591 SearchResults[j++] = SearchResults[i];
595 NumSearchResults = j;
599 void CheatSearchNotEqual8(u8 val) {
602 CheatSearchInitBackupMemory();
604 if (SearchResults == NULL) {
605 // search the whole memory
606 for (i = 0; i < 0x200000; i++) {
607 if (PSXMu8(i) != val) {
608 CheatSearchAddResult(i);
613 // only search within the previous results
616 for (i = 0; i < NumSearchResults; i++) {
617 if (PSXMu8(SearchResults[i]) != val) {
618 SearchResults[j++] = SearchResults[i];
622 NumSearchResults = j;
626 void CheatSearchNotEqual16(u16 val) {
629 CheatSearchInitBackupMemory();
631 if (SearchResults == NULL) {
632 // search the whole memory
633 for (i = 0; i < 0x200000; i += 2) {
634 if (PSXMu16(i) != val) {
635 CheatSearchAddResult(i);
640 // only search within the previous results
643 for (i = 0; i < NumSearchResults; i++) {
644 if (PSXMu16(SearchResults[i]) != val) {
645 SearchResults[j++] = SearchResults[i];
649 NumSearchResults = j;
653 void CheatSearchNotEqual32(u32 val) {
656 CheatSearchInitBackupMemory();
658 if (SearchResults == NULL) {
659 // search the whole memory
660 for (i = 0; i < 0x200000; i += 4) {
661 if (PSXMu32(i) != val) {
662 CheatSearchAddResult(i);
667 // only search within the previous results
670 for (i = 0; i < NumSearchResults; i++) {
671 if (PSXMu32(SearchResults[i]) != val) {
672 SearchResults[j++] = SearchResults[i];
676 NumSearchResults = j;
680 void CheatSearchRange8(u8 min, u8 max) {
683 CheatSearchInitBackupMemory();
685 if (SearchResults == NULL) {
686 // search the whole memory
687 for (i = 0; i < 0x200000; i++) {
688 if (PSXMu8(i) >= min && PSXMu8(i) <= max) {
689 CheatSearchAddResult(i);
694 // only search within the previous results
697 for (i = 0; i < NumSearchResults; i++) {
698 if (PSXMu8(SearchResults[i]) >= min && PSXMu8(SearchResults[i]) <= max) {
699 SearchResults[j++] = SearchResults[i];
703 NumSearchResults = j;
707 void CheatSearchRange16(u16 min, u16 max) {
710 CheatSearchInitBackupMemory();
712 if (SearchResults == NULL) {
713 // search the whole memory
714 for (i = 0; i < 0x200000; i += 2) {
715 if (PSXMu16(i) >= min && PSXMu16(i) <= max) {
716 CheatSearchAddResult(i);
721 // only search within the previous results
724 for (i = 0; i < NumSearchResults; i++) {
725 if (PSXMu16(SearchResults[i]) >= min && PSXMu16(SearchResults[i]) <= max) {
726 SearchResults[j++] = SearchResults[i];
730 NumSearchResults = j;
734 void CheatSearchRange32(u32 min, u32 max) {
737 CheatSearchInitBackupMemory();
739 if (SearchResults == NULL) {
740 // search the whole memory
741 for (i = 0; i < 0x200000; i += 4) {
742 if (PSXMu32(i) >= min && PSXMu32(i) <= max) {
743 CheatSearchAddResult(i);
748 // only search within the previous results
751 for (i = 0; i < NumSearchResults; i++) {
752 if (PSXMu32(SearchResults[i]) >= min && PSXMu32(SearchResults[i]) <= max) {
753 SearchResults[j++] = SearchResults[i];
757 NumSearchResults = j;
761 void CheatSearchIncreasedBy8(u8 val) {
764 assert(prevM != NULL); // not possible for the first search
768 for (i = 0; i < NumSearchResults; i++) {
769 if (PSXMu8(SearchResults[i]) - PrevMu8(SearchResults[i]) == val) {
770 SearchResults[j++] = SearchResults[i];
774 NumSearchResults = j;
777 void CheatSearchIncreasedBy16(u16 val) {
780 assert(prevM != NULL); // not possible for the first search
784 for (i = 0; i < NumSearchResults; i++) {
785 if (PSXMu16(SearchResults[i]) - PrevMu16(SearchResults[i]) == val) {
786 SearchResults[j++] = SearchResults[i];
790 NumSearchResults = j;
793 void CheatSearchIncreasedBy32(u32 val) {
796 assert(prevM != NULL); // not possible for the first search
800 for (i = 0; i < NumSearchResults; i++) {
801 if (PSXMu32(SearchResults[i]) - PrevMu32(SearchResults[i]) == val) {
802 SearchResults[j++] = SearchResults[i];
806 NumSearchResults = j;
809 void CheatSearchDecreasedBy8(u8 val) {
812 assert(prevM != NULL); // not possible for the first search
816 for (i = 0; i < NumSearchResults; i++) {
817 if (PrevMu8(SearchResults[i]) - PSXMu8(SearchResults[i]) == val) {
818 SearchResults[j++] = SearchResults[i];
822 NumSearchResults = j;
825 void CheatSearchDecreasedBy16(u16 val) {
828 assert(prevM != NULL); // not possible for the first search
832 for (i = 0; i < NumSearchResults; i++) {
833 if (PrevMu16(SearchResults[i]) - PSXMu16(SearchResults[i]) == val) {
834 SearchResults[j++] = SearchResults[i];
838 NumSearchResults = j;
841 void CheatSearchDecreasedBy32(u32 val) {
844 assert(prevM != NULL); // not possible for the first search
848 for (i = 0; i < NumSearchResults; i++) {
849 if (PrevMu32(SearchResults[i]) - PSXMu32(SearchResults[i]) == val) {
850 SearchResults[j++] = SearchResults[i];
854 NumSearchResults = j;
857 void CheatSearchIncreased8() {
860 assert(prevM != NULL); // not possible for the first search
864 for (i = 0; i < NumSearchResults; i++) {
865 if (PrevMu8(SearchResults[i]) < PSXMu8(SearchResults[i])) {
866 SearchResults[j++] = SearchResults[i];
870 NumSearchResults = j;
873 void CheatSearchIncreased16() {
876 assert(prevM != NULL); // not possible for the first search
880 for (i = 0; i < NumSearchResults; i++) {
881 if (PrevMu16(SearchResults[i]) < PSXMu16(SearchResults[i])) {
882 SearchResults[j++] = SearchResults[i];
886 NumSearchResults = j;
889 void CheatSearchIncreased32() {
892 assert(prevM != NULL); // not possible for the first search
896 for (i = 0; i < NumSearchResults; i++) {
897 if (PrevMu32(SearchResults[i]) < PSXMu32(SearchResults[i])) {
898 SearchResults[j++] = SearchResults[i];
902 NumSearchResults = j;
905 void CheatSearchDecreased8() {
908 assert(prevM != NULL); // not possible for the first search
912 for (i = 0; i < NumSearchResults; i++) {
913 if (PrevMu8(SearchResults[i]) > PSXMu8(SearchResults[i])) {
914 SearchResults[j++] = SearchResults[i];
918 NumSearchResults = j;
921 void CheatSearchDecreased16() {
924 assert(prevM != NULL); // not possible for the first search
928 for (i = 0; i < NumSearchResults; i++) {
929 if (PrevMu16(SearchResults[i]) > PSXMu16(SearchResults[i])) {
930 SearchResults[j++] = SearchResults[i];
934 NumSearchResults = j;
937 void CheatSearchDecreased32() {
940 assert(prevM != NULL); // not possible for the first search
944 for (i = 0; i < NumSearchResults; i++) {
945 if (PrevMu32(SearchResults[i]) > PSXMu32(SearchResults[i])) {
946 SearchResults[j++] = SearchResults[i];
950 NumSearchResults = j;
953 void CheatSearchDifferent8() {
956 assert(prevM != NULL); // not possible for the first search
960 for (i = 0; i < NumSearchResults; i++) {
961 if (PrevMu8(SearchResults[i]) != PSXMu8(SearchResults[i])) {
962 SearchResults[j++] = SearchResults[i];
966 NumSearchResults = j;
969 void CheatSearchDifferent16() {
972 assert(prevM != NULL); // not possible for the first search
976 for (i = 0; i < NumSearchResults; i++) {
977 if (PrevMu16(SearchResults[i]) != PSXMu16(SearchResults[i])) {
978 SearchResults[j++] = SearchResults[i];
982 NumSearchResults = j;
985 void CheatSearchDifferent32() {
988 assert(prevM != NULL); // not possible for the first search
992 for (i = 0; i < NumSearchResults; i++) {
993 if (PrevMu32(SearchResults[i]) != PSXMu32(SearchResults[i])) {
994 SearchResults[j++] = SearchResults[i];
998 NumSearchResults = j;
1001 void CheatSearchNoChange8() {
1004 assert(prevM != NULL); // not possible for the first search
1008 for (i = 0; i < NumSearchResults; i++) {
1009 if (PrevMu8(SearchResults[i]) == PSXMu8(SearchResults[i])) {
1010 SearchResults[j++] = SearchResults[i];
1014 NumSearchResults = j;
1017 void CheatSearchNoChange16() {
1020 assert(prevM != NULL); // not possible for the first search
1024 for (i = 0; i < NumSearchResults; i++) {
1025 if (PrevMu16(SearchResults[i]) == PSXMu16(SearchResults[i])) {
1026 SearchResults[j++] = SearchResults[i];
1030 NumSearchResults = j;
1033 void CheatSearchNoChange32() {
1036 assert(prevM != NULL); // not possible for the first search
1040 for (i = 0; i < NumSearchResults; i++) {
1041 if (PrevMu32(SearchResults[i]) == PSXMu32(SearchResults[i])) {
1042 SearchResults[j++] = SearchResults[i];
1046 NumSearchResults = j;