2020-09-09 12:11:28 +00:00
|
|
|
#include "cheats.h"
|
2020-10-21 11:43:51 +00:00
|
|
|
#include "bus.h"
|
2020-10-19 15:14:49 +00:00
|
|
|
#include "common/assert.h"
|
2020-11-29 06:42:49 +00:00
|
|
|
#include "common/byte_stream.h"
|
2020-09-09 12:11:28 +00:00
|
|
|
#include "common/file_system.h"
|
|
|
|
#include "common/log.h"
|
|
|
|
#include "common/string.h"
|
|
|
|
#include "common/string_util.h"
|
2020-12-06 05:47:00 +00:00
|
|
|
#include "controller.h"
|
2020-10-22 01:09:11 +00:00
|
|
|
#include "cpu_code_cache.h"
|
2020-09-09 12:11:28 +00:00
|
|
|
#include "cpu_core.h"
|
2020-10-19 15:14:49 +00:00
|
|
|
#include "host_interface.h"
|
2020-12-06 05:47:00 +00:00
|
|
|
#include "system.h"
|
2020-09-09 12:11:28 +00:00
|
|
|
#include <cctype>
|
2020-10-19 15:14:49 +00:00
|
|
|
#include <iomanip>
|
|
|
|
#include <sstream>
|
2021-09-10 05:53:15 +00:00
|
|
|
#include <type_traits>
|
2020-09-09 12:11:28 +00:00
|
|
|
Log_SetChannel(Cheats);
|
2021-09-10 05:53:15 +00:00
|
|
|
static std::array<u32, 256> cht_register; // Used for D7 ,51 & 52 cheat types
|
2020-09-09 12:11:28 +00:00
|
|
|
|
|
|
|
using KeyValuePairVector = std::vector<std::pair<std::string, std::string>>;
|
|
|
|
|
2020-10-21 12:01:50 +00:00
|
|
|
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>
|
2021-09-10 05:53:15 +00:00
|
|
|
static T DoMemoryRead(VirtualMemoryAddress address)
|
2020-10-21 12:01:50 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
using UnsignedType = typename std::make_unsigned_t<T>;
|
|
|
|
static_assert(std::is_same_v<UnsignedType, u8> || std::is_same_v<UnsignedType, u16> ||
|
|
|
|
std::is_same_v<UnsignedType, u32>);
|
2020-10-21 12:01:50 +00:00
|
|
|
|
2021-09-10 05:53:15 +00:00
|
|
|
T result;
|
|
|
|
if constexpr (std::is_same_v<UnsignedType, u8>)
|
|
|
|
return CPU::SafeReadMemoryByte(address, &result) ? result : static_cast<T>(0);
|
|
|
|
else if constexpr (std::is_same_v<UnsignedType, u16>)
|
|
|
|
return CPU::SafeReadMemoryHalfWord(address, &result) ? result : static_cast<T>(0);
|
|
|
|
else // if constexpr (std::is_same_v<UnsignedType, u32>)
|
|
|
|
return CPU::SafeReadMemoryWord(address, &result) ? result : static_cast<T>(0);
|
2020-10-21 12:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static void DoMemoryWrite(PhysicalMemoryAddress address, T value)
|
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
using UnsignedType = typename std::make_unsigned_t<T>;
|
|
|
|
static_assert(std::is_same_v<UnsignedType, u8> || std::is_same_v<UnsignedType, u16> ||
|
|
|
|
std::is_same_v<UnsignedType, u32>);
|
|
|
|
|
|
|
|
if constexpr (std::is_same_v<UnsignedType, u8>)
|
|
|
|
CPU::SafeWriteMemoryByte(address, value);
|
|
|
|
else if constexpr (std::is_same_v<UnsignedType, u16>)
|
|
|
|
CPU::SafeWriteMemoryHalfWord(address, value);
|
|
|
|
else // if constexpr (std::is_same_v<UnsignedType, u32>)
|
|
|
|
CPU::SafeWriteMemoryWord(address, value);
|
2020-10-21 12:01:50 +00:00
|
|
|
}
|
|
|
|
|
2020-12-06 05:47:00 +00:00
|
|
|
static u32 GetControllerButtonBits()
|
|
|
|
{
|
|
|
|
static constexpr std::array<u16, 16> button_mapping = {{
|
|
|
|
0x0100, // Select
|
|
|
|
0x0200, // L3
|
|
|
|
0x0400, // R3
|
|
|
|
0x0800, // Start
|
|
|
|
0x1000, // Up
|
|
|
|
0x2000, // Right
|
|
|
|
0x4000, // Down
|
|
|
|
0x8000, // Left
|
|
|
|
0x0001, // L2
|
|
|
|
0x0002, // R2
|
|
|
|
0x0004, // L1
|
|
|
|
0x0008, // R1
|
|
|
|
0x0010, // Triangle
|
|
|
|
0x0020, // Circle
|
|
|
|
0x0040, // Cross
|
|
|
|
0x0080, // Square
|
|
|
|
}};
|
|
|
|
|
|
|
|
u32 bits = 0;
|
|
|
|
for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++)
|
|
|
|
{
|
|
|
|
Controller* controller = System::GetController(i);
|
|
|
|
if (!controller)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bits |= controller->GetButtonStateBits();
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 translated_bits = 0;
|
|
|
|
for (u32 i = 0, bit = 1; i < static_cast<u32>(button_mapping.size()); i++, bit <<= 1)
|
|
|
|
{
|
|
|
|
if (bits & bit)
|
|
|
|
translated_bits |= button_mapping[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return translated_bits;
|
|
|
|
}
|
|
|
|
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-09-09 12:11:28 +00:00
|
|
|
CheatList::CheatList() = default;
|
|
|
|
|
|
|
|
CheatList::~CheatList() = default;
|
|
|
|
|
|
|
|
static bool IsHexCharacter(char c)
|
|
|
|
{
|
|
|
|
return (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9');
|
|
|
|
}
|
|
|
|
|
2020-12-26 02:58:18 +00:00
|
|
|
static int SignedCharToInt(char ch)
|
|
|
|
{
|
|
|
|
return static_cast<int>(static_cast<unsigned char>(ch));
|
|
|
|
}
|
|
|
|
|
2020-09-09 12:11:28 +00:00
|
|
|
static const std::string* FindKey(const KeyValuePairVector& kvp, const char* search)
|
|
|
|
{
|
|
|
|
for (const auto& it : kvp)
|
|
|
|
{
|
|
|
|
if (StringUtil::Strcasecmp(it.first.c_str(), search) == 0)
|
|
|
|
return &it.second;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheatList::LoadFromPCSXRFile(const char* filename)
|
|
|
|
{
|
2020-11-07 10:36:30 +00:00
|
|
|
std::optional<std::string> str = FileSystem::ReadFileToString(filename);
|
|
|
|
if (!str.has_value() || str->empty())
|
2020-09-09 12:11:28 +00:00
|
|
|
return false;
|
|
|
|
|
2020-11-07 10:36:30 +00:00
|
|
|
return LoadFromPCSXRString(str.value());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheatList::LoadFromPCSXRString(const std::string& str)
|
|
|
|
{
|
|
|
|
std::istringstream iss(str);
|
|
|
|
|
|
|
|
std::string line;
|
2020-10-21 10:41:44 +00:00
|
|
|
std::string comments;
|
2020-10-21 10:51:36 +00:00
|
|
|
std::string group;
|
|
|
|
CheatCode::Type type = CheatCode::Type::Gameshark;
|
|
|
|
CheatCode::Activation activation = CheatCode::Activation::EndFrame;
|
2020-09-09 12:11:28 +00:00
|
|
|
CheatCode current_code;
|
2020-11-07 10:36:30 +00:00
|
|
|
while (std::getline(iss, line))
|
2020-09-09 12:11:28 +00:00
|
|
|
{
|
2020-11-07 10:36:30 +00:00
|
|
|
char* start = line.data();
|
2020-12-26 02:58:18 +00:00
|
|
|
while (*start != '\0' && std::isspace(SignedCharToInt(*start)))
|
2020-09-09 12:11:28 +00:00
|
|
|
start++;
|
|
|
|
|
|
|
|
// skip empty lines
|
|
|
|
if (*start == '\0')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
char* end = start + std::strlen(start) - 1;
|
2020-12-26 02:58:18 +00:00
|
|
|
while (end > start && std::isspace(SignedCharToInt(*end)))
|
2020-09-09 12:11:28 +00:00
|
|
|
{
|
|
|
|
*end = '\0';
|
|
|
|
end--;
|
|
|
|
}
|
|
|
|
|
2020-10-21 10:51:36 +00:00
|
|
|
// DuckStation metadata
|
|
|
|
if (StringUtil::Strncasecmp(start, "#group=", 7) == 0)
|
|
|
|
{
|
|
|
|
group = start + 7;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (StringUtil::Strncasecmp(start, "#type=", 6) == 0)
|
|
|
|
{
|
|
|
|
type = CheatCode::ParseTypeName(start + 6).value_or(CheatCode::Type::Gameshark);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (StringUtil::Strncasecmp(start, "#activation=", 12) == 0)
|
|
|
|
{
|
|
|
|
activation = CheatCode::ParseActivationName(start + 12).value_or(CheatCode::Activation::EndFrame);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-09-09 12:11:28 +00:00
|
|
|
// skip comments and empty line
|
|
|
|
if (*start == '#' || *start == ';' || *start == '/' || *start == '\"')
|
2020-10-21 10:41:44 +00:00
|
|
|
{
|
|
|
|
comments.append(start);
|
|
|
|
comments += '\n';
|
2020-09-09 12:11:28 +00:00
|
|
|
continue;
|
2020-10-21 10:41:44 +00:00
|
|
|
}
|
2020-09-09 12:11:28 +00:00
|
|
|
|
|
|
|
if (*start == '[' && *end == ']')
|
|
|
|
{
|
|
|
|
start++;
|
|
|
|
*end = '\0';
|
|
|
|
|
|
|
|
// new cheat
|
|
|
|
if (current_code.Valid())
|
|
|
|
m_codes.push_back(std::move(current_code));
|
|
|
|
|
2020-10-19 15:14:49 +00:00
|
|
|
current_code = CheatCode();
|
2020-10-21 10:51:36 +00:00
|
|
|
if (group.empty())
|
|
|
|
group = "Ungrouped";
|
|
|
|
|
|
|
|
current_code.group = std::move(group);
|
|
|
|
group = std::string();
|
2020-10-21 10:41:44 +00:00
|
|
|
current_code.comments = std::move(comments);
|
|
|
|
comments = std::string();
|
2020-10-21 10:51:36 +00:00
|
|
|
current_code.type = type;
|
|
|
|
type = CheatCode::Type::Gameshark;
|
|
|
|
current_code.activation = activation;
|
|
|
|
activation = CheatCode::Activation::EndFrame;
|
2020-10-19 15:14:49 +00:00
|
|
|
|
2020-09-09 12:11:28 +00:00
|
|
|
if (*start == '*')
|
|
|
|
{
|
|
|
|
current_code.enabled = true;
|
|
|
|
start++;
|
|
|
|
}
|
|
|
|
|
|
|
|
current_code.description.append(start);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!IsHexCharacter(*start) && start != end)
|
|
|
|
start++;
|
|
|
|
if (start == end)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
char* end_ptr;
|
|
|
|
CheatCode::Instruction inst;
|
|
|
|
inst.first = static_cast<u32>(std::strtoul(start, &end_ptr, 16));
|
|
|
|
inst.second = 0;
|
|
|
|
if (end_ptr)
|
|
|
|
{
|
|
|
|
while (!IsHexCharacter(*end_ptr) && end_ptr != end)
|
|
|
|
end_ptr++;
|
|
|
|
if (end_ptr != end)
|
|
|
|
inst.second = static_cast<u32>(std::strtoul(end_ptr, nullptr, 16));
|
|
|
|
}
|
|
|
|
current_code.instructions.push_back(inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_code.Valid())
|
2020-10-21 10:41:44 +00:00
|
|
|
{
|
2020-10-21 10:51:36 +00:00
|
|
|
// technically this isn't the place for end of file
|
2020-10-21 10:41:44 +00:00
|
|
|
if (!comments.empty())
|
|
|
|
current_code.comments += comments;
|
2020-09-09 12:11:28 +00:00
|
|
|
m_codes.push_back(std::move(current_code));
|
2020-10-21 10:41:44 +00:00
|
|
|
}
|
2020-09-09 12:11:28 +00:00
|
|
|
|
2020-11-07 10:36:30 +00:00
|
|
|
Log_InfoPrintf("Loaded %zu cheats (PCSXR format)", m_codes.size());
|
2020-09-09 12:11:28 +00:00
|
|
|
return !m_codes.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheatList::LoadFromLibretroFile(const char* filename)
|
|
|
|
{
|
2020-11-07 10:36:30 +00:00
|
|
|
std::optional<std::string> str = FileSystem::ReadFileToString(filename);
|
|
|
|
if (!str.has_value() || str->empty())
|
2020-09-09 12:11:28 +00:00
|
|
|
return false;
|
|
|
|
|
2020-11-07 10:36:30 +00:00
|
|
|
return LoadFromLibretroString(str.value());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheatList::LoadFromLibretroString(const std::string& str)
|
|
|
|
{
|
|
|
|
std::istringstream iss(str);
|
|
|
|
std::string line;
|
2020-09-09 12:11:28 +00:00
|
|
|
KeyValuePairVector kvp;
|
2020-11-07 10:36:30 +00:00
|
|
|
while (std::getline(iss, line))
|
2020-09-09 12:11:28 +00:00
|
|
|
{
|
2020-11-07 10:36:30 +00:00
|
|
|
char* start = line.data();
|
2020-12-26 02:58:18 +00:00
|
|
|
while (*start != '\0' && std::isspace(SignedCharToInt(*start)))
|
2020-09-09 12:11:28 +00:00
|
|
|
start++;
|
|
|
|
|
|
|
|
// skip empty lines
|
|
|
|
if (*start == '\0' || *start == '=')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
char* end = start + std::strlen(start) - 1;
|
2020-12-26 02:58:18 +00:00
|
|
|
while (end > start && std::isspace(SignedCharToInt(*end)))
|
2020-09-09 12:11:28 +00:00
|
|
|
{
|
|
|
|
*end = '\0';
|
|
|
|
end--;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* equals = start;
|
|
|
|
while (*equals != '=' && equals != end)
|
|
|
|
equals++;
|
|
|
|
if (equals == end)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
*equals = '\0';
|
|
|
|
|
|
|
|
char* key_end = equals - 1;
|
2020-12-26 02:58:18 +00:00
|
|
|
while (key_end > start && std::isspace(SignedCharToInt(*key_end)))
|
2020-09-09 12:11:28 +00:00
|
|
|
{
|
|
|
|
*key_end = '\0';
|
|
|
|
key_end--;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* value_start = equals + 1;
|
2020-12-26 02:58:18 +00:00
|
|
|
while (*value_start != '\0' && std::isspace(SignedCharToInt(*value_start)))
|
2020-09-09 12:11:28 +00:00
|
|
|
value_start++;
|
|
|
|
|
2020-09-25 12:00:34 +00:00
|
|
|
if (*value_start == '\0')
|
2020-09-09 12:11:28 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
char* value_end = value_start + std::strlen(value_start) - 1;
|
2020-12-26 02:58:18 +00:00
|
|
|
while (value_end > value_start && std::isspace(SignedCharToInt(*value_end)))
|
2020-09-09 12:11:28 +00:00
|
|
|
{
|
|
|
|
*value_end = '\0';
|
|
|
|
value_end--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*value_start == '\"')
|
|
|
|
{
|
|
|
|
if (*value_end != '\"')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
value_start++;
|
|
|
|
*value_end = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
kvp.emplace_back(start, value_start);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kvp.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const std::string* num_cheats_value = FindKey(kvp, "cheats");
|
2020-09-25 12:00:34 +00:00
|
|
|
const u32 num_cheats = num_cheats_value ? StringUtil::FromChars<u32>(*num_cheats_value).value_or(0) : 0;
|
2020-09-09 12:11:28 +00:00
|
|
|
if (num_cheats == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (u32 i = 0; i < num_cheats; i++)
|
|
|
|
{
|
|
|
|
const std::string* desc = FindKey(kvp, TinyString::FromFormat("cheat%u_desc", i));
|
|
|
|
const std::string* code = FindKey(kvp, TinyString::FromFormat("cheat%u_code", i));
|
|
|
|
const std::string* enable = FindKey(kvp, TinyString::FromFormat("cheat%u_enable", i));
|
|
|
|
if (!desc || !code || !enable)
|
|
|
|
{
|
2020-11-07 10:36:30 +00:00
|
|
|
Log_WarningPrintf("Missing desc/code/enable for cheat %u", i);
|
2020-09-09 12:11:28 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
CheatCode cc;
|
2020-10-19 15:14:49 +00:00
|
|
|
cc.group = "Ungrouped";
|
2020-09-09 12:11:28 +00:00
|
|
|
cc.description = *desc;
|
|
|
|
cc.enabled = StringUtil::FromChars<bool>(*enable).value_or(false);
|
2020-09-25 11:16:33 +00:00
|
|
|
if (ParseLibretroCheat(&cc, code->c_str()))
|
|
|
|
m_codes.push_back(std::move(cc));
|
|
|
|
}
|
|
|
|
|
2020-11-07 10:36:30 +00:00
|
|
|
Log_InfoPrintf("Loaded %zu cheats (libretro format)", m_codes.size());
|
2020-09-25 11:16:33 +00:00
|
|
|
return !m_codes.empty();
|
|
|
|
}
|
2020-09-09 12:11:28 +00:00
|
|
|
|
2020-12-26 02:58:30 +00:00
|
|
|
bool CheatList::LoadFromEPSXeString(const std::string& str)
|
|
|
|
{
|
|
|
|
std::istringstream iss(str);
|
|
|
|
|
|
|
|
std::string line;
|
|
|
|
std::string group;
|
|
|
|
CheatCode::Type type = CheatCode::Type::Gameshark;
|
|
|
|
CheatCode::Activation activation = CheatCode::Activation::EndFrame;
|
|
|
|
CheatCode current_code;
|
|
|
|
while (std::getline(iss, line))
|
|
|
|
{
|
|
|
|
char* start = line.data();
|
|
|
|
while (*start != '\0' && std::isspace(SignedCharToInt(*start)))
|
|
|
|
start++;
|
|
|
|
|
|
|
|
// skip empty lines
|
|
|
|
if (*start == '\0')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
char* end = start + std::strlen(start) - 1;
|
|
|
|
while (end > start && std::isspace(SignedCharToInt(*end)))
|
|
|
|
{
|
|
|
|
*end = '\0';
|
|
|
|
end--;
|
|
|
|
}
|
|
|
|
|
|
|
|
// skip comments and empty line
|
|
|
|
if (*start == ';' || *start == '\0')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (*start == '#')
|
|
|
|
{
|
|
|
|
start++;
|
|
|
|
|
|
|
|
// new cheat
|
|
|
|
if (current_code.Valid())
|
|
|
|
m_codes.push_back(std::move(current_code));
|
|
|
|
|
|
|
|
current_code = CheatCode();
|
|
|
|
if (group.empty())
|
|
|
|
group = "Ungrouped";
|
|
|
|
|
|
|
|
current_code.group = std::move(group);
|
|
|
|
group = std::string();
|
|
|
|
current_code.type = type;
|
|
|
|
type = CheatCode::Type::Gameshark;
|
|
|
|
current_code.activation = activation;
|
|
|
|
activation = CheatCode::Activation::EndFrame;
|
|
|
|
|
|
|
|
char* separator = std::strchr(start, '\\');
|
|
|
|
if (separator)
|
|
|
|
{
|
|
|
|
*separator = 0;
|
|
|
|
current_code.group = start;
|
|
|
|
start = separator + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
current_code.description.append(start);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!IsHexCharacter(*start) && start != end)
|
|
|
|
start++;
|
|
|
|
if (start == end)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
char* end_ptr;
|
|
|
|
CheatCode::Instruction inst;
|
|
|
|
inst.first = static_cast<u32>(std::strtoul(start, &end_ptr, 16));
|
|
|
|
inst.second = 0;
|
|
|
|
if (end_ptr)
|
|
|
|
{
|
|
|
|
while (!IsHexCharacter(*end_ptr) && end_ptr != end)
|
|
|
|
end_ptr++;
|
|
|
|
if (end_ptr != end)
|
|
|
|
inst.second = static_cast<u32>(std::strtoul(end_ptr, nullptr, 16));
|
|
|
|
}
|
|
|
|
current_code.instructions.push_back(inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_code.Valid())
|
|
|
|
m_codes.push_back(std::move(current_code));
|
|
|
|
|
|
|
|
Log_InfoPrintf("Loaded %zu cheats (EPSXe format)", m_codes.size());
|
|
|
|
return !m_codes.empty();
|
|
|
|
}
|
|
|
|
|
2020-09-25 12:00:34 +00:00
|
|
|
static bool IsLibretroSeparator(char ch)
|
|
|
|
{
|
|
|
|
return (ch == ' ' || ch == '-' || ch == ':' || ch == '+');
|
|
|
|
}
|
|
|
|
|
2020-09-25 11:16:33 +00:00
|
|
|
bool CheatList::ParseLibretroCheat(CheatCode* cc, const char* line)
|
|
|
|
{
|
|
|
|
const char* current_ptr = line;
|
|
|
|
while (current_ptr)
|
|
|
|
{
|
|
|
|
char* end_ptr;
|
|
|
|
CheatCode::Instruction inst;
|
|
|
|
inst.first = static_cast<u32>(std::strtoul(current_ptr, &end_ptr, 16));
|
|
|
|
current_ptr = end_ptr;
|
|
|
|
if (end_ptr)
|
2020-09-09 12:11:28 +00:00
|
|
|
{
|
2020-09-25 12:00:34 +00:00
|
|
|
if (!IsLibretroSeparator(*end_ptr))
|
2020-09-25 11:16:33 +00:00
|
|
|
{
|
|
|
|
Log_WarningPrintf("Malformed code '%s'", line);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
end_ptr++;
|
|
|
|
inst.second = static_cast<u32>(std::strtoul(current_ptr, &end_ptr, 16));
|
|
|
|
if (end_ptr && *end_ptr == '\0')
|
|
|
|
end_ptr = nullptr;
|
|
|
|
|
2020-09-25 12:00:34 +00:00
|
|
|
if (end_ptr && *end_ptr != '\0')
|
2020-09-09 12:11:28 +00:00
|
|
|
{
|
2020-09-25 12:00:34 +00:00
|
|
|
if (!IsLibretroSeparator(*end_ptr))
|
2020-09-09 12:11:28 +00:00
|
|
|
{
|
2020-09-25 11:16:33 +00:00
|
|
|
Log_WarningPrintf("Malformed code '%s'", line);
|
2020-09-09 12:11:28 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
end_ptr++;
|
|
|
|
}
|
|
|
|
|
2020-09-25 11:16:33 +00:00
|
|
|
current_ptr = end_ptr;
|
|
|
|
cc->instructions.push_back(inst);
|
|
|
|
}
|
2020-09-09 12:11:28 +00:00
|
|
|
}
|
|
|
|
|
2020-09-25 11:16:33 +00:00
|
|
|
return !cc->instructions.empty();
|
2020-09-09 12:11:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CheatList::Apply()
|
|
|
|
{
|
2021-03-04 14:53:20 +00:00
|
|
|
if (!m_master_enable)
|
|
|
|
return;
|
|
|
|
|
2020-09-09 12:11:28 +00:00
|
|
|
for (const CheatCode& code : m_codes)
|
|
|
|
{
|
|
|
|
if (code.enabled)
|
|
|
|
code.Apply();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheatList::AddCode(CheatCode cc)
|
|
|
|
{
|
|
|
|
m_codes.push_back(std::move(cc));
|
|
|
|
}
|
|
|
|
|
2020-09-25 11:16:33 +00:00
|
|
|
void CheatList::SetCode(u32 index, CheatCode cc)
|
|
|
|
{
|
|
|
|
if (index > m_codes.size())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (index == m_codes.size())
|
|
|
|
{
|
|
|
|
m_codes.push_back(std::move(cc));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_codes[index] = std::move(cc);
|
|
|
|
}
|
|
|
|
|
2020-09-09 12:11:28 +00:00
|
|
|
void CheatList::RemoveCode(u32 i)
|
|
|
|
{
|
|
|
|
m_codes.erase(m_codes.begin() + i);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<CheatList::Format> CheatList::DetectFileFormat(const char* filename)
|
|
|
|
{
|
2020-11-07 10:36:30 +00:00
|
|
|
std::optional<std::string> str = FileSystem::ReadFileToString(filename);
|
|
|
|
if (!str.has_value() || str->empty())
|
|
|
|
return std::nullopt;
|
|
|
|
|
|
|
|
return DetectFileFormat(str.value());
|
|
|
|
}
|
2020-09-09 12:11:28 +00:00
|
|
|
|
2020-11-07 10:36:30 +00:00
|
|
|
CheatList::Format CheatList::DetectFileFormat(const std::string& str)
|
|
|
|
{
|
|
|
|
std::istringstream iss(str);
|
|
|
|
std::string line;
|
|
|
|
while (std::getline(iss, line))
|
2020-09-09 12:11:28 +00:00
|
|
|
{
|
2020-11-07 10:36:30 +00:00
|
|
|
char* start = line.data();
|
2020-12-26 02:58:18 +00:00
|
|
|
while (*start != '\0' && std::isspace(SignedCharToInt(*start)))
|
2020-09-09 12:11:28 +00:00
|
|
|
start++;
|
|
|
|
|
|
|
|
// skip empty lines
|
2020-12-26 02:58:30 +00:00
|
|
|
if (*start == '\0')
|
2020-09-09 12:11:28 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
char* end = start + std::strlen(start) - 1;
|
2020-12-26 02:58:18 +00:00
|
|
|
while (end > start && std::isspace(SignedCharToInt(*end)))
|
2020-09-09 12:11:28 +00:00
|
|
|
{
|
|
|
|
*end = '\0';
|
|
|
|
end--;
|
|
|
|
}
|
|
|
|
|
2020-12-26 02:58:30 +00:00
|
|
|
// eat comments
|
|
|
|
if (start[0] == '#' || start[0] == ';')
|
|
|
|
continue;
|
|
|
|
|
2020-11-07 10:36:30 +00:00
|
|
|
if (std::strncmp(line.data(), "cheats", 6) == 0)
|
2020-09-09 12:11:28 +00:00
|
|
|
return Format::Libretro;
|
2020-12-26 02:58:30 +00:00
|
|
|
|
|
|
|
// pcsxr if we see brackets
|
|
|
|
if (start[0] == '[')
|
2020-09-09 12:11:28 +00:00
|
|
|
return Format::PCSXR;
|
2020-12-26 02:58:30 +00:00
|
|
|
|
|
|
|
// otherwise if it's a code, it's probably epsxe
|
|
|
|
if (std::isdigit(start[0]))
|
|
|
|
return Format::EPSXe;
|
2020-09-09 12:11:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return Format::Count;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheatList::LoadFromFile(const char* filename, Format format)
|
2020-11-07 10:36:30 +00:00
|
|
|
{
|
2021-02-11 14:20:04 +00:00
|
|
|
if (!FileSystem::FileExists(filename))
|
|
|
|
return false;
|
|
|
|
|
2020-11-07 10:36:30 +00:00
|
|
|
std::optional<std::string> str = FileSystem::ReadFileToString(filename);
|
2021-02-11 14:20:04 +00:00
|
|
|
if (!str.has_value())
|
2020-11-07 10:36:30 +00:00
|
|
|
return false;
|
|
|
|
|
2021-02-11 14:20:04 +00:00
|
|
|
if (str->empty())
|
|
|
|
return true;
|
|
|
|
|
2020-11-07 10:36:30 +00:00
|
|
|
return LoadFromString(str.value(), format);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheatList::LoadFromString(const std::string& str, Format format)
|
2020-09-09 12:11:28 +00:00
|
|
|
{
|
|
|
|
if (format == Format::Autodetect)
|
2020-11-07 10:36:30 +00:00
|
|
|
format = DetectFileFormat(str);
|
2020-09-09 12:11:28 +00:00
|
|
|
|
|
|
|
if (format == Format::PCSXR)
|
2020-11-07 10:36:30 +00:00
|
|
|
return LoadFromPCSXRString(str);
|
2020-09-09 12:11:28 +00:00
|
|
|
else if (format == Format::Libretro)
|
2020-11-07 10:36:30 +00:00
|
|
|
return LoadFromLibretroString(str);
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
format = Format::EPSXe;
|
|
|
|
return LoadFromEPSXeString(str);
|
2020-09-09 12:11:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CheatList::SaveToPCSXRFile(const char* filename)
|
|
|
|
{
|
|
|
|
auto fp = FileSystem::OpenManagedCFile(filename, "wb");
|
|
|
|
if (!fp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (const CheatCode& cc : m_codes)
|
|
|
|
{
|
2020-10-21 10:41:44 +00:00
|
|
|
if (!cc.comments.empty())
|
|
|
|
std::fputs(cc.comments.c_str(), fp.get());
|
2020-10-21 10:51:36 +00:00
|
|
|
std::fprintf(fp.get(), "#group=%s\n", cc.group.c_str());
|
|
|
|
std::fprintf(fp.get(), "#type=%s\n", CheatCode::GetTypeName(cc.type));
|
|
|
|
std::fprintf(fp.get(), "#activation=%s\n", CheatCode::GetActivationName(cc.activation));
|
2020-09-09 12:11:28 +00:00
|
|
|
std::fprintf(fp.get(), "[%s%s]\n", cc.enabled ? "*" : "", cc.description.c_str());
|
|
|
|
for (const CheatCode::Instruction& i : cc.instructions)
|
|
|
|
std::fprintf(fp.get(), "%08X %04X\n", i.first, i.second);
|
|
|
|
std::fprintf(fp.get(), "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
std::fflush(fp.get());
|
|
|
|
return (std::ferror(fp.get()) == 0);
|
|
|
|
}
|
|
|
|
|
2020-11-29 06:42:49 +00:00
|
|
|
bool CheatList::LoadFromPackage(const std::string& game_code)
|
|
|
|
{
|
|
|
|
std::unique_ptr<ByteStream> stream =
|
|
|
|
g_host_interface->OpenPackageFile("database/chtdb.txt", BYTESTREAM_OPEN_READ | BYTESTREAM_OPEN_STREAMED);
|
|
|
|
if (!stream)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::string db_string = FileSystem::ReadStreamToString(stream.get());
|
|
|
|
stream.reset();
|
|
|
|
if (db_string.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::istringstream iss(db_string);
|
|
|
|
std::string line;
|
|
|
|
while (std::getline(iss, line))
|
|
|
|
{
|
|
|
|
char* start = line.data();
|
2020-12-26 02:58:18 +00:00
|
|
|
while (*start != '\0' && std::isspace(SignedCharToInt(*start)))
|
2020-11-29 06:42:49 +00:00
|
|
|
start++;
|
|
|
|
|
|
|
|
// skip empty lines
|
|
|
|
if (*start == '\0' || *start == ';')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
char* end = start + std::strlen(start) - 1;
|
2020-12-26 02:58:18 +00:00
|
|
|
while (end > start && std::isspace(SignedCharToInt(*end)))
|
2020-11-29 06:42:49 +00:00
|
|
|
{
|
|
|
|
*end = '\0';
|
|
|
|
end--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start == end)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (start[0] != ':' || std::strcmp(&start[1], game_code.c_str()) != 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// game code match
|
|
|
|
CheatCode current_code;
|
|
|
|
while (std::getline(iss, line))
|
|
|
|
{
|
|
|
|
start = line.data();
|
2020-12-26 02:58:18 +00:00
|
|
|
while (*start != '\0' && std::isspace(SignedCharToInt(*start)))
|
2020-11-29 06:42:49 +00:00
|
|
|
start++;
|
|
|
|
|
|
|
|
// skip empty lines
|
|
|
|
if (*start == '\0' || *start == ';')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
end = start + std::strlen(start) - 1;
|
2020-12-26 02:58:18 +00:00
|
|
|
while (end > start && std::isspace(SignedCharToInt(*end)))
|
2020-11-29 06:42:49 +00:00
|
|
|
{
|
|
|
|
*end = '\0';
|
|
|
|
end--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start == end)
|
|
|
|
continue;
|
|
|
|
|
2021-03-12 17:04:32 +00:00
|
|
|
// stop adding codes when we hit a different game
|
|
|
|
if (start[0] == ':' && (!m_codes.empty() || current_code.Valid()))
|
2020-11-29 06:42:49 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
if (start[0] == '#')
|
|
|
|
{
|
|
|
|
start++;
|
|
|
|
|
|
|
|
if (current_code.Valid())
|
|
|
|
{
|
|
|
|
m_codes.push_back(std::move(current_code));
|
|
|
|
current_code = CheatCode();
|
|
|
|
}
|
|
|
|
|
|
|
|
// new code
|
|
|
|
char* slash = std::strrchr(start, '\\');
|
|
|
|
if (slash)
|
|
|
|
{
|
|
|
|
*slash = '\0';
|
|
|
|
current_code.group = start;
|
|
|
|
start = slash + 1;
|
|
|
|
}
|
|
|
|
if (current_code.group.empty())
|
|
|
|
current_code.group = "Ungrouped";
|
|
|
|
|
|
|
|
current_code.description = start;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!IsHexCharacter(*start) && start != end)
|
|
|
|
start++;
|
|
|
|
if (start == end)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
char* end_ptr;
|
|
|
|
CheatCode::Instruction inst;
|
|
|
|
inst.first = static_cast<u32>(std::strtoul(start, &end_ptr, 16));
|
|
|
|
inst.second = 0;
|
|
|
|
if (end_ptr)
|
|
|
|
{
|
|
|
|
while (!IsHexCharacter(*end_ptr) && end_ptr != end)
|
|
|
|
end_ptr++;
|
|
|
|
if (end_ptr != end)
|
|
|
|
inst.second = static_cast<u32>(std::strtoul(end_ptr, nullptr, 16));
|
|
|
|
}
|
|
|
|
current_code.instructions.push_back(inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_code.Valid())
|
|
|
|
m_codes.push_back(std::move(current_code));
|
|
|
|
|
|
|
|
Log_InfoPrintf("Loaded %zu codes from package for %s", m_codes.size(), game_code.c_str());
|
|
|
|
return !m_codes.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
Log_WarningPrintf("No codes found in package for %s", game_code.c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-09-09 13:44:02 +00:00
|
|
|
u32 CheatList::GetEnabledCodeCount() const
|
|
|
|
{
|
|
|
|
u32 count = 0;
|
|
|
|
for (const CheatCode& cc : m_codes)
|
|
|
|
{
|
|
|
|
if (cc.enabled)
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2020-10-19 15:14:49 +00:00
|
|
|
std::vector<std::string> CheatList::GetCodeGroups() const
|
|
|
|
{
|
|
|
|
std::vector<std::string> groups;
|
|
|
|
for (const CheatCode& cc : m_codes)
|
|
|
|
{
|
|
|
|
if (std::any_of(groups.begin(), groups.end(), [cc](const std::string& group) { return (group == cc.group); }))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
groups.emplace_back(cc.group);
|
|
|
|
}
|
|
|
|
|
|
|
|
return groups;
|
|
|
|
}
|
|
|
|
|
2020-09-09 13:44:02 +00:00
|
|
|
void CheatList::SetCodeEnabled(u32 index, bool state)
|
|
|
|
{
|
2020-12-25 04:21:43 +00:00
|
|
|
if (index >= m_codes.size() || m_codes[index].enabled == state)
|
2020-09-09 13:44:02 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
m_codes[index].enabled = state;
|
2020-12-25 04:21:43 +00:00
|
|
|
if (!state)
|
|
|
|
m_codes[index].ApplyOnDisable();
|
2020-09-09 13:44:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CheatList::EnableCode(u32 index)
|
|
|
|
{
|
|
|
|
SetCodeEnabled(index, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheatList::DisableCode(u32 index)
|
|
|
|
{
|
|
|
|
SetCodeEnabled(index, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheatList::ApplyCode(u32 index)
|
|
|
|
{
|
|
|
|
if (index >= m_codes.size())
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_codes[index].Apply();
|
|
|
|
}
|
|
|
|
|
2020-11-07 09:58:59 +00:00
|
|
|
const CheatCode* CheatList::FindCode(const char* name) const
|
|
|
|
{
|
|
|
|
for (const CheatCode& cc : m_codes)
|
|
|
|
{
|
|
|
|
if (cc.description == name)
|
|
|
|
return &cc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CheatCode* CheatList::FindCode(const char* group, const char* name) const
|
|
|
|
{
|
|
|
|
for (const CheatCode& cc : m_codes)
|
|
|
|
{
|
|
|
|
if (cc.group == group && cc.description == name)
|
|
|
|
return &cc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheatList::MergeList(const CheatList& cl)
|
|
|
|
{
|
|
|
|
for (const CheatCode& cc : cl.m_codes)
|
|
|
|
{
|
|
|
|
if (!FindCode(cc.group.c_str(), cc.description.c_str()))
|
|
|
|
AddCode(cc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-19 15:14:49 +00:00
|
|
|
std::string CheatCode::GetInstructionsAsString() const
|
|
|
|
{
|
|
|
|
std::stringstream ss;
|
|
|
|
|
|
|
|
for (const Instruction& inst : instructions)
|
|
|
|
{
|
|
|
|
ss << std::hex << std::uppercase << std::setw(8) << std::setfill('0') << inst.first;
|
|
|
|
ss << " ";
|
|
|
|
ss << std::hex << std::uppercase << std::setw(8) << std::setfill('0') << inst.second;
|
|
|
|
ss << '\n';
|
|
|
|
}
|
|
|
|
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheatCode::SetInstructionsFromString(const std::string& str)
|
|
|
|
{
|
|
|
|
std::vector<Instruction> new_instructions;
|
|
|
|
std::istringstream ss(str);
|
|
|
|
|
|
|
|
for (std::string line; std::getline(ss, line);)
|
|
|
|
{
|
|
|
|
char* start = line.data();
|
2020-12-26 02:58:18 +00:00
|
|
|
while (*start != '\0' && std::isspace(SignedCharToInt(*start)))
|
2020-10-19 15:14:49 +00:00
|
|
|
start++;
|
|
|
|
|
|
|
|
// skip empty lines
|
|
|
|
if (*start == '\0')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
char* end = start + std::strlen(start) - 1;
|
2020-12-26 02:58:18 +00:00
|
|
|
while (end > start && std::isspace(SignedCharToInt(*end)))
|
2020-10-19 15:14:49 +00:00
|
|
|
{
|
|
|
|
*end = '\0';
|
|
|
|
end--;
|
|
|
|
}
|
|
|
|
|
|
|
|
// skip comments and empty line
|
|
|
|
if (*start == '#' || *start == ';' || *start == '/' || *start == '\"')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
while (!IsHexCharacter(*start) && start != end)
|
|
|
|
start++;
|
|
|
|
if (start == end)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
char* end_ptr;
|
|
|
|
CheatCode::Instruction inst;
|
|
|
|
inst.first = static_cast<u32>(std::strtoul(start, &end_ptr, 16));
|
|
|
|
inst.second = 0;
|
|
|
|
if (end_ptr)
|
|
|
|
{
|
|
|
|
while (!IsHexCharacter(*end_ptr) && end_ptr != end)
|
|
|
|
end_ptr++;
|
|
|
|
if (end_ptr != end)
|
|
|
|
inst.second = static_cast<u32>(std::strtoul(end_ptr, nullptr, 16));
|
|
|
|
}
|
|
|
|
new_instructions.push_back(inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new_instructions.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
instructions = std::move(new_instructions);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-12-09 10:22:43 +00:00
|
|
|
static bool IsConditionalInstruction(CheatCode::InstructionCode code)
|
|
|
|
{
|
|
|
|
switch (code)
|
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
case CheatCode::InstructionCode::CompareEqual16: // D0
|
|
|
|
case CheatCode::InstructionCode::CompareNotEqual16: // D1
|
|
|
|
case CheatCode::InstructionCode::CompareLess16: // D2
|
|
|
|
case CheatCode::InstructionCode::CompareGreater16: // D3
|
|
|
|
case CheatCode::InstructionCode::CompareEqual8: // E0
|
|
|
|
case CheatCode::InstructionCode::CompareNotEqual8: // E1
|
|
|
|
case CheatCode::InstructionCode::CompareLess8: // E2
|
|
|
|
case CheatCode::InstructionCode::CompareGreater8: // E3
|
|
|
|
case CheatCode::InstructionCode::CompareButtons: // D4
|
2021-08-19 20:21:07 +00:00
|
|
|
case CheatCode::InstructionCode::ExtCompareEqual32: // A0
|
|
|
|
case CheatCode::InstructionCode::ExtCompareNotEqual32: // A1
|
|
|
|
case CheatCode::InstructionCode::ExtCompareLess32: // A2
|
|
|
|
case CheatCode::InstructionCode::ExtCompareGreater32: // A3
|
2020-12-09 10:22:43 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 CheatCode::GetNextNonConditionalInstruction(u32 index) const
|
|
|
|
{
|
|
|
|
const u32 count = static_cast<u32>(instructions.size());
|
|
|
|
for (; index < count; index++)
|
|
|
|
{
|
|
|
|
if (!IsConditionalInstruction(instructions[index].code))
|
|
|
|
{
|
|
|
|
// we've found the first non conditional instruction in the chain, so skip over the instruction following it
|
|
|
|
return index + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
2020-09-09 12:11:28 +00:00
|
|
|
void CheatCode::Apply() const
|
|
|
|
{
|
|
|
|
const u32 count = static_cast<u32>(instructions.size());
|
|
|
|
u32 index = 0;
|
|
|
|
for (; index < count;)
|
|
|
|
{
|
|
|
|
const Instruction& inst = instructions[index];
|
|
|
|
switch (inst.code)
|
|
|
|
{
|
2020-09-28 10:09:14 +00:00
|
|
|
case InstructionCode::Nop:
|
|
|
|
{
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-09-09 12:11:28 +00:00
|
|
|
case InstructionCode::ConstantWrite8:
|
|
|
|
{
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u8>(inst.address, inst.value8);
|
2020-09-09 12:11:28 +00:00
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::ConstantWrite16:
|
|
|
|
{
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u16>(inst.address, inst.value16);
|
2020-09-09 12:11:28 +00:00
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-12-17 13:33:00 +00:00
|
|
|
case InstructionCode::ExtConstantWrite32:
|
|
|
|
{
|
|
|
|
DoMemoryWrite<u32>(inst.address, inst.value32);
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-12-25 04:21:43 +00:00
|
|
|
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;
|
|
|
|
|
2020-09-28 11:18:08 +00:00
|
|
|
case InstructionCode::ScratchpadWrite16:
|
|
|
|
{
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u16>(CPU::DCACHE_LOCATION | (inst.address & CPU::DCACHE_OFFSET_MASK), inst.value16);
|
2020-09-28 11:18:08 +00:00
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-12-17 13:33:00 +00:00
|
|
|
case InstructionCode::ExtScratchpadWrite32:
|
|
|
|
{
|
|
|
|
DoMemoryWrite<u32>(CPU::DCACHE_LOCATION | (inst.address & CPU::DCACHE_OFFSET_MASK), inst.value32);
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::ExtIncrement32:
|
|
|
|
{
|
|
|
|
const u32 value = DoMemoryRead<u32>(inst.address);
|
|
|
|
DoMemoryWrite<u32>(inst.address, value + inst.value32);
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::ExtDecrement32:
|
|
|
|
{
|
|
|
|
const u32 value = DoMemoryRead<u32>(inst.address);
|
|
|
|
DoMemoryWrite<u32>(inst.address, value - inst.value32);
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-09-09 12:11:28 +00:00
|
|
|
case InstructionCode::Increment16:
|
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
const u16 value = DoMemoryRead<u16>(inst.address);
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u16>(inst.address, value + inst.value16);
|
2020-09-09 12:11:28 +00:00
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::Decrement16:
|
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
const u16 value = DoMemoryRead<u16>(inst.address);
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u16>(inst.address, value - inst.value16);
|
2020-09-09 12:11:28 +00:00
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::Increment8:
|
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
const u8 value = DoMemoryRead<u8>(inst.address);
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u8>(inst.address, value + inst.value8);
|
2020-09-09 12:11:28 +00:00
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::Decrement8:
|
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
const u8 value = DoMemoryRead<u8>(inst.address);
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u8>(inst.address, value - inst.value8);
|
2020-09-09 12:11:28 +00:00
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-12-17 13:33:00 +00:00
|
|
|
case InstructionCode::ExtCompareEqual32:
|
|
|
|
{
|
|
|
|
const u32 value = DoMemoryRead<u32>(inst.address);
|
|
|
|
if (value == inst.value32)
|
|
|
|
index++;
|
|
|
|
else
|
|
|
|
index = GetNextNonConditionalInstruction(index);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::ExtCompareNotEqual32:
|
|
|
|
{
|
|
|
|
const u32 value = DoMemoryRead<u32>(inst.address);
|
|
|
|
if (value != inst.value32)
|
|
|
|
index++;
|
|
|
|
else
|
|
|
|
index = GetNextNonConditionalInstruction(index);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::ExtCompareLess32:
|
|
|
|
{
|
|
|
|
const u32 value = DoMemoryRead<u32>(inst.address);
|
|
|
|
if (value < inst.value32)
|
|
|
|
index++;
|
|
|
|
else
|
|
|
|
index = GetNextNonConditionalInstruction(index);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::ExtCompareGreater32:
|
|
|
|
{
|
|
|
|
const u32 value = DoMemoryRead<u32>(inst.address);
|
|
|
|
if (value > inst.value32)
|
|
|
|
index++;
|
|
|
|
else
|
|
|
|
index = GetNextNonConditionalInstruction(index);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-12-25 04:21:43 +00:00
|
|
|
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;
|
2021-02-06 09:19:55 +00:00
|
|
|
|
2021-03-13 15:21:40 +00:00
|
|
|
case InstructionCode::ExtConstantSwap16:
|
|
|
|
{
|
|
|
|
const u16 value1 = Truncate16(inst.value32 & 0x0000FFFFu);
|
|
|
|
const u16 value2 = Truncate16((inst.value32 & 0xFFFF0000u) >> 16);
|
|
|
|
const u16 value = DoMemoryRead<u16>(inst.address);
|
|
|
|
|
2021-09-10 05:53:15 +00:00
|
|
|
if (value == value1)
|
2021-03-13 15:21:40 +00:00
|
|
|
DoMemoryWrite<u16>(inst.address, value2);
|
2021-09-10 05:53:15 +00:00
|
|
|
else if (value == value2)
|
2021-03-13 15:21:40 +00:00
|
|
|
DoMemoryWrite<u16>(inst.address, value1);
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-12-29 14:55:49 +00:00
|
|
|
case InstructionCode::ExtFindAndReplace:
|
|
|
|
{
|
2021-02-06 09:19:55 +00:00
|
|
|
|
2020-12-29 14:55:49 +00:00
|
|
|
if ((index + 4) >= instructions.size())
|
|
|
|
{
|
|
|
|
Log_ErrorPrintf("Incomplete find/replace instruction");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const Instruction& inst2 = instructions[index + 1];
|
|
|
|
const Instruction& inst3 = instructions[index + 2];
|
|
|
|
const Instruction& inst4 = instructions[index + 3];
|
2021-02-06 09:19:55 +00:00
|
|
|
const Instruction& inst5 = instructions[index + 4];
|
|
|
|
|
2020-12-29 14:55:49 +00:00
|
|
|
const u32 offset = Truncate16(inst.value32 & 0x0000FFFFu) << 1;
|
|
|
|
const u8 wildcard = Truncate8((inst.value32 & 0x00FF0000u) >> 16);
|
|
|
|
const u32 minaddress = inst.address - offset;
|
|
|
|
const u32 maxaddress = inst.address + offset;
|
2021-02-06 09:19:55 +00:00
|
|
|
const u8 f1 = Truncate8((inst2.first & 0xFF000000u) >> 24);
|
|
|
|
const u8 f2 = Truncate8((inst2.first & 0x00FF0000u) >> 16);
|
|
|
|
const u8 f3 = Truncate8((inst2.first & 0x0000FF00u) >> 8);
|
|
|
|
const u8 f4 = Truncate8(inst2.first & 0x000000FFu);
|
|
|
|
const u8 f5 = Truncate8((inst2.value32 & 0xFF000000u) >> 24);
|
|
|
|
const u8 f6 = Truncate8((inst2.value32 & 0x00FF0000u) >> 16);
|
|
|
|
const u8 f7 = Truncate8((inst2.value32 & 0x0000FF00u) >> 8);
|
|
|
|
const u8 f8 = Truncate8(inst2.value32 & 0x000000FFu);
|
|
|
|
const u8 f9 = Truncate8((inst3.first & 0xFF000000u) >> 24);
|
2020-12-29 14:55:49 +00:00
|
|
|
const u8 f10 = Truncate8((inst3.first & 0x00FF0000u) >> 16);
|
|
|
|
const u8 f11 = Truncate8((inst3.first & 0x0000FF00u) >> 8);
|
2021-02-06 09:19:55 +00:00
|
|
|
const u8 f12 = Truncate8(inst3.first & 0x000000FFu);
|
2020-12-29 14:55:49 +00:00
|
|
|
const u8 f13 = Truncate8((inst3.value32 & 0xFF000000u) >> 24);
|
|
|
|
const u8 f14 = Truncate8((inst3.value32 & 0x00FF0000u) >> 16);
|
|
|
|
const u8 f15 = Truncate8((inst3.value32 & 0x0000FF00u) >> 8);
|
2021-02-06 09:19:55 +00:00
|
|
|
const u8 f16 = Truncate8(inst3.value32 & 0x000000FFu);
|
|
|
|
const u8 r1 = Truncate8((inst4.first & 0xFF000000u) >> 24);
|
|
|
|
const u8 r2 = Truncate8((inst4.first & 0x00FF0000u) >> 16);
|
|
|
|
const u8 r3 = Truncate8((inst4.first & 0x0000FF00u) >> 8);
|
|
|
|
const u8 r4 = Truncate8(inst4.first & 0x000000FFu);
|
|
|
|
const u8 r5 = Truncate8((inst4.value32 & 0xFF000000u) >> 24);
|
|
|
|
const u8 r6 = Truncate8((inst4.value32 & 0x00FF0000u) >> 16);
|
|
|
|
const u8 r7 = Truncate8((inst4.value32 & 0x0000FF00u) >> 8);
|
|
|
|
const u8 r8 = Truncate8(inst4.value32 & 0x000000FFu);
|
|
|
|
const u8 r9 = Truncate8((inst5.first & 0xFF000000u) >> 24);
|
2020-12-29 14:55:49 +00:00
|
|
|
const u8 r10 = Truncate8((inst5.first & 0x00FF0000u) >> 16);
|
|
|
|
const u8 r11 = Truncate8((inst5.first & 0x0000FF00u) >> 8);
|
2021-02-06 09:19:55 +00:00
|
|
|
const u8 r12 = Truncate8(inst5.first & 0x000000FFu);
|
2020-12-29 14:55:49 +00:00
|
|
|
const u8 r13 = Truncate8((inst5.value32 & 0xFF000000u) >> 24);
|
|
|
|
const u8 r14 = Truncate8((inst5.value32 & 0x00FF0000u) >> 16);
|
|
|
|
const u8 r15 = Truncate8((inst5.value32 & 0x0000FF00u) >> 8);
|
2021-02-06 09:19:55 +00:00
|
|
|
const u8 r16 = Truncate8(inst5.value32 & 0x000000FFu);
|
|
|
|
|
|
|
|
for (u32 address = minaddress; address <= maxaddress; address += 2)
|
2020-12-29 14:55:49 +00:00
|
|
|
{
|
2021-02-06 09:19:55 +00:00
|
|
|
if ((DoMemoryRead<u8>(address) == f1 || f1 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 1) == f2 || f2 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 2) == f3 || f3 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 3) == f4 || f4 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 4) == f5 || f5 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 5) == f6 || f6 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 6) == f7 || f7 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 7) == f8 || f8 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 8) == f9 || f9 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 9) == f10 || f10 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 10) == f11 || f11 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 11) == f12 || f12 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 12) == f13 || f13 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 13) == f14 || f14 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 14) == f15 || f15 == wildcard) &&
|
|
|
|
(DoMemoryRead<u8>(address + 15) == f16 || f16 == wildcard))
|
2020-12-29 14:55:49 +00:00
|
|
|
{
|
2021-02-06 09:19:55 +00:00
|
|
|
if (r1 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address, r1);
|
|
|
|
if (r2 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 1, r2);
|
|
|
|
if (r3 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 2, r3);
|
|
|
|
if (r4 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 3, r4);
|
|
|
|
if (r5 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 4, r5);
|
|
|
|
if (r6 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 5, r6);
|
|
|
|
if (r7 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 6, r7);
|
|
|
|
if (r8 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 7, r8);
|
|
|
|
if (r9 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 8, r9);
|
|
|
|
if (r10 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 9, r10);
|
|
|
|
if (r11 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 10, r11);
|
|
|
|
if (r12 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 11, r12);
|
|
|
|
if (r13 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 12, r13);
|
|
|
|
if (r14 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 13, r14);
|
|
|
|
if (r15 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 14, r15);
|
|
|
|
if (r16 != wildcard)
|
|
|
|
DoMemoryWrite<u8>(address + 15, r16);
|
|
|
|
address = address + 15;
|
|
|
|
}
|
2020-12-29 14:55:49 +00:00
|
|
|
}
|
|
|
|
index += 5;
|
|
|
|
}
|
|
|
|
break;
|
2020-12-25 04:21:43 +00:00
|
|
|
|
2020-09-09 12:11:28 +00:00
|
|
|
case InstructionCode::CompareEqual16:
|
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
const u16 value = DoMemoryRead<u16>(inst.address);
|
2020-09-09 12:11:28 +00:00
|
|
|
if (value == inst.value16)
|
|
|
|
index++;
|
|
|
|
else
|
2020-12-09 10:22:43 +00:00
|
|
|
index = GetNextNonConditionalInstruction(index);
|
2020-09-09 12:11:28 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::CompareNotEqual16:
|
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
const u16 value = DoMemoryRead<u16>(inst.address);
|
2020-09-09 12:11:28 +00:00
|
|
|
if (value != inst.value16)
|
|
|
|
index++;
|
|
|
|
else
|
2020-12-09 10:22:43 +00:00
|
|
|
index = GetNextNonConditionalInstruction(index);
|
2020-09-09 12:11:28 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::CompareLess16:
|
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
const u16 value = DoMemoryRead<u16>(inst.address);
|
2020-09-09 12:11:28 +00:00
|
|
|
if (value < inst.value16)
|
|
|
|
index++;
|
|
|
|
else
|
2020-12-09 10:22:43 +00:00
|
|
|
index = GetNextNonConditionalInstruction(index);
|
2020-09-09 12:11:28 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::CompareGreater16:
|
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
const u16 value = DoMemoryRead<u16>(inst.address);
|
2020-09-09 12:11:28 +00:00
|
|
|
if (value > inst.value16)
|
|
|
|
index++;
|
|
|
|
else
|
2020-12-09 10:22:43 +00:00
|
|
|
index = GetNextNonConditionalInstruction(index);
|
2020-09-09 12:11:28 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::CompareEqual8:
|
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
const u8 value = DoMemoryRead<u8>(inst.address);
|
2020-09-09 12:11:28 +00:00
|
|
|
if (value == inst.value8)
|
|
|
|
index++;
|
|
|
|
else
|
2020-12-09 10:22:43 +00:00
|
|
|
index = GetNextNonConditionalInstruction(index);
|
2020-09-09 12:11:28 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::CompareNotEqual8:
|
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
const u8 value = DoMemoryRead<u8>(inst.address);
|
2020-09-09 12:11:28 +00:00
|
|
|
if (value != inst.value8)
|
|
|
|
index++;
|
|
|
|
else
|
2020-12-09 10:22:43 +00:00
|
|
|
index = GetNextNonConditionalInstruction(index);
|
2020-09-09 12:11:28 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::CompareLess8:
|
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
const u8 value = DoMemoryRead<u8>(inst.address);
|
2020-09-09 12:11:28 +00:00
|
|
|
if (value < inst.value8)
|
|
|
|
index++;
|
|
|
|
else
|
2020-12-09 10:22:43 +00:00
|
|
|
index = GetNextNonConditionalInstruction(index);
|
2020-09-09 12:11:28 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::CompareGreater8:
|
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
const u8 value = DoMemoryRead<u8>(inst.address);
|
2020-09-09 12:11:28 +00:00
|
|
|
if (value > inst.value8)
|
|
|
|
index++;
|
|
|
|
else
|
2020-12-09 10:22:43 +00:00
|
|
|
index = GetNextNonConditionalInstruction(index);
|
2020-09-09 12:11:28 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-12-06 05:47:00 +00:00
|
|
|
case InstructionCode::CompareButtons: // D4
|
|
|
|
{
|
|
|
|
if (inst.value16 == GetControllerButtonBits())
|
|
|
|
index++;
|
|
|
|
else
|
2020-12-09 10:22:43 +00:00
|
|
|
index = GetNextNonConditionalInstruction(index);
|
2020-12-06 05:47:00 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2021-03-13 15:21:40 +00:00
|
|
|
case InstructionCode::ExtCheatRegisters: // 51
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
{
|
2021-03-13 15:21:40 +00:00
|
|
|
const u32 poke_value = inst.value32;
|
|
|
|
const u8 cht_reg_no1 = Truncate8(inst.address & 0xFFu);
|
|
|
|
const u8 cht_reg_no2 = Truncate8((inst.address & 0xFF00u) >> 8);
|
|
|
|
const u8 cht_reg_no3 = Truncate8(inst.value32 & 0xFFu);
|
|
|
|
const u8 sub_type = Truncate8((inst.address & 0xFF0000u) >> 16);
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
|
|
|
|
switch (sub_type)
|
|
|
|
{
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x00: // Write the u8 from cht_register[cht_reg_no1] to address
|
|
|
|
DoMemoryWrite<u8>(inst.value32, Truncate8(cht_register[cht_reg_no1]) & 0xFFu);
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x01: // Read the u8 from address to cht_register[cht_reg_no1]
|
|
|
|
cht_register[cht_reg_no1] = DoMemoryRead<u8>(inst.value32);
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x02: // Write the u8 from address field to the address stored in cht_register[cht_reg_no1]
|
|
|
|
DoMemoryWrite<u8>(cht_register[cht_reg_no1], Truncate8(poke_value & 0xFFu));
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x03: // Write the u8 from cht_register[cht_reg_no2] to cht_register[cht_reg_no1]
|
|
|
|
// and add the u8 from the address field to it
|
|
|
|
cht_register[cht_reg_no1] = Truncate8(cht_register[cht_reg_no2] & 0xFFu) + Truncate8(poke_value & 0xFFu);
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x04: // Write the u8 from the value stored in cht_register[cht_reg_no2] + poke_value to the address
|
|
|
|
// stored in cht_register[cht_reg_no1]
|
|
|
|
DoMemoryWrite<u8>(cht_register[cht_reg_no1],
|
|
|
|
Truncate8(cht_register[cht_reg_no2] & 0xFFu) + Truncate8(poke_value & 0xFFu));
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x05: // Write the u8 poke value to cht_register[cht_reg_no1]
|
|
|
|
cht_register[cht_reg_no1] = Truncate8(poke_value & 0xFFu);
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
|
|
|
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x40: // Write the u16 from cht_register[cht_reg_no1] to address
|
|
|
|
DoMemoryWrite<u16>(inst.value32, Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x41: // Read the u16 from address to cht_register[cht_reg_no1]
|
|
|
|
cht_register[cht_reg_no1] = DoMemoryRead<u16>(inst.value32);
|
|
|
|
break;
|
|
|
|
case 0x42: // Write the u16 from address field to the address stored in cht_register[cht_reg_no1]
|
|
|
|
DoMemoryWrite<u16>(cht_register[cht_reg_no1], Truncate16(poke_value & 0xFFFFu));
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x43: // Write the u16 from cht_register[cht_reg_no2] to cht_register[cht_reg_no1]
|
|
|
|
// and add the u16 from the address field to it
|
2021-09-10 05:53:15 +00:00
|
|
|
cht_register[cht_reg_no1] =
|
|
|
|
Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) + Truncate16(poke_value & 0xFFFFu);
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x44: // Write the u16 from the value stored in cht_register[cht_reg_no2] + poke_value to the address
|
|
|
|
// stored in cht_register[cht_reg_no1]
|
|
|
|
DoMemoryWrite<u16>(cht_register[cht_reg_no1],
|
|
|
|
Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) + Truncate16(poke_value & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x45: // Write the u16 poke value to cht_register[cht_reg_no1]
|
|
|
|
cht_register[cht_reg_no1] = Truncate16(poke_value & 0xFFFFu);
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
|
|
|
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x80: // Write the u32 from cht_register[cht_reg_no1] to address
|
|
|
|
DoMemoryWrite<u32>(inst.value32, cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
case 0x81: // Read the u32 from address to cht_register[cht_reg_no1]
|
|
|
|
cht_register[cht_reg_no1] = DoMemoryRead<u32>(inst.value32);
|
|
|
|
break;
|
|
|
|
case 0x82: // Write the u32 from address field to the address stored in cht_register[cht_reg_no]
|
|
|
|
DoMemoryWrite<u32>(cht_register[cht_reg_no1], poke_value);
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x83: // Write the u32 from cht_register[cht_reg_no2] to cht_register[cht_reg_no1]
|
|
|
|
// and add the u32 from the address field to it
|
|
|
|
cht_register[cht_reg_no1] = cht_register[cht_reg_no2] + poke_value;
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x84: // Write the u32 from the value stored in cht_register[cht_reg_no2] + poke_value to the address
|
|
|
|
// stored in cht_register[cht_reg_no1]
|
|
|
|
DoMemoryWrite<u32>(cht_register[cht_reg_no1], cht_register[cht_reg_no2] + poke_value);
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0x85: // Write the u32 poke value to cht_register[cht_reg_no1]
|
|
|
|
cht_register[cht_reg_no1] = poke_value;
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
|
|
|
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0xC0: // Reg3 = Reg2 + Reg1
|
|
|
|
cht_register[cht_reg_no3] = cht_register[cht_reg_no2] + cht_register[cht_reg_no1];
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0xC1: // Reg3 = Reg2 - Reg1
|
|
|
|
cht_register[cht_reg_no3] = cht_register[cht_reg_no2] - cht_register[cht_reg_no1];
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
2021-03-13 15:21:40 +00:00
|
|
|
case 0xC2: // Reg3 = Reg2 * Reg1
|
|
|
|
cht_register[cht_reg_no3] = cht_register[cht_reg_no2] * cht_register[cht_reg_no1];
|
|
|
|
break;
|
|
|
|
case 0xC3: // Reg3 = Reg2 / Reg1 with DIV0 handling
|
|
|
|
if (cht_register[cht_reg_no1] == 0)
|
|
|
|
cht_register[cht_reg_no3] = 0;
|
|
|
|
else
|
|
|
|
cht_register[cht_reg_no3] = cht_register[cht_reg_no2] / cht_register[cht_reg_no1];
|
|
|
|
break;
|
|
|
|
case 0xC4: // Reg3 = Reg2 % Reg1 (with DIV0 handling)
|
|
|
|
if (cht_register[cht_reg_no1] == 0)
|
|
|
|
cht_register[cht_reg_no3] = cht_register[cht_reg_no2];
|
|
|
|
else
|
|
|
|
cht_register[cht_reg_no3] = cht_register[cht_reg_no2] % cht_register[cht_reg_no1];
|
|
|
|
break;
|
|
|
|
case 0xC5: // Reg3 = Reg2 & Reg1
|
|
|
|
cht_register[cht_reg_no3] = cht_register[cht_reg_no2] & cht_register[cht_reg_no1];
|
|
|
|
break;
|
|
|
|
case 0xC6: // Reg3 = Reg2 | Reg1
|
|
|
|
cht_register[cht_reg_no3] = cht_register[cht_reg_no2] | cht_register[cht_reg_no1];
|
|
|
|
break;
|
|
|
|
case 0xC7: // Reg3 = Reg2 ^ Reg1
|
|
|
|
cht_register[cht_reg_no3] = cht_register[cht_reg_no2] ^ cht_register[cht_reg_no1];
|
|
|
|
break;
|
|
|
|
case 0xC8: // Reg3 = ~Reg1
|
|
|
|
cht_register[cht_reg_no3] = ~cht_register[cht_reg_no1];
|
|
|
|
break;
|
|
|
|
case 0xC9: // Reg3 = Reg1 << X
|
|
|
|
cht_register[cht_reg_no3] = cht_register[cht_reg_no1] << cht_reg_no2;
|
|
|
|
break;
|
|
|
|
case 0xCA: // Reg3 = Reg1 >> X
|
|
|
|
cht_register[cht_reg_no3] = cht_register[cht_reg_no1] >> cht_reg_no2;
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
break;
|
|
|
|
// Lots of options exist for expanding into this space
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2021-03-13 15:21:40 +00:00
|
|
|
index++;
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-12-06 05:47:00 +00:00
|
|
|
case InstructionCode::SkipIfNotEqual16: // C0
|
2020-12-17 13:33:00 +00:00
|
|
|
case InstructionCode::ExtSkipIfNotEqual32: // A4
|
2020-12-06 05:47:00 +00:00
|
|
|
case InstructionCode::SkipIfButtonsNotEqual: // D5
|
|
|
|
case InstructionCode::SkipIfButtonsEqual: // D6
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
case InstructionCode::ExtSkipIfNotLess8: // C3
|
|
|
|
case InstructionCode::ExtSkipIfNotGreater8: // C4
|
|
|
|
case InstructionCode::ExtSkipIfNotLess16: // C5
|
|
|
|
case InstructionCode::ExtSkipIfNotGreater16: // C6
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
case InstructionCode::ExtMultiConditionals: // F6
|
2020-12-02 12:50:36 +00:00
|
|
|
{
|
2020-12-04 16:00:37 +00:00
|
|
|
index++;
|
|
|
|
|
2020-12-06 05:47:00 +00:00
|
|
|
bool activate_codes;
|
|
|
|
switch (inst.code)
|
|
|
|
{
|
|
|
|
case InstructionCode::SkipIfNotEqual16: // C0
|
|
|
|
activate_codes = (DoMemoryRead<u16>(inst.address) == inst.value16);
|
|
|
|
break;
|
2020-12-17 13:33:00 +00:00
|
|
|
case InstructionCode::ExtSkipIfNotEqual32: // A4
|
|
|
|
activate_codes = (DoMemoryRead<u32>(inst.address) == inst.value32);
|
|
|
|
break;
|
2020-12-06 05:47:00 +00:00
|
|
|
case InstructionCode::SkipIfButtonsNotEqual: // D5
|
|
|
|
activate_codes = (GetControllerButtonBits() == inst.value16);
|
|
|
|
break;
|
|
|
|
case InstructionCode::SkipIfButtonsEqual: // D6
|
|
|
|
activate_codes = (GetControllerButtonBits() != inst.value16);
|
|
|
|
break;
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
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;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
case InstructionCode::ExtMultiConditionals: // F6
|
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
// Ensure any else if or else that are hit outside the if context are skipped
|
|
|
|
if ((inst.value32 & 0xFFFFFF00u) != 0x1F000000)
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
activate_codes = false;
|
|
|
|
break;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
}
|
|
|
|
for (;;)
|
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
const u8 totalConds = Truncate8(instructions[index - 1].value32 & 0x000000FFu);
|
|
|
|
const u8 conditionType = Truncate8(instructions[index - 1].address & 0x000000FFu);
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
|
2021-09-10 05:53:15 +00:00
|
|
|
bool conditions_check;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
|
2021-09-10 05:53:15 +00:00
|
|
|
if (conditionType == 0x00 && totalConds > 0) // AND
|
|
|
|
{
|
|
|
|
conditions_check = true;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
|
2021-09-10 05:53:15 +00:00
|
|
|
for (int i = 1; totalConds >= i; index++, i++)
|
|
|
|
{
|
|
|
|
switch (instructions[index].code)
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
case InstructionCode::CompareEqual16: // D0
|
|
|
|
conditions_check &=
|
|
|
|
(DoMemoryRead<u16>(instructions[index].address) == instructions[index].value16);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareNotEqual16: // D1
|
|
|
|
conditions_check &=
|
|
|
|
(DoMemoryRead<u16>(instructions[index].address) != instructions[index].value16);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareLess16: // D2
|
|
|
|
conditions_check &=
|
|
|
|
(DoMemoryRead<u16>(instructions[index].address) < instructions[index].value16);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareGreater16: // D3
|
|
|
|
conditions_check &=
|
|
|
|
(DoMemoryRead<u16>(instructions[index].address) > instructions[index].value16);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareEqual8: // E0
|
|
|
|
conditions_check &= (DoMemoryRead<u8>(instructions[index].address) == instructions[index].value8);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareNotEqual8: // E1
|
|
|
|
conditions_check &= (DoMemoryRead<u8>(instructions[index].address) != instructions[index].value8);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareLess8: // E2
|
|
|
|
conditions_check &= (DoMemoryRead<u8>(instructions[index].address) < instructions[index].value8);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareGreater8: // E3
|
|
|
|
conditions_check &= (DoMemoryRead<u8>(instructions[index].address) > instructions[index].value8);
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtCompareEqual32: // A0
|
|
|
|
conditions_check &=
|
|
|
|
(DoMemoryRead<u32>(instructions[index].address) == instructions[index].value32);
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtCompareNotEqual32: // A1
|
|
|
|
conditions_check &=
|
|
|
|
(DoMemoryRead<u32>(instructions[index].address) != instructions[index].value32);
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtCompareLess32: // A2
|
|
|
|
conditions_check &=
|
|
|
|
(DoMemoryRead<u32>(instructions[index].address) < instructions[index].value32);
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtCompareGreater32: // A3
|
|
|
|
conditions_check &=
|
|
|
|
(DoMemoryRead<u32>(instructions[index].address) > instructions[index].value32);
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtCompareBitsSet8: // E4 Internal to F6
|
|
|
|
conditions_check &=
|
|
|
|
(instructions[index].value8 ==
|
|
|
|
(DoMemoryRead<u8>(instructions[index].address) & instructions[index].value8));
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtCompareBitsClear8: // E5 Internal to F6
|
|
|
|
conditions_check &=
|
|
|
|
((DoMemoryRead<u8>(instructions[index].address) & instructions[index].value8) == 0);
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtBitCompareButtons: // D7
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
const u32 frame_compare_value = instructions[index].address & 0xFFFFu;
|
|
|
|
const u8 cht_reg_no = Truncate8((instructions[index].value32 & 0xFF000000u) >> 24);
|
|
|
|
const bool bit_comparison_type = ((instructions[index].address & 0x100000u) >> 20);
|
|
|
|
const u8 frame_comparison = Truncate8((instructions[index].address & 0xF0000u) >> 16);
|
|
|
|
const u32 check_value = (instructions[index].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
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
cht_register[cht_reg_no] += 1;
|
|
|
|
switch (frame_comparison)
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
case 0x0: // No comparison on frame count, just do it
|
|
|
|
conditions_check &= true;
|
|
|
|
break;
|
|
|
|
case 0x1: // Check if frame_compare_value == current count
|
|
|
|
conditions_check &= (cht_register[cht_reg_no] == frame_compare_value);
|
|
|
|
break;
|
|
|
|
case 0x2: // Check if frame_compare_value < current count
|
|
|
|
conditions_check &= (cht_register[cht_reg_no] < frame_compare_value);
|
|
|
|
break;
|
|
|
|
case 0x3: // Check if frame_compare_value > current count
|
|
|
|
conditions_check &= (cht_register[cht_reg_no] > frame_compare_value);
|
|
|
|
break;
|
|
|
|
case 0x4: // Check if frame_compare_value != current count
|
|
|
|
conditions_check &= (cht_register[cht_reg_no] != frame_compare_value);
|
|
|
|
break;
|
|
|
|
default:
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
conditions_check &= false;
|
2021-09-10 05:53:15 +00:00
|
|
|
break;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-10 05:53:15 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cht_register[cht_reg_no] = 0;
|
|
|
|
conditions_check &= false;
|
|
|
|
}
|
|
|
|
break;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
}
|
2021-09-10 05:53:15 +00:00
|
|
|
default:
|
|
|
|
Log_ErrorPrintf("Incorrect conditional instruction (see chtdb.txt for supported instructions)");
|
|
|
|
return;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-10 05:53:15 +00:00
|
|
|
}
|
|
|
|
else if (conditionType == 0x01 && totalConds > 0) // OR
|
|
|
|
{
|
|
|
|
conditions_check = false;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
|
2021-09-10 05:53:15 +00:00
|
|
|
for (int i = 1; totalConds >= i; index++, i++)
|
|
|
|
{
|
|
|
|
switch (instructions[index].code)
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
case InstructionCode::CompareEqual16: // D0
|
|
|
|
conditions_check |=
|
|
|
|
(DoMemoryRead<u16>(instructions[index].address) == instructions[index].value16);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareNotEqual16: // D1
|
|
|
|
conditions_check |=
|
|
|
|
(DoMemoryRead<u16>(instructions[index].address) != instructions[index].value16);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareLess16: // D2
|
|
|
|
conditions_check |=
|
|
|
|
(DoMemoryRead<u16>(instructions[index].address) < instructions[index].value16);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareGreater16: // D3
|
|
|
|
conditions_check |=
|
|
|
|
(DoMemoryRead<u16>(instructions[index].address) > instructions[index].value16);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareEqual8: // E0
|
|
|
|
conditions_check |= (DoMemoryRead<u8>(instructions[index].address) == instructions[index].value8);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareNotEqual8: // E1
|
|
|
|
conditions_check |= (DoMemoryRead<u8>(instructions[index].address) != instructions[index].value8);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareLess8: // E2
|
|
|
|
conditions_check |= (DoMemoryRead<u8>(instructions[index].address) < instructions[index].value8);
|
|
|
|
break;
|
|
|
|
case InstructionCode::CompareGreater8: // E3
|
|
|
|
conditions_check |= (DoMemoryRead<u8>(instructions[index].address) > instructions[index].value8);
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtCompareEqual32: // A0
|
|
|
|
conditions_check |=
|
|
|
|
(DoMemoryRead<u32>(instructions[index].address) == instructions[index].value32);
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtCompareNotEqual32: // A1
|
|
|
|
conditions_check |=
|
|
|
|
(DoMemoryRead<u32>(instructions[index].address) != instructions[index].value32);
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtCompareLess32: // A2
|
|
|
|
conditions_check |=
|
|
|
|
(DoMemoryRead<u32>(instructions[index].address) < instructions[index].value32);
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtCompareGreater32: // A3
|
|
|
|
conditions_check |=
|
|
|
|
(DoMemoryRead<u32>(instructions[index].address) > instructions[index].value32);
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtCompareBitsSet8: // E4 Internal to F6
|
|
|
|
conditions_check |=
|
|
|
|
(instructions[index].value8 ==
|
|
|
|
(DoMemoryRead<u8>(instructions[index].address) & instructions[index].value8));
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtCompareBitsClear8: // E5 Internal to F6
|
|
|
|
conditions_check |=
|
|
|
|
((DoMemoryRead<u8>(instructions[index].address) & instructions[index].value8) == 0);
|
|
|
|
break;
|
|
|
|
case InstructionCode::ExtBitCompareButtons: // D7
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
const u32 frame_compare_value = instructions[index].address & 0xFFFFu;
|
|
|
|
const u8 cht_reg_no = Truncate8((instructions[index].value32 & 0xFF000000u) >> 24);
|
|
|
|
const bool bit_comparison_type = ((instructions[index].address & 0x100000u) >> 20);
|
|
|
|
const u8 frame_comparison = Truncate8((instructions[index].address & 0xF0000u) >> 16);
|
|
|
|
const u32 check_value = (instructions[index].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
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
cht_register[cht_reg_no] += 1;
|
|
|
|
switch (frame_comparison)
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
case 0x0: // No comparison on frame count, just do it
|
|
|
|
conditions_check |= true;
|
|
|
|
break;
|
|
|
|
case 0x1: // Check if frame_compare_value == current count
|
|
|
|
conditions_check |= (cht_register[cht_reg_no] == frame_compare_value);
|
|
|
|
break;
|
|
|
|
case 0x2: // Check if frame_compare_value < current count
|
|
|
|
conditions_check |= (cht_register[cht_reg_no] < frame_compare_value);
|
|
|
|
break;
|
|
|
|
case 0x3: // Check if frame_compare_value > current count
|
|
|
|
conditions_check |= (cht_register[cht_reg_no] > frame_compare_value);
|
|
|
|
break;
|
|
|
|
case 0x4: // Check if frame_compare_value != current count
|
|
|
|
conditions_check |= (cht_register[cht_reg_no] != frame_compare_value);
|
|
|
|
break;
|
|
|
|
default:
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
conditions_check |= false;
|
2021-09-10 05:53:15 +00:00
|
|
|
break;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-10 05:53:15 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cht_register[cht_reg_no] = 0;
|
|
|
|
conditions_check |= false;
|
|
|
|
}
|
|
|
|
break;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
}
|
2021-09-10 05:53:15 +00:00
|
|
|
default:
|
|
|
|
Log_ErrorPrintf("Incorrect conditional instruction (see chtdb.txt for supported instructions)");
|
|
|
|
return;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-10 05:53:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Log_ErrorPrintf("Incomplete multi conditional instruction");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (conditions_check == true)
|
|
|
|
{
|
|
|
|
activate_codes = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // parse through to 00000000 FFFF and peek if next line is a F6 type associated with a ELSE
|
|
|
|
activate_codes = false;
|
|
|
|
// skip to the next separator (00000000 FFFF), or end
|
|
|
|
constexpr u64 separator_value = UINT64_C(0x000000000000FFFF);
|
|
|
|
constexpr u64 else_value = UINT64_C(0x00000000E15E0000);
|
|
|
|
constexpr u64 elseif_value = UINT64_C(0x00000000E15E1F00);
|
|
|
|
while (index < count)
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
const u64 bits = instructions[index++].bits;
|
|
|
|
if (bits == separator_value)
|
|
|
|
{
|
|
|
|
const u64 bits_ahead = instructions[index].bits;
|
|
|
|
if ((bits_ahead & 0xFFFFFF00u) == elseif_value)
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
break;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
}
|
2021-09-10 05:53:15 +00:00
|
|
|
if ((bits_ahead & 0xFFFF0000u) == else_value)
|
|
|
|
{
|
|
|
|
// index++;
|
|
|
|
activate_codes = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
index--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((bits & 0xFFFFFF00u) == elseif_value)
|
|
|
|
{
|
|
|
|
// index--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((bits & 0xFFFFFFFFu) == else_value)
|
|
|
|
{
|
|
|
|
// index++;
|
|
|
|
activate_codes = true;
|
|
|
|
break;
|
|
|
|
}
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
}
|
2021-09-10 05:53:15 +00:00
|
|
|
if (activate_codes == true)
|
|
|
|
break;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
}
|
2021-09-10 05:53:15 +00:00
|
|
|
}
|
|
|
|
break;
|
New F6 Cheat Type (IF,ELSE IF, ELSE structure)
Cheat Type F6 lets you perform cheats in IF / ELSE IF / ELSE constructs along
with multiple conditions for each one.
It supports conditions D0, D1, D2, D3, E0, E1, E2, E3, A0, A1, A2, A3, D7 and
two new types that will only be available in the F6 conditions :-
E4 & E5 which are bit comparisons on bytes (set and clear).
Any of those types which are "block conditionals" like D7 will be treated as a
single condition with the other conditions so you wont need to worry about
extra 00000000 FFFFs just for them (infact you can drop them completely apart
from the last 00000000 FFFF, which you can also drop if you have no trailing
cheat lines after the end of the construct.
#IF / ELSE IF / ELSE Statement Example with Notes
80001000 00000001 Setup Test Condition 1
80001004 00000002 Setup Test Condition 2
80001008 00000003 Setup Test Condition 3
8000100C 00000004 Setup Test Condition 4
1F = IF, last two digits determine the number of conditions to check
F600000x x = 0 All conditions must be true, x = 1 At least One condition must be true
F6000000 1F000004 Check the next 4 lines as the conditions for the IF loop to be taken
D0001000 00000001 )
D0001004 00000002 )Conditions
D0001008 00000003 )
D000100C 00000004 )
80001010 00005555 Poke(s)
00000000 0000FFFF End of IF Statement
F6000000 E15E1F02 E15E1F = ELSE IF (same format as IF) - Can have multiple ELSE IF Blocks or none at all
D0001008 00000003 )
D000100C 00000005 )Conditions
80001010 00008888 Poke(s)
00000000 0000FFFF End of ELSE IF Statement
F6000000 E15E0000 E15E = ELSE (no need for conditions - this will poke if the others dont)
80001010 0000AAAA Poke(s)
00000000 0000FFFF End of ELSE Statement
#Multiple Test Using Joypad Left Thumb Directions, Look at Address 1100 in Debugger
F6000000 1F000001
D7020002 00100000
90001100 50205055
90001104 53534552
90001108 20204445
9000110C 20202020
F6000000 E15E1F01
D7020002 00400000
90001100 4E574F44
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00800000
90001100 5446454C
90001104 45525020
90001108 44455353
9000110C 20202020
F6000000 E15E1F01
D7020002 00200000
90001100 48474952
90001104 52502054
90001108 45535345
9000110C 20202044
F6000000 E15E0000
90001100 20202020
90001104 20202020
90001108 20202020
9000110C 20202020
00000000 0000FFFF
2021-08-21 14:08:34 +00:00
|
|
|
}
|
2020-12-06 05:47:00 +00:00
|
|
|
default:
|
|
|
|
activate_codes = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (activate_codes)
|
2020-12-04 16:00:37 +00:00
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
}
|
2020-12-02 12:50:36 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2021-09-10 05:53:15 +00:00
|
|
|
case InstructionCode::ExtBitCompareButtons: // D7
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
{
|
|
|
|
index++;
|
|
|
|
bool activate_codes;
|
2021-09-10 05:53:15 +00:00
|
|
|
const u32 frame_compare_value = inst.address & 0xFFFFu;
|
|
|
|
const u8 cht_reg_no = Truncate8((inst.value32 & 0xFF000000u) >> 24);
|
|
|
|
const bool bit_comparison_type = ((inst.address & 0x100000u) >> 20);
|
|
|
|
const u8 frame_comparison = Truncate8((inst.address & 0xF0000u) >> 16);
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
const u32 check_value = (inst.value32 & 0xFFFFFFu);
|
|
|
|
const u32 value1 = GetControllerButtonBits();
|
|
|
|
const u32 value2 = GetControllerAnalogBits();
|
|
|
|
u32 value = value1 | value2;
|
|
|
|
|
2021-09-10 05:53:15 +00:00
|
|
|
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
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
cht_register[cht_reg_no] += 1;
|
2021-03-13 15:21:40 +00:00
|
|
|
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 = (cht_register[cht_reg_no] == frame_compare_value);
|
|
|
|
break;
|
|
|
|
case 0x2: // Check if frame_compare_value < current count
|
|
|
|
activate_codes = (cht_register[cht_reg_no] < frame_compare_value);
|
|
|
|
break;
|
|
|
|
case 0x3: // Check if frame_compare_value > current count
|
|
|
|
activate_codes = (cht_register[cht_reg_no] > frame_compare_value);
|
|
|
|
break;
|
|
|
|
case 0x4: // Check if frame_compare_value != current count
|
|
|
|
activate_codes = (cht_register[cht_reg_no] != frame_compare_value);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
activate_codes = false;
|
|
|
|
break;
|
|
|
|
}
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-09-10 05:53:15 +00:00
|
|
|
cht_register[cht_reg_no] = 0;
|
|
|
|
activate_codes = false;
|
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.
2021-03-03 23:06:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2021-03-13 15:21:40 +00:00
|
|
|
case InstructionCode::ExtCheatRegistersCompare: // 52
|
|
|
|
{
|
|
|
|
index++;
|
|
|
|
bool activate_codes = false;
|
|
|
|
const u8 cht_reg_no1 = Truncate8(inst.address & 0xFFu);
|
|
|
|
const u8 cht_reg_no2 = Truncate8((inst.address & 0xFF00u) >> 8);
|
2021-07-31 10:14:15 +00:00
|
|
|
const u8 sub_type = Truncate8((inst.first & 0xFF0000u) >> 16);
|
2021-03-13 15:21:40 +00:00
|
|
|
|
|
|
|
switch (sub_type)
|
|
|
|
{
|
|
|
|
case 0x00:
|
|
|
|
activate_codes =
|
|
|
|
(Truncate8(cht_register[cht_reg_no2] & 0xFFu) == Truncate8(cht_register[cht_reg_no1] & 0xFFu));
|
|
|
|
break;
|
|
|
|
case 0x01:
|
|
|
|
activate_codes =
|
|
|
|
(Truncate8(cht_register[cht_reg_no2] & 0xFFu) != Truncate8(cht_register[cht_reg_no1] & 0xFFu));
|
|
|
|
break;
|
|
|
|
case 0x02:
|
|
|
|
activate_codes =
|
|
|
|
(Truncate8(cht_register[cht_reg_no2] & 0xFFu) > Truncate8(cht_register[cht_reg_no1] & 0xFFu));
|
|
|
|
break;
|
|
|
|
case 0x03:
|
|
|
|
activate_codes =
|
|
|
|
(Truncate8(cht_register[cht_reg_no2] & 0xFFu) >= Truncate8(cht_register[cht_reg_no1] & 0xFFu));
|
|
|
|
break;
|
|
|
|
case 0x04:
|
|
|
|
activate_codes =
|
|
|
|
(Truncate8(cht_register[cht_reg_no2] & 0xFFu) < Truncate8(cht_register[cht_reg_no1] & 0xFFu));
|
|
|
|
break;
|
|
|
|
case 0x05:
|
|
|
|
activate_codes =
|
|
|
|
(Truncate8(cht_register[cht_reg_no2] & 0xFFu) <= Truncate8(cht_register[cht_reg_no1] & 0xFFu));
|
|
|
|
break;
|
|
|
|
case 0x06:
|
|
|
|
activate_codes =
|
|
|
|
((Truncate8(cht_register[cht_reg_no2] & 0xFFu) & Truncate8(cht_register[cht_reg_no1] & 0xFFu)) ==
|
|
|
|
(Truncate8(cht_register[cht_reg_no1] & 0xFFu)));
|
|
|
|
break;
|
|
|
|
case 0x07:
|
|
|
|
activate_codes =
|
|
|
|
((Truncate8(cht_register[cht_reg_no2] & 0xFFu) & Truncate8(cht_register[cht_reg_no1] & 0xFFu)) !=
|
|
|
|
(Truncate8(cht_register[cht_reg_no1] & 0xFFu)));
|
|
|
|
break;
|
|
|
|
case 0x0A:
|
|
|
|
activate_codes =
|
|
|
|
((Truncate8(cht_register[cht_reg_no2] & 0xFFu) & Truncate8(cht_register[cht_reg_no1] & 0xFFu)) ==
|
|
|
|
(Truncate8(cht_register[cht_reg_no2] & 0xFFu)));
|
|
|
|
break;
|
|
|
|
case 0x0B:
|
|
|
|
activate_codes =
|
|
|
|
((Truncate8(cht_register[cht_reg_no2] & 0xFFu) & Truncate8(cht_register[cht_reg_no1] & 0xFFu)) !=
|
|
|
|
(Truncate8(cht_register[cht_reg_no2] & 0xFFu)));
|
|
|
|
break;
|
|
|
|
case 0x10:
|
|
|
|
activate_codes = (Truncate8(cht_register[cht_reg_no1] & 0xFFu) == inst.value8);
|
|
|
|
break;
|
|
|
|
case 0x11:
|
|
|
|
activate_codes = (Truncate8(cht_register[cht_reg_no1] & 0xFFu) != inst.value8);
|
|
|
|
break;
|
|
|
|
case 0x12:
|
|
|
|
activate_codes = (Truncate8(cht_register[cht_reg_no1] & 0xFFu) > inst.value8);
|
|
|
|
break;
|
|
|
|
case 0x13:
|
|
|
|
activate_codes = (Truncate8(cht_register[cht_reg_no1] & 0xFFu) >= inst.value8);
|
|
|
|
break;
|
|
|
|
case 0x14:
|
|
|
|
activate_codes = (Truncate8(cht_register[cht_reg_no1] & 0xFFu) < inst.value8);
|
|
|
|
break;
|
|
|
|
case 0x15:
|
|
|
|
activate_codes = (Truncate8(cht_register[cht_reg_no1] & 0xFFu) <= inst.value8);
|
|
|
|
break;
|
|
|
|
case 0x16:
|
|
|
|
activate_codes = ((Truncate8(cht_register[cht_reg_no1] & 0xFFu) & inst.value8) == inst.value8);
|
|
|
|
break;
|
|
|
|
case 0x17:
|
|
|
|
activate_codes = ((Truncate8(cht_register[cht_reg_no1] & 0xFFu) & inst.value8) != inst.value8);
|
|
|
|
break;
|
|
|
|
case 0x18:
|
|
|
|
activate_codes =
|
|
|
|
((Truncate8(cht_register[cht_reg_no1] & 0xFFu) > inst.value8) &&
|
|
|
|
(Truncate8(cht_register[cht_reg_no1] & 0xFFu) < Truncate8((inst.value32 & 0xFF0000u) >> 16)));
|
|
|
|
break;
|
|
|
|
case 0x19:
|
|
|
|
activate_codes =
|
|
|
|
((Truncate8(cht_register[cht_reg_no1] & 0xFFu) >= inst.value8) &&
|
|
|
|
(Truncate8(cht_register[cht_reg_no1] & 0xFFu) <= Truncate8((inst.value32 & 0xFF0000u) >> 16)));
|
|
|
|
break;
|
|
|
|
case 0x1A:
|
|
|
|
activate_codes = ((Truncate8(cht_register[cht_reg_no2] & 0xFFu) & inst.value8) ==
|
|
|
|
Truncate8(cht_register[cht_reg_no1] & 0xFFu));
|
|
|
|
break;
|
|
|
|
case 0x1B:
|
|
|
|
activate_codes = ((Truncate8(cht_register[cht_reg_no1] & 0xFFu) & inst.value8) !=
|
|
|
|
Truncate8(cht_register[cht_reg_no1] & 0xFFu));
|
|
|
|
break;
|
|
|
|
case 0x20:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u8>(cht_register[cht_reg_no2]) == DoMemoryRead<u8>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x21:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u8>(cht_register[cht_reg_no2]) != DoMemoryRead<u8>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x22:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u8>(cht_register[cht_reg_no2]) > DoMemoryRead<u8>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x23:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u8>(cht_register[cht_reg_no2]) >= DoMemoryRead<u8>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x24:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u8>(cht_register[cht_reg_no2]) < DoMemoryRead<u8>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x25:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u8>(cht_register[cht_reg_no2]) <= DoMemoryRead<u8>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x26:
|
|
|
|
activate_codes = ((DoMemoryRead<u8>(cht_register[cht_reg_no1]) & inst.value8) == inst.value8);
|
|
|
|
break;
|
|
|
|
case 0x27:
|
|
|
|
activate_codes = ((DoMemoryRead<u8>(cht_register[cht_reg_no1]) & inst.value8) != inst.value8);
|
|
|
|
break;
|
|
|
|
case 0x28:
|
|
|
|
activate_codes =
|
|
|
|
((DoMemoryRead<u8>(cht_register[cht_reg_no1]) > inst.value8) &&
|
|
|
|
(DoMemoryRead<u8>(cht_register[cht_reg_no1]) < Truncate8((inst.value32 & 0xFF0000u) >> 16)));
|
|
|
|
break;
|
|
|
|
case 0x29:
|
|
|
|
activate_codes =
|
|
|
|
((DoMemoryRead<u8>(cht_register[cht_reg_no1]) >= inst.value8) &&
|
|
|
|
(DoMemoryRead<u8>(cht_register[cht_reg_no1]) <= Truncate8((inst.value32 & 0xFF0000u) >> 16)));
|
|
|
|
break;
|
|
|
|
case 0x2A:
|
|
|
|
activate_codes = ((DoMemoryRead<u8>(cht_register[cht_reg_no1]) & inst.value8) ==
|
|
|
|
DoMemoryRead<u8>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x2B:
|
|
|
|
activate_codes = ((DoMemoryRead<u8>(cht_register[cht_reg_no1]) & inst.value8) !=
|
|
|
|
DoMemoryRead<u8>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x30:
|
|
|
|
activate_codes = (Truncate8(cht_register[cht_reg_no1] & 0xFFu) == DoMemoryRead<u8>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x31:
|
|
|
|
activate_codes = (Truncate8(cht_register[cht_reg_no1] & 0xFFu) != DoMemoryRead<u8>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x32:
|
|
|
|
activate_codes = (Truncate8(cht_register[cht_reg_no1] & 0xFFu) > DoMemoryRead<u8>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x33:
|
|
|
|
activate_codes = (Truncate8(cht_register[cht_reg_no1] & 0xFFu) >= DoMemoryRead<u8>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x34:
|
|
|
|
activate_codes = (Truncate8(cht_register[cht_reg_no1] & 0xFFu) < DoMemoryRead<u8>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x36:
|
|
|
|
activate_codes = ((Truncate8(cht_register[cht_reg_no1] & 0xFFu) & DoMemoryRead<u8>(inst.value32)) ==
|
|
|
|
DoMemoryRead<u8>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x37:
|
|
|
|
activate_codes = ((Truncate8(cht_register[cht_reg_no1] & 0xFFu) & DoMemoryRead<u8>(inst.value32)) !=
|
|
|
|
DoMemoryRead<u8>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x3A:
|
|
|
|
activate_codes = ((Truncate8(cht_register[cht_reg_no1] & 0xFFu) & DoMemoryRead<u8>(inst.value32)) ==
|
|
|
|
Truncate8(cht_register[cht_reg_no1] & 0xFFu));
|
|
|
|
break;
|
|
|
|
case 0x3B:
|
|
|
|
activate_codes = ((Truncate8(cht_register[cht_reg_no1] & 0xFFu) & DoMemoryRead<u8>(inst.value32)) !=
|
|
|
|
Truncate8(cht_register[cht_reg_no1] & 0xFFu));
|
|
|
|
break;
|
|
|
|
case 0x40:
|
|
|
|
activate_codes =
|
|
|
|
(Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) == Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x41:
|
|
|
|
activate_codes =
|
|
|
|
(Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) != Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x42:
|
|
|
|
activate_codes =
|
|
|
|
(Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) > Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x43:
|
|
|
|
activate_codes =
|
|
|
|
(Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) >= Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x44:
|
|
|
|
activate_codes =
|
|
|
|
(Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) < Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x45:
|
|
|
|
activate_codes =
|
|
|
|
(Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) <= Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x46:
|
|
|
|
activate_codes =
|
|
|
|
((Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) & Truncate16(cht_register[cht_reg_no1] & 0xFFFFu)) ==
|
|
|
|
Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x47:
|
|
|
|
activate_codes =
|
|
|
|
((Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) & Truncate16(cht_register[cht_reg_no1] & 0xFFFFu)) !=
|
|
|
|
Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x4A:
|
|
|
|
activate_codes =
|
|
|
|
((Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) & Truncate16(cht_register[cht_reg_no1] & 0xFFFFu)) ==
|
|
|
|
Truncate16(cht_register[cht_reg_no2] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x4B:
|
|
|
|
activate_codes =
|
|
|
|
((Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) & Truncate16(cht_register[cht_reg_no1] & 0xFFFFu)) !=
|
|
|
|
Truncate16(cht_register[cht_reg_no2] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x50:
|
|
|
|
activate_codes = (Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) == inst.value16);
|
|
|
|
break;
|
|
|
|
case 0x51:
|
|
|
|
activate_codes = (Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) != inst.value16);
|
|
|
|
break;
|
|
|
|
case 0x52:
|
|
|
|
activate_codes = (Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) > inst.value16);
|
|
|
|
break;
|
|
|
|
case 0x53:
|
|
|
|
activate_codes = (Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) >= inst.value16);
|
|
|
|
break;
|
|
|
|
case 0x54:
|
|
|
|
activate_codes = (Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) < inst.value16);
|
|
|
|
break;
|
|
|
|
case 0x55:
|
|
|
|
activate_codes = (Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) <= inst.value16);
|
|
|
|
break;
|
|
|
|
case 0x56:
|
|
|
|
activate_codes = ((Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) & inst.value16) == inst.value16);
|
|
|
|
break;
|
|
|
|
case 0x57:
|
|
|
|
activate_codes = ((Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) & inst.value16) != inst.value16);
|
|
|
|
break;
|
|
|
|
case 0x58:
|
|
|
|
activate_codes =
|
|
|
|
((Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) > inst.value16) &&
|
|
|
|
(Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) < Truncate16((inst.value32 & 0xFFFF0000u) >> 16)));
|
|
|
|
break;
|
|
|
|
case 0x59:
|
|
|
|
activate_codes =
|
|
|
|
((Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) >= inst.value16) &&
|
|
|
|
(Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) <= Truncate16((inst.value32 & 0xFFFF0000u) >> 16)));
|
|
|
|
break;
|
|
|
|
case 0x5A:
|
|
|
|
activate_codes = ((Truncate16(cht_register[cht_reg_no2] & 0xFFFFu) & inst.value16) ==
|
|
|
|
Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x5B:
|
|
|
|
activate_codes = ((Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) & inst.value16) !=
|
|
|
|
Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x60:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u16>(cht_register[cht_reg_no2]) == DoMemoryRead<u16>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x61:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u16>(cht_register[cht_reg_no2]) != DoMemoryRead<u16>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x62:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u16>(cht_register[cht_reg_no2]) > DoMemoryRead<u16>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x63:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u16>(cht_register[cht_reg_no2]) >= DoMemoryRead<u16>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x64:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u16>(cht_register[cht_reg_no2]) < DoMemoryRead<u16>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x65:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u16>(cht_register[cht_reg_no2]) <= DoMemoryRead<u16>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x66:
|
|
|
|
activate_codes = ((DoMemoryRead<u16>(cht_register[cht_reg_no1]) & inst.value16) == inst.value16);
|
|
|
|
break;
|
|
|
|
case 0x67:
|
|
|
|
activate_codes = ((DoMemoryRead<u16>(cht_register[cht_reg_no1]) & inst.value16) != inst.value16);
|
|
|
|
break;
|
|
|
|
case 0x68:
|
|
|
|
activate_codes =
|
|
|
|
((DoMemoryRead<u16>(cht_register[cht_reg_no1]) > inst.value16) &&
|
|
|
|
(DoMemoryRead<u16>(cht_register[cht_reg_no1]) < Truncate16((inst.value32 & 0xFFFF0000u) >> 16)));
|
|
|
|
break;
|
|
|
|
case 0x69:
|
|
|
|
activate_codes =
|
|
|
|
((DoMemoryRead<u16>(cht_register[cht_reg_no1]) >= inst.value16) &&
|
|
|
|
(DoMemoryRead<u16>(cht_register[cht_reg_no1]) <= Truncate16((inst.value32 & 0xFFFF0000u) >> 16)));
|
|
|
|
break;
|
|
|
|
case 0x6A:
|
|
|
|
activate_codes = ((DoMemoryRead<u16>(cht_register[cht_reg_no1]) & inst.value16) ==
|
|
|
|
DoMemoryRead<u16>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x6B:
|
|
|
|
activate_codes = ((DoMemoryRead<u16>(cht_register[cht_reg_no1]) & inst.value16) !=
|
|
|
|
DoMemoryRead<u16>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0x70:
|
|
|
|
activate_codes = (Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) == DoMemoryRead<u16>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x71:
|
|
|
|
activate_codes = (Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) != DoMemoryRead<u16>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x72:
|
|
|
|
activate_codes = (Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) > DoMemoryRead<u16>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x73:
|
|
|
|
activate_codes = (Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) >= DoMemoryRead<u16>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x74:
|
|
|
|
activate_codes = (Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) < DoMemoryRead<u16>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x76:
|
|
|
|
activate_codes = ((Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) & DoMemoryRead<u16>(inst.value32)) ==
|
|
|
|
DoMemoryRead<u16>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x77:
|
|
|
|
activate_codes = ((Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) & DoMemoryRead<u16>(inst.value32)) !=
|
|
|
|
DoMemoryRead<u16>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0x7A:
|
|
|
|
activate_codes = ((Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) & DoMemoryRead<u16>(inst.value32)) ==
|
|
|
|
Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x7B:
|
|
|
|
activate_codes = ((Truncate16(cht_register[cht_reg_no1] & 0xFFFFu) & DoMemoryRead<u16>(inst.value32)) !=
|
|
|
|
Truncate16(cht_register[cht_reg_no1] & 0xFFFFu));
|
|
|
|
break;
|
|
|
|
case 0x80:
|
|
|
|
activate_codes = (cht_register[cht_reg_no2] == cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
case 0x81:
|
|
|
|
activate_codes = (cht_register[cht_reg_no2] != cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
case 0x82:
|
|
|
|
activate_codes = (cht_register[cht_reg_no2] > cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
case 0x83:
|
|
|
|
activate_codes = (cht_register[cht_reg_no2] >= cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
case 0x84:
|
|
|
|
activate_codes = (cht_register[cht_reg_no2] < cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
case 0x85:
|
|
|
|
activate_codes = (cht_register[cht_reg_no2] <= cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
case 0x86:
|
|
|
|
activate_codes = ((cht_register[cht_reg_no2] & cht_register[cht_reg_no1]) == cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
case 0x87:
|
|
|
|
activate_codes = ((cht_register[cht_reg_no2] & cht_register[cht_reg_no1]) != cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
case 0x8A:
|
|
|
|
activate_codes = ((cht_register[cht_reg_no2] & cht_register[cht_reg_no1]) == cht_register[cht_reg_no2]);
|
|
|
|
break;
|
|
|
|
case 0x8B:
|
|
|
|
activate_codes = ((cht_register[cht_reg_no2] & cht_register[cht_reg_no1]) != cht_register[cht_reg_no2]);
|
|
|
|
break;
|
|
|
|
case 0x90:
|
|
|
|
activate_codes = (cht_register[cht_reg_no1] == inst.value32);
|
|
|
|
break;
|
|
|
|
case 0x91:
|
|
|
|
activate_codes = (cht_register[cht_reg_no1] != inst.value32);
|
|
|
|
break;
|
|
|
|
case 0x92:
|
|
|
|
activate_codes = (cht_register[cht_reg_no1] > inst.value32);
|
|
|
|
break;
|
|
|
|
case 0x93:
|
|
|
|
activate_codes = (cht_register[cht_reg_no1] >= inst.value32);
|
|
|
|
break;
|
|
|
|
case 0x94:
|
|
|
|
activate_codes = (cht_register[cht_reg_no1] < inst.value32);
|
|
|
|
break;
|
|
|
|
case 0x95:
|
|
|
|
activate_codes = (cht_register[cht_reg_no1] <= inst.value32);
|
|
|
|
break;
|
|
|
|
case 0x96:
|
|
|
|
activate_codes = ((cht_register[cht_reg_no1] & inst.value32) == inst.value32);
|
|
|
|
break;
|
|
|
|
case 0x97:
|
|
|
|
activate_codes = ((cht_register[cht_reg_no1] & inst.value32) != inst.value32);
|
|
|
|
break;
|
|
|
|
case 0x9A:
|
|
|
|
activate_codes = ((cht_register[cht_reg_no2] & inst.value32) == cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
case 0x9B:
|
|
|
|
activate_codes = ((cht_register[cht_reg_no1] & inst.value32) != cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
case 0xA0:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u32>(cht_register[cht_reg_no2]) == DoMemoryRead<u32>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0xA1:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u32>(cht_register[cht_reg_no2]) != DoMemoryRead<u32>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0xA2:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u32>(cht_register[cht_reg_no2]) > DoMemoryRead<u32>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0xA3:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u32>(cht_register[cht_reg_no2]) >= DoMemoryRead<u32>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0xA4:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u32>(cht_register[cht_reg_no2]) < DoMemoryRead<u32>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0xA5:
|
|
|
|
activate_codes =
|
|
|
|
(DoMemoryRead<u32>(cht_register[cht_reg_no2]) <= DoMemoryRead<u32>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0xA6:
|
|
|
|
activate_codes = ((DoMemoryRead<u32>(cht_register[cht_reg_no1]) & inst.value32) == inst.value32);
|
|
|
|
break;
|
|
|
|
case 0xA7:
|
|
|
|
activate_codes = ((DoMemoryRead<u32>(cht_register[cht_reg_no1]) & inst.value32) != inst.value32);
|
|
|
|
break;
|
|
|
|
case 0xAA:
|
|
|
|
activate_codes = ((DoMemoryRead<u32>(cht_register[cht_reg_no1]) & inst.value32) ==
|
|
|
|
DoMemoryRead<u32>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0xAB:
|
|
|
|
activate_codes = ((DoMemoryRead<u32>(cht_register[cht_reg_no1]) & inst.value32) !=
|
|
|
|
DoMemoryRead<u32>(cht_register[cht_reg_no1]));
|
|
|
|
break;
|
|
|
|
case 0xB0:
|
|
|
|
activate_codes = (cht_register[cht_reg_no1] == DoMemoryRead<u32>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0xB1:
|
|
|
|
activate_codes = (cht_register[cht_reg_no1] != DoMemoryRead<u32>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0xB2:
|
|
|
|
activate_codes = (cht_register[cht_reg_no1] > DoMemoryRead<u32>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0xB3:
|
|
|
|
activate_codes = (cht_register[cht_reg_no1] >= DoMemoryRead<u32>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0xB4:
|
|
|
|
activate_codes = (cht_register[cht_reg_no1] < DoMemoryRead<u32>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0xB6:
|
|
|
|
activate_codes =
|
|
|
|
((cht_register[cht_reg_no1] & DoMemoryRead<u32>(inst.value32)) == DoMemoryRead<u32>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0xB7:
|
|
|
|
activate_codes =
|
|
|
|
((cht_register[cht_reg_no1] & DoMemoryRead<u32>(inst.value32)) != DoMemoryRead<u32>(inst.value32));
|
|
|
|
break;
|
|
|
|
case 0xBA:
|
|
|
|
activate_codes =
|
|
|
|
((cht_register[cht_reg_no1] & DoMemoryRead<u32>(inst.value32)) == cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
case 0xBB:
|
|
|
|
activate_codes =
|
|
|
|
((cht_register[cht_reg_no1] & DoMemoryRead<u32>(inst.value32)) != cht_register[cht_reg_no1]);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
activate_codes = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
|
2020-12-06 05:50:58 +00:00
|
|
|
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.
|
|
|
|
// Frame number * 0.3 -> (20 * 60) * 10 / 3 => 4000
|
|
|
|
const u32 comp_value = (System::GetFrameNumber() * 10) / 3;
|
|
|
|
if (comp_value < inst.value16)
|
|
|
|
index = count;
|
|
|
|
else
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-09-28 10:06:01 +00:00
|
|
|
case InstructionCode::Slide:
|
|
|
|
{
|
|
|
|
if ((index + 1) >= instructions.size())
|
|
|
|
{
|
|
|
|
Log_ErrorPrintf("Incomplete slide instruction");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const u32 slide_count = (inst.first >> 8) & 0xFFu;
|
2020-12-24 00:17:09 +00:00
|
|
|
const u32 address_increment = inst.first & 0xFFu;
|
|
|
|
const u16 value_increment = Truncate16(inst.second);
|
2020-09-28 10:06:01 +00:00
|
|
|
const Instruction& inst2 = instructions[index + 1];
|
|
|
|
const InstructionCode write_type = inst2.code;
|
|
|
|
u32 address = inst2.address;
|
|
|
|
u16 value = inst2.value16;
|
|
|
|
|
|
|
|
if (write_type == InstructionCode::ConstantWrite8)
|
|
|
|
{
|
|
|
|
for (u32 i = 0; i < slide_count; i++)
|
|
|
|
{
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u8>(address, Truncate8(value));
|
2020-09-28 10:06:01 +00:00
|
|
|
address += address_increment;
|
|
|
|
value += value_increment;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (write_type == InstructionCode::ConstantWrite16)
|
|
|
|
{
|
|
|
|
for (u32 i = 0; i < slide_count; i++)
|
|
|
|
{
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u16>(address, value);
|
2020-09-28 10:06:01 +00:00
|
|
|
address += address_increment;
|
|
|
|
value += value_increment;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-02-06 09:19:55 +00:00
|
|
|
Log_ErrorPrintf("Invalid command in second slide parameter 0x%02X", static_cast<unsigned>(write_type));
|
2020-09-28 10:06:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
index += 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2021-03-13 15:21:40 +00:00
|
|
|
case InstructionCode::ExtImprovedSlide:
|
|
|
|
{
|
|
|
|
if ((index + 1) >= instructions.size())
|
|
|
|
{
|
|
|
|
Log_ErrorPrintf("Incomplete slide instruction");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const u32 slide_count = inst.first & 0xFFFFu;
|
|
|
|
const u32 address_change = (inst.second >> 16) & 0xFFFFu;
|
|
|
|
const u16 value_change = Truncate16(inst.second);
|
|
|
|
const Instruction& inst2 = instructions[index + 1];
|
|
|
|
const InstructionCode write_type = inst2.code;
|
|
|
|
const bool address_change_negative = (inst.first >> 20) & 0x1u;
|
|
|
|
const bool value_change_negative = (inst.first >> 16) & 0x1u;
|
|
|
|
u32 address = inst2.address;
|
|
|
|
u32 value = inst2.value32;
|
|
|
|
|
|
|
|
if (write_type == InstructionCode::ConstantWrite8)
|
|
|
|
{
|
|
|
|
for (u32 i = 0; i < slide_count; i++)
|
|
|
|
{
|
|
|
|
DoMemoryWrite<u8>(address, Truncate8(value));
|
|
|
|
if (address_change_negative)
|
2021-09-10 05:53:15 +00:00
|
|
|
address -= address_change;
|
2021-03-13 15:21:40 +00:00
|
|
|
else
|
2021-09-10 05:53:15 +00:00
|
|
|
address += address_change;
|
2021-03-13 15:21:40 +00:00
|
|
|
if (value_change_negative)
|
2021-09-10 05:53:15 +00:00
|
|
|
value -= value_change;
|
2021-03-13 15:21:40 +00:00
|
|
|
else
|
2021-09-10 05:53:15 +00:00
|
|
|
value += value_change;
|
2021-03-13 15:21:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (write_type == InstructionCode::ConstantWrite16)
|
|
|
|
{
|
|
|
|
for (u32 i = 0; i < slide_count; i++)
|
|
|
|
{
|
|
|
|
DoMemoryWrite<u16>(address, Truncate16(value));
|
|
|
|
if (address_change_negative)
|
2021-09-10 05:53:15 +00:00
|
|
|
address -= address_change;
|
2021-03-13 15:21:40 +00:00
|
|
|
else
|
2021-09-10 05:53:15 +00:00
|
|
|
address += address_change;
|
2021-03-13 15:21:40 +00:00
|
|
|
if (value_change_negative)
|
2021-09-10 05:53:15 +00:00
|
|
|
value -= value_change;
|
2021-03-13 15:21:40 +00:00
|
|
|
else
|
2021-09-10 05:53:15 +00:00
|
|
|
value += value_change;
|
2021-03-13 15:21:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (write_type == InstructionCode::ExtConstantWrite32)
|
|
|
|
{
|
|
|
|
for (u32 i = 0; i < slide_count; i++)
|
|
|
|
{
|
|
|
|
DoMemoryWrite<u32>(address, value);
|
|
|
|
if (address_change_negative)
|
2021-09-10 05:53:15 +00:00
|
|
|
address -= address_change;
|
2021-03-13 15:21:40 +00:00
|
|
|
else
|
2021-09-10 05:53:15 +00:00
|
|
|
address += address_change;
|
2021-03-13 15:21:40 +00:00
|
|
|
if (value_change_negative)
|
2021-09-10 05:53:15 +00:00
|
|
|
value -= value_change;
|
2021-03-13 15:21:40 +00:00
|
|
|
else
|
2021-09-10 05:53:15 +00:00
|
|
|
value += value_change;
|
2021-03-13 15:21:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Log_ErrorPrintf("Invalid command in second slide parameter 0x%02X", static_cast<unsigned>(write_type));
|
|
|
|
}
|
|
|
|
|
|
|
|
index += 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-09-28 10:24:58 +00:00
|
|
|
case InstructionCode::MemoryCopy:
|
|
|
|
{
|
|
|
|
if ((index + 1) >= instructions.size())
|
|
|
|
{
|
|
|
|
Log_ErrorPrintf("Incomplete memory copy instruction");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Instruction& inst2 = instructions[index + 1];
|
|
|
|
const u32 byte_count = inst.value16;
|
|
|
|
u32 src_address = inst.address;
|
|
|
|
u32 dst_address = inst2.address;
|
|
|
|
|
|
|
|
for (u32 i = 0; i < byte_count; i++)
|
|
|
|
{
|
2020-10-21 12:01:50 +00:00
|
|
|
u8 value = DoMemoryRead<u8>(src_address);
|
|
|
|
DoMemoryWrite<u8>(dst_address, value);
|
2020-09-28 10:24:58 +00:00
|
|
|
src_address++;
|
|
|
|
dst_address++;
|
|
|
|
}
|
|
|
|
|
|
|
|
index += 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-09-09 12:11:28 +00:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
Log_ErrorPrintf("Unhandled instruction code 0x%02X (%08X %08X)", static_cast<u8>(inst.code.GetValue()),
|
|
|
|
inst.first, inst.second);
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-19 15:14:49 +00:00
|
|
|
|
2020-12-25 04:21:43 +00:00
|
|
|
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:
|
2021-03-13 15:21:40 +00:00
|
|
|
case InstructionCode::ExtConstantSwap16:
|
2020-12-25 04:21:43 +00:00
|
|
|
case InstructionCode::DelayActivation: // C1
|
|
|
|
case InstructionCode::ExtConstantWriteIfMatch16:
|
2021-03-13 15:21:40 +00:00
|
|
|
case InstructionCode::ExtCheatRegisters:
|
2020-12-25 04:21:43 +00:00
|
|
|
index++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case InstructionCode::ExtConstantForceRange16:
|
|
|
|
case InstructionCode::Slide:
|
2021-03-13 15:21:40 +00:00
|
|
|
case InstructionCode::ExtImprovedSlide:
|
2020-12-25 04:21:43 +00:00
|
|
|
case InstructionCode::MemoryCopy:
|
|
|
|
index += 2;
|
|
|
|
break;
|
2021-02-06 09:19:55 +00:00
|
|
|
case InstructionCode::ExtFindAndReplace:
|
|
|
|
index += 5;
|
2020-12-29 14:55:49 +00:00
|
|
|
break;
|
2020-12-25 04:21:43 +00:00
|
|
|
// 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
|
2021-09-10 05:53:15 +00:00
|
|
|
case InstructionCode::SkipIfNotEqual16: // C0
|
|
|
|
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
|
|
|
|
case InstructionCode::ExtMultiConditionals: // F6
|
2021-03-13 15:21:40 +00:00
|
|
|
case InstructionCode::ExtCheatRegistersCompare: // 52
|
2020-12-25 04:21:43 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-19 15:14:49 +00:00
|
|
|
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")}};
|
|
|
|
|
|
|
|
const char* CheatCode::GetTypeName(Type type)
|
|
|
|
{
|
|
|
|
return s_cheat_code_type_names[static_cast<u32>(type)];
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* CheatCode::GetTypeDisplayName(Type type)
|
|
|
|
{
|
|
|
|
return s_cheat_code_type_display_names[static_cast<u32>(type)];
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<CheatCode::Type> CheatCode::ParseTypeName(const char* str)
|
|
|
|
{
|
|
|
|
for (u32 i = 0; i < static_cast<u32>(s_cheat_code_type_names.size()); i++)
|
|
|
|
{
|
|
|
|
if (std::strcmp(s_cheat_code_type_names[i], str) == 0)
|
|
|
|
return static_cast<Type>(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::array<const char*, 2> s_cheat_code_activation_names = {{"Manual", "EndFrame"}};
|
|
|
|
static std::array<const char*, 2> s_cheat_code_activation_display_names{
|
|
|
|
{TRANSLATABLE("Cheats", "Manual"), TRANSLATABLE("Cheats", "Automatic (Frame End)")}};
|
|
|
|
|
|
|
|
const char* CheatCode::GetActivationName(Activation activation)
|
|
|
|
{
|
|
|
|
return s_cheat_code_activation_names[static_cast<u32>(activation)];
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* CheatCode::GetActivationDisplayName(Activation activation)
|
|
|
|
{
|
|
|
|
return s_cheat_code_activation_display_names[static_cast<u32>(activation)];
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<CheatCode::Activation> CheatCode::ParseActivationName(const char* str)
|
|
|
|
{
|
|
|
|
for (u32 i = 0; i < static_cast<u32>(s_cheat_code_activation_names.size()); i++)
|
|
|
|
{
|
|
|
|
if (std::strcmp(s_cheat_code_activation_names[i], str) == 0)
|
|
|
|
return static_cast<Activation>(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
MemoryScan::MemoryScan() = default;
|
|
|
|
|
|
|
|
MemoryScan::~MemoryScan() = default;
|
|
|
|
|
|
|
|
void MemoryScan::ResetSearch()
|
|
|
|
{
|
|
|
|
m_results.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryScan::Search()
|
|
|
|
{
|
|
|
|
m_results.clear();
|
|
|
|
|
|
|
|
switch (m_size)
|
|
|
|
{
|
|
|
|
case MemoryAccessSize::Byte:
|
|
|
|
SearchBytes();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MemoryAccessSize::HalfWord:
|
|
|
|
SearchHalfwords();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MemoryAccessSize::Word:
|
|
|
|
SearchWords();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryScan::SearchBytes()
|
|
|
|
{
|
|
|
|
for (PhysicalMemoryAddress address = m_start_address; address < m_end_address; address++)
|
|
|
|
{
|
2020-10-21 11:43:51 +00:00
|
|
|
if (!IsValidScanAddress(address))
|
|
|
|
continue;
|
|
|
|
|
2020-10-21 12:01:50 +00:00
|
|
|
const u8 bvalue = DoMemoryRead<u8>(address);
|
2020-10-19 15:14:49 +00:00
|
|
|
|
|
|
|
Result res;
|
|
|
|
res.address = address;
|
|
|
|
res.value = m_signed ? SignExtend32(bvalue) : ZeroExtend32(bvalue);
|
|
|
|
res.last_value = res.value;
|
|
|
|
res.value_changed = false;
|
|
|
|
|
|
|
|
if (res.Filter(m_operator, m_value, m_signed))
|
|
|
|
m_results.push_back(res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryScan::SearchHalfwords()
|
|
|
|
{
|
|
|
|
for (PhysicalMemoryAddress address = m_start_address; address < m_end_address; address += 2)
|
|
|
|
{
|
2020-10-21 11:43:51 +00:00
|
|
|
if (!IsValidScanAddress(address))
|
|
|
|
continue;
|
|
|
|
|
2020-10-21 12:01:50 +00:00
|
|
|
const u16 bvalue = DoMemoryRead<u16>(address);
|
2020-10-19 15:14:49 +00:00
|
|
|
|
|
|
|
Result res;
|
|
|
|
res.address = address;
|
|
|
|
res.value = m_signed ? SignExtend32(bvalue) : ZeroExtend32(bvalue);
|
|
|
|
res.last_value = res.value;
|
|
|
|
res.value_changed = false;
|
|
|
|
|
|
|
|
if (res.Filter(m_operator, m_value, m_signed))
|
|
|
|
m_results.push_back(res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryScan::SearchWords()
|
|
|
|
{
|
|
|
|
for (PhysicalMemoryAddress address = m_start_address; address < m_end_address; address += 4)
|
|
|
|
{
|
2020-10-21 11:43:51 +00:00
|
|
|
if (!IsValidScanAddress(address))
|
|
|
|
continue;
|
|
|
|
|
2020-10-19 15:14:49 +00:00
|
|
|
Result res;
|
|
|
|
res.address = address;
|
2020-10-21 12:01:50 +00:00
|
|
|
res.value = DoMemoryRead<u32>(address);
|
2020-10-19 15:14:49 +00:00
|
|
|
res.last_value = res.value;
|
|
|
|
res.value_changed = false;
|
|
|
|
|
|
|
|
if (res.Filter(m_operator, m_value, m_signed))
|
|
|
|
m_results.push_back(res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryScan::SearchAgain()
|
|
|
|
{
|
|
|
|
ResultVector new_results;
|
|
|
|
new_results.reserve(m_results.size());
|
|
|
|
for (Result& res : m_results)
|
|
|
|
{
|
|
|
|
res.UpdateValue(m_size, m_signed);
|
|
|
|
|
|
|
|
if (res.Filter(m_operator, m_value, m_signed))
|
|
|
|
{
|
|
|
|
res.last_value = res.value;
|
|
|
|
new_results.push_back(res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_results.swap(new_results);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryScan::UpdateResultsValues()
|
|
|
|
{
|
|
|
|
for (Result& res : m_results)
|
|
|
|
res.UpdateValue(m_size, m_signed);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryScan::SetResultValue(u32 index, u32 value)
|
|
|
|
{
|
|
|
|
if (index >= m_results.size())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Result& res = m_results[index];
|
|
|
|
if (res.value == value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (m_size)
|
|
|
|
{
|
|
|
|
case MemoryAccessSize::Byte:
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u8>(res.address, Truncate8(value));
|
2020-10-19 15:14:49 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MemoryAccessSize::HalfWord:
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u16>(res.address, Truncate16(value));
|
2020-10-19 15:14:49 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MemoryAccessSize::Word:
|
|
|
|
CPU::SafeWriteMemoryWord(res.address, value);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
res.value = value;
|
|
|
|
res.value_changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemoryScan::Result::Filter(Operator op, u32 comp_value, bool is_signed) const
|
|
|
|
{
|
|
|
|
switch (op)
|
|
|
|
{
|
|
|
|
case Operator::Equal:
|
|
|
|
{
|
|
|
|
return (value == comp_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::NotEqual:
|
|
|
|
{
|
|
|
|
return (value != comp_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::GreaterThan:
|
|
|
|
{
|
|
|
|
return is_signed ? (static_cast<s32>(value) > static_cast<s32>(comp_value)) : (value > comp_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::GreaterEqual:
|
|
|
|
{
|
|
|
|
return is_signed ? (static_cast<s32>(value) >= static_cast<s32>(comp_value)) : (value >= comp_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::LessThan:
|
|
|
|
{
|
|
|
|
return is_signed ? (static_cast<s32>(value) < static_cast<s32>(comp_value)) : (value < comp_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::LessEqual:
|
|
|
|
{
|
|
|
|
return is_signed ? (static_cast<s32>(value) <= static_cast<s32>(comp_value)) : (value <= comp_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::IncreasedBy:
|
|
|
|
{
|
|
|
|
return is_signed ? ((static_cast<s32>(value) - static_cast<s32>(last_value)) == static_cast<s32>(comp_value)) :
|
|
|
|
((value - last_value) == comp_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::DecreasedBy:
|
|
|
|
{
|
|
|
|
return is_signed ? ((static_cast<s32>(last_value) - static_cast<s32>(value)) == static_cast<s32>(comp_value)) :
|
|
|
|
((last_value - value) == comp_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::ChangedBy:
|
|
|
|
{
|
|
|
|
if (is_signed)
|
|
|
|
return (std::abs(static_cast<s32>(last_value) - static_cast<s32>(value)) == static_cast<s32>(comp_value));
|
|
|
|
else
|
|
|
|
return ((last_value > value) ? (last_value - value) : (value - last_value)) == comp_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::EqualLast:
|
|
|
|
{
|
|
|
|
return (value == last_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::NotEqualLast:
|
|
|
|
{
|
|
|
|
return (value != last_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::GreaterThanLast:
|
|
|
|
{
|
|
|
|
return is_signed ? (static_cast<s32>(value) > static_cast<s32>(last_value)) : (value > last_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::GreaterEqualLast:
|
|
|
|
{
|
|
|
|
return is_signed ? (static_cast<s32>(value) >= static_cast<s32>(last_value)) : (value >= last_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::LessThanLast:
|
|
|
|
{
|
|
|
|
return is_signed ? (static_cast<s32>(value) < static_cast<s32>(last_value)) : (value < last_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Operator::LessEqualLast:
|
|
|
|
{
|
|
|
|
return is_signed ? (static_cast<s32>(value) <= static_cast<s32>(last_value)) : (value <= last_value);
|
|
|
|
}
|
|
|
|
|
2020-10-21 11:40:17 +00:00
|
|
|
case Operator::Any:
|
|
|
|
return true;
|
|
|
|
|
2020-10-19 15:14:49 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryScan::Result::UpdateValue(MemoryAccessSize size, bool is_signed)
|
|
|
|
{
|
|
|
|
const u32 old_value = value;
|
|
|
|
|
|
|
|
switch (size)
|
|
|
|
{
|
|
|
|
case MemoryAccessSize::Byte:
|
|
|
|
{
|
2020-10-21 12:01:50 +00:00
|
|
|
u8 bvalue = DoMemoryRead<u8>(address);
|
2020-10-19 15:14:49 +00:00
|
|
|
value = is_signed ? SignExtend32(bvalue) : ZeroExtend32(bvalue);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MemoryAccessSize::HalfWord:
|
|
|
|
{
|
2020-10-21 12:01:50 +00:00
|
|
|
u16 bvalue = DoMemoryRead<u16>(address);
|
2020-10-19 15:14:49 +00:00
|
|
|
value = is_signed ? SignExtend32(bvalue) : ZeroExtend32(bvalue);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MemoryAccessSize::Word:
|
|
|
|
{
|
|
|
|
CPU::SafeReadMemoryWord(address, &value);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
value_changed = (value != old_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
MemoryWatchList::MemoryWatchList() = default;
|
|
|
|
|
|
|
|
MemoryWatchList::~MemoryWatchList() = default;
|
|
|
|
|
|
|
|
const MemoryWatchList::Entry* MemoryWatchList::GetEntryByAddress(u32 address) const
|
|
|
|
{
|
|
|
|
for (const Entry& entry : m_entries)
|
|
|
|
{
|
|
|
|
if (entry.address == address)
|
|
|
|
return &entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemoryWatchList::AddEntry(std::string description, u32 address, MemoryAccessSize size, bool is_signed, bool freeze)
|
|
|
|
{
|
|
|
|
if (GetEntryByAddress(address))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Entry entry;
|
|
|
|
entry.description = std::move(description);
|
|
|
|
entry.address = address;
|
|
|
|
entry.size = size;
|
|
|
|
entry.is_signed = is_signed;
|
|
|
|
entry.freeze = false;
|
|
|
|
|
|
|
|
UpdateEntryValue(&entry);
|
|
|
|
|
|
|
|
entry.changed = false;
|
|
|
|
entry.freeze = freeze;
|
|
|
|
|
|
|
|
m_entries.push_back(std::move(entry));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWatchList::RemoveEntry(u32 index)
|
|
|
|
{
|
|
|
|
if (index >= m_entries.size())
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_entries.erase(m_entries.begin() + index);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemoryWatchList::RemoveEntryByAddress(u32 address)
|
|
|
|
{
|
|
|
|
for (auto it = m_entries.begin(); it != m_entries.end(); ++it)
|
|
|
|
{
|
|
|
|
if (it->address == address)
|
|
|
|
{
|
|
|
|
m_entries.erase(it);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWatchList::SetEntryDescription(u32 index, std::string description)
|
|
|
|
{
|
|
|
|
if (index >= m_entries.size())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Entry& entry = m_entries[index];
|
|
|
|
entry.description = std::move(description);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWatchList::SetEntryFreeze(u32 index, bool freeze)
|
|
|
|
{
|
|
|
|
if (index >= m_entries.size())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Entry& entry = m_entries[index];
|
|
|
|
entry.freeze = freeze;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWatchList::SetEntryValue(u32 index, u32 value)
|
|
|
|
{
|
|
|
|
if (index >= m_entries.size())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Entry& entry = m_entries[index];
|
|
|
|
if (entry.value == value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
SetEntryValue(&entry, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemoryWatchList::RemoveEntryByDescription(const char* description)
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
for (auto it = m_entries.begin(); it != m_entries.end();)
|
|
|
|
{
|
|
|
|
if (it->description == description)
|
|
|
|
{
|
|
|
|
it = m_entries.erase(it);
|
|
|
|
result = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWatchList::UpdateValues()
|
|
|
|
{
|
|
|
|
for (Entry& entry : m_entries)
|
|
|
|
UpdateEntryValue(&entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWatchList::SetEntryValue(Entry* entry, u32 value)
|
|
|
|
{
|
|
|
|
switch (entry->size)
|
|
|
|
{
|
|
|
|
case MemoryAccessSize::Byte:
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u8>(entry->address, Truncate8(value));
|
2020-10-19 15:14:49 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MemoryAccessSize::HalfWord:
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u16>(entry->address, Truncate16(value));
|
2020-10-19 15:14:49 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MemoryAccessSize::Word:
|
2020-10-21 12:01:50 +00:00
|
|
|
DoMemoryWrite<u32>(entry->address, value);
|
2020-10-19 15:14:49 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
entry->changed = (entry->value != value);
|
|
|
|
entry->value = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWatchList::UpdateEntryValue(Entry* entry)
|
|
|
|
{
|
|
|
|
const u32 old_value = entry->value;
|
|
|
|
|
|
|
|
switch (entry->size)
|
|
|
|
{
|
|
|
|
case MemoryAccessSize::Byte:
|
|
|
|
{
|
2020-10-21 12:01:50 +00:00
|
|
|
u8 bvalue = DoMemoryRead<u8>(entry->address);
|
2020-10-19 15:14:49 +00:00
|
|
|
entry->value = entry->is_signed ? SignExtend32(bvalue) : ZeroExtend32(bvalue);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MemoryAccessSize::HalfWord:
|
|
|
|
{
|
2020-10-21 12:01:50 +00:00
|
|
|
u16 bvalue = DoMemoryRead<u16>(entry->address);
|
2020-10-19 15:14:49 +00:00
|
|
|
entry->value = entry->is_signed ? SignExtend32(bvalue) : ZeroExtend32(bvalue);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MemoryAccessSize::Word:
|
|
|
|
{
|
2020-10-21 12:01:50 +00:00
|
|
|
entry->value = DoMemoryRead<u32>(entry->address);
|
2020-10-19 15:14:49 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
entry->changed = (old_value != entry->value);
|
|
|
|
|
|
|
|
if (entry->freeze && entry->changed)
|
|
|
|
SetEntryValue(entry, old_value);
|
|
|
|
}
|