Merge pull request #1736 from PugsyMAME/master

Added new cheat cheat types: C3, C4, C5, C6, D7&52
This commit is contained in:
Connor McLaughlin 2021-03-07 02:46:50 +10:00 committed by GitHub
commit fd7d77bc70
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 243 additions and 5 deletions

View file

@ -15,6 +15,7 @@
#include <iomanip>
#include <sstream>
Log_SetChannel(Cheats);
static std::array<u32, 256> temp_variable; //Used for D7 ,51 & 52 cheat types
using KeyValuePairVector = std::vector<std::pair<std::string, std::string>>;
@ -138,6 +139,58 @@ static u32 GetControllerButtonBits()
return translated_bits;
}
static u32 GetControllerAnalogBits()
{
// 0x010000 - Right Thumb Up
// 0x020000 - Right Thumb Right
// 0x040000 - Right Thumb Down
// 0x080000 - Right Thumb Left
// 0x100000 - Left Thumb Up
// 0x200000 - Left Thumb Right
// 0x400000 - Left Thumb Down
// 0x800000 - Left Thumb Left
u32 bits = 0;
u8 l_ypos = 0;
u8 l_xpos = 0;
u8 r_ypos = 0;
u8 r_xpos = 0;
std::optional<u32> analog = 0;
for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++)
{
Controller* controller = System::GetController(i);
if (!controller)
continue;
analog = controller->GetAnalogInputBytes();
if (analog.has_value())
{
l_ypos = Truncate8((analog.value() & 0xFF000000u) >> 24);
l_xpos = Truncate8((analog.value() & 0x00FF0000u) >> 16);
r_ypos = Truncate8((analog.value() & 0x0000FF00u) >> 8);
r_xpos = Truncate8(analog.value() & 0x000000FFu);
if (l_ypos < 0x50)
bits |= 0x100000;
else if (l_ypos > 0xA0)
bits |= 0x400000;
if (l_xpos < 0x50)
bits |= 0x800000;
else if (l_xpos > 0xA0)
bits |= 0x200000;
if (r_ypos < 0x50)
bits |= 0x10000;
else if (r_ypos > 0xA0)
bits |= 0x40000;
if (r_xpos < 0x50)
bits |= 0x80000;
else if (r_xpos > 0xA0)
bits |= 0x20000;
}
}
return bits;
}
CheatList::CheatList() = default;
CheatList::~CheatList() = default;
@ -632,11 +685,8 @@ bool CheatList::LoadFromString(const std::string& str, Format format)
return LoadFromPCSXRString(str);
else if (format == Format::Libretro)
return LoadFromLibretroString(str);
else if (format == Format::EPSXe)
format = Format::EPSXe;
return LoadFromEPSXeString(str);
Log_ErrorPrintf("Invalid or unknown cheat format");
return false;
}
bool CheatList::SaveToPCSXRFile(const char* filename)
@ -1420,10 +1470,109 @@ void CheatCode::Apply() const
}
break;
case InstructionCode::ExtTempVariable: // 51
{
const u32 poke_value = inst.address;
const u8 temp_variable_number1 = Truncate8(inst.value32 & 0xFFu);
const u8 temp_variable_number2 = Truncate8((inst.value32 & 0xFF00u) >> 8);
const u8 sub_type = Truncate8((inst.value32 & 0xFF0000u) >> 16);
switch (sub_type)
{
case 0x00: // Write the u8 from temp_variable[temp_variable_number1] to address
DoMemoryWrite<u8>(inst.address, Truncate8(temp_variable[temp_variable_number1]));
index++;
break;
case 0x01: // Read the u8 from address to temp_variable[temp_variable_number1]
temp_variable[temp_variable_number1] = DoMemoryRead<u8>(inst.address);
index++;
break;
case 0x02: // Write the u8 from address field to the address stored in temp_variable[temp_variable_number1]
DoMemoryWrite<u8>(temp_variable[temp_variable_number1], Truncate8(poke_value));
index++;
break;
case 0x10: // Write the u16 from temp_variable[temp_variable_number1] to address
DoMemoryWrite<u16>(inst.address, Truncate16(temp_variable[temp_variable_number1]));
index++;
break;
case 0x11: // Read the u16 from address to temp_variable[temp_variable_number1]
temp_variable[temp_variable_number1] = DoMemoryRead<u16>(inst.address);
index++;
break;
case 0x12: // Write the u16 from address field to the address stored in temp_variable[temp_variable_number1]
DoMemoryWrite<u16>(temp_variable[temp_variable_number1], Truncate16(poke_value));
index++;
break;
case 0x30: // Write the u32 from temp_variable[temp_variable_number1] to address
DoMemoryWrite<u32>(inst.address, temp_variable[temp_variable_number1]);
index++;
break;
case 0x31: // Read the u32 from address to temp_variable[temp_variable_number1]
temp_variable[temp_variable_number1] = DoMemoryRead<u32>(inst.address);
index++;
break;
case 0x32: // Write the u16 from address field to the address stored in temp_variable[temp_variable_number]
DoMemoryWrite<u32>(temp_variable[temp_variable_number1], poke_value);
index++;
break;
case 0x04: // Write the u8 from temp_variable[temp_variable_number2] to the address stored in
// temp_variable[temp_variable_number1]
DoMemoryWrite<u8>(temp_variable[temp_variable_number1], Truncate8(temp_variable[temp_variable_number2]));
index++;
break;
case 0x14: // Write the u16 from temp_variable[temp_variable_number2] to the address stored in
// temp_variable[temp_variable_number1]
DoMemoryWrite<u16>(temp_variable[temp_variable_number1], Truncate16(temp_variable[temp_variable_number2]));
index++;
break;
case 0x24: // Write the u32 from temp_variable[temp_variable_number2] to the address stored in
// temp_variable[temp_variable_number1]
DoMemoryWrite<u32>(temp_variable[temp_variable_number1], temp_variable[temp_variable_number2]);
index++;
break;
case 0x34: // Write the u16 from address field to the address stored in temp_variable[temp_variable_number]
DoMemoryWrite<u32>(temp_variable[temp_variable_number1], poke_value);
index++;
break;
case 0x05: // Write the u8 from the address stored in temp_variable[temp_variable_number2] to the address
// stored in temp_variable[temp_variable_number1]
DoMemoryWrite<u8>(temp_variable[temp_variable_number1],
DoMemoryRead<u8>(temp_variable[temp_variable_number2]));
index++;
break;
case 0x15: // Write the u16 from the address stored in temp_variable[temp_variable_number2] to the address
// stored in temp_variable[temp_variable_number1]
DoMemoryWrite<u16>(temp_variable[temp_variable_number1],
DoMemoryRead<u16>(temp_variable[temp_variable_number2]));
index++;
break;
case 0x25: // Write the u32 from the address stored in temp_variable[temp_variable_number2] to the address
// stored in temp_variable[temp_variable_number1]
DoMemoryWrite<u32>(temp_variable[temp_variable_number1],
DoMemoryRead<u32>(temp_variable[temp_variable_number2]));
index++;
break;
// Lots of options exist for expanding into this space
default:
index++;
break;
}
}
break;
case InstructionCode::SkipIfNotEqual16: // C0
case InstructionCode::ExtSkipIfNotEqual32: // A4
case InstructionCode::SkipIfButtonsNotEqual: // D5
case InstructionCode::SkipIfButtonsEqual: // D6
case InstructionCode::ExtSkipIfNotLess8: // C3
case InstructionCode::ExtSkipIfNotGreater8: // C4
case InstructionCode::ExtSkipIfNotLess16: // C5
case InstructionCode::ExtSkipIfNotGreater16: // C6
{
index++;
@ -1442,6 +1591,18 @@ void CheatCode::Apply() const
case InstructionCode::SkipIfButtonsEqual: // D6
activate_codes = (GetControllerButtonBits() != inst.value16);
break;
case InstructionCode::ExtSkipIfNotLess8: // C3
activate_codes = (DoMemoryRead<u8>(inst.address) < inst.value8);
break;
case InstructionCode::ExtSkipIfNotGreater8: // C4
activate_codes = (DoMemoryRead<u8>(inst.address) > inst.value8);
break;
case InstructionCode::ExtSkipIfNotLess16: // C5
activate_codes = (DoMemoryRead<u16>(inst.address) < inst.value16);
break;
case InstructionCode::ExtSkipIfNotGreater16: // C6
activate_codes = (DoMemoryRead<u16>(inst.address) > inst.value16);
break;
default:
activate_codes = false;
break;
@ -1465,6 +1626,69 @@ void CheatCode::Apply() const
}
break;
case InstructionCode::ExtBitCompareButtons: // D7
{
index++;
bool activate_codes;
const u32 frame_compare_value = inst.address & 0xFFFFu;
const u8 temp_variable_number = Truncate8((inst.value32 & 0xFF000000u)>>24);
const bool bit_comparison_type = ((inst.address & 0x100000u) >>20);
const u8 frame_comparison = Truncate8((inst.address & 0xF0000u) >>16);
const u32 check_value = (inst.value32 & 0xFFFFFFu);
const u32 value1 = GetControllerButtonBits();
const u32 value2 = GetControllerAnalogBits();
u32 value = value1 | value2;
if ((bit_comparison_type==false && check_value==(value & check_value))//Check Bits are set
|| (bit_comparison_type==true && check_value!=(value & check_value))) //Check Bits are clear
{
temp_variable[temp_variable_number]+=1;
switch (frame_comparison)
{
case 0x0: // No comparison on frame count, just do it
activate_codes = true;
break;
case 0x1: // Check if frame_compare_value == current count
activate_codes = (temp_variable[temp_variable_number] == frame_compare_value);
break;
case 0x2: // Check if frame_compare_value < current count
activate_codes = (temp_variable[temp_variable_number] < frame_compare_value);
break;
case 0x3: // Check if frame_compare_value > current count
activate_codes = (temp_variable[temp_variable_number] > frame_compare_value);
break;
case 0x4: // Check if frame_compare_value != current count
activate_codes = (temp_variable[temp_variable_number] != frame_compare_value);
break;
default:
activate_codes = false;
break;
}
}
else
{
temp_variable[temp_variable_number]=0;
activate_codes = false;
}
if (activate_codes)
{
// execute following instructions
continue;
}
// skip to the next separator (00000000 FFFF), or end
constexpr u64 separator_value = UINT64_C(0x000000000000FFFF);
while (index < count)
{
// we don't want to execute the separator instruction
const u64 bits = instructions[index++].bits;
if (bits == separator_value)
break;
}
}
break;
case InstructionCode::DelayActivation: // C1
{
// A value of around 4000 or 5000 will usually give you a good 20-30 second delay before codes are activated.
@ -1588,6 +1812,7 @@ void CheatCode::ApplyOnDisable() const
case InstructionCode::ExtConstantForceRangeRollRound16:
case InstructionCode::DelayActivation: // C1
case InstructionCode::ExtConstantWriteIfMatch16:
case InstructionCode::ExtTempVariable:
index++;
break;
@ -1621,6 +1846,11 @@ void CheatCode::ApplyOnDisable() const
case InstructionCode::ExtSkipIfNotEqual32: // A4
case InstructionCode::SkipIfButtonsNotEqual: // D5
case InstructionCode::SkipIfButtonsEqual: // D6
case InstructionCode::ExtBitCompareButtons: // D7
case InstructionCode::ExtSkipIfNotLess8: // C3
case InstructionCode::ExtSkipIfNotGreater8: // C4
case InstructionCode::ExtSkipIfNotLess16: // C5
case InstructionCode::ExtSkipIfNotGreater16: // C6
index++;
break;

View file

@ -69,6 +69,14 @@ struct CheatCode
ExtConstantBitClear16 = 0x82,
ExtConstantBitSet32 = 0x91,
ExtConstantBitClear32 = 0x92,
ExtBitCompareButtons = 0xD7,
ExtSkipIfNotLess8 = 0xC3,
ExtSkipIfNotGreater8 = 0xC4,
ExtSkipIfNotLess16 = 0xC5,
ExtSkipIfNotGreater16 = 0xC6,
ExtTempVariable = 0x51,
};
union Instruction