From 0588b9967411411d430444af3280b16e06e05feb Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Fri, 21 Jul 2023 14:49:04 +0300 Subject: [PATCH 1/2] [ActionReplay] More conditional ops --- include/cheats.hpp | 2 +- src/core/action_replay.cpp | 30 ++++++++++++++++++++++-------- src/core/cheats.cpp | 7 +------ 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/include/cheats.hpp b/include/cheats.hpp index 6ada7d20..be370c24 100644 --- a/include/cheats.hpp +++ b/include/cheats.hpp @@ -13,7 +13,7 @@ class Cheats { public: enum class CheatType { ActionReplay, // CTRPF cheats - Gateway, + // TODO: Other cheat devices and standards? }; struct Cheat { diff --git a/src/core/action_replay.cpp b/src/core/action_replay.cpp index ad391b36..8a5b511c 100644 --- a/src/core/action_replay.cpp +++ b/src/core/action_replay.cpp @@ -96,14 +96,28 @@ void ActionReplay::runInstruction(const Cheat& cheat, u32 instruction) { break; } - // Less Than (YYYYYYYY < [XXXXXXX + offset]) - case 0x4: { - const u32 baseAddr = Helpers::getBits<0, 28>(instruction); - const u32 imm = cheat[pc++]; - const u32 value = read32(baseAddr + *activeOffset); - Helpers::panic("TODO: How do ActionReplay conditional blocks work?"); - break; - } + #define MAKE_IF_INSTRUCTION(opcode, comparator) \ + case opcode: { \ + const u32 baseAddr = Helpers::getBits<0, 28>(instruction); \ + const u32 imm = cheat[pc++]; \ + const u32 value = read32(baseAddr + *activeOffset); \ + \ + pushConditionBlock(imm comparator value); \ + break; \ + } + + // Greater Than (YYYYYYYY > [XXXXXXX + offset]) (Unsigned) + MAKE_IF_INSTRUCTION(3, >) + + // Less Than (YYYYYYYY < [XXXXXXX + offset]) (Unsigned) + MAKE_IF_INSTRUCTION(4, <) + + // Equal to (YYYYYYYY == [XXXXXXX + offset]) (Unsigned) + MAKE_IF_INSTRUCTION(5, ==) + + // Not Equal (YYYYYYYY != [XXXXXXX + offset]) (Unsigned) + MAKE_IF_INSTRUCTION(6, !=) + #undef MAKE_IF_INSTRUCTION case 0xD: executeDType(cheat, instruction); break; default: Helpers::panic("Unimplemented ActionReplay instruction type %X", type); break; diff --git a/src/core/cheats.cpp b/src/core/cheats.cpp index 4c63652b..8bf5e316 100644 --- a/src/core/cheats.cpp +++ b/src/core/cheats.cpp @@ -17,12 +17,7 @@ void Cheats::run() { break; } - case CheatType::Gateway: { - Helpers::panic("Gateway cheats not supported yet! Only Action Replay is supported!"); - break; - } - - default: Helpers::panic("Unknown cheat type"); + default: Helpers::panic("Unknown cheat device!"); } } } \ No newline at end of file From 5d8f75a38521ff4cc48517ab66c87cc93caf8b90 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Fri, 21 Jul 2023 15:12:40 +0300 Subject: [PATCH 2/2] Format --- src/core/action_replay.cpp | 43 ++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/core/action_replay.cpp b/src/core/action_replay.cpp index 8a5b511c..e8467425 100644 --- a/src/core/action_replay.cpp +++ b/src/core/action_replay.cpp @@ -29,14 +29,14 @@ void ActionReplay::runCheat(const Cheat& cheat) { } // Fetch instruction const u32 instruction = cheat[pc++]; - + // Instructions D0000000 00000000 and D2000000 00000000 are unconditional bool isUnconditional = cheat[pc] == 0 && (instruction == 0xD0000000 || instruction == 0xD2000000); if (ifStackIndex > 0 && !isUnconditional && !ifStack[ifStackIndex - 1]) { - pc++; // Eat up dummy word - continue; // Skip conditional instructions where the condition is false + pc++; // Eat up dummy word + continue; // Skip conditional instructions where the condition is false } - + runInstruction(cheat, instruction); } } @@ -96,15 +96,16 @@ void ActionReplay::runInstruction(const Cheat& cheat, u32 instruction) { break; } - #define MAKE_IF_INSTRUCTION(opcode, comparator) \ - case opcode: { \ - const u32 baseAddr = Helpers::getBits<0, 28>(instruction); \ - const u32 imm = cheat[pc++]; \ - const u32 value = read32(baseAddr + *activeOffset); \ - \ - pushConditionBlock(imm comparator value); \ - break; \ - } +// clang-format off + #define MAKE_IF_INSTRUCTION(opcode, comparator) \ + case opcode: { \ + const u32 baseAddr = Helpers::getBits<0, 28>(instruction); \ + const u32 imm = cheat[pc++]; \ + const u32 value = read32(baseAddr + *activeOffset); \ + \ + pushConditionBlock(imm comparator value); \ + break; \ + } // Greater Than (YYYYYYYY > [XXXXXXX + offset]) (Unsigned) MAKE_IF_INSTRUCTION(3, >) @@ -112,12 +113,22 @@ void ActionReplay::runInstruction(const Cheat& cheat, u32 instruction) { // Less Than (YYYYYYYY < [XXXXXXX + offset]) (Unsigned) MAKE_IF_INSTRUCTION(4, <) - // Equal to (YYYYYYYY == [XXXXXXX + offset]) (Unsigned) + // Equal to (YYYYYYYY == [XXXXXXX + offset]) MAKE_IF_INSTRUCTION(5, ==) - // Not Equal (YYYYYYYY != [XXXXXXX + offset]) (Unsigned) + // Not Equal (YYYYYYYY != [XXXXXXX + offset]) MAKE_IF_INSTRUCTION(6, !=) #undef MAKE_IF_INSTRUCTION +// clang-format on + + // BXXXXXXX 00000000 - offset = *(XXXXXXX + offset) + case 0xB: { + const u32 baseAddr = Helpers::getBits<0, 28>(instruction); + *activeOffset = read32(baseAddr + *activeOffset); + + pc++; // Eat up dummy word + break; + } case 0xD: executeDType(cheat, instruction); break; default: Helpers::panic("Unimplemented ActionReplay instruction type %X", type); break; @@ -199,7 +210,7 @@ void ActionReplay::executeDType(const Cheat& cheat, u32 instruction) { case 0xD2000000: { const u32 subopcode = cheat[pc++]; switch (subopcode) { - // Ends all loop/execute blocks + // Ends all loop/execute blocks case 0: loopStackIndex = 0; ifStackIndex = 0;