Cheat System: Standardize memory writes for all cheat types. Most notably, Internal cheats now reset the JIT in the same way as Action Replay cheats do.
This commit is contained in:
parent
12347c7cd9
commit
f240472f5e
|
@ -3216,6 +3216,99 @@ bool validateIORegsRead(u32 addr, u8 size)
|
||||||
#define VALIDATE_IO_REGS_READ(PROC, SIZE) ;
|
#define VALIDATE_IO_REGS_READ(PROC, SIZE) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <typename T, size_t LENGTH>
|
||||||
|
bool MMU_WriteFromExternal(const int targetProc, const u32 targetAddress, T newValue)
|
||||||
|
{
|
||||||
|
u32 oldValue32;
|
||||||
|
|
||||||
|
switch (LENGTH)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
if (sizeof(T) > LENGTH)
|
||||||
|
newValue &= 0x000000FF;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
if (sizeof(T) > LENGTH)
|
||||||
|
newValue &= 0x0000FFFF;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
oldValue32 = _MMU_read32(targetProc, MMU_AT_DEBUG, targetAddress);
|
||||||
|
if (sizeof(T) > LENGTH)
|
||||||
|
newValue = (oldValue32 & 0xFF000000) | (newValue & 0x00FFFFFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
oldValue32 = _MMU_read32(targetProc, MMU_AT_DEBUG, targetAddress);
|
||||||
|
if (sizeof(T) > LENGTH)
|
||||||
|
newValue &= 0xFFFFFFFF;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needsJitReset = ( (targetAddress >= 0x02000000) && (targetAddress < 0x02400000) );
|
||||||
|
if (needsJitReset)
|
||||||
|
{
|
||||||
|
bool willValueChange = false;
|
||||||
|
|
||||||
|
switch (LENGTH)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
willValueChange = (_MMU_read08(targetProc, MMU_AT_DEBUG, targetAddress) != (u8)newValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
willValueChange = (_MMU_read16(targetProc, MMU_AT_DEBUG, targetAddress) != (u16)newValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
willValueChange = (oldValue32 != (u32)newValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!willValueChange)
|
||||||
|
{
|
||||||
|
needsJitReset = false;
|
||||||
|
return needsJitReset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (LENGTH)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
_MMU_write08(targetProc, MMU_AT_DEBUG, targetAddress, (u8)newValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
_MMU_write16(targetProc, MMU_AT_DEBUG, targetAddress, (u16)newValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
_MMU_write32(targetProc, MMU_AT_DEBUG, targetAddress, (u32)newValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return needsJitReset;
|
||||||
|
}
|
||||||
|
|
||||||
|
template bool MMU_WriteFromExternal< u8, 1>(const int targetProc, const u32 targetAddress, u8 newValue);
|
||||||
|
template bool MMU_WriteFromExternal<u16, 2>(const int targetProc, const u32 targetAddress, u16 newValue);
|
||||||
|
template bool MMU_WriteFromExternal<u32, 1>(const int targetProc, const u32 targetAddress, u32 newValue);
|
||||||
|
template bool MMU_WriteFromExternal<u32, 2>(const int targetProc, const u32 targetAddress, u32 newValue);
|
||||||
|
template bool MMU_WriteFromExternal<u32, 3>(const int targetProc, const u32 targetAddress, u32 newValue);
|
||||||
|
template bool MMU_WriteFromExternal<u32, 4>(const int targetProc, const u32 targetAddress, u32 newValue);
|
||||||
|
|
||||||
//================================================================================================== ARM9 *
|
//================================================================================================== ARM9 *
|
||||||
//=========================================================================================================
|
//=========================================================================================================
|
||||||
//=========================================================================================================
|
//=========================================================================================================
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2006 yopyop
|
Copyright (C) 2006 yopyop
|
||||||
Copyright (C) 2007 shash
|
Copyright (C) 2007 shash
|
||||||
Copyright (C) 2007-2017 DeSmuME team
|
Copyright (C) 2007-2023 DeSmuME team
|
||||||
|
|
||||||
This file is free software: you can redistribute it and/or modify
|
This file is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -626,6 +626,10 @@ FORCEINLINE void* MMU_gpu_map(const u32 vram_addr)
|
||||||
return MMU.ARM9_LCD + (vram_page << 14) + ofs;
|
return MMU.ARM9_LCD + (vram_page << 14) + ofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call MMU_WriteFromExternal() when modifying memory outside of the normal execution process, such
|
||||||
|
// as when using cheats or when the client wants to write to memory directly. This function returns
|
||||||
|
// true if memory is modified in such a way that requires the JIT execution be reset.
|
||||||
|
template<typename T, size_t LENGTH> bool MMU_WriteFromExternal(const int targetProc, const u32 targetAddress, T newValue);
|
||||||
|
|
||||||
template<int PROCNUM, MMU_ACCESS_TYPE AT> u8 _MMU_read08(u32 addr);
|
template<int PROCNUM, MMU_ACCESS_TYPE AT> u8 _MMU_read08(u32 addr);
|
||||||
template<int PROCNUM, MMU_ACCESS_TYPE AT> u16 _MMU_read16(u32 addr);
|
template<int PROCNUM, MMU_ACCESS_TYPE AT> u16 _MMU_read16(u32 addr);
|
||||||
|
|
|
@ -1454,8 +1454,11 @@ static void execHardware_hstart_vblankStart()
|
||||||
|
|
||||||
//for ARM7, cheats process when a vblank IRQ fires. necessary for AR compatibility and to stop cheats from breaking game boot-ups.
|
//for ARM7, cheats process when a vblank IRQ fires. necessary for AR compatibility and to stop cheats from breaking game boot-ups.
|
||||||
//note that how we process raw cheats is up to us. so we'll do it the same way we used to, elsewhere
|
//note that how we process raw cheats is up to us. so we'll do it the same way we used to, elsewhere
|
||||||
if (i==1 && cheats)
|
if ( (i == 1) && (cheats != NULL) )
|
||||||
|
{
|
||||||
cheats->process(CHEAT_TYPE_AR);
|
cheats->process(CHEAT_TYPE_AR);
|
||||||
|
CHEATS::ResetJitIfNeeded();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2197,7 +2200,11 @@ void NDS_exec(s32 nb)
|
||||||
}
|
}
|
||||||
currFrameCounter++;
|
currFrameCounter++;
|
||||||
DEBUG_Notify.NextFrame();
|
DEBUG_Notify.NextFrame();
|
||||||
if(cheats) cheats->process(CHEAT_TYPE_INTERNAL);
|
if (cheats != NULL)
|
||||||
|
{
|
||||||
|
cheats->process(CHEAT_TYPE_INTERNAL);
|
||||||
|
CHEATS::ResetJitIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
GDBSTUB_MUTEX_UNLOCK();
|
GDBSTUB_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ static const char hexValid[23] = {"0123456789ABCDEFabcdef"};
|
||||||
CHEATS *cheats = NULL;
|
CHEATS *cheats = NULL;
|
||||||
CHEATSEARCH *cheatSearch = NULL;
|
CHEATSEARCH *cheatSearch = NULL;
|
||||||
|
|
||||||
static bool cheatsResetJit;
|
static bool cheatsResetJit = false;
|
||||||
|
|
||||||
void CHEATS::clear()
|
void CHEATS::clear()
|
||||||
{
|
{
|
||||||
|
@ -143,34 +143,34 @@ bool CHEATS::move(size_t srcPos, size_t dstPos)
|
||||||
#define CHEATLOG(...)
|
#define CHEATLOG(...)
|
||||||
//#define CHEATLOG(...) printf(__VA_ARGS__)
|
//#define CHEATLOG(...) printf(__VA_ARGS__)
|
||||||
|
|
||||||
static void CheatWrite(int size, int proc, u32 addr, u32 val)
|
template <size_t LENGTH>
|
||||||
|
bool CHEATS::DirectWrite(const int targetProc, const u32 targetAddress, u32 newValue)
|
||||||
{
|
{
|
||||||
bool dirty = true;
|
return MMU_WriteFromExternal<u32, LENGTH>(targetProc, targetAddress, newValue);
|
||||||
|
|
||||||
bool isDangerous = false;
|
|
||||||
if(addr >= 0x02000000 && addr < 0x02400000)
|
|
||||||
isDangerous = true;
|
|
||||||
|
|
||||||
if(isDangerous)
|
|
||||||
{
|
|
||||||
//test dirtiness
|
|
||||||
if(size == 8) dirty = _MMU_read08(proc, MMU_AT_DEBUG, addr) != val;
|
|
||||||
if(size == 16) dirty = _MMU_read16(proc, MMU_AT_DEBUG, addr) != val;
|
|
||||||
if(size == 32) dirty = _MMU_read32(proc, MMU_AT_DEBUG, addr) != val;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!dirty) return;
|
|
||||||
|
|
||||||
if(size == 8) _MMU_write08(proc, MMU_AT_DEBUG, addr, val);
|
|
||||||
if(size == 16) _MMU_write16(proc, MMU_AT_DEBUG, addr, val);
|
|
||||||
if(size == 32) _MMU_write32(proc, MMU_AT_DEBUG, addr, val);
|
|
||||||
|
|
||||||
if(isDangerous)
|
|
||||||
cheatsResetJit = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template bool CHEATS::DirectWrite<1>(const int targetProc, const u32 targetAddress, u32 newValue);
|
||||||
|
template bool CHEATS::DirectWrite<2>(const int targetProc, const u32 targetAddress, u32 newValue);
|
||||||
|
template bool CHEATS::DirectWrite<3>(const int targetProc, const u32 targetAddress, u32 newValue);
|
||||||
|
template bool CHEATS::DirectWrite<4>(const int targetProc, const u32 targetAddress, u32 newValue);
|
||||||
|
|
||||||
void CHEATS::ARparser(const CHEATS_LIST &theList)
|
bool CHEATS::DirectWrite(const size_t newValueLength, const int targetProc, const u32 targetAddress, u32 newValue)
|
||||||
|
{
|
||||||
|
switch (newValueLength)
|
||||||
|
{
|
||||||
|
case 1: return CHEATS::DirectWrite<1>(targetProc, targetAddress, newValue);
|
||||||
|
case 2: return CHEATS::DirectWrite<2>(targetProc, targetAddress, newValue);
|
||||||
|
case 3: return CHEATS::DirectWrite<3>(targetProc, targetAddress, newValue);
|
||||||
|
case 4: return CHEATS::DirectWrite<4>(targetProc, targetAddress, newValue);
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
{
|
{
|
||||||
//primary organizational source (seems to be referenced by cheaters the most) - http://doc.kodewerx.org/hacking_nds.html
|
//primary organizational source (seems to be referenced by cheaters the most) - http://doc.kodewerx.org/hacking_nds.html
|
||||||
//secondary clarification and details (for programmers) - http://problemkaputt.de/gbatek.htm#dscartcheatactionreplayds
|
//secondary clarification and details (for programmers) - http://problemkaputt.de/gbatek.htm#dscartcheatactionreplayds
|
||||||
|
@ -184,6 +184,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
|
|
||||||
bool v154 = true; //on advice of power users, v154 is so old, we can assume all cheats use it
|
bool v154 = true; //on advice of power users, v154 is so old, we can assume all cheats use it
|
||||||
bool vEmulator = true;
|
bool vEmulator = true;
|
||||||
|
bool needsJitReset = false;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
//LSB is
|
//LSB is
|
||||||
|
@ -218,6 +219,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
|
|
||||||
for (u32 i = 0; i < theList.num; i++)
|
for (u32 i = 0; i < theList.num; i++)
|
||||||
{
|
{
|
||||||
|
bool shouldResetJit = false;
|
||||||
const u32 hi = theList.code[i][0];
|
const u32 hi = theList.code[i][0];
|
||||||
const u32 lo = theList.code[i][1];
|
const u32 lo = theList.code[i][1];
|
||||||
|
|
||||||
|
@ -273,7 +275,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
x = hi & 0x0FFFFFFF;
|
x = hi & 0x0FFFFFFF;
|
||||||
y = lo;
|
y = lo;
|
||||||
addr = x + st.offset;
|
addr = x + st.offset;
|
||||||
CheatWrite(32,st.proc,addr, y);
|
shouldResetJit = CHEATS::DirectWrite<4>(st.proc, addr, y);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x01:
|
case 0x01:
|
||||||
|
@ -283,7 +285,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
x = hi & 0x0FFFFFFF;
|
x = hi & 0x0FFFFFFF;
|
||||||
y = lo & 0xFFFF;
|
y = lo & 0xFFFF;
|
||||||
addr = x + st.offset;
|
addr = x + st.offset;
|
||||||
CheatWrite(16,st.proc,addr, y);
|
shouldResetJit = CHEATS::DirectWrite<2>(st.proc, addr, y);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02:
|
case 0x02:
|
||||||
|
@ -293,7 +295,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
x = hi & 0x0FFFFFFF;
|
x = hi & 0x0FFFFFFF;
|
||||||
y = lo & 0xFF;
|
y = lo & 0xFF;
|
||||||
addr = x + st.offset;
|
addr = x + st.offset;
|
||||||
CheatWrite(8,st.proc,addr, y);
|
shouldResetJit = CHEATS::DirectWrite<1>(st.proc, addr, y);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03:
|
case 0x03:
|
||||||
|
@ -443,7 +445,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
//<gbatek> C6000000 XXXXXXXX [XXXXXXXX]=offset
|
//<gbatek> C6000000 XXXXXXXX [XXXXXXXX]=offset
|
||||||
if(!v154) break;
|
if(!v154) break;
|
||||||
x = lo;
|
x = lo;
|
||||||
CheatWrite(32,st.proc,x, st.offset);
|
shouldResetJit = CHEATS::DirectWrite<4>(st.proc, x, st.offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xD0:
|
case 0xD0:
|
||||||
|
@ -524,7 +526,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
//<gbatek> word[XXXXXXXX+offset]=datareg, offset=offset+4
|
//<gbatek> word[XXXXXXXX+offset]=datareg, offset=offset+4
|
||||||
x = lo;
|
x = lo;
|
||||||
addr = x + st.offset;
|
addr = x + st.offset;
|
||||||
CheatWrite(32,st.proc,addr, st.data);
|
shouldResetJit = CHEATS::DirectWrite<4>(st.proc, addr, st.data);
|
||||||
st.offset += 4;
|
st.offset += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -535,7 +537,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
//<gbatek> half[XXXXXXXX+offset]=datareg, offset=offset+2
|
//<gbatek> half[XXXXXXXX+offset]=datareg, offset=offset+2
|
||||||
x = lo;
|
x = lo;
|
||||||
addr = x + st.offset;
|
addr = x + st.offset;
|
||||||
CheatWrite(16,st.proc,addr, st.data);
|
shouldResetJit = CHEATS::DirectWrite<2>(st.proc, addr, st.data);
|
||||||
st.offset += 2;
|
st.offset += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -546,7 +548,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
//<gbatek> byte[XXXXXXXX+offset]=datareg, offset=offset+1
|
//<gbatek> byte[XXXXXXXX+offset]=datareg, offset=offset+1
|
||||||
x = lo;
|
x = lo;
|
||||||
addr = x + st.offset;
|
addr = x + st.offset;
|
||||||
CheatWrite(8,st.proc,addr, st.data);
|
shouldResetJit = CHEATS::DirectWrite<1>(st.proc, addr, st.data);
|
||||||
st.offset += 1;
|
st.offset += 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -623,7 +625,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
u32 tmp = theList.code[i][t];
|
u32 tmp = theList.code[i][t];
|
||||||
if (t == 1) i++;
|
if (t == 1) i++;
|
||||||
t ^= 1;
|
t ^= 1;
|
||||||
CheatWrite(32,st.proc,addr,tmp);
|
shouldResetJit = CHEATS::DirectWrite<4>(st.proc, addr, tmp);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
y -= 4;
|
y -= 4;
|
||||||
}
|
}
|
||||||
|
@ -631,7 +633,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
{
|
{
|
||||||
if (i == theList.num) break; //if we erroneously went off the end, bail
|
if (i == theList.num) break; //if we erroneously went off the end, bail
|
||||||
u32 tmp = theList.code[i][t]>>b;
|
u32 tmp = theList.code[i][t]>>b;
|
||||||
CheatWrite(8,st.proc,addr,tmp);
|
shouldResetJit = CHEATS::DirectWrite<1>(st.proc, addr, tmp);
|
||||||
addr += 1;
|
addr += 1;
|
||||||
y -= 1;
|
y -= 1;
|
||||||
b += 4;
|
b += 4;
|
||||||
|
@ -657,7 +659,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
{
|
{
|
||||||
if (i == theList.num) break; //if we erroneously went off the end, bail
|
if (i == theList.num) break; //if we erroneously went off the end, bail
|
||||||
u32 tmp = _MMU_read32(st.proc,MMU_AT_DEBUG,addr);
|
u32 tmp = _MMU_read32(st.proc,MMU_AT_DEBUG,addr);
|
||||||
CheatWrite(32, st.proc,operand,tmp);
|
shouldResetJit = CHEATS::DirectWrite<4>(st.proc, operand, tmp);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
operand += 4;
|
operand += 4;
|
||||||
y -= 4;
|
y -= 4;
|
||||||
|
@ -666,7 +668,7 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
{
|
{
|
||||||
if (i == theList.num) break; //if we erroneously went off the end, bail
|
if (i == theList.num) break; //if we erroneously went off the end, bail
|
||||||
u8 tmp = _MMU_read08(st.proc,MMU_AT_DEBUG,addr);
|
u8 tmp = _MMU_read08(st.proc,MMU_AT_DEBUG,addr);
|
||||||
CheatWrite(8,st.proc,operand,tmp);
|
shouldResetJit = CHEATS::DirectWrite<1>(st.proc, operand, tmp);
|
||||||
addr += 1;
|
addr += 1;
|
||||||
operand += 1;
|
operand += 1;
|
||||||
y -= 1;
|
y -= 1;
|
||||||
|
@ -677,8 +679,14 @@ void CHEATS::ARparser(const CHEATS_LIST &theList)
|
||||||
printf("AR: ERROR unknown command %08X %08X\n", hi, lo);
|
printf("AR: ERROR unknown command %08X %08X\n", hi, lo);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shouldResetJit)
|
||||||
|
{
|
||||||
|
needsJitReset = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return needsJitReset;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CHEATS::add_AR_Direct(const CHEATS_LIST &srcCheat)
|
size_t CHEATS::add_AR_Direct(const CHEATS_LIST &srcCheat)
|
||||||
|
@ -1140,73 +1148,82 @@ bool CHEATS::load()
|
||||||
return didLoadAllItems;
|
return didLoadAllItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHEATS::process(int targetType) const
|
bool CHEATS::process(int targetType) const
|
||||||
{
|
{
|
||||||
if (CommonSettings.cheatsDisable) return;
|
bool needsJitReset = false;
|
||||||
|
|
||||||
if (this->_list.size() == 0) return;
|
if (CommonSettings.cheatsDisable || (this->_list.size() == 0))
|
||||||
|
return needsJitReset;
|
||||||
cheatsResetJit = false;
|
|
||||||
|
|
||||||
size_t num = this->_list.size();
|
size_t num = this->_list.size();
|
||||||
for (size_t i = 0; i < num; i++)
|
for (size_t i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
if (this->_list[i].enabled == 0) continue;
|
bool shouldResetJit = false;
|
||||||
|
|
||||||
|
if (this->_list[i].enabled == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
int type = this->_list[i].type;
|
int type = this->_list[i].type;
|
||||||
|
|
||||||
if(type != targetType)
|
if (type != targetType)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch(type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 0: // internal cheat system
|
case CHEAT_TYPE_INTERNAL:
|
||||||
{
|
|
||||||
//INFO("list at 0x0|%07X value %i (size %i)\n",list[i].code[0], list[i].lo[0], list[i].size);
|
//INFO("list at 0x0|%07X value %i (size %i)\n",list[i].code[0], list[i].lo[0], list[i].size);
|
||||||
u32 addr = this->_list[i].code[0][0];
|
shouldResetJit = CHEATS::DirectWrite(this->_list[i].size + 1, ARMCPU_ARM9, this->_list[i].code[0][0], this->_list[i].code[0][1]);
|
||||||
u32 val = this->_list[i].code[0][1];
|
|
||||||
switch (this->_list[i].size)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
_MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr,val);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
_MMU_write16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr,val);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
u32 tmp = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr);
|
|
||||||
tmp &= 0xFF000000;
|
|
||||||
tmp |= (val & 0x00FFFFFF);
|
|
||||||
_MMU_write32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr,tmp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
_MMU_write32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr,val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
} //end case 0 internal cheat system
|
|
||||||
|
|
||||||
case 1: // Action Replay
|
case CHEAT_TYPE_AR:
|
||||||
CHEATS::ARparser(this->_list[i]);
|
shouldResetJit = CHEATS::ARparser(this->_list[i]);
|
||||||
break;
|
break;
|
||||||
case 2: // Codebreaker
|
|
||||||
|
case CHEAT_TYPE_CODEBREAKER:
|
||||||
break;
|
break;
|
||||||
default: continue;
|
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldResetJit)
|
||||||
|
{
|
||||||
|
needsJitReset = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_JIT
|
if (needsJitReset)
|
||||||
if(cheatsResetJit)
|
|
||||||
{
|
{
|
||||||
if(CommonSettings.use_jit)
|
CHEATS::JitNeedsReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return needsJitReset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHEATS::JitNeedsReset()
|
||||||
|
{
|
||||||
|
cheatsResetJit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CHEATS::ResetJitIfNeeded()
|
||||||
|
{
|
||||||
|
bool didJitReset = false;
|
||||||
|
|
||||||
|
#ifdef HAVE_JIT
|
||||||
|
if (cheatsResetJit)
|
||||||
|
{
|
||||||
|
if (CommonSettings.use_jit)
|
||||||
{
|
{
|
||||||
printf("Cheat code operation potentially not compatible with JIT operations. Resetting JIT...\n");
|
printf("Cheat code operation potentially not compatible with JIT operations. Resetting JIT...\n");
|
||||||
arm_jit_reset(true, true);
|
arm_jit_reset(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cheatsResetJit = false;
|
||||||
|
didJitReset = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return didJitReset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHEATS::StringFromXXCode(const CHEATS_LIST &srcCheatItem, char *outCStringBuffer)
|
void CHEATS::StringFromXXCode(const CHEATS_LIST &srcCheatItem, char *outCStringBuffer)
|
||||||
|
@ -1441,7 +1458,7 @@ u32 CHEATSEARCH::search(u8 comp)
|
||||||
|
|
||||||
this->_amount = 0;
|
this->_amount = 0;
|
||||||
|
|
||||||
switch (_size)
|
switch (this->_size)
|
||||||
{
|
{
|
||||||
case 0: // 1 byte
|
case 0: // 1 byte
|
||||||
for (u32 i = 0; i < (4 * 1024 * 1024); i++)
|
for (u32 i = 0; i < (4 * 1024 * 1024); i++)
|
||||||
|
@ -1561,10 +1578,10 @@ u32 CHEATSEARCH::getAmount()
|
||||||
bool CHEATSEARCH::getList(u32 *address, u32 *curVal)
|
bool CHEATSEARCH::getList(u32 *address, u32 *curVal)
|
||||||
{
|
{
|
||||||
bool didGetValue = false;
|
bool didGetValue = false;
|
||||||
u8 step = (_size+1);
|
u8 step = this->_size + 1;
|
||||||
u8 stepMem = 1;
|
u8 stepMem = 1;
|
||||||
|
|
||||||
switch (_size)
|
switch (this->_size)
|
||||||
{
|
{
|
||||||
case 1: stepMem = 0x3; break;
|
case 1: stepMem = 0x3; break;
|
||||||
case 2: stepMem = 0x7; break;
|
case 2: stepMem = 0x7; break;
|
||||||
|
@ -1580,7 +1597,7 @@ bool CHEATSEARCH::getList(u32 *address, u32 *curVal)
|
||||||
*address = i;
|
*address = i;
|
||||||
this->_lastRecord = i+step;
|
this->_lastRecord = i+step;
|
||||||
|
|
||||||
switch (_size)
|
switch (this->_size)
|
||||||
{
|
{
|
||||||
case 0: *curVal = (u32)T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i); break;
|
case 0: *curVal = (u32)T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i); break;
|
||||||
case 1: *curVal = (u32)T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i); break;
|
case 1: *curVal = (u32)T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i); break;
|
||||||
|
|
|
@ -110,9 +110,15 @@ public:
|
||||||
void setDescription(const char *description, const size_t pos);
|
void setDescription(const char *description, const size_t pos);
|
||||||
bool save();
|
bool save();
|
||||||
bool load();
|
bool load();
|
||||||
void process(int targetType) const;
|
bool process(int targetType) const;
|
||||||
|
|
||||||
static void ARparser(const CHEATS_LIST &cheat);
|
static void JitNeedsReset();
|
||||||
|
static bool ResetJitIfNeeded();
|
||||||
|
|
||||||
|
template<size_t LENGTH> static bool DirectWrite(const int targetProc, const u32 targetAddress, u32 newValue);
|
||||||
|
static bool DirectWrite(const size_t newValueLength, const int targetProc, const u32 targetAddress, u32 newValue);
|
||||||
|
|
||||||
|
static bool ARparser(const CHEATS_LIST &cheat);
|
||||||
|
|
||||||
static void StringFromXXCode(const CHEATS_LIST &srcCheatItem, char *outCStringBuffer);
|
static void StringFromXXCode(const CHEATS_LIST &srcCheatItem, char *outCStringBuffer);
|
||||||
static bool XXCodeFromString(const std::string codeString, CHEATS_LIST &outCheatItem);
|
static bool XXCodeFromString(const std::string codeString, CHEATS_LIST &outCheatItem);
|
||||||
|
@ -213,5 +219,3 @@ public:
|
||||||
|
|
||||||
extern CHEATS *cheats;
|
extern CHEATS *cheats;
|
||||||
extern CHEATSEARCH *cheatSearch;
|
extern CHEATSEARCH *cheatSearch;
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue