Cheats: Use internal memory handlers which can't trash MMIO
Safer and faster.
This commit is contained in:
parent
ffc0a5def4
commit
13aa5e0554
|
@ -14,6 +14,74 @@ Log_SetChannel(Cheats);
|
|||
|
||||
using KeyValuePairVector = std::vector<std::pair<std::string, std::string>>;
|
||||
|
||||
static bool IsValidScanAddress(PhysicalMemoryAddress address)
|
||||
{
|
||||
if ((address & CPU::DCACHE_LOCATION_MASK) == CPU::DCACHE_LOCATION &&
|
||||
(address & CPU::DCACHE_OFFSET_MASK) < CPU::DCACHE_SIZE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
address &= CPU::PHYSICAL_MEMORY_ADDRESS_MASK;
|
||||
|
||||
if (address < Bus::RAM_MIRROR_END)
|
||||
return true;
|
||||
|
||||
if (address >= Bus::BIOS_BASE && address < (Bus::BIOS_BASE + Bus::BIOS_SIZE))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T DoMemoryRead(PhysicalMemoryAddress address)
|
||||
{
|
||||
T result;
|
||||
|
||||
if ((address & CPU::DCACHE_LOCATION_MASK) == CPU::DCACHE_LOCATION &&
|
||||
(address & CPU::DCACHE_OFFSET_MASK) < CPU::DCACHE_SIZE)
|
||||
{
|
||||
std::memcpy(&result, &CPU::g_state.dcache[address & CPU::DCACHE_OFFSET_MASK], sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
address &= CPU::PHYSICAL_MEMORY_ADDRESS_MASK;
|
||||
|
||||
if (address < Bus::RAM_MIRROR_END)
|
||||
{
|
||||
std::memcpy(&result, &Bus::g_ram[address & Bus::RAM_MASK], sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (address >= Bus::BIOS_BASE && address < (Bus::BIOS_BASE + Bus::BIOS_SIZE))
|
||||
{
|
||||
std::memcpy(&result, &Bus::g_bios[address & Bus::BIOS_MASK], sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
result = static_cast<T>(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void DoMemoryWrite(PhysicalMemoryAddress address, T value)
|
||||
{
|
||||
if ((address & CPU::DCACHE_LOCATION_MASK) == CPU::DCACHE_LOCATION &&
|
||||
(address & CPU::DCACHE_OFFSET_MASK) < CPU::DCACHE_SIZE)
|
||||
{
|
||||
std::memcpy(&CPU::g_state.dcache[address & CPU::DCACHE_OFFSET_MASK], &value, sizeof(value));
|
||||
return;
|
||||
}
|
||||
|
||||
address &= CPU::PHYSICAL_MEMORY_ADDRESS_MASK;
|
||||
|
||||
if (address < Bus::RAM_MIRROR_END)
|
||||
{
|
||||
std::memcpy(&Bus::g_ram[address & Bus::RAM_MASK], &value, sizeof(value));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CheatList::CheatList() = default;
|
||||
|
||||
CheatList::~CheatList() = default;
|
||||
|
@ -533,65 +601,60 @@ void CheatCode::Apply() const
|
|||
|
||||
case InstructionCode::ConstantWrite8:
|
||||
{
|
||||
CPU::SafeWriteMemoryByte(inst.address, inst.value8);
|
||||
DoMemoryWrite<u8>(inst.address, inst.value8);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ConstantWrite16:
|
||||
{
|
||||
CPU::SafeWriteMemoryHalfWord(inst.address, inst.value16);
|
||||
DoMemoryWrite<u16>(inst.address, inst.value16);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ScratchpadWrite16:
|
||||
{
|
||||
CPU::SafeWriteMemoryHalfWord(CPU::DCACHE_LOCATION | (inst.address & CPU::DCACHE_OFFSET_MASK), inst.value16);
|
||||
DoMemoryWrite<u16>(CPU::DCACHE_LOCATION | (inst.address & CPU::DCACHE_OFFSET_MASK), inst.value16);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::Increment16:
|
||||
{
|
||||
u16 value = 0;
|
||||
CPU::SafeReadMemoryHalfWord(inst.address, &value);
|
||||
CPU::SafeWriteMemoryHalfWord(inst.address, value + inst.value16);
|
||||
u16 value = DoMemoryRead<u16>(inst.address);
|
||||
DoMemoryWrite<u16>(inst.address, value + inst.value16);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::Decrement16:
|
||||
{
|
||||
u16 value = 0;
|
||||
CPU::SafeReadMemoryHalfWord(inst.address, &value);
|
||||
CPU::SafeWriteMemoryHalfWord(inst.address, value - inst.value16);
|
||||
u16 value = DoMemoryRead<u16>(inst.address);
|
||||
DoMemoryWrite<u16>(inst.address, value - inst.value16);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::Increment8:
|
||||
{
|
||||
u8 value = 0;
|
||||
CPU::SafeReadMemoryByte(inst.address, &value);
|
||||
CPU::SafeWriteMemoryByte(inst.address, value + inst.value8);
|
||||
u8 value = DoMemoryRead<u8>(inst.address);
|
||||
DoMemoryWrite<u8>(inst.address, value + inst.value8);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::Decrement8:
|
||||
{
|
||||
u8 value = 0;
|
||||
CPU::SafeReadMemoryByte(inst.address, &value);
|
||||
CPU::SafeWriteMemoryByte(inst.address, value - inst.value8);
|
||||
u8 value = DoMemoryRead<u8>(inst.address);
|
||||
DoMemoryWrite<u8>(inst.address, value - inst.value8);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::CompareEqual16:
|
||||
{
|
||||
u16 value = 0;
|
||||
CPU::SafeReadMemoryHalfWord(inst.address, &value);
|
||||
u16 value = DoMemoryRead<u16>(inst.address);
|
||||
if (value == inst.value16)
|
||||
index++;
|
||||
else
|
||||
|
@ -601,8 +664,7 @@ void CheatCode::Apply() const
|
|||
|
||||
case InstructionCode::CompareNotEqual16:
|
||||
{
|
||||
u16 value = 0;
|
||||
CPU::SafeReadMemoryHalfWord(inst.address, &value);
|
||||
u16 value = DoMemoryRead<u16>(inst.address);
|
||||
if (value != inst.value16)
|
||||
index++;
|
||||
else
|
||||
|
@ -612,8 +674,7 @@ void CheatCode::Apply() const
|
|||
|
||||
case InstructionCode::CompareLess16:
|
||||
{
|
||||
u16 value = 0;
|
||||
CPU::SafeReadMemoryHalfWord(inst.address, &value);
|
||||
u16 value = DoMemoryRead<u16>(inst.address);
|
||||
if (value < inst.value16)
|
||||
index++;
|
||||
else
|
||||
|
@ -623,8 +684,7 @@ void CheatCode::Apply() const
|
|||
|
||||
case InstructionCode::CompareGreater16:
|
||||
{
|
||||
u16 value = 0;
|
||||
CPU::SafeReadMemoryHalfWord(inst.address, &value);
|
||||
u16 value = DoMemoryRead<u16>(inst.address);
|
||||
if (value > inst.value16)
|
||||
index++;
|
||||
else
|
||||
|
@ -634,8 +694,7 @@ void CheatCode::Apply() const
|
|||
|
||||
case InstructionCode::CompareEqual8:
|
||||
{
|
||||
u8 value = 0;
|
||||
CPU::SafeReadMemoryByte(inst.address, &value);
|
||||
u8 value = DoMemoryRead<u8>(inst.address);
|
||||
if (value == inst.value8)
|
||||
index++;
|
||||
else
|
||||
|
@ -645,8 +704,7 @@ void CheatCode::Apply() const
|
|||
|
||||
case InstructionCode::CompareNotEqual8:
|
||||
{
|
||||
u8 value = 0;
|
||||
CPU::SafeReadMemoryByte(inst.address, &value);
|
||||
u8 value = DoMemoryRead<u8>(inst.address);
|
||||
if (value != inst.value8)
|
||||
index++;
|
||||
else
|
||||
|
@ -656,8 +714,7 @@ void CheatCode::Apply() const
|
|||
|
||||
case InstructionCode::CompareLess8:
|
||||
{
|
||||
u8 value = 0;
|
||||
CPU::SafeReadMemoryByte(inst.address, &value);
|
||||
u8 value = DoMemoryRead<u8>(inst.address);
|
||||
if (value < inst.value8)
|
||||
index++;
|
||||
else
|
||||
|
@ -667,8 +724,7 @@ void CheatCode::Apply() const
|
|||
|
||||
case InstructionCode::CompareGreater8:
|
||||
{
|
||||
u8 value = 0;
|
||||
CPU::SafeReadMemoryByte(inst.address, &value);
|
||||
u8 value = DoMemoryRead<u8>(inst.address);
|
||||
if (value > inst.value8)
|
||||
index++;
|
||||
else
|
||||
|
@ -696,7 +752,7 @@ void CheatCode::Apply() const
|
|||
{
|
||||
for (u32 i = 0; i < slide_count; i++)
|
||||
{
|
||||
CPU::SafeWriteMemoryByte(address, Truncate8(value));
|
||||
DoMemoryWrite<u8>(address, Truncate8(value));
|
||||
address += address_increment;
|
||||
value += value_increment;
|
||||
}
|
||||
|
@ -705,7 +761,7 @@ void CheatCode::Apply() const
|
|||
{
|
||||
for (u32 i = 0; i < slide_count; i++)
|
||||
{
|
||||
CPU::SafeWriteMemoryHalfWord(address, value);
|
||||
DoMemoryWrite<u16>(address, value);
|
||||
address += address_increment;
|
||||
value += value_increment;
|
||||
}
|
||||
|
@ -734,9 +790,8 @@ void CheatCode::Apply() const
|
|||
|
||||
for (u32 i = 0; i < byte_count; i++)
|
||||
{
|
||||
u8 value = 0;
|
||||
CPU::SafeReadMemoryByte(src_address, &value);
|
||||
CPU::SafeWriteMemoryByte(dst_address, value);
|
||||
u8 value = DoMemoryRead<u8>(src_address);
|
||||
DoMemoryWrite<u8>(dst_address, value);
|
||||
src_address++;
|
||||
dst_address++;
|
||||
}
|
||||
|
@ -837,21 +892,6 @@ void MemoryScan::Search()
|
|||
}
|
||||
}
|
||||
|
||||
static bool IsValidScanAddress(PhysicalMemoryAddress address)
|
||||
{
|
||||
address &= CPU::PHYSICAL_MEMORY_ADDRESS_MASK;
|
||||
if (address < Bus::RAM_MIRROR_END)
|
||||
return true;
|
||||
|
||||
if (address >= CPU::DCACHE_LOCATION && address < (CPU::DCACHE_LOCATION + CPU::DCACHE_SIZE))
|
||||
return true;
|
||||
|
||||
if (address >= Bus::BIOS_BASE && address < (Bus::BIOS_BASE + Bus::BIOS_SIZE))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MemoryScan::SearchBytes()
|
||||
{
|
||||
for (PhysicalMemoryAddress address = m_start_address; address < m_end_address; address++)
|
||||
|
@ -859,8 +899,7 @@ void MemoryScan::SearchBytes()
|
|||
if (!IsValidScanAddress(address))
|
||||
continue;
|
||||
|
||||
u8 bvalue = 0;
|
||||
CPU::SafeReadMemoryByte(address, &bvalue);
|
||||
const u8 bvalue = DoMemoryRead<u8>(address);
|
||||
|
||||
Result res;
|
||||
res.address = address;
|
||||
|
@ -880,8 +919,7 @@ void MemoryScan::SearchHalfwords()
|
|||
if (!IsValidScanAddress(address))
|
||||
continue;
|
||||
|
||||
u16 bvalue = 0;
|
||||
CPU::SafeReadMemoryHalfWord(address, &bvalue);
|
||||
const u16 bvalue = DoMemoryRead<u16>(address);
|
||||
|
||||
Result res;
|
||||
res.address = address;
|
||||
|
@ -903,7 +941,7 @@ void MemoryScan::SearchWords()
|
|||
|
||||
Result res;
|
||||
res.address = address;
|
||||
CPU::SafeReadMemoryWord(address, &res.value);
|
||||
res.value = DoMemoryRead<u32>(address);
|
||||
res.last_value = res.value;
|
||||
res.value_changed = false;
|
||||
|
||||
|
@ -948,11 +986,11 @@ void MemoryScan::SetResultValue(u32 index, u32 value)
|
|||
switch (m_size)
|
||||
{
|
||||
case MemoryAccessSize::Byte:
|
||||
CPU::SafeWriteMemoryByte(res.address, Truncate8(value));
|
||||
DoMemoryWrite<u8>(res.address, Truncate8(value));
|
||||
break;
|
||||
|
||||
case MemoryAccessSize::HalfWord:
|
||||
CPU::SafeWriteMemoryHalfWord(res.address, Truncate16(value));
|
||||
DoMemoryWrite<u16>(res.address, Truncate16(value));
|
||||
break;
|
||||
|
||||
case MemoryAccessSize::Word:
|
||||
|
@ -1064,16 +1102,14 @@ void MemoryScan::Result::UpdateValue(MemoryAccessSize size, bool is_signed)
|
|||
{
|
||||
case MemoryAccessSize::Byte:
|
||||
{
|
||||
u8 bvalue = 0;
|
||||
CPU::SafeReadMemoryByte(address, &bvalue);
|
||||
u8 bvalue = DoMemoryRead<u8>(address);
|
||||
value = is_signed ? SignExtend32(bvalue) : ZeroExtend32(bvalue);
|
||||
}
|
||||
break;
|
||||
|
||||
case MemoryAccessSize::HalfWord:
|
||||
{
|
||||
u16 bvalue = 0;
|
||||
CPU::SafeReadMemoryHalfWord(address, &bvalue);
|
||||
u16 bvalue = DoMemoryRead<u16>(address);
|
||||
value = is_signed ? SignExtend32(bvalue) : ZeroExtend32(bvalue);
|
||||
}
|
||||
break;
|
||||
|
@ -1205,15 +1241,15 @@ void MemoryWatchList::SetEntryValue(Entry* entry, u32 value)
|
|||
switch (entry->size)
|
||||
{
|
||||
case MemoryAccessSize::Byte:
|
||||
CPU::SafeWriteMemoryByte(entry->address, Truncate8(value));
|
||||
DoMemoryWrite<u8>(entry->address, Truncate8(value));
|
||||
break;
|
||||
|
||||
case MemoryAccessSize::HalfWord:
|
||||
CPU::SafeWriteMemoryHalfWord(entry->address, Truncate16(value));
|
||||
DoMemoryWrite<u16>(entry->address, Truncate16(value));
|
||||
break;
|
||||
|
||||
case MemoryAccessSize::Word:
|
||||
CPU::SafeWriteMemoryWord(entry->address, value);
|
||||
DoMemoryWrite<u32>(entry->address, value);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1229,23 +1265,21 @@ void MemoryWatchList::UpdateEntryValue(Entry* entry)
|
|||
{
|
||||
case MemoryAccessSize::Byte:
|
||||
{
|
||||
u8 bvalue = 0;
|
||||
CPU::SafeReadMemoryByte(entry->address, &bvalue);
|
||||
u8 bvalue = DoMemoryRead<u8>(entry->address);
|
||||
entry->value = entry->is_signed ? SignExtend32(bvalue) : ZeroExtend32(bvalue);
|
||||
}
|
||||
break;
|
||||
|
||||
case MemoryAccessSize::HalfWord:
|
||||
{
|
||||
u16 bvalue = 0;
|
||||
CPU::SafeReadMemoryHalfWord(entry->address, &bvalue);
|
||||
u16 bvalue = DoMemoryRead<u16>(entry->address);
|
||||
entry->value = entry->is_signed ? SignExtend32(bvalue) : ZeroExtend32(bvalue);
|
||||
}
|
||||
break;
|
||||
|
||||
case MemoryAccessSize::Word:
|
||||
{
|
||||
CPU::SafeReadMemoryWord(entry->address, &entry->value);
|
||||
entry->value = DoMemoryRead<u32>(entry->address);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue