mirror of
https://github.com/libretro/beetle-psx-libretro.git
synced 2024-11-23 08:49:47 +00:00
Downsize mempatcher.cpp
This commit is contained in:
parent
162483a4e3
commit
87d9ebf5d4
@ -39,12 +39,6 @@ static uint8 **RAMPtrs = NULL;
|
||||
static uint32 PageSize;
|
||||
static uint32 NumPages;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool excluded;
|
||||
uint8 value;
|
||||
} CompareStruct;
|
||||
|
||||
typedef struct __CHEATF
|
||||
{
|
||||
char *name;
|
||||
@ -63,7 +57,6 @@ typedef struct __CHEATF
|
||||
|
||||
static std::vector<CHEATF> cheats;
|
||||
static int savecheats;
|
||||
static CompareStruct **CheatComp = NULL;
|
||||
static uint32 resultsbytelen = 1;
|
||||
static bool resultsbigendian = 0;
|
||||
static bool CheatsActive = TRUE;
|
||||
@ -114,7 +107,6 @@ bool MDFNMP_Init(uint32 ps, uint32 numpages)
|
||||
NumPages = numpages;
|
||||
|
||||
RAMPtrs = (uint8 **)calloc(numpages, sizeof(uint8 *));
|
||||
CheatComp = (CompareStruct **)calloc(numpages, sizeof(CompareStruct *));
|
||||
|
||||
CheatsActive = MDFN_GetSettingB("cheats");
|
||||
return(1);
|
||||
@ -122,16 +114,11 @@ bool MDFNMP_Init(uint32 ps, uint32 numpages)
|
||||
|
||||
void MDFNMP_Kill(void)
|
||||
{
|
||||
if(CheatComp)
|
||||
{
|
||||
free(CheatComp);
|
||||
CheatComp = NULL;
|
||||
}
|
||||
if(RAMPtrs)
|
||||
{
|
||||
free(RAMPtrs);
|
||||
RAMPtrs = NULL;
|
||||
}
|
||||
if(RAMPtrs)
|
||||
{
|
||||
free(RAMPtrs);
|
||||
RAMPtrs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -196,262 +183,24 @@ static int AddCheatEntry(char *name, char *conditions, uint32 addr, uint64 val,
|
||||
return(1);
|
||||
}
|
||||
|
||||
static bool SeekToOurSection(void *fp_ptr)
|
||||
{
|
||||
FILE *fp = (FILE*)fp_ptr;
|
||||
char buf[2048];
|
||||
|
||||
while(fgets(buf,2048,fp) > 0)
|
||||
{
|
||||
if(buf[0] == '[')
|
||||
{
|
||||
if(!strncmp((char *)buf + 1, md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str(), 16))
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void MDFN_LoadGameCheats(void *override_ptr)
|
||||
{
|
||||
char linebuf[2048];
|
||||
FILE *fp;
|
||||
FILE *override = (FILE*)override_ptr;
|
||||
|
||||
unsigned int addr;
|
||||
unsigned long long val;
|
||||
unsigned int status;
|
||||
char type;
|
||||
unsigned long long compare;
|
||||
unsigned int x;
|
||||
unsigned int length;
|
||||
unsigned int icount;
|
||||
bool bigendian;
|
||||
|
||||
int tc=0;
|
||||
|
||||
savecheats=0;
|
||||
|
||||
if(override)
|
||||
fp = override;
|
||||
else
|
||||
{
|
||||
const char *fn = MDFN_MakeFName(MDFNMKF_CHEAT,0,0).c_str();
|
||||
|
||||
if (log_cb && fn[0] != '\0')
|
||||
{
|
||||
log_cb(RETRO_LOG_INFO, "Loading cheats from %s...\n", fn);
|
||||
|
||||
if(!(fp = fopen(fn,"rb")))
|
||||
{
|
||||
if (log_cb)
|
||||
log_cb(RETRO_LOG_ERROR, "Error opening file.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
if(SeekToOurSection(fp))
|
||||
{
|
||||
while(fgets(linebuf,2048,fp) > 0)
|
||||
{
|
||||
char namebuf[2048];
|
||||
char *tbuf=linebuf;
|
||||
|
||||
addr=val=compare=status=type=0;
|
||||
bigendian = 0;
|
||||
icount = 0;
|
||||
|
||||
if(tbuf[0] == '[') // No more cheats for this game, so sad :(
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(tbuf[0] == '\n' || tbuf[0] == '\r' || tbuf[0] == '\t' || tbuf[0] == ' ') // Don't parse if the line starts(or is just) white space
|
||||
continue;
|
||||
|
||||
if(tbuf[0] != 'R' && tbuf[0] != 'C' && tbuf[0] != 'S')
|
||||
{
|
||||
if (log_cb)
|
||||
log_cb(RETRO_LOG_ERROR, "Invalid cheat type: %c\n", tbuf[0]);
|
||||
break;
|
||||
}
|
||||
type = tbuf[0];
|
||||
namebuf[0] = 0;
|
||||
|
||||
char status_tmp, endian_tmp;
|
||||
if(type == 'C')
|
||||
trio_sscanf(tbuf, "%c %c %d %c %d %08x %16llx %16llx %.2047[^\r\n]", &type, &status_tmp, &length, &endian_tmp, &icount, &addr, &val, &compare, namebuf);
|
||||
else
|
||||
trio_sscanf(tbuf, "%c %c %d %c %d %08x %16llx %.2047[^\r\n]", &type, &status_tmp, &length, &endian_tmp, &icount, &addr, &val, namebuf);
|
||||
|
||||
status = (status_tmp == 'A') ? 1 : 0;
|
||||
bigendian = (endian_tmp == 'B') ? 1 : 0;
|
||||
|
||||
for(x=0;x<strlen(namebuf);x++)
|
||||
{
|
||||
if(namebuf[x]==10 || namebuf[x]==13)
|
||||
{
|
||||
namebuf[x]=0;
|
||||
break;
|
||||
}
|
||||
else if(namebuf[x]<0x20) namebuf[x]=' ';
|
||||
}
|
||||
|
||||
// November 9, 2009 return value fix.
|
||||
if(fgets(linebuf, 2048, fp) == NULL)
|
||||
linebuf[0] = 0;
|
||||
|
||||
for(x=0;x<strlen(linebuf);x++)
|
||||
{
|
||||
if(linebuf[x]==10 || linebuf[x]==13)
|
||||
{
|
||||
linebuf[x]=0;
|
||||
break;
|
||||
}
|
||||
else if(linebuf[x]<0x20) linebuf[x]=' ';
|
||||
}
|
||||
|
||||
AddCheatEntry(strdup(namebuf), strdup(linebuf), addr, val, compare, status, type, length, bigendian);
|
||||
tc++;
|
||||
}
|
||||
}
|
||||
|
||||
RebuildSubCheats();
|
||||
|
||||
if(!override)
|
||||
{
|
||||
if (log_cb)
|
||||
log_cb(RETRO_LOG_INFO, "%lu cheats loaded.\n", (unsigned long)cheats.size());
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteOurCheats(FILE *tmp_fp, bool needheader)
|
||||
{
|
||||
if(needheader)
|
||||
trio_fprintf(tmp_fp, "[%s] %s\n", md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str(), MDFNGameInfo->name ? (char *)MDFNGameInfo->name : "");
|
||||
|
||||
std::vector<CHEATF>::iterator next;
|
||||
|
||||
for(next = cheats.begin(); next != cheats.end(); next++)
|
||||
{
|
||||
if(next->type == 'C')
|
||||
{
|
||||
if(next->length == 1)
|
||||
trio_fprintf(tmp_fp, "%c %c %d %c %d %08x %02llx %02llx %s\n", next->type, next->status ? 'A' : 'I', next->length, next->bigendian ? 'B' : 'L', next->icount, next->addr, next->val, next->compare, next->name);
|
||||
else if(next->length == 2)
|
||||
trio_fprintf(tmp_fp, "%c %c %d %c %d %08x %04llx %04llx %s\n", next->type, next->status ? 'A' : 'I', next->length, next->bigendian ? 'B' : 'L', next->icount, next->addr, next->val, next->compare, next->name);
|
||||
else
|
||||
trio_fprintf(tmp_fp, "%c %c %d %c %d %08x %016llx %016llx %s\n", next->type, next->status ? 'A' : 'I', next->length, next->bigendian ? 'B' : 'L', next->icount, next->addr, next->val, next->compare, next->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(next->length == 1)
|
||||
trio_fprintf(tmp_fp, "%c %c %d %c %d %08x %02llx %s\n", next->type, next->status ? 'A' : 'I', next->length, next->bigendian ? 'B' : 'L', next->icount, next->addr, next->val, next->name);
|
||||
else if(next->length == 2)
|
||||
trio_fprintf(tmp_fp, "%c %c %d %c %d %08x %04llx %s\n", next->type, next->status ? 'A' : 'I', next->length, next->bigendian ? 'B' : 'L', next->icount, next->addr, next->val, next->name);
|
||||
else
|
||||
trio_fprintf(tmp_fp, "%c %c %d %c %d %08x %016llx %s\n", next->type, next->status ? 'A' : 'I', next->length, next->bigendian ? 'B' : 'L', next->icount, next->addr, next->val, next->name);
|
||||
}
|
||||
trio_fprintf(tmp_fp, "%s\n", next->conditions ? next->conditions : "");
|
||||
free(next->name);
|
||||
if(next->conditions)
|
||||
free(next->conditions);
|
||||
}
|
||||
}
|
||||
|
||||
void MDFN_FlushGameCheats(int nosave)
|
||||
{
|
||||
if(CheatComp)
|
||||
{
|
||||
free(CheatComp);
|
||||
CheatComp = 0;
|
||||
}
|
||||
std::vector<CHEATF>::iterator chit;
|
||||
|
||||
if(!savecheats || nosave)
|
||||
{
|
||||
std::vector<CHEATF>::iterator chit;
|
||||
|
||||
for(chit = cheats.begin(); chit != cheats.end(); chit++)
|
||||
{
|
||||
free(chit->name);
|
||||
if(chit->conditions)
|
||||
free(chit->conditions);
|
||||
}
|
||||
cheats.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8 linebuf[2048];
|
||||
std::string fn, tmp_fn;
|
||||
|
||||
fn = MDFN_MakeFName(MDFNMKF_CHEAT, 0, 0);
|
||||
tmp_fn = MDFN_MakeFName(MDFNMKF_CHEAT_TMP, 0, 0);
|
||||
|
||||
FILE *fp;
|
||||
int insection = 0;
|
||||
|
||||
if((fp = fopen(fn.c_str(), "rb")))
|
||||
{
|
||||
FILE *tmp_fp = fopen(tmp_fn.c_str(), "wb");
|
||||
|
||||
while(fgets((char*)linebuf, 2048, fp) > 0)
|
||||
for(chit = cheats.begin(); chit != cheats.end(); chit++)
|
||||
{
|
||||
if(linebuf[0] == '[' && !insection)
|
||||
{
|
||||
if(!strncmp((char *)linebuf + 1, md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str(), 16))
|
||||
{
|
||||
insection = 1;
|
||||
if(cheats.size())
|
||||
fputs((char*)linebuf, tmp_fp);
|
||||
}
|
||||
else
|
||||
fputs((char*)linebuf, tmp_fp);
|
||||
}
|
||||
else if(insection == 1)
|
||||
{
|
||||
if(linebuf[0] == '[')
|
||||
{
|
||||
// Write any of our game cheats here.
|
||||
WriteOurCheats(tmp_fp, 0);
|
||||
insection = 2;
|
||||
fputs((char*)linebuf, tmp_fp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fputs((char*)linebuf, tmp_fp);
|
||||
}
|
||||
free(chit->name);
|
||||
if(chit->conditions)
|
||||
free(chit->conditions);
|
||||
}
|
||||
cheats.clear();
|
||||
|
||||
if(cheats.size())
|
||||
{
|
||||
if(!insection)
|
||||
WriteOurCheats(tmp_fp, 1);
|
||||
else if(insection == 1)
|
||||
WriteOurCheats(tmp_fp, 0);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fclose(tmp_fp);
|
||||
|
||||
#ifdef WIN32
|
||||
unlink(fn.c_str()); // Windows is evil. EVIIILL. rename() won't overwrite an existing file. TODO: Change this to an autoconf define or something
|
||||
// if we ever come across other platforms with lame rename().
|
||||
#endif
|
||||
rename(tmp_fn.c_str(), fn.c_str());
|
||||
}
|
||||
else if(errno == ENOENT) // Only overwrite the cheats file if it doesn't exist...heh. Race conditions abound!
|
||||
{
|
||||
fp = fopen(fn.c_str(), "wb");
|
||||
WriteOurCheats(fp, 1);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
RebuildSubCheats();
|
||||
RebuildSubCheats();
|
||||
}
|
||||
|
||||
int MDFNI_AddCheat(const char *name, uint32 addr, uint64 val, uint64 compare, char type, unsigned int length, bool bigendian)
|
||||
@ -636,36 +385,33 @@ static bool TestConditions(const char *string)
|
||||
|
||||
void MDFNMP_ApplyPeriodicCheats(void)
|
||||
{
|
||||
std::vector<CHEATF>::iterator chit;
|
||||
std::vector<CHEATF>::iterator chit;
|
||||
|
||||
if(!CheatsActive)
|
||||
return;
|
||||
|
||||
if(!CheatsActive)
|
||||
return;
|
||||
for(chit = cheats.begin(); chit != cheats.end(); chit++)
|
||||
{
|
||||
if(chit->status && chit->type == 'R')
|
||||
{
|
||||
if(!chit->conditions || TestConditions(chit->conditions))
|
||||
for(unsigned int x = 0; x < chit->length; x++)
|
||||
{
|
||||
uint32 page = ((chit->addr + x) / PageSize) % NumPages;
|
||||
if(RAMPtrs[page])
|
||||
{
|
||||
uint64 tmpval = chit->val;
|
||||
|
||||
//TestConditions("2 L 0x1F00F5 == 0xDEAD");
|
||||
//if(TestConditions("1 L 0x1F0058 > 0")) //, 1 L 0xC000 == 0x01"));
|
||||
for(chit = cheats.begin(); chit != cheats.end(); chit++)
|
||||
{
|
||||
if(chit->status && chit->type == 'R')
|
||||
{
|
||||
if(!chit->conditions || TestConditions(chit->conditions))
|
||||
for(unsigned int x = 0; x < chit->length; x++)
|
||||
{
|
||||
uint32 page = ((chit->addr + x) / PageSize) % NumPages;
|
||||
if(RAMPtrs[page])
|
||||
{
|
||||
uint64 tmpval = chit->val;
|
||||
if(chit->bigendian)
|
||||
tmpval >>= (chit->length - 1 - x) * 8;
|
||||
else
|
||||
tmpval >>= x * 8;
|
||||
|
||||
if(chit->bigendian)
|
||||
tmpval >>= (chit->length - 1 - x) * 8;
|
||||
else
|
||||
tmpval >>= x * 8;
|
||||
|
||||
RAMPtrs[page][(chit->addr + x) % PageSize] = tmpval;
|
||||
}
|
||||
RAMPtrs[page][(chit->addr + x) % PageSize] = tmpval;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -909,202 +655,6 @@ int MDFNI_ToggleCheat(uint32 which)
|
||||
return(cheats[which].status);
|
||||
}
|
||||
|
||||
void MDFNI_CheatSearchSetCurrentAsOriginal(void)
|
||||
{
|
||||
for(uint32 page = 0; page < NumPages; page++)
|
||||
{
|
||||
if(CheatComp[page])
|
||||
{
|
||||
for(uint32 addr = 0; addr < PageSize; addr++)
|
||||
{
|
||||
if(!CheatComp[page][addr].excluded)
|
||||
{
|
||||
CheatComp[page][addr].value = RAMPtrs[page][addr];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MDFNI_CheatSearchShowExcluded(void)
|
||||
{
|
||||
for(uint32 page = 0; page < NumPages; page++)
|
||||
{
|
||||
if(CheatComp[page])
|
||||
{
|
||||
for(uint32 addr = 0; addr < PageSize; addr++)
|
||||
{
|
||||
CheatComp[page][addr].excluded = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32 MDFNI_CheatSearchGetCount(void)
|
||||
{
|
||||
uint32 count = 0;
|
||||
|
||||
for(uint32 page = 0; page < NumPages; page++)
|
||||
{
|
||||
if(CheatComp[page])
|
||||
{
|
||||
for(uint32 addr = 0; addr < PageSize; addr++)
|
||||
{
|
||||
if(!CheatComp[page][addr].excluded)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* This function will give the initial value of the search and the current value at a location. */
|
||||
|
||||
void MDFNI_CheatSearchGet(int (*callb)(uint32 a, uint64 last, uint64 current, void *data), void *data)
|
||||
{
|
||||
for(uint32 page = 0; page < NumPages; page++)
|
||||
{
|
||||
if(CheatComp[page])
|
||||
{
|
||||
for(uint32 addr = 0; addr < PageSize; addr++)
|
||||
{
|
||||
if(!CheatComp[page][addr].excluded)
|
||||
{
|
||||
uint64 ccval;
|
||||
uint64 ramval;
|
||||
|
||||
ccval = ramval = 0;
|
||||
for(unsigned int x = 0; x < resultsbytelen; x++)
|
||||
{
|
||||
uint32 curpage = (page + (addr + x) / PageSize) % NumPages;
|
||||
if(CheatComp[curpage])
|
||||
{
|
||||
unsigned int shiftie;
|
||||
|
||||
if(resultsbigendian)
|
||||
shiftie = (resultsbytelen - 1 - x) * 8;
|
||||
else
|
||||
shiftie = x * 8;
|
||||
ccval |= CheatComp[curpage][(addr + x) % PageSize].value << shiftie;
|
||||
ramval |= RAMPtrs[curpage][(addr + x) % PageSize] << shiftie;
|
||||
}
|
||||
}
|
||||
|
||||
if(!callb(page * PageSize + addr, ccval, ramval, data))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MDFNI_CheatSearchBegin(void)
|
||||
{
|
||||
resultsbytelen = 1;
|
||||
resultsbigendian = 0;
|
||||
|
||||
for(uint32 page = 0; page < NumPages; page++)
|
||||
{
|
||||
if(RAMPtrs[page])
|
||||
{
|
||||
if(!CheatComp[page])
|
||||
CheatComp[page] = (CompareStruct *)calloc(PageSize, sizeof(CompareStruct));
|
||||
|
||||
for(uint32 addr = 0; addr < PageSize; addr++)
|
||||
{
|
||||
CheatComp[page][addr].excluded = 0;
|
||||
CheatComp[page][addr].value = RAMPtrs[page][addr];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint64 INLINE CAbs(uint64 x)
|
||||
{
|
||||
if(x < 0)
|
||||
return(0 - x);
|
||||
return x;
|
||||
}
|
||||
|
||||
void MDFNI_CheatSearchEnd(int type, uint64 v1, uint64 v2, unsigned int bytelen, bool bigendian)
|
||||
{
|
||||
v1 &= (~0ULL) >> (8 - bytelen);
|
||||
v2 &= (~0ULL) >> (8 - bytelen);
|
||||
|
||||
resultsbytelen = bytelen;
|
||||
resultsbigendian = bigendian;
|
||||
|
||||
for(uint32 page = 0; page < NumPages; page++)
|
||||
{
|
||||
if(CheatComp[page])
|
||||
{
|
||||
for(uint32 addr = 0; addr < PageSize; addr++)
|
||||
{
|
||||
if(!CheatComp[page][addr].excluded)
|
||||
{
|
||||
bool doexclude = 0;
|
||||
uint64 ccval;
|
||||
uint64 ramval;
|
||||
|
||||
ccval = ramval = 0;
|
||||
for(unsigned int x = 0; x < bytelen; x++)
|
||||
{
|
||||
uint32 curpage = (page + (addr + x) / PageSize) % NumPages;
|
||||
if(CheatComp[curpage])
|
||||
{
|
||||
unsigned int shiftie;
|
||||
|
||||
if(bigendian)
|
||||
shiftie = (bytelen - 1 - x) * 8;
|
||||
else
|
||||
shiftie = x * 8;
|
||||
ccval |= CheatComp[curpage][(addr + x) % PageSize].value << shiftie;
|
||||
ramval |= RAMPtrs[curpage][(addr + x) % PageSize] << shiftie;
|
||||
}
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case 0: // Change to a specific value.
|
||||
if(!(ccval == v1 && ramval == v2))
|
||||
doexclude = 1;
|
||||
break;
|
||||
|
||||
case 1: // Search for relative change(between values).
|
||||
if(!(ccval == v1 && CAbs(ccval - ramval) == v2))
|
||||
doexclude = 1;
|
||||
break;
|
||||
|
||||
case 2: // Purely relative change.
|
||||
if(!(CAbs(ccval - ramval) == v2))
|
||||
doexclude = 1;
|
||||
break;
|
||||
case 3: // Any change
|
||||
if(!(ccval != ramval))
|
||||
doexclude = 1;
|
||||
break;
|
||||
case 4: // Value decreased
|
||||
if(ramval >= ccval)
|
||||
doexclude = 1;
|
||||
break;
|
||||
case 5: // Value increased
|
||||
if(ramval <= ccval)
|
||||
doexclude = 1;
|
||||
break;
|
||||
}
|
||||
if(doexclude)
|
||||
CheatComp[page][addr].excluded = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(type >= 4)
|
||||
MDFNI_CheatSearchSetCurrentAsOriginal();
|
||||
}
|
||||
|
||||
static void SettingChanged(const char *name)
|
||||
{
|
||||
MDFNMP_RemoveReadPatches();
|
||||
|
Loading…
Reference in New Issue
Block a user