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 static int NumCheatsAllocated = 0;
29 CheatCode *CheatCodes = NULL;
31 static 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;
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;
186 for (i = 0; i < NumCheats; i++) {
187 if (!Cheats[i].Enabled) {
191 // process all cheat codes
192 endindex = Cheats[i].First + Cheats[i].n;
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;
202 psxMu8ref(addr) = (u8)val;
206 psxMu16ref(addr) = SWAPu16(val);
210 psxMu16ref(addr) = SWAPu16(psxMu16(addr) + val);
214 psxMu16ref(addr) = SWAPu16(psxMu16(addr) - val);
218 psxMu8ref(addr) += (u8)val;
222 psxMu8ref(addr) -= (u8)val;
230 type = (uint8_t)(CheatCodes[j].Addr >> 24);
231 taddr = (CheatCodes[j].Addr & 0x001FFFFF);
232 val = CheatCodes[j].Val;
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);
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);
255 taddr = (CheatCodes[j].Addr & 0x001FFFFF);
256 for (k = 0; k < val; k++) {
257 psxMu8ref(taddr + k) = PSXMu8(addr + k);
262 if (PSXMu8(addr) != (u8)val)
263 j++; // skip the next code
267 if (PSXMu8(addr) == (u8)val)
268 j++; // skip the next code
271 case CHEAT_LESSTHAN8:
272 if (PSXMu8(addr) >= (u8)val)
273 j++; // skip the next code
276 case CHEAT_GREATERTHAN8:
277 if (PSXMu8(addr) <= (u8)val)
278 j++; // skip the next code
282 if (PSXMu16(addr) != val)
283 j++; // skip the next code
287 if (PSXMu16(addr) == val)
288 j++; // skip the next code
291 case CHEAT_LESSTHAN16:
292 if (PSXMu16(addr) >= val)
293 j++; // skip the next code
296 case CHEAT_GREATERTHAN16:
297 if (PSXMu16(addr) <= val)
298 j++; // skip the next code
305 int AddCheat(const char *descr, char *code) {
309 if (NumCheats >= NumCheatsAllocated) {
310 NumCheatsAllocated += ALLOC_INCREMENT;
312 if (Cheats == NULL) {
313 assert(NumCheats == 0);
314 assert(NumCheatsAllocated == ALLOC_INCREMENT);
315 Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated);
318 Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated);
322 Cheats[NumCheats].Descr = strdup(descr[0] ? descr : _("(Untitled)"));
323 Cheats[NumCheats].Enabled = 0;
324 Cheats[NumCheats].First = NumCodes;
325 Cheats[NumCheats].n = 0;
333 while (*p2 != '\n' && *p2 != '\0')
344 sscanf(p1, "%x %x", &t1, &t2);
346 if (t1 > 0x10000000) {
347 if (NumCodes >= NumCodesAllocated) {
348 NumCodesAllocated += ALLOC_INCREMENT;
350 if (CheatCodes == NULL) {
351 assert(NumCodes == 0);
352 assert(NumCodesAllocated == ALLOC_INCREMENT);
353 CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
356 CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
360 CheatCodes[NumCodes].Addr = t1;
361 CheatCodes[NumCodes].Val = t2;
363 Cheats[NumCheats].n++;
369 if (Cheats[NumCheats].n == 0) {
377 void RemoveCheat(int index) {
378 assert(index >= 0 && index < NumCheats);
380 free(Cheats[index].Descr);
382 while (index < NumCheats - 1) {
383 Cheats[index] = Cheats[index + 1];
390 int EditCheat(int index, const char *descr, char *code) {
395 assert(index >= 0 && index < NumCheats);
403 while (*p2 != '\n' && *p2 != '\0')
414 sscanf(p1, "%x %x", &t1, &t2);
416 if (t1 > 0x10000000) {
417 if (NumCodes >= NumCodesAllocated) {
418 NumCodesAllocated += ALLOC_INCREMENT;
420 if (CheatCodes == NULL) {
421 assert(NumCodes == 0);
422 assert(NumCodesAllocated == ALLOC_INCREMENT);
423 CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
426 CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
430 CheatCodes[NumCodes].Addr = t1;
431 CheatCodes[NumCodes].Val = t2;
438 if (NumCodes == prev) {
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;
450 void FreeCheatSearchResults() {
451 if (SearchResults != NULL) {
454 SearchResults = NULL;
456 NumSearchResults = 0;
457 NumSearchResultsAllocated = 0;
460 void FreeCheatSearchMem() {
467 void CheatSearchBackupMemory() {
469 memcpy(prevM, psxM, 0x200000);
473 static void CheatSearchInitBackupMemory() {
475 prevM = (s8 *)malloc(0x200000);
476 CheatSearchBackupMemory();
480 static void CheatSearchAddResult(u32 addr) {
481 if (NumSearchResults >= NumSearchResultsAllocated) {
482 NumSearchResultsAllocated += ALLOC_INCREMENT;
484 if (SearchResults == NULL) {
485 SearchResults = (u32 *)malloc(sizeof(u32) * NumSearchResultsAllocated);
488 SearchResults = (u32 *)realloc(SearchResults, sizeof(u32) * NumSearchResultsAllocated);
492 SearchResults[NumSearchResults++] = addr;
495 void CheatSearchEqual8(u8 val) {
498 CheatSearchInitBackupMemory();
500 if (SearchResults == NULL) {
501 // search the whole memory
502 for (i = 0; i < 0x200000; i++) {
503 if (PSXMu8(i) == val) {
504 CheatSearchAddResult(i);
509 // only search within the previous results
512 for (i = 0; i < NumSearchResults; i++) {
513 if (PSXMu8(SearchResults[i]) == val) {
514 SearchResults[j++] = SearchResults[i];
518 NumSearchResults = j;
522 void CheatSearchEqual16(u16 val) {
525 CheatSearchInitBackupMemory();
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);
536 // only search within the previous results
539 for (i = 0; i < NumSearchResults; i++) {
540 if (PSXMu16(SearchResults[i]) == val) {
541 SearchResults[j++] = SearchResults[i];
545 NumSearchResults = j;
549 void CheatSearchEqual32(u32 val) {
552 CheatSearchInitBackupMemory();
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);
563 // only search within the previous results
566 for (i = 0; i < NumSearchResults; i++) {
567 if (PSXMu32(SearchResults[i]) == val) {
568 SearchResults[j++] = SearchResults[i];
572 NumSearchResults = j;
576 void CheatSearchNotEqual8(u8 val) {
579 CheatSearchInitBackupMemory();
581 if (SearchResults == NULL) {
582 // search the whole memory
583 for (i = 0; i < 0x200000; i++) {
584 if (PSXMu8(i) != val) {
585 CheatSearchAddResult(i);
590 // only search within the previous results
593 for (i = 0; i < NumSearchResults; i++) {
594 if (PSXMu8(SearchResults[i]) != val) {
595 SearchResults[j++] = SearchResults[i];
599 NumSearchResults = j;
603 void CheatSearchNotEqual16(u16 val) {
606 CheatSearchInitBackupMemory();
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);
617 // only search within the previous results
620 for (i = 0; i < NumSearchResults; i++) {
621 if (PSXMu16(SearchResults[i]) != val) {
622 SearchResults[j++] = SearchResults[i];
626 NumSearchResults = j;
630 void CheatSearchNotEqual32(u32 val) {
633 CheatSearchInitBackupMemory();
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);
644 // only search within the previous results
647 for (i = 0; i < NumSearchResults; i++) {
648 if (PSXMu32(SearchResults[i]) != val) {
649 SearchResults[j++] = SearchResults[i];
653 NumSearchResults = j;
657 void CheatSearchRange8(u8 min, u8 max) {
660 CheatSearchInitBackupMemory();
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);
671 // only search within the previous results
674 for (i = 0; i < NumSearchResults; i++) {
675 if (PSXMu8(SearchResults[i]) >= min && PSXMu8(SearchResults[i]) <= max) {
676 SearchResults[j++] = SearchResults[i];
680 NumSearchResults = j;
684 void CheatSearchRange16(u16 min, u16 max) {
687 CheatSearchInitBackupMemory();
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);
698 // only search within the previous results
701 for (i = 0; i < NumSearchResults; i++) {
702 if (PSXMu16(SearchResults[i]) >= min && PSXMu16(SearchResults[i]) <= max) {
703 SearchResults[j++] = SearchResults[i];
707 NumSearchResults = j;
711 void CheatSearchRange32(u32 min, u32 max) {
714 CheatSearchInitBackupMemory();
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);
725 // only search within the previous results
728 for (i = 0; i < NumSearchResults; i++) {
729 if (PSXMu32(SearchResults[i]) >= min && PSXMu32(SearchResults[i]) <= max) {
730 SearchResults[j++] = SearchResults[i];
734 NumSearchResults = j;
738 void CheatSearchIncreasedBy8(u8 val) {
741 assert(prevM != NULL); // not possible for the first search
745 for (i = 0; i < NumSearchResults; i++) {
746 if (PSXMu8(SearchResults[i]) - PrevMu8(SearchResults[i]) == val) {
747 SearchResults[j++] = SearchResults[i];
751 NumSearchResults = j;
754 void CheatSearchIncreasedBy16(u16 val) {
757 assert(prevM != NULL); // not possible for the first search
761 for (i = 0; i < NumSearchResults; i++) {
762 if (PSXMu16(SearchResults[i]) - PrevMu16(SearchResults[i]) == val) {
763 SearchResults[j++] = SearchResults[i];
767 NumSearchResults = j;
770 void CheatSearchIncreasedBy32(u32 val) {
773 assert(prevM != NULL); // not possible for the first search
777 for (i = 0; i < NumSearchResults; i++) {
778 if (PSXMu32(SearchResults[i]) - PrevMu32(SearchResults[i]) == val) {
779 SearchResults[j++] = SearchResults[i];
783 NumSearchResults = j;
786 void CheatSearchDecreasedBy8(u8 val) {
789 assert(prevM != NULL); // not possible for the first search
793 for (i = 0; i < NumSearchResults; i++) {
794 if (PrevMu8(SearchResults[i]) - PSXMu8(SearchResults[i]) == val) {
795 SearchResults[j++] = SearchResults[i];
799 NumSearchResults = j;
802 void CheatSearchDecreasedBy16(u16 val) {
805 assert(prevM != NULL); // not possible for the first search
809 for (i = 0; i < NumSearchResults; i++) {
810 if (PrevMu16(SearchResults[i]) - PSXMu16(SearchResults[i]) == val) {
811 SearchResults[j++] = SearchResults[i];
815 NumSearchResults = j;
818 void CheatSearchDecreasedBy32(u32 val) {
821 assert(prevM != NULL); // not possible for the first search
825 for (i = 0; i < NumSearchResults; i++) {
826 if (PrevMu32(SearchResults[i]) - PSXMu32(SearchResults[i]) == val) {
827 SearchResults[j++] = SearchResults[i];
831 NumSearchResults = j;
834 void CheatSearchIncreased8() {
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])) {
843 SearchResults[j++] = SearchResults[i];
847 NumSearchResults = j;
850 void CheatSearchIncreased16() {
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])) {
859 SearchResults[j++] = SearchResults[i];
863 NumSearchResults = j;
866 void CheatSearchIncreased32() {
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])) {
875 SearchResults[j++] = SearchResults[i];
879 NumSearchResults = j;
882 void CheatSearchDecreased8() {
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 CheatSearchDecreased16() {
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 CheatSearchDecreased32() {
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 CheatSearchDifferent8() {
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 CheatSearchDifferent16() {
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 CheatSearchDifferent32() {
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 CheatSearchNoChange8() {
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 CheatSearchNoChange16() {
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 CheatSearchNoChange32() {
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;