diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-04-16 06:22:51 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-04-16 06:22:51 +0000 |
| commit | 8139fbf8204882663446bcb06f68789353597820 (patch) | |
| tree | 6ea1f39932b33faee84d603e956470e37f135804 /libpcsxcore/cheat.c | |
| download | pcsxr-8139fbf8204882663446bcb06f68789353597820.tar.gz | |
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@23061 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'libpcsxcore/cheat.c')
| -rw-r--r-- | libpcsxcore/cheat.c | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/libpcsxcore/cheat.c b/libpcsxcore/cheat.c new file mode 100644 index 00000000..284d833b --- /dev/null +++ b/libpcsxcore/cheat.c @@ -0,0 +1,459 @@ +/* Cheat Support for PCSX-Reloaded + * + * Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307 USA + */ + +#include "psxcommon.h" +#include "r3000a.h" +#include "psxmem.h" + +#include "cheat.h" + +Cheat *Cheats = NULL; +int NumCheats = 0; +static int NumCheatsAllocated = 0; + +CheatCode *CheatCodes = NULL; +int NumCodes = 0; +static int NumCodesAllocated = 0; + +#define ALLOC_INCREMENT 100 + +// cheat types +#define CHEAT_CONST8 0x30 /* 8-bit Constant Write */ +#define CHEAT_CONST16 0x80 /* 16-bit Constant Write */ +#define CHEAT_INC16 0x10 /* 16-bit Increment */ +#define CHEAT_DEC16 0x11 /* 16-bit Decrement */ +#define CHEAT_INC8 0x20 /* 8-bit Increment */ +#define CHEAT_DEC8 0x21 /* 8-bit Decrement */ +#define CHEAT_SLIDE 0x50 /* Slide Codes */ +#define CHEAT_MEMCPY 0xC2 /* Memory Copy */ + +#define CHEAT_EQU8 0xE0 /* 8-bit Equal To */ +#define CHEAT_NOTEQU8 0xE1 /* 8-bit Not Equal To */ +#define CHEAT_LESSTHAN8 0xE2 /* 8-bit Less Than */ +#define CHEAT_GREATERTHAN8 0xE3 /* 8-bit Greater Than */ +#define CHEAT_EQU16 0xD0 /* 16-bit Equal To */ +#define CHEAT_NOTEQU16 0xD1 /* 16-bit Not Equal To */ +#define CHEAT_LESSTHAN16 0xD2 /* 16-bit Less Than */ +#define CHEAT_GREATERTHAN16 0xD3 /* 16-bit Greater Than */ + +void ClearAllCheats() { + int i; + + if (Cheats != NULL) { + for (i = 0; i < NumCheats; i++) { + free(Cheats[i].Descr); + } + free(Cheats); + } + + Cheats = NULL; + NumCheats = 0; + NumCheatsAllocated = 0; + + if (CheatCodes != NULL) { + free(CheatCodes); + } + + CheatCodes = NULL; + NumCodes = 0; + NumCodesAllocated = 0; +} + +// load cheats from the specific filename +void LoadCheats(const char *filename) { + FILE *fp; + char buf[256]; + int count = 0; + unsigned int t1, t2; + + fp = fopen(filename, "r"); + if (fp == NULL) { + return; + } + + ClearAllCheats(); + + while (fgets(buf, 255, fp) != NULL) { + buf[255] = '\0'; + trim(buf); + + // Skip comment or blank lines + if (buf[0] == '#' || buf[0] == ';' || buf[0] == '/' || buf[0] == '\"' || buf[0] == '\0') + continue; + + if (buf[0] == '[' && buf[strlen(buf) - 1] == ']') { + if (NumCheats > 0) + Cheats[NumCheats - 1].n = count; + + if (NumCheats >= NumCheatsAllocated) { + NumCheatsAllocated += ALLOC_INCREMENT; + + if (Cheats == NULL) { + assert(NumCheats == 0); + assert(NumCheatsAllocated == ALLOC_INCREMENT); + Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated); + } else { + Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated); + } + } + + buf[strlen(buf) - 1] = '\0'; + count = 0; + + if (buf[1] == '*') { + Cheats[NumCheats].Descr = strdup(buf + 2); + Cheats[NumCheats].Enabled = 1; + } else { + Cheats[NumCheats].Descr = strdup(buf + 1); + Cheats[NumCheats].Enabled = 0; + } + + Cheats[NumCheats].First = NumCodes; + + NumCheats++; + continue; + } + + if (NumCheats <= 0) + continue; + + if (NumCodes >= NumCodesAllocated) { + NumCodesAllocated += ALLOC_INCREMENT; + + if (CheatCodes == NULL) { + assert(NumCodes == 0); + assert(NumCodesAllocated == ALLOC_INCREMENT); + CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated); + } else { + CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated); + } + } + + sscanf(buf, "%x %x", &t1, &t2); + + CheatCodes[NumCodes].Addr = t1; + CheatCodes[NumCodes].Val = t2; + + NumCodes++; + count++; + } + + if (NumCheats > 0) + Cheats[NumCheats - 1].n = count; + + fclose(fp); + + SysPrintf("Cheats loaded from: %s\n", filename); +} + +// save all cheats to the specified filename +void SaveCheats(const char *filename) { + FILE *fp; + int i, j; + + fp = fopen(filename, "w"); + if (fp == NULL) { + return; + } + + for (i = 0; i < NumCheats; i++) { + // write the description + if (Cheats[i].Enabled) + fprintf(fp, "[*%s]\n", Cheats[i].Descr); + else + fprintf(fp, "[%s]\n", Cheats[i].Descr); + + // write all cheat codes + for (j = 0; j < Cheats[i].n; j++) { + fprintf(fp, "%.8X %.4X\n", + CheatCodes[Cheats[i].First + j].Addr, + CheatCodes[Cheats[i].First + j].Val); + } + + fprintf(fp, "\n"); + } + + fclose(fp); + + SysPrintf("Cheats saved to: %s\n", filename); +} + +// apply all enabled cheats +void ApplyCheats() { + int i, j, k, endindex; + + for (i = 0; i < NumCheats; i++) { + if (!Cheats[i].Enabled) { + continue; + } + + // process all cheat codes + endindex = Cheats[i].First + Cheats[i].n; + + for (j = Cheats[i].First; j < endindex; j++) { + u8 type = (uint8_t)(CheatCodes[j].Addr >> 24); + u32 addr = (CheatCodes[j].Addr & 0x001FFFFF); + u16 val = CheatCodes[j].Val; + u32 taddr; + + switch (type) { + case CHEAT_CONST8: + psxMemWrite8(addr, (u8)val); + break; + + case CHEAT_CONST16: + psxMemWrite16(addr, (u16)val); + break; + + case CHEAT_INC16: + psxMemWrite16(addr, psxMemRead16(addr) + val); + break; + + case CHEAT_DEC16: + psxMemWrite16(addr, psxMemRead16(addr) - val); + break; + + case CHEAT_INC8: + psxMemWrite8(addr, psxMemRead8(addr) + (u8)val); + break; + + case CHEAT_DEC8: + psxMemWrite8(addr, psxMemRead8(addr) - (u8)val); + break; + + case CHEAT_SLIDE: + j++; + if (j >= endindex) + break; + + type = (uint8_t)(CheatCodes[j].Addr >> 24); + taddr = (CheatCodes[j].Addr & 0x001FFFFF); + val = CheatCodes[j].Val; + + if (type == CHEAT_CONST8) { + for (k = 0; k < ((addr >> 8) & 0xFF); k++) { + psxMemWrite8(taddr, (u8)val); + taddr += (s8)(addr & 0xFF); + val += (s8)(CheatCodes[j - 1].Val & 0xFF); + } + } else if (type == CHEAT_CONST16) { + for (k = 0; k < ((addr >> 8) & 0xFF); k++) { + psxMemWrite16(taddr, val); + taddr += (s8)(addr & 0xFF); + val += (s8)(CheatCodes[j - 1].Val & 0xFF); + } + } + break; + + case CHEAT_MEMCPY: + j++; + if (j >= endindex) + break; + + taddr = (CheatCodes[j].Addr & 0x001FFFFF); + for (k = 0; k < val; k++) { + psxMemWrite8(taddr + k, psxMemRead8(addr + k)); + } + break; + + case CHEAT_EQU8: + if (psxMemRead8(addr) != (u8)val) + j++; // skip the next code + break; + + case CHEAT_NOTEQU8: + if (psxMemRead8(addr) == (u8)val) + j++; // skip the next code + break; + + case CHEAT_LESSTHAN8: + if (psxMemRead8(addr) >= (u8)val) + j++; // skip the next code + break; + + case CHEAT_GREATERTHAN8: + if (psxMemRead8(addr) <= (u8)val) + j++; // skip the next code + break; + + case CHEAT_EQU16: + if (psxMemRead16(addr) != val) + j++; // skip the next code + break; + + case CHEAT_NOTEQU16: + if (psxMemRead16(addr) == val) + j++; // skip the next code + break; + + case CHEAT_LESSTHAN16: + if (psxMemRead16(addr) >= val) + j++; // skip the next code + break; + + case CHEAT_GREATERTHAN16: + if (psxMemRead16(addr) <= val) + j++; // skip the next code + break; + } + } + } +} + +int AddCheat(const char *descr, char *code) { + int c = 1; + char *p1, *p2; + + if (NumCheats >= NumCheatsAllocated) { + NumCheatsAllocated += ALLOC_INCREMENT; + + if (Cheats == NULL) { + assert(NumCheats == 0); + assert(NumCheatsAllocated == ALLOC_INCREMENT); + Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated); + } else { + Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated); + } + } + + Cheats[NumCheats].Descr = strdup(descr[0] ? descr : _("(Untitled)")); + Cheats[NumCheats].Enabled = 0; + Cheats[NumCheats].First = NumCodes; + Cheats[NumCheats].n = 0; + + p1 = code; + p2 = code; + + while (c) { + unsigned int t1, t2; + + while (*p2 != '\n' && *p2 != '\0') + p2++; + + if (*p2 == '\0') + c = 0; + + *p2 = '\0'; + p2++; + + t1 = 0; + t2 = 0; + sscanf(p1, "%x %x", &t1, &t2); + + if (t1 > 0x10000000) { + if (NumCodes >= NumCodesAllocated) { + NumCodesAllocated += ALLOC_INCREMENT; + + if (CheatCodes == NULL) { + assert(NumCodes == 0); + assert(NumCodesAllocated == ALLOC_INCREMENT); + CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated); + } else { + CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated); + } + } + + CheatCodes[NumCodes].Addr = t1; + CheatCodes[NumCodes].Val = t2; + NumCodes++; + Cheats[NumCheats].n++; + } + + p1 = p2; + } + + if (Cheats[NumCheats].n == 0) { + return -1; + } + + NumCheats++; + return 0; +} + +void RemoveCheat(int index) { + assert(index >= 0 && index < NumCheats); + + free(Cheats[index].Descr); + + while (index < NumCheats - 1) { + Cheats[index] = Cheats[index + 1]; + index++; + } + + NumCheats--; +} + +int EditCheat(int index, const char *descr, char *code) { + int c = 1; + int prev = NumCodes; + char *p1, *p2; + + assert(index >= 0 && index < NumCheats); + + p1 = code; + p2 = code; + + while (c) { + unsigned int t1, t2; + + while (*p2 != '\n' && *p2 != '\0') + p2++; + + if (*p2 == '\0') + c = 0; + + *p2 = '\0'; + p2++; + + t1 = 0; + t2 = 0; + sscanf(p1, "%x %x", &t1, &t2); + + if (t1 > 0x10000000) { + if (NumCodes >= NumCodesAllocated) { + NumCodesAllocated += ALLOC_INCREMENT; + + if (CheatCodes == NULL) { + assert(NumCodes == 0); + assert(NumCodesAllocated == ALLOC_INCREMENT); + CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated); + } else { + CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated); + } + } + + CheatCodes[NumCodes].Addr = t1; + CheatCodes[NumCodes].Val = t2; + NumCodes++; + } + + p1 = p2; + } + + if (NumCodes == prev) { + return -1; + } + + free(Cheats[index].Descr); + Cheats[index].Descr = strdup(descr[0] ? descr : _("(Untitled)")); + Cheats[index].First = prev; + Cheats[index].n = NumCodes - prev; + + return 0; +} |
