mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-22 22:05:38 +00:00
Cheats: Add additional code types from @PugsyMAME
This commit is contained in:
parent
7dcacc2cda
commit
3f410ebbac
|
@ -694,10 +694,12 @@ std::vector<std::string> CheatList::GetCodeGroups() const
|
|||
|
||||
void CheatList::SetCodeEnabled(u32 index, bool state)
|
||||
{
|
||||
if (index >= m_codes.size())
|
||||
if (index >= m_codes.size() || m_codes[index].enabled == state)
|
||||
return;
|
||||
|
||||
m_codes[index].enabled = state;
|
||||
if (!state)
|
||||
m_codes[index].ApplyOnDisable();
|
||||
}
|
||||
|
||||
void CheatList::EnableCode(u32 index)
|
||||
|
@ -887,6 +889,54 @@ void CheatCode::Apply() const
|
|||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantBitSet8:
|
||||
{
|
||||
const u8 value = DoMemoryRead<u8>(inst.address) | inst.value8;
|
||||
DoMemoryWrite<u8>(inst.address, value);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantBitSet16:
|
||||
{
|
||||
const u16 value = DoMemoryRead<u16>(inst.address) | inst.value16;
|
||||
DoMemoryWrite<u16>(inst.address, value);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantBitSet32:
|
||||
{
|
||||
const u32 value = DoMemoryRead<u32>(inst.address) | inst.value32;
|
||||
DoMemoryWrite<u32>(inst.address, value);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantBitClear8:
|
||||
{
|
||||
const u8 value = DoMemoryRead<u8>(inst.address) & ~inst.value8;
|
||||
DoMemoryWrite<u8>(inst.address, value);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantBitClear16:
|
||||
{
|
||||
const u16 value = DoMemoryRead<u16>(inst.address) & ~inst.value16;
|
||||
DoMemoryWrite<u16>(inst.address, value);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantBitClear32:
|
||||
{
|
||||
const u32 value = DoMemoryRead<u32>(inst.address) & ~inst.value32;
|
||||
DoMemoryWrite<u32>(inst.address, value);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ScratchpadWrite16:
|
||||
{
|
||||
DoMemoryWrite<u16>(CPU::DCACHE_LOCATION | (inst.address & CPU::DCACHE_OFFSET_MASK), inst.value16);
|
||||
|
@ -989,6 +1039,77 @@ void CheatCode::Apply() const
|
|||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantWriteIfMatch16:
|
||||
case InstructionCode::ExtConstantWriteIfMatchWithRestore16:
|
||||
{
|
||||
const u16 value = DoMemoryRead<u16>(inst.address);
|
||||
const u16 comparevalue = Truncate16(inst.value32 >> 16);
|
||||
const u16 newvalue = Truncate16(inst.value32 & 0xFFFFu);
|
||||
if (value == comparevalue)
|
||||
DoMemoryWrite<u16>(inst.address, newvalue);
|
||||
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantForceRange8:
|
||||
{
|
||||
const u8 value = DoMemoryRead<u8>(inst.address);
|
||||
const u8 min = Truncate8(inst.value32 & 0x000000FFu);
|
||||
const u8 max = Truncate8((inst.value32 & 0x0000FF00u) >> 8);
|
||||
const u8 overmin = Truncate8((inst.value32 & 0x00FF0000u) >> 16);
|
||||
const u8 overmax = Truncate8((inst.value32 & 0xFF000000u) >> 24);
|
||||
if ((value < min) || (value < min && min == 0x00u && max < 0xFEu))
|
||||
DoMemoryWrite<u8>(inst.address, overmin); // also handles a min value of 0x00
|
||||
else if (value > max)
|
||||
DoMemoryWrite<u8>(inst.address, overmax);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantForceRangeLimits16:
|
||||
{
|
||||
const u16 value = DoMemoryRead<u16>(inst.address);
|
||||
const u16 min = Truncate16(inst.value32 & 0x0000FFFFu);
|
||||
const u16 max = Truncate16((inst.value32 & 0xFFFF0000u) >> 16);
|
||||
if ((value < min) || (value < min && min == 0x0000u && max < 0xFFFEu))
|
||||
DoMemoryWrite<u16>(inst.address, min); // also handles a min value of 0x0000
|
||||
else if (value > max)
|
||||
DoMemoryWrite<u16>(inst.address, max);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantForceRangeRollRound16:
|
||||
{
|
||||
const u16 value = DoMemoryRead<u16>(inst.address);
|
||||
const u16 min = Truncate16(inst.value32 & 0x0000FFFFu);
|
||||
const u16 max = Truncate16((inst.value32 & 0xFFFF0000u) >> 16);
|
||||
if ((value < min) || (value < min && min == 0x0000u && max < 0xFFFEu))
|
||||
DoMemoryWrite<u16>(inst.address, max); // also handles a min value of 0x0000
|
||||
else if (value > max)
|
||||
DoMemoryWrite<u16>(inst.address, min);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantForceRange16:
|
||||
{
|
||||
const u16 min = Truncate16(inst.value32 & 0x0000FFFFu);
|
||||
const u16 max = Truncate16((inst.value32 & 0xFFFF0000u) >> 16);
|
||||
const u16 value = DoMemoryRead<u16>(inst.address);
|
||||
const Instruction& inst2 = instructions[index + 1];
|
||||
const u16 overmin = Truncate16(inst2.value32 & 0x0000FFFFu);
|
||||
const u16 overmax = Truncate16((inst2.value32 & 0xFFFF0000u) >> 16);
|
||||
|
||||
if ((value < min) || (value < min && min == 0x0000u && max < 0xFFFEu))
|
||||
DoMemoryWrite<u16>(inst.address, overmin); // also handles a min value of 0x0000
|
||||
else if (value > max)
|
||||
DoMemoryWrite<u16>(inst.address, overmax);
|
||||
index += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCode::CompareEqual16:
|
||||
{
|
||||
const u16 value = DoMemoryRead<u16>(inst.address);
|
||||
|
@ -1214,6 +1335,95 @@ void CheatCode::Apply() const
|
|||
}
|
||||
}
|
||||
|
||||
void CheatCode::ApplyOnDisable() const
|
||||
{
|
||||
const u32 count = static_cast<u32>(instructions.size());
|
||||
u32 index = 0;
|
||||
for (; index < count;)
|
||||
{
|
||||
const Instruction& inst = instructions[index];
|
||||
switch (inst.code)
|
||||
{
|
||||
case InstructionCode::Nop:
|
||||
case InstructionCode::ConstantWrite8:
|
||||
case InstructionCode::ConstantWrite16:
|
||||
case InstructionCode::ExtConstantWrite32:
|
||||
case InstructionCode::ExtConstantBitSet8:
|
||||
case InstructionCode::ExtConstantBitSet16:
|
||||
case InstructionCode::ExtConstantBitSet32:
|
||||
case InstructionCode::ExtConstantBitClear8:
|
||||
case InstructionCode::ExtConstantBitClear16:
|
||||
case InstructionCode::ExtConstantBitClear32:
|
||||
case InstructionCode::ScratchpadWrite16:
|
||||
case InstructionCode::ExtScratchpadWrite32:
|
||||
case InstructionCode::ExtIncrement32:
|
||||
case InstructionCode::ExtDecrement32:
|
||||
case InstructionCode::Increment16:
|
||||
case InstructionCode::Decrement16:
|
||||
case InstructionCode::Increment8:
|
||||
case InstructionCode::Decrement8:
|
||||
case InstructionCode::ExtConstantForceRange8:
|
||||
case InstructionCode::ExtConstantForceRangeLimits16:
|
||||
case InstructionCode::ExtConstantForceRangeRollRound16:
|
||||
case InstructionCode::DelayActivation: // C1
|
||||
case InstructionCode::ExtConstantWriteIfMatch16:
|
||||
index++;
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantForceRange16:
|
||||
case InstructionCode::Slide:
|
||||
case InstructionCode::MemoryCopy:
|
||||
index += 2;
|
||||
break;
|
||||
|
||||
// for conditionals, we don't want to skip over in case it changed at some point
|
||||
case InstructionCode::ExtCompareEqual32:
|
||||
case InstructionCode::ExtCompareNotEqual32:
|
||||
case InstructionCode::ExtCompareLess32:
|
||||
case InstructionCode::ExtCompareGreater32:
|
||||
case InstructionCode::CompareEqual16:
|
||||
case InstructionCode::CompareNotEqual16:
|
||||
case InstructionCode::CompareLess16:
|
||||
case InstructionCode::CompareGreater16:
|
||||
case InstructionCode::CompareEqual8:
|
||||
case InstructionCode::CompareNotEqual8:
|
||||
case InstructionCode::CompareLess8:
|
||||
case InstructionCode::CompareGreater8:
|
||||
case InstructionCode::CompareButtons: // D4
|
||||
index++;
|
||||
break;
|
||||
|
||||
// same deal for block conditionals
|
||||
case InstructionCode::SkipIfNotEqual16: // C0
|
||||
case InstructionCode::ExtSkipIfNotEqual32: // A4
|
||||
case InstructionCode::SkipIfButtonsNotEqual: // D5
|
||||
case InstructionCode::SkipIfButtonsEqual: // D6
|
||||
index++;
|
||||
break;
|
||||
|
||||
case InstructionCode::ExtConstantWriteIfMatchWithRestore16:
|
||||
{
|
||||
const u16 value = DoMemoryRead<u16>(inst.address);
|
||||
const u16 comparevalue = Truncate16(inst.value32 >> 16);
|
||||
const u16 newvalue = Truncate16(inst.value32 & 0xFFFFu);
|
||||
if (value == newvalue)
|
||||
DoMemoryWrite<u16>(inst.address, comparevalue);
|
||||
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
Log_ErrorPrintf("Unhandled instruction code 0x%02X (%08X %08X)", static_cast<u8>(inst.code.GetValue()),
|
||||
inst.first, inst.second);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::array<const char*, 1> s_cheat_code_type_names = {{"Gameshark"}};
|
||||
static std::array<const char*, 1> s_cheat_code_type_display_names{{TRANSLATABLE("Cheats", "Gameshark")}};
|
||||
|
||||
|
|
|
@ -56,6 +56,18 @@ struct CheatCode
|
|||
ExtSkipIfNotEqual32 = 0xA4,
|
||||
ExtIncrement32 = 0x60,
|
||||
ExtDecrement32 = 0x61,
|
||||
ExtConstantWriteIfMatch16 = 0xA6,
|
||||
ExtConstantWriteIfMatchWithRestore16 = 0xA7,
|
||||
ExtConstantForceRange8 = 0xF0,
|
||||
ExtConstantForceRangeLimits16 = 0xF1,
|
||||
ExtConstantForceRangeRollRound16 = 0xF2,
|
||||
ExtConstantForceRange16 = 0xF3,
|
||||
ExtConstantBitSet8 = 0x31,
|
||||
ExtConstantBitClear8 = 0x32,
|
||||
ExtConstantBitSet16 = 0x81,
|
||||
ExtConstantBitClear16 = 0x82,
|
||||
ExtConstantBitSet32 = 0x91,
|
||||
ExtConstantBitClear32 = 0x92,
|
||||
};
|
||||
|
||||
union Instruction
|
||||
|
@ -92,6 +104,7 @@ struct CheatCode
|
|||
u32 GetNextNonConditionalInstruction(u32 index) const;
|
||||
|
||||
void Apply() const;
|
||||
void ApplyOnDisable() const;
|
||||
|
||||
static const char* GetTypeName(Type type);
|
||||
static const char* GetTypeDisplayName(Type type);
|
||||
|
|
Loading…
Reference in a new issue