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"
28 int NumCheatsAllocated = 0;
30 CheatCode *CheatCodes = NULL;
32 int NumCodesAllocated = 0;
35 u32 *SearchResults = NULL;
36 int NumSearchResults = 0;
37 static int NumSearchResultsAllocated = 0;
39 #define ALLOC_INCREMENT 100
41 void ClearAllCheats() {
45 for (i = 0; i < NumCheats; i++) {
46 free(Cheats[i].Descr);
53 NumCheatsAllocated = 0;
55 if (CheatCodes != NULL) {
61 NumCodesAllocated = 0;
64 // load cheats from the specific filename
65 void LoadCheats(const char *filename) {
71 fp = fopen(filename, "r");
78 while (fgets(buf, 255, fp) != NULL) {
82 // Skip comment or blank lines
83 if (buf[0] == '#' || buf[0] == ';' || buf[0] == '/' || buf[0] == '\"' || buf[0] == '\0')
86 if (buf[0] == '[' && buf[strlen(buf) - 1] == ']') {
88 Cheats[NumCheats - 1].n = count;
90 if (NumCheats >= NumCheatsAllocated) {
91 NumCheatsAllocated += ALLOC_INCREMENT;
94 assert(NumCheats == 0);
95 assert(NumCheatsAllocated == ALLOC_INCREMENT);
96 Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated);
98 Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated);
102 buf[strlen(buf) - 1] = '\0';
106 Cheats[NumCheats].Descr = strdup(buf + 2);
107 Cheats[NumCheats].Enabled = 1;
109 Cheats[NumCheats].Descr = strdup(buf + 1);
110 Cheats[NumCheats].Enabled = 0;
112 Cheats[NumCheats].WasEnabled = 0;
114 Cheats[NumCheats].First = NumCodes;
123 if (NumCodes >= NumCodesAllocated) {
124 NumCodesAllocated += ALLOC_INCREMENT;
126 if (CheatCodes == NULL) {
127 assert(NumCodes == 0);
128 assert(NumCodesAllocated == ALLOC_INCREMENT);
129 CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
131 CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
135 sscanf(buf, "%x %x", &t1, &t2);
137 CheatCodes[NumCodes].Addr = t1;
138 CheatCodes[NumCodes].Val = t2;
145 Cheats[NumCheats - 1].n = count;
149 SysPrintf(_("Cheats loaded from: %s\n"), filename);
152 // save all cheats to the specified filename
153 void SaveCheats(const char *filename) {
157 fp = fopen(filename, "w");
162 for (i = 0; i < NumCheats; i++) {
163 // write the description
164 if (Cheats[i].Enabled)
165 fprintf(fp, "[*%s]\n", Cheats[i].Descr);
167 fprintf(fp, "[%s]\n", Cheats[i].Descr);
169 // write all cheat codes
170 for (j = 0; j < Cheats[i].n; j++) {
171 fprintf(fp, "%.8X %.4X\n",
172 CheatCodes[Cheats[i].First + j].Addr,
173 CheatCodes[Cheats[i].First + j].Val);
181 SysPrintf(_("Cheats saved to: %s\n"), filename);
184 // apply all enabled cheats
186 int i, j, k, endindex;
189 for (i = 0; i < NumCheats; i++) {
190 was_enabled = Cheats[i].WasEnabled;
191 if (!Cheats[i].Enabled) {
192 if (!Cheats[i].WasEnabled)
195 Cheats[i].WasEnabled = Cheats[i].Enabled;
197 // process all cheat codes
198 endindex = Cheats[i].First + Cheats[i].n;
200 for (j = Cheats[i].First; j < endindex; j++) {
201 u8 type = (uint8_t)(CheatCodes[j].Addr >> 24);
202 u32 addr = (CheatCodes[j].Addr & 0x001FFFFF);
203 u16 val = CheatCodes[j].Val;
209 CheatCodes[j].OldVal = psxMu16(addr);
212 CheatCodes[j].OldVal = psxMu8(addr);
216 else if (!Cheats[i].Enabled) {
217 val = CheatCodes[j].OldVal;
218 if (type != CHEAT_CONST16 && type != CHEAT_CONST8)
224 psxMu8ref(addr) = (u8)val;
228 psxMu16ref(addr) = SWAPu16(val);
232 psxMu16ref(addr) = SWAPu16(psxMu16(addr) + val);
236 psxMu16ref(addr) = SWAPu16(psxMu16(addr) - val);
240 psxMu8ref(addr) += (u8)val;
244 psxMu8ref(addr) -= (u8)val;
252 type = (uint8_t)(CheatCodes[j].Addr >> 24);
253 taddr = (CheatCodes[j].Addr & 0x001FFFFF);
254 val = CheatCodes[j].Val;
256 if (type == CHEAT_CONST8) {
257 for (k = 0; k < ((addr >> 8) & 0xFF); k++) {
258 psxMu8ref(taddr) = (u8)val;
259 taddr += (s8)(addr & 0xFF);
260 val += (s8)(CheatCodes[j - 1].Val & 0xFF);
263 else if (type == CHEAT_CONST16) {
264 for (k = 0; k < ((addr >> 8) & 0xFF); k++) {
265 psxMu16ref(taddr) = SWAPu16(val);
266 taddr += (s8)(addr & 0xFF);
267 val += (s8)(CheatCodes[j - 1].Val & 0xFF);
277 taddr = (CheatCodes[j].Addr & 0x001FFFFF);
278 for (k = 0; k < val; k++) {
279 psxMu8ref(taddr + k) = PSXMu8(addr + k);
284 if (PSXMu8(addr) != (u8)val)
285 j++; // skip the next code
289 if (PSXMu8(addr) == (u8)val)
290 j++; // skip the next code
293 case CHEAT_LESSTHAN8:
294 if (PSXMu8(addr) >= (u8)val)
295 j++; // skip the next code
298 case CHEAT_GREATERTHAN8:
299 if (PSXMu8(addr) <= (u8)val)
300 j++; // skip the next code
304 if (PSXMu16(addr) != val)
305 j++; // skip the next code
309 if (PSXMu16(addr) == val)
310 j++; // skip the next code
313 case CHEAT_LESSTHAN16:
314 if (PSXMu16(addr) >= val)
315 j++; // skip the next code
318 case CHEAT_GREATERTHAN16:
319 if (PSXMu16(addr) <= val)
320 j++; // skip the next code
327 int AddCheat(const char *descr, char *code) {
331 if (NumCheats >= NumCheatsAllocated) {
332 NumCheatsAllocated += ALLOC_INCREMENT;
334 if (Cheats == NULL) {
335 assert(NumCheats == 0);
336 assert(NumCheatsAllocated == ALLOC_INCREMENT);
337 Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated);
340 Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated);
344 Cheats[NumCheats].Enabled = 0;
345 Cheats[NumCheats].WasEnabled = 0;
346 Cheats[NumCheats].First = NumCodes;
347 Cheats[NumCheats].n = 0;
355 while (*p2 != '\n' && *p2 != '\0')
366 sscanf(p1, "%x %x", &t1, &t2);
368 if (t1 > 0x10000000) {
369 if (NumCodes >= NumCodesAllocated) {
370 NumCodesAllocated += ALLOC_INCREMENT;
372 if (CheatCodes == NULL) {
373 assert(NumCodes == 0);
374 assert(NumCodesAllocated == ALLOC_INCREMENT);
375 CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
378 CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
382 CheatCodes[NumCodes].Addr = t1;
383 CheatCodes[NumCodes].Val = t2;
385 Cheats[NumCheats].n++;
391 if (Cheats[NumCheats].n == 0) {
395 Cheats[NumCheats].Descr = strdup(descr[0] ? descr : _("(Untitled)"));
400 void RemoveCheat(int index) {
401 assert(index >= 0 && index < NumCheats);
403 free(Cheats[index].Descr);
404 Cheats[index].Descr = NULL;
406 while (index < NumCheats - 1) {
407 Cheats[index] = Cheats[index + 1];
414 int EditCheat(int index, const char *descr, char *code) {
419 assert(index >= 0 && index < NumCheats);
427 while (*p2 != '\n' && *p2 != '\0')
438 sscanf(p1, "%x %x", &t1, &t2);
440 if (t1 > 0x10000000) {
441 if (NumCodes >= NumCodesAllocated) {
442 NumCodesAllocated += ALLOC_INCREMENT;
444 if (CheatCodes == NULL) {
445 assert(NumCodes == 0);
446 assert(NumCodesAllocated == ALLOC_INCREMENT);
447 CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated);
450 CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated);
454 CheatCodes[NumCodes].Addr = t1;
455 CheatCodes[NumCodes].Val = t2;
462 if (NumCodes == prev) {
466 free(Cheats[index].Descr);
467 Cheats[index].Descr = strdup(descr[0] ? descr : _("(Untitled)"));
468 Cheats[index].First = prev;
469 Cheats[index].n = NumCodes - prev;
474 void FreeCheatSearchResults() {
475 if (SearchResults != NULL) {
478 SearchResults = NULL;
480 NumSearchResults = 0;
481 NumSearchResultsAllocated = 0;
484 void FreeCheatSearchMem() {
491 void CheatSearchBackupMemory() {
493 memcpy(prevM, psxM, 0x200000);
497 static void CheatSearchInitBackupMemory() {
499 prevM = (s8 *)malloc(0x200000);
500 CheatSearchBackupMemory();
504 static void CheatSearchAddResult(u32 addr) {
505 if (NumSearchResults >= NumSearchResultsAllocated) {
506 NumSearchResultsAllocated += ALLOC_INCREMENT;
508 if (SearchResults == NULL) {
509 SearchResults = (u32 *)malloc(sizeof(u32) * NumSearchResultsAllocated);
512 SearchResults = (u32 *)realloc(SearchResults, sizeof(u32) * NumSearchResultsAllocated);
516 SearchResults[NumSearchResults++] = addr;
519 void CheatSearchEqual8(u8 val) {
522 CheatSearchInitBackupMemory();
524 if (SearchResults == NULL) {
525 // search the whole memory
526 for (i = 0; i < 0x200000; i++) {
527 if (PSXMu8(i) == val) {
528 CheatSearchAddResult(i);
533 // only search within the previous results
536 for (i = 0; i < NumSearchResults; i++) {
537 if (PSXMu8(SearchResults[i]) == val) {
538 SearchResults[j++] = SearchResults[i];
542 NumSearchResults = j;
546 void CheatSearchEqual16(u16 val) {
549 CheatSearchInitBackupMemory();
551 if (SearchResults == NULL) {
552 // search the whole memory
553 for (i = 0; i < 0x200000; i += 2) {
554 if (PSXMu16(i) == val) {
555 CheatSearchAddResult(i);
560 // only search within the previous results
563 for (i = 0; i < NumSearchResults; i++) {
564 if (PSXMu16(SearchResults[i]) == val) {
565 SearchResults[j++] = SearchResults[i];
569 NumSearchResults = j;
573 void CheatSearchEqual32(u32 val) {
576 CheatSearchInitBackupMemory();
578 if (SearchResults == NULL) {
579 // search the whole memory
580 for (i = 0; i < 0x200000; i += 4) {
581 if (PSXMu32(i) == val) {
582 CheatSearchAddResult(i);
587 // only search within the previous results
590 for (i = 0; i < NumSearchResults; i++) {
591 if (PSXMu32(SearchResults[i]) == val) {
592 SearchResults[j++] = SearchResults[i];
596 NumSearchResults = j;
600 void CheatSearchNotEqual8(u8 val) {
603 CheatSearchInitBackupMemory();
605 if (SearchResults == NULL) {
606 // search the whole memory
607 for (i = 0; i < 0x200000; i++) {
608 if (PSXMu8(i) != val) {
609 CheatSearchAddResult(i);
614 // only search within the previous results
617 for (i = 0; i < NumSearchResults; i++) {
618 if (PSXMu8(SearchResults[i]) != val) {
619 SearchResults[j++] = SearchResults[i];
623 NumSearchResults = j;
627 void CheatSearchNotEqual16(u16 val) {
630 CheatSearchInitBackupMemory();
632 if (SearchResults == NULL) {
633 // search the whole memory
634 for (i = 0; i < 0x200000; i += 2) {
635 if (PSXMu16(i) != val) {
636 CheatSearchAddResult(i);
641 // only search within the previous results
644 for (i = 0; i < NumSearchResults; i++) {
645 if (PSXMu16(SearchResults[i]) != val) {
646 SearchResults[j++] = SearchResults[i];
650 NumSearchResults = j;
654 void CheatSearchNotEqual32(u32 val) {
657 CheatSearchInitBackupMemory();
659 if (SearchResults == NULL) {
660 // search the whole memory
661 for (i = 0; i < 0x200000; i += 4) {
662 if (PSXMu32(i) != val) {
663 CheatSearchAddResult(i);
668 // only search within the previous results
671 for (i = 0; i < NumSearchResults; i++) {
672 if (PSXMu32(SearchResults[i]) != val) {
673 SearchResults[j++] = SearchResults[i];
677 NumSearchResults = j;
681 void CheatSearchRange8(u8 min, u8 max) {
684 CheatSearchInitBackupMemory();
686 if (SearchResults == NULL) {
687 // search the whole memory
688 for (i = 0; i < 0x200000; i++) {
689 if (PSXMu8(i) >= min && PSXMu8(i) <= max) {
690 CheatSearchAddResult(i);
695 // only search within the previous results
698 for (i = 0; i < NumSearchResults; i++) {
699 if (PSXMu8(SearchResults[i]) >= min && PSXMu8(SearchResults[i]) <= max) {
700 SearchResults[j++] = SearchResults[i];
704 NumSearchResults = j;
708 void CheatSearchRange16(u16 min, u16 max) {
711 CheatSearchInitBackupMemory();
713 if (SearchResults == NULL) {
714 // search the whole memory
715 for (i = 0; i < 0x200000; i += 2) {
716 if (PSXMu16(i) >= min && PSXMu16(i) <= max) {
717 CheatSearchAddResult(i);
722 // only search within the previous results
725 for (i = 0; i < NumSearchResults; i++) {
726 if (PSXMu16(SearchResults[i]) >= min && PSXMu16(SearchResults[i]) <= max) {
727 SearchResults[j++] = SearchResults[i];
731 NumSearchResults = j;
735 void CheatSearchRange32(u32 min, u32 max) {
738 CheatSearchInitBackupMemory();
740 if (SearchResults == NULL) {
741 // search the whole memory
742 for (i = 0; i < 0x200000; i += 4) {
743 if (PSXMu32(i) >= min && PSXMu32(i) <= max) {
744 CheatSearchAddResult(i);
749 // only search within the previous results
752 for (i = 0; i < NumSearchResults; i++) {
753 if (PSXMu32(SearchResults[i]) >= min && PSXMu32(SearchResults[i]) <= max) {
754 SearchResults[j++] = SearchResults[i];
758 NumSearchResults = j;
762 void CheatSearchIncreasedBy8(u8 val) {
765 assert(prevM != NULL); // not possible for the first search
769 for (i = 0; i < NumSearchResults; i++) {
770 if (PSXMu8(SearchResults[i]) - PrevMu8(SearchResults[i]) == val) {
771 SearchResults[j++] = SearchResults[i];
775 NumSearchResults = j;
778 void CheatSearchIncreasedBy16(u16 val) {
781 assert(prevM != NULL); // not possible for the first search
785 for (i = 0; i < NumSearchResults; i++) {
786 if (PSXMu16(SearchResults[i]) - PrevMu16(SearchResults[i]) == val) {
787 SearchResults[j++] = SearchResults[i];
791 NumSearchResults = j;
794 void CheatSearchIncreasedBy32(u32 val) {
797 assert(prevM != NULL); // not possible for the first search
801 for (i = 0; i < NumSearchResults; i++) {
802 if (PSXMu32(SearchResults[i]) - PrevMu32(SearchResults[i]) == val) {
803 SearchResults[j++] = SearchResults[i];
807 NumSearchResults = j;
810 void CheatSearchDecreasedBy8(u8 val) {
813 assert(prevM != NULL); // not possible for the first search
817 for (i = 0; i < NumSearchResults; i++) {
818 if (PrevMu8(SearchResults[i]) - PSXMu8(SearchResults[i]) == val) {
819 SearchResults[j++] = SearchResults[i];
823 NumSearchResults = j;
826 void CheatSearchDecreasedBy16(u16 val) {
829 assert(prevM != NULL); // not possible for the first search
833 for (i = 0; i < NumSearchResults; i++) {
834 if (PrevMu16(SearchResults[i]) - PSXMu16(SearchResults[i]) == val) {
835 SearchResults[j++] = SearchResults[i];
839 NumSearchResults = j;
842 void CheatSearchDecreasedBy32(u32 val) {
845 assert(prevM != NULL); // not possible for the first search
849 for (i = 0; i < NumSearchResults; i++) {
850 if (PrevMu32(SearchResults[i]) - PSXMu32(SearchResults[i]) == val) {
851 SearchResults[j++] = SearchResults[i];
855 NumSearchResults = j;
858 void CheatSearchIncreased8() {
861 assert(prevM != NULL); // not possible for the first search
865 for (i = 0; i < NumSearchResults; i++) {
866 if (PrevMu8(SearchResults[i]) < PSXMu8(SearchResults[i])) {
867 SearchResults[j++] = SearchResults[i];
871 NumSearchResults = j;
874 void CheatSearchIncreased16() {
877 assert(prevM != NULL); // not possible for the first search
881 for (i = 0; i < NumSearchResults; i++) {
882 if (PrevMu16(SearchResults[i]) < PSXMu16(SearchResults[i])) {
883 SearchResults[j++] = SearchResults[i];
887 NumSearchResults = j;
890 void CheatSearchIncreased32() {
893 assert(prevM != NULL); // not possible for the first search
897 for (i = 0; i < NumSearchResults; i++) {
898 if (PrevMu32(SearchResults[i]) < PSXMu32(SearchResults[i])) {
899 SearchResults[j++] = SearchResults[i];
903 NumSearchResults = j;
906 void CheatSearchDecreased8() {
909 assert(prevM != NULL); // not possible for the first search
913 for (i = 0; i < NumSearchResults; i++) {
914 if (PrevMu8(SearchResults[i]) > PSXMu8(SearchResults[i])) {
915 SearchResults[j++] = SearchResults[i];
919 NumSearchResults = j;
922 void CheatSearchDecreased16() {
925 assert(prevM != NULL); // not possible for the first search
929 for (i = 0; i < NumSearchResults; i++) {
930 if (PrevMu16(SearchResults[i]) > PSXMu16(SearchResults[i])) {
931 SearchResults[j++] = SearchResults[i];
935 NumSearchResults = j;
938 void CheatSearchDecreased32() {
941 assert(prevM != NULL); // not possible for the first search
945 for (i = 0; i < NumSearchResults; i++) {
946 if (PrevMu32(SearchResults[i]) > PSXMu32(SearchResults[i])) {
947 SearchResults[j++] = SearchResults[i];
951 NumSearchResults = j;
954 void CheatSearchDifferent8() {
957 assert(prevM != NULL); // not possible for the first search
961 for (i = 0; i < NumSearchResults; i++) {
962 if (PrevMu8(SearchResults[i]) != PSXMu8(SearchResults[i])) {
963 SearchResults[j++] = SearchResults[i];
967 NumSearchResults = j;
970 void CheatSearchDifferent16() {
973 assert(prevM != NULL); // not possible for the first search
977 for (i = 0; i < NumSearchResults; i++) {
978 if (PrevMu16(SearchResults[i]) != PSXMu16(SearchResults[i])) {
979 SearchResults[j++] = SearchResults[i];
983 NumSearchResults = j;
986 void CheatSearchDifferent32() {
989 assert(prevM != NULL); // not possible for the first search
993 for (i = 0; i < NumSearchResults; i++) {
994 if (PrevMu32(SearchResults[i]) != PSXMu32(SearchResults[i])) {
995 SearchResults[j++] = SearchResults[i];
999 NumSearchResults = j;
1002 void CheatSearchNoChange8() {
1005 assert(prevM != NULL); // not possible for the first search
1009 for (i = 0; i < NumSearchResults; i++) {
1010 if (PrevMu8(SearchResults[i]) == PSXMu8(SearchResults[i])) {
1011 SearchResults[j++] = SearchResults[i];
1015 NumSearchResults = j;
1018 void CheatSearchNoChange16() {
1021 assert(prevM != NULL); // not possible for the first search
1025 for (i = 0; i < NumSearchResults; i++) {
1026 if (PrevMu16(SearchResults[i]) == PSXMu16(SearchResults[i])) {
1027 SearchResults[j++] = SearchResults[i];
1031 NumSearchResults = j;
1034 void CheatSearchNoChange32() {
1037 assert(prevM != NULL); // not possible for the first search
1041 for (i = 0; i < NumSearchResults; i++) {
1042 if (PrevMu32(SearchResults[i]) == PSXMu32(SearchResults[i])) {
1043 SearchResults[j++] = SearchResults[i];
1047 NumSearchResults = j;