From a3fc2c95b8bbf16345db8cc5c4eb1c46f61bef3b Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 27 Feb 2019 19:30:29 -0800 Subject: [PATCH] dmnt-cheat: Add new, better math instruction to vm --- stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 82 ++++++++++++++++++++++ stratosphere/dmnt/source/dmnt_cheat_vm.hpp | 24 +++++++ 2 files changed, 106 insertions(+) diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index afa19505b..627c94d06 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -37,6 +37,22 @@ void DmntCheatVm::SkipConditionalBlock() { } } +u64 DmntCheatVm::GetVmInt(VmInt value, u32 bit_width) { + switch (bit_width) { + case 1: + return value.bit8; + case 2: + return value.bit16; + case 4: + return value.bit32; + case 8: + return value.bit64; + default: + /* Invalid bit width -> return 0. */ + return 0; + } +} + void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { CheatVmOpcode cur_opcode; u64 kDown = 0; @@ -111,6 +127,9 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { case RegisterArithmeticType_RightShift: this->registers[cur_opcode.perform_math_static.reg_index] >>= (u64)cur_opcode.perform_math_static.value; break; + default: + /* Do not handle extensions here. */ + break; } /* Apply bit width. */ switch (cur_opcode.perform_math_static.bit_width) { @@ -136,6 +155,69 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { this->SkipConditionalBlock(); } break; + case CheatVmOpcodeType_PerformArithmeticRegister: + { + const u64 operand_1_value = this->registers[cur_opcode.perform_math_reg.src_reg_1_index]; + const u64 operand_2_value = cur_opcode.perform_math_reg.has_immediate ? + GetVmInt(cur_opcode.perform_math_reg.value, cur_opcode.perform_math_reg.bit_width) : + this->registers[cur_opcode.perform_math_reg.src_reg_2_index]; + + u64 res_val = 0; + /* Do requested math. */ + switch (cur_opcode.perform_math_reg.math_type) { + case RegisterArithmeticType_Addition: + res_val = operand_1_value + operand_2_value; + break; + case RegisterArithmeticType_Subtraction: + res_val = operand_1_value - operand_2_value; + break; + case RegisterArithmeticType_Multiplication: + res_val = operand_1_value * operand_2_value; + break; + case RegisterArithmeticType_LeftShift: + res_val = operand_1_value << operand_2_value; + break; + case RegisterArithmeticType_RightShift: + res_val = operand_1_value >> operand_2_value; + break; + case RegisterArithmeticType_LogicalAnd: + res_val = operand_1_value & operand_2_value; + break; + case RegisterArithmeticType_LogicalOr: + res_val = operand_1_value | operand_2_value; + break; + case RegisterArithmeticType_LogicalNot: + res_val = ~operand_1_value; + break; + case RegisterArithmeticType_LogicalXor: + res_val = operand_1_value ^ operand_2_value; + break; + case RegisterArithmeticType_None: + res_val = operand_1_value; + break; + } + + + /* Apply bit width. */ + switch (cur_opcode.perform_math_reg.bit_width) { + case 1: + res_val = static_cast(res_val); + break; + case 2: + res_val = static_cast(res_val); + break; + case 4: + res_val = static_cast(res_val); + break; + case 8: + res_val = static_cast(res_val); + break; + } + + /* Save to register. */ + this->registers[cur_opcode.perform_math_reg.dst_reg_index] = res_val; + } + break; } } } \ No newline at end of file diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp index 55e4cffce..51499690a 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp @@ -30,6 +30,9 @@ enum CheatVmOpcodeType : u32 { CheatVmOpcodeType_StoreToRegisterAddress = 6, CheatVmOpcodeType_PerformArithmeticStatic = 7, CheatVmOpcodeType_BeginKeypressConditionalBlock = 8, + + /* These are not implemented by Gateway's VM. */ + CheatVmOpcodeType_PerformArithmeticRegister = 9, }; enum MemoryAccessType : u32 { @@ -52,6 +55,14 @@ enum RegisterArithmeticType : u32 { RegisterArithmeticType_Multiplication = 2, RegisterArithmeticType_LeftShift = 3, RegisterArithmeticType_RightShift = 4, + + /* These are not supported by Gateway's VM. */ + RegisterArithmeticType_LogicalAnd = 5, + RegisterArithmeticType_LogicalOr = 6, + RegisterArithmeticType_LogicalNot = 7, + RegisterArithmeticType_LogicalXor = 8, + + RegisterArithmeticType_None = 9, }; union VmInt { @@ -118,6 +129,16 @@ struct BeginKeypressConditionalOpcode { u32 key_mask; }; +struct PerformArithmeticRegisterOpcode { + u32 bit_width; + RegisterArithmeticType math_type; + u32 dst_reg_index; + u32 src_reg_1_index; + u32 src_reg_2_index; + bool has_immediate; + VmInt value; +}; + struct CheatVmOpcode { CheatVmOpcodeType opcode; union { @@ -130,6 +151,7 @@ struct CheatVmOpcode { StoreToRegisterAddressOpcode str_regaddr; PerformArithmeticStaticOpcode perform_math_static; BeginKeypressConditionalOpcode begin_keypress_cond; + PerformArithmeticRegisterOpcode perform_math_reg; }; }; @@ -146,6 +168,8 @@ class DmntCheatVm { private: bool DecodeNextOpcode(CheatVmOpcode *out); void SkipConditionalBlock(); + + static u64 GetVmInt(VmInt value, u32 bit_width); public: DmntCheatVm() { }