mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-19 06:45:39 +00:00
Merge pull request #1736 from PugsyMAME/master
Added new cheat cheat types: C3, C4, C5, C6, D7&52
This commit is contained in:
commit
fd7d77bc70
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue