Added new cheat cheat types: C3, C4, C5, C6, D7&52

C3-C7 are variants of C0
D7 is a BIT based joker to rule them all. It includes the analog sticks (@ggrtk thanks for adding the analog reading capability). Also added the facility of making dual single key joker by varying the amount of time a button is held down.
51 is a complicated beast that I still need to document

* C3XXXXXX 00YY - 8-Bit Master Code, if ($XXXXXX) is less than 0xYY poke all
  00000000 FFFF       following codes for rest of the cheat or until it reaches the
                      00000000 FFFF line.
* C4XXXXXX 00YY - 8-Bit Master Code, if ($XXXXXX) is greater than 0xYY poke all
  00000000 FFFF       following codes for rest of the cheat or until it reaches the
                      00000000 FFFF line.
* C5XXXXXX YYYY - 16-Bit Master Code, if ($XXXXXX) is less than 0xYYYY poke all
  00000000 FFFF       following codes for rest of the cheat or until it reaches the
                      00000000 FFFF line.
* C6XXXXXX YYYY - 16-Bit Master Code, if ($XXXXXX) is greater than 0xYYYY poke all
  00000000 FFFF       following codes for rest of the cheat or until it reaches the
                      00000000 FFFF line.
* D7PQRRRR TTYYYYYY - 24-Bit Universal BIT Joker, OR the hex values to
                     combine into a multi-button joker. Because it is BIT
                     based it is better than D4, D5, D6 or using a D0 joker as you
                     do not need to worry about any other buttons being
                     pressed at the same time and you get both analog
                     sticks for extra functionality. Note if you want to use it
                     just as a enhanced joker just use D7000000 00YYYYYY when
                     the buttons/directions are pressed or D7100000 00YYYYYY
                     when you want to ensure they are not all pressed.
                     QRRRR TT provides the capability of only activating the
                     following codes after the keys have been held in for a set
                     amount of frames. 003C = 60 Frames = 1 Second at 100% Speed
                        YYYYYY = 000001 L2 Button
                        YYYYYY = 000002 R2 Button
                        YYYYYY = 000004 L1 Button
                        YYYYYY = 000008 R1 Button
                        YYYYYY = 000010 Triangle Button
                        YYYYYY = 000020 Circle Button
                        YYYYYY = 000040 X Button
                        YYYYYY = 000080 Square Button
                        YYYYYY = 000100 Select Button
                        YYYYYY = 000200 L3 Button
                        YYYYYY = 000400 R3 Button
                        YYYYYY = 000800 Start Button
                        YYYYYY = 001000 Up (Digital)
                        YYYYYY = 002000 Right (Digital)
                        YYYYYY = 004000 Down (Digital)
                        YYYYYY = 008000 Left (Digital)
                        YYYYYY = 010000 Up (Right Thumb)
                        YYYYYY = 020000 Right (Right Thumb)
                        YYYYYY = 040000 Down (Right Thumb)
                        YYYYYY = 080000 Left (Right Thumb)
                        YYYYYY = 100000 Up (Left Thumb)
                        YYYYYY = 200000 Right (Left Thumb)
                        YYYYYY = 400000 Down (Left Thumb)
                        YYYYYY = 800000 Left (Left Thumb)
                      NOTE: The 0s in the code are reserved for possible
                            future use.
                       TT=Temp Internal Variable 00-FF, 00 will mean it wont be
                            used, if it's not 00 do not use the same value for
                            jokers using different keypress combinations for
                            the same game.
                       P = 0 or 1. 0 = Check ALL YYYYYY Bits are ON
                                   1 = Check ALL YYYYYY Bits are OFF
                       Q = Frame Comparison 0 = Dont do any comparison
                                            1 = Check that the button combination
                                                has been held down for exactly
                                                RRRR frames.
                                            2 = Check that the button combination
                                                has been held down for more than
                                                RRRR frames.
                                            3 = Check that the button combination
                                                has been held down for less than
                                                RRRR frames.
                                            4 = Check that the button combination
                                                has been held down for anything
                                                but RRRR frames.
                       RRRR = 0000 to FFFF, Frame Comparison Value
                      It will then poke all following codes for rest of cheat
  00000000 FFFF       or until it reaches the 00000000 FFFF line.
This commit is contained in:
PugsyMAME 2021-03-03 23:06:08 +00:00 committed by GitHub
parent 21e53016d7
commit 74b2b2ddfe
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;
@ -629,11 +682,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)
return LoadFromEPSXeString(str);
Log_ErrorPrintf("Invalid or unknown cheat format");
return false;
format = Format::EPSXe;
return LoadFromEPSXeString(str);
}
bool CheatList::SaveToPCSXRFile(const char* filename)
@ -1417,10 +1467,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++;
@ -1439,6 +1588,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;
@ -1462,6 +1623,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.
@ -1585,6 +1809,7 @@ void CheatCode::ApplyOnDisable() const
case InstructionCode::ExtConstantForceRangeRollRound16:
case InstructionCode::DelayActivation: // C1
case InstructionCode::ExtConstantWriteIfMatch16:
case InstructionCode::ExtTempVariable:
index++;
break;
@ -1618,6 +1843,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