dmnt_cheat_vm: Make Cheat VM compliant to code style

This commit is contained in:
Zach Hilman 2019-09-21 18:13:10 -04:00
parent 3e729c13cc
commit 682174b112
4 changed files with 859 additions and 867 deletions

View File

@ -17,6 +17,7 @@
#include "core/file_sys/bis_factory.h" #include "core/file_sys/bis_factory.h"
#include "core/file_sys/card_image.h" #include "core/file_sys/card_image.h"
#include "core/file_sys/mode.h" #include "core/file_sys/mode.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h" #include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs_factory.h" #include "core/file_sys/romfs_factory.h"
#include "core/file_sys/savedata_factory.h" #include "core/file_sys/savedata_factory.h"
@ -43,8 +44,6 @@
#include "core/settings.h" #include "core/settings.h"
#include "core/telemetry_session.h" #include "core/telemetry_session.h"
#include "core/tools/freezer.h" #include "core/tools/freezer.h"
#include "file_sys/cheat_engine.h"
#include "file_sys/patch_manager.h"
#include "video_core/debug_utils/debug_utils.h" #include "video_core/debug_utils/debug_utils.h"
#include "video_core/renderer_base.h" #include "video_core/renderer_base.h"
#include "video_core/video_core.h" #include "video_core/video_core.h"

View File

@ -102,7 +102,7 @@ std::vector<CheatEntry> TextCheatParser::Parse(const Core::System& system,
std::optional<u64> current_entry = std::nullopt; std::optional<u64> current_entry = std::nullopt;
for (std::size_t i = 0; i < data.size(); ++i) { for (std::size_t i = 0; i < data.size(); ++i) {
if (std::isspace(data[i])) { if (::isspace(data[i])) {
continue; continue;
} }
@ -143,7 +143,7 @@ std::vector<CheatEntry> TextCheatParser::Parse(const Core::System& system,
'\0'; '\0';
i += name.length() + 1; i += name.length() + 1;
} else if (std::isxdigit(data[i])) { } else if (::isxdigit(data[i])) {
if (!current_entry || out[*current_entry].definition.num_opcodes >= if (!current_entry || out[*current_entry].definition.num_opcodes >=
out[*current_entry].definition.opcodes.size()) { out[*current_entry].definition.opcodes.size()) {
return {}; return {};
@ -188,7 +188,7 @@ CheatEngine::~CheatEngine() {
void CheatEngine::Initialize() { void CheatEngine::Initialize() {
event = core_timing.RegisterEvent( event = core_timing.RegisterEvent(
"CheatEngine::FrameCallback::" + Common::HexArrayToString(metadata.main_nso_build_id), "CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id),
[this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); }); [this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); });
core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event); core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event);

File diff suppressed because it is too large Load Diff

View File

@ -24,6 +24,7 @@
#pragma once #pragma once
#include <variant>
#include <vector> #include <vector>
#include <fmt/printf.h> #include <fmt/printf.h>
#include "common/common_types.h" #include "common/common_types.h"
@ -31,100 +32,100 @@
namespace Memory { namespace Memory {
enum CheatVmOpcodeType : u32 { enum class CheatVmOpcodeType : u32 {
CheatVmOpcodeType_StoreStatic = 0, StoreStatic = 0,
CheatVmOpcodeType_BeginConditionalBlock = 1, BeginConditionalBlock = 1,
CheatVmOpcodeType_EndConditionalBlock = 2, EndConditionalBlock = 2,
CheatVmOpcodeType_ControlLoop = 3, ControlLoop = 3,
CheatVmOpcodeType_LoadRegisterStatic = 4, LoadRegisterStatic = 4,
CheatVmOpcodeType_LoadRegisterMemory = 5, LoadRegisterMemory = 5,
CheatVmOpcodeType_StoreStaticToAddress = 6, StoreStaticToAddress = 6,
CheatVmOpcodeType_PerformArithmeticStatic = 7, PerformArithmeticStatic = 7,
CheatVmOpcodeType_BeginKeypressConditionalBlock = 8, BeginKeypressConditionalBlock = 8,
/* These are not implemented by Gateway's VM. */ // These are not implemented by Gateway's VM.
CheatVmOpcodeType_PerformArithmeticRegister = 9, PerformArithmeticRegister = 9,
CheatVmOpcodeType_StoreRegisterToAddress = 10, StoreRegisterToAddress = 10,
CheatVmOpcodeType_Reserved11 = 11, Reserved11 = 11,
/* This is a meta entry, and not a real opcode. */ // This is a meta entry, and not a real opcode.
/* This is to facilitate multi-nybble instruction decoding. */ // This is to facilitate multi-nybble instruction decoding.
CheatVmOpcodeType_ExtendedWidth = 12, ExtendedWidth = 12,
/* Extended width opcodes. */ // Extended width opcodes.
CheatVmOpcodeType_BeginRegisterConditionalBlock = 0xC0, BeginRegisterConditionalBlock = 0xC0,
CheatVmOpcodeType_SaveRestoreRegister = 0xC1, SaveRestoreRegister = 0xC1,
CheatVmOpcodeType_SaveRestoreRegisterMask = 0xC2, SaveRestoreRegisterMask = 0xC2,
/* This is a meta entry, and not a real opcode. */ // This is a meta entry, and not a real opcode.
/* This is to facilitate multi-nybble instruction decoding. */ // This is to facilitate multi-nybble instruction decoding.
CheatVmOpcodeType_DoubleExtendedWidth = 0xF0, DoubleExtendedWidth = 0xF0,
/* Double-extended width opcodes. */ // Double-extended width opcodes.
CheatVmOpcodeType_DebugLog = 0xFFF, DebugLog = 0xFFF,
}; };
enum MemoryAccessType : u32 { enum class MemoryAccessType : u32 {
MemoryAccessType_MainNso = 0, MainNso = 0,
MemoryAccessType_Heap = 1, Heap = 1,
}; };
enum ConditionalComparisonType : u32 { enum class ConditionalComparisonType : u32 {
ConditionalComparisonType_GT = 1, GT = 1,
ConditionalComparisonType_GE = 2, GE = 2,
ConditionalComparisonType_LT = 3, LT = 3,
ConditionalComparisonType_LE = 4, LE = 4,
ConditionalComparisonType_EQ = 5, EQ = 5,
ConditionalComparisonType_NE = 6, NE = 6,
}; };
enum RegisterArithmeticType : u32 { enum class RegisterArithmeticType : u32 {
RegisterArithmeticType_Addition = 0, Addition = 0,
RegisterArithmeticType_Subtraction = 1, Subtraction = 1,
RegisterArithmeticType_Multiplication = 2, Multiplication = 2,
RegisterArithmeticType_LeftShift = 3, LeftShift = 3,
RegisterArithmeticType_RightShift = 4, RightShift = 4,
/* These are not supported by Gateway's VM. */ // These are not supported by Gateway's VM.
RegisterArithmeticType_LogicalAnd = 5, LogicalAnd = 5,
RegisterArithmeticType_LogicalOr = 6, LogicalOr = 6,
RegisterArithmeticType_LogicalNot = 7, LogicalNot = 7,
RegisterArithmeticType_LogicalXor = 8, LogicalXor = 8,
RegisterArithmeticType_None = 9, None = 9,
}; };
enum StoreRegisterOffsetType : u32 { enum class StoreRegisterOffsetType : u32 {
StoreRegisterOffsetType_None = 0, None = 0,
StoreRegisterOffsetType_Reg = 1, Reg = 1,
StoreRegisterOffsetType_Imm = 2, Imm = 2,
StoreRegisterOffsetType_MemReg = 3, MemReg = 3,
StoreRegisterOffsetType_MemImm = 4, MemImm = 4,
StoreRegisterOffsetType_MemImmReg = 5, MemImmReg = 5,
}; };
enum CompareRegisterValueType : u32 { enum class CompareRegisterValueType : u32 {
CompareRegisterValueType_MemoryRelAddr = 0, MemoryRelAddr = 0,
CompareRegisterValueType_MemoryOfsReg = 1, MemoryOfsReg = 1,
CompareRegisterValueType_RegisterRelAddr = 2, RegisterRelAddr = 2,
CompareRegisterValueType_RegisterOfsReg = 3, RegisterOfsReg = 3,
CompareRegisterValueType_StaticValue = 4, StaticValue = 4,
CompareRegisterValueType_OtherRegister = 5, OtherRegister = 5,
}; };
enum SaveRestoreRegisterOpType : u32 { enum class SaveRestoreRegisterOpType : u32 {
SaveRestoreRegisterOpType_Restore = 0, Restore = 0,
SaveRestoreRegisterOpType_Save = 1, Save = 1,
SaveRestoreRegisterOpType_ClearSaved = 2, ClearSaved = 2,
SaveRestoreRegisterOpType_ClearRegs = 3, ClearRegs = 3,
}; };
enum DebugLogValueType : u32 { enum class DebugLogValueType : u32 {
DebugLogValueType_MemoryRelAddr = 0, MemoryRelAddr = 0,
DebugLogValueType_MemoryOfsReg = 1, MemoryOfsReg = 1,
DebugLogValueType_RegisterRelAddr = 2, RegisterRelAddr = 2,
DebugLogValueType_RegisterOfsReg = 3, RegisterOfsReg = 3,
DebugLogValueType_RegisterValue = 4, RegisterValue = 4,
}; };
union VmInt { union VmInt {
@ -247,26 +248,19 @@ struct DebugLogOpcode {
u64 rel_address; u64 rel_address;
}; };
struct CheatVmOpcode { struct UnrecognizedInstruction {
CheatVmOpcodeType opcode; CheatVmOpcodeType opcode;
bool begin_conditional_block;
union {
StoreStaticOpcode store_static;
BeginConditionalOpcode begin_cond;
EndConditionalOpcode end_cond;
ControlLoopOpcode ctrl_loop;
LoadRegisterStaticOpcode ldr_static;
LoadRegisterMemoryOpcode ldr_memory;
StoreStaticToAddressOpcode str_static;
PerformArithmeticStaticOpcode perform_math_static;
BeginKeypressConditionalOpcode begin_keypress_cond;
PerformArithmeticRegisterOpcode perform_math_reg;
StoreRegisterToAddressOpcode str_register;
BeginRegisterConditionalOpcode begin_reg_cond;
SaveRestoreRegisterOpcode save_restore_reg;
SaveRestoreRegisterMaskOpcode save_restore_regmask;
DebugLogOpcode debug_log;
}; };
struct CheatVmOpcode {
bool begin_conditional_block;
std::variant<StoreStaticOpcode, BeginConditionalOpcode, EndConditionalOpcode, ControlLoopOpcode,
LoadRegisterStaticOpcode, LoadRegisterMemoryOpcode, StoreStaticToAddressOpcode,
PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode,
PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode,
BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode,
SaveRestoreRegisterMaskOpcode, DebugLogOpcode, UnrecognizedInstruction>
opcode;
}; };
class DmntCheatVm { class DmntCheatVm {
@ -285,50 +279,43 @@ public:
virtual void CommandLog(std::string_view data) = 0; virtual void CommandLog(std::string_view data) = 0;
}; };
constexpr static size_t MaximumProgramOpcodeCount = 0x400; static constexpr std::size_t MaximumProgramOpcodeCount = 0x400;
constexpr static size_t NumRegisters = 0x10; static constexpr std::size_t NumRegisters = 0x10;
explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks);
~DmntCheatVm();
std::size_t GetProgramSize() const {
return this->num_opcodes;
}
bool LoadProgram(const std::vector<CheatEntry>& cheats);
void Execute(const CheatProcessMetadata& metadata);
private: private:
std::unique_ptr<Callbacks> callbacks; std::unique_ptr<Callbacks> callbacks;
size_t num_opcodes = 0; std::size_t num_opcodes = 0;
size_t instruction_ptr = 0; std::size_t instruction_ptr = 0;
size_t condition_depth = 0; std::size_t condition_depth = 0;
bool decode_success = false; bool decode_success = false;
std::array<u32, MaximumProgramOpcodeCount> program{}; std::array<u32, MaximumProgramOpcodeCount> program{};
std::array<u64, NumRegisters> registers{}; std::array<u64, NumRegisters> registers{};
std::array<u64, NumRegisters> saved_values{}; std::array<u64, NumRegisters> saved_values{};
std::array<size_t, NumRegisters> loop_tops{}; std::array<std::size_t, NumRegisters> loop_tops{};
private:
bool DecodeNextOpcode(CheatVmOpcode& out); bool DecodeNextOpcode(CheatVmOpcode& out);
void SkipConditionalBlock(); void SkipConditionalBlock();
void ResetState(); void ResetState();
/* For implementing the DebugLog opcode. */ // For implementing the DebugLog opcode.
void DebugLog(u32 log_id, u64 value); void DebugLog(u32 log_id, u64 value);
/* For debugging. These will be IFDEF'd out normally. */
template <typename... Args>
void LogToDebugFile(const char* format, const Args&... args) {
callbacks->CommandLog(fmt::sprintf(format, args...));
}
void LogOpcode(const CheatVmOpcode& opcode); void LogOpcode(const CheatVmOpcode& opcode);
static u64 GetVmInt(VmInt value, u32 bit_width); static u64 GetVmInt(VmInt value, u32 bit_width);
static u64 GetCheatProcessAddress(const CheatProcessMetadata& metadata, static u64 GetCheatProcessAddress(const CheatProcessMetadata& metadata,
MemoryAccessType mem_type, u64 rel_address); MemoryAccessType mem_type, u64 rel_address);
public:
DmntCheatVm(std::unique_ptr<Callbacks> callbacks) : callbacks(std::move(callbacks)) {}
size_t GetProgramSize() {
return this->num_opcodes;
}
bool LoadProgram(const std::vector<CheatEntry>& cheats);
void Execute(const CheatProcessMetadata& metadata);
}; };
}; // namespace Memory }; // namespace Memory