diff options
| author | 2024-02-04 15:19:54 -0600 | |
|---|---|---|
| committer | 2024-02-04 17:46:20 -0600 | |
| commit | 504abbd6e0ca8073e6a3e60776b2278bd0ffcaed (patch) | |
| tree | 9f689eab1feb3d1a3b5de570f2fa107837449828 | |
| parent | Merge pull request #12892 from liamwhite/serialization-stuff (diff) | |
| download | yuzu-504abbd6e0ca8073e6a3e60776b2278bd0ffcaed.tar.gz yuzu-504abbd6e0ca8073e6a3e60776b2278bd0ffcaed.tar.xz yuzu-504abbd6e0ca8073e6a3e60776b2278bd0ffcaed.zip | |
dmnt: cheats: Update cheat vm to latest version
| -rw-r--r-- | src/core/memory/cheat_engine.cpp | 21 | ||||
| -rw-r--r-- | src/core/memory/cheat_engine.h | 2 | ||||
| -rw-r--r-- | src/core/memory/dmnt_cheat_types.h | 2 | ||||
| -rw-r--r-- | src/core/memory/dmnt_cheat_vm.cpp | 57 | ||||
| -rw-r--r-- | src/core/memory/dmnt_cheat_vm.h | 18 |
5 files changed, 71 insertions, 29 deletions
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index 96fa7fa3a..7a8c14c2b 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "core/core_timing.h" | 9 | #include "core/core_timing.h" |
| 10 | #include "core/hle/kernel/k_page_table.h" | 10 | #include "core/hle/kernel/k_page_table.h" |
| 11 | #include "core/hle/kernel/k_process.h" | 11 | #include "core/hle/kernel/k_process.h" |
| 12 | #include "core/hle/kernel/k_process_page_table.h" | ||
| 12 | #include "core/hle/service/hid/hid_server.h" | 13 | #include "core/hle/service/hid/hid_server.h" |
| 13 | #include "core/hle/service/sm/sm.h" | 14 | #include "core/hle/service/sm/sm.h" |
| 14 | #include "core/memory.h" | 15 | #include "core/memory.h" |
| @@ -85,8 +86,12 @@ VAddr StandardVmCallbacks::SanitizeAddress(VAddr in) const { | |||
| 85 | if ((in < metadata.main_nso_extents.base || | 86 | if ((in < metadata.main_nso_extents.base || |
| 86 | in >= metadata.main_nso_extents.base + metadata.main_nso_extents.size) && | 87 | in >= metadata.main_nso_extents.base + metadata.main_nso_extents.size) && |
| 87 | (in < metadata.heap_extents.base || | 88 | (in < metadata.heap_extents.base || |
| 88 | in >= metadata.heap_extents.base + metadata.heap_extents.size)) { | 89 | in >= metadata.heap_extents.base + metadata.heap_extents.size) && |
| 89 | LOG_ERROR(CheatEngine, | 90 | (in < metadata.alias_extents.base || |
| 91 | in >= metadata.heap_extents.base + metadata.alias_extents.size) && | ||
| 92 | (in < metadata.aslr_extents.base || | ||
| 93 | in >= metadata.heap_extents.base + metadata.aslr_extents.size)) { | ||
| 94 | LOG_DEBUG(CheatEngine, | ||
| 90 | "Cheat attempting to access memory at invalid address={:016X}, if this " | 95 | "Cheat attempting to access memory at invalid address={:016X}, if this " |
| 91 | "persists, " | 96 | "persists, " |
| 92 | "the cheat may be incorrect. However, this may be normal early in execution if " | 97 | "the cheat may be incorrect. However, this may be normal early in execution if " |
| @@ -211,16 +216,14 @@ void CheatEngine::Initialize() { | |||
| 211 | .base = GetInteger(page_table.GetHeapRegionStart()), | 216 | .base = GetInteger(page_table.GetHeapRegionStart()), |
| 212 | .size = page_table.GetHeapRegionSize(), | 217 | .size = page_table.GetHeapRegionSize(), |
| 213 | }; | 218 | }; |
| 214 | 219 | metadata.aslr_extents = { | |
| 215 | metadata.address_space_extents = { | ||
| 216 | .base = GetInteger(page_table.GetAddressSpaceStart()), | ||
| 217 | .size = page_table.GetAddressSpaceSize(), | ||
| 218 | }; | ||
| 219 | |||
| 220 | metadata.alias_extents = { | ||
| 221 | .base = GetInteger(page_table.GetAliasCodeRegionStart()), | 220 | .base = GetInteger(page_table.GetAliasCodeRegionStart()), |
| 222 | .size = page_table.GetAliasCodeRegionSize(), | 221 | .size = page_table.GetAliasCodeRegionSize(), |
| 223 | }; | 222 | }; |
| 223 | metadata.alias_extents = { | ||
| 224 | .base = GetInteger(page_table.GetAliasRegionStart()), | ||
| 225 | .size = page_table.GetAliasRegionSize(), | ||
| 226 | }; | ||
| 224 | 227 | ||
| 225 | is_pending_reload.exchange(true); | 228 | is_pending_reload.exchange(true); |
| 226 | } | 229 | } |
diff --git a/src/core/memory/cheat_engine.h b/src/core/memory/cheat_engine.h index ced2168d1..64a9c486b 100644 --- a/src/core/memory/cheat_engine.h +++ b/src/core/memory/cheat_engine.h | |||
| @@ -37,7 +37,7 @@ private: | |||
| 37 | VAddr SanitizeAddress(VAddr address) const; | 37 | VAddr SanitizeAddress(VAddr address) const; |
| 38 | 38 | ||
| 39 | const CheatProcessMetadata& metadata; | 39 | const CheatProcessMetadata& metadata; |
| 40 | System& system; | 40 | Core::System& system; |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | // Intermediary class that parses a text file or other disk format for storing cheats into a | 43 | // Intermediary class that parses a text file or other disk format for storing cheats into a |
diff --git a/src/core/memory/dmnt_cheat_types.h b/src/core/memory/dmnt_cheat_types.h index c6b40e505..64c072d3d 100644 --- a/src/core/memory/dmnt_cheat_types.h +++ b/src/core/memory/dmnt_cheat_types.h | |||
| @@ -18,7 +18,7 @@ struct CheatProcessMetadata { | |||
| 18 | MemoryRegionExtents main_nso_extents{}; | 18 | MemoryRegionExtents main_nso_extents{}; |
| 19 | MemoryRegionExtents heap_extents{}; | 19 | MemoryRegionExtents heap_extents{}; |
| 20 | MemoryRegionExtents alias_extents{}; | 20 | MemoryRegionExtents alias_extents{}; |
| 21 | MemoryRegionExtents address_space_extents{}; | 21 | MemoryRegionExtents aslr_extents{}; |
| 22 | std::array<u8, 0x20> main_nso_build_id{}; | 22 | std::array<u8, 0x20> main_nso_build_id{}; |
| 23 | }; | 23 | }; |
| 24 | 24 | ||
diff --git a/src/core/memory/dmnt_cheat_vm.cpp b/src/core/memory/dmnt_cheat_vm.cpp index 31ffc4fbb..9424e0f73 100644 --- a/src/core/memory/dmnt_cheat_vm.cpp +++ b/src/core/memory/dmnt_cheat_vm.cpp | |||
| @@ -322,8 +322,9 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 322 | } break; | 322 | } break; |
| 323 | case CheatVmOpcodeType::EndConditionalBlock: { | 323 | case CheatVmOpcodeType::EndConditionalBlock: { |
| 324 | // 20000000 | 324 | // 20000000 |
| 325 | // There's actually nothing left to process here! | 325 | opcode.opcode = EndConditionalOpcode{ |
| 326 | opcode.opcode = EndConditionalOpcode{}; | 326 | .is_else = ((first_dword >> 24) & 0xf) == 1, |
| 327 | }; | ||
| 327 | } break; | 328 | } break; |
| 328 | case CheatVmOpcodeType::ControlLoop: { | 329 | case CheatVmOpcodeType::ControlLoop: { |
| 329 | // 300R0000 VVVVVVVV | 330 | // 300R0000 VVVVVVVV |
| @@ -555,6 +556,18 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 555 | .idx = first_dword & 0xF, | 556 | .idx = first_dword & 0xF, |
| 556 | }; | 557 | }; |
| 557 | } break; | 558 | } break; |
| 559 | case CheatVmOpcodeType::PauseProcess: { | ||
| 560 | /* FF0????? */ | ||
| 561 | /* FF0 = opcode 0xFF0 */ | ||
| 562 | /* Pauses the current process. */ | ||
| 563 | opcode.opcode = PauseProcessOpcode{}; | ||
| 564 | } break; | ||
| 565 | case CheatVmOpcodeType::ResumeProcess: { | ||
| 566 | /* FF0????? */ | ||
| 567 | /* FF0 = opcode 0xFF0 */ | ||
| 568 | /* Pauses the current process. */ | ||
| 569 | opcode.opcode = ResumeProcessOpcode{}; | ||
| 570 | } break; | ||
| 558 | case CheatVmOpcodeType::DebugLog: { | 571 | case CheatVmOpcodeType::DebugLog: { |
| 559 | // FFFTIX## | 572 | // FFFTIX## |
| 560 | // FFFTI0Ma aaaaaaaa | 573 | // FFFTI0Ma aaaaaaaa |
| @@ -621,7 +634,7 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 621 | return valid; | 634 | return valid; |
| 622 | } | 635 | } |
| 623 | 636 | ||
| 624 | void DmntCheatVm::SkipConditionalBlock() { | 637 | void DmntCheatVm::SkipConditionalBlock(bool is_if) { |
| 625 | if (condition_depth > 0) { | 638 | if (condition_depth > 0) { |
| 626 | // We want to continue until we're out of the current block. | 639 | // We want to continue until we're out of the current block. |
| 627 | const std::size_t desired_depth = condition_depth - 1; | 640 | const std::size_t desired_depth = condition_depth - 1; |
| @@ -637,8 +650,12 @@ void DmntCheatVm::SkipConditionalBlock() { | |||
| 637 | // We also support nesting of conditional blocks, and Gateway does not. | 650 | // We also support nesting of conditional blocks, and Gateway does not. |
| 638 | if (skip_opcode.begin_conditional_block) { | 651 | if (skip_opcode.begin_conditional_block) { |
| 639 | condition_depth++; | 652 | condition_depth++; |
| 640 | } else if (std::holds_alternative<EndConditionalOpcode>(skip_opcode.opcode)) { | 653 | } else if (auto end_cond = std::get_if<EndConditionalOpcode>(&skip_opcode.opcode)) { |
| 641 | condition_depth--; | 654 | if (!end_cond->is_else) { |
| 655 | condition_depth--; | ||
| 656 | } else if (is_if && condition_depth - 1 == desired_depth) { | ||
| 657 | break; | ||
| 658 | } | ||
| 642 | } | 659 | } |
| 643 | } | 660 | } |
| 644 | } else { | 661 | } else { |
| @@ -675,6 +692,10 @@ u64 DmntCheatVm::GetCheatProcessAddress(const CheatProcessMetadata& metadata, | |||
| 675 | return metadata.main_nso_extents.base + rel_address; | 692 | return metadata.main_nso_extents.base + rel_address; |
| 676 | case MemoryAccessType::Heap: | 693 | case MemoryAccessType::Heap: |
| 677 | return metadata.heap_extents.base + rel_address; | 694 | return metadata.heap_extents.base + rel_address; |
| 695 | case MemoryAccessType::Alias: | ||
| 696 | return metadata.alias_extents.base + rel_address; | ||
| 697 | case MemoryAccessType::Aslr: | ||
| 698 | return metadata.aslr_extents.base + rel_address; | ||
| 678 | } | 699 | } |
| 679 | } | 700 | } |
| 680 | 701 | ||
| @@ -682,7 +703,6 @@ void DmntCheatVm::ResetState() { | |||
| 682 | registers.fill(0); | 703 | registers.fill(0); |
| 683 | saved_values.fill(0); | 704 | saved_values.fill(0); |
| 684 | loop_tops.fill(0); | 705 | loop_tops.fill(0); |
| 685 | static_registers.fill(0); | ||
| 686 | instruction_ptr = 0; | 706 | instruction_ptr = 0; |
| 687 | condition_depth = 0; | 707 | condition_depth = 0; |
| 688 | decode_success = true; | 708 | decode_success = true; |
| @@ -794,13 +814,18 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) { | |||
| 794 | } | 814 | } |
| 795 | // Skip conditional block if condition not met. | 815 | // Skip conditional block if condition not met. |
| 796 | if (!cond_met) { | 816 | if (!cond_met) { |
| 797 | SkipConditionalBlock(); | 817 | SkipConditionalBlock(true); |
| 798 | } | 818 | } |
| 799 | } else if (std::holds_alternative<EndConditionalOpcode>(cur_opcode.opcode)) { | 819 | } else if (auto end_cond = std::get_if<EndConditionalOpcode>(&cur_opcode.opcode)) { |
| 800 | // Decrement the condition depth. | 820 | if (end_cond->is_else) { |
| 801 | // We will assume, graciously, that mismatched conditional block ends are a nop. | 821 | /* Skip to the end of the conditional block. */ |
| 802 | if (condition_depth > 0) { | 822 | this->SkipConditionalBlock(false); |
| 803 | condition_depth--; | 823 | } else { |
| 824 | /* Decrement the condition depth. */ | ||
| 825 | /* We will assume, graciously, that mismatched conditional block ends are a nop. */ | ||
| 826 | if (condition_depth > 0) { | ||
| 827 | condition_depth--; | ||
| 828 | } | ||
| 804 | } | 829 | } |
| 805 | } else if (auto ctrl_loop = std::get_if<ControlLoopOpcode>(&cur_opcode.opcode)) { | 830 | } else if (auto ctrl_loop = std::get_if<ControlLoopOpcode>(&cur_opcode.opcode)) { |
| 806 | if (ctrl_loop->start_loop) { | 831 | if (ctrl_loop->start_loop) { |
| @@ -908,7 +933,7 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) { | |||
| 908 | // Check for keypress. | 933 | // Check for keypress. |
| 909 | if ((begin_keypress_cond->key_mask & kDown) != begin_keypress_cond->key_mask) { | 934 | if ((begin_keypress_cond->key_mask & kDown) != begin_keypress_cond->key_mask) { |
| 910 | // Keys not pressed. Skip conditional block. | 935 | // Keys not pressed. Skip conditional block. |
| 911 | SkipConditionalBlock(); | 936 | SkipConditionalBlock(true); |
| 912 | } | 937 | } |
| 913 | } else if (auto perform_math_reg = | 938 | } else if (auto perform_math_reg = |
| 914 | std::get_if<PerformArithmeticRegisterOpcode>(&cur_opcode.opcode)) { | 939 | std::get_if<PerformArithmeticRegisterOpcode>(&cur_opcode.opcode)) { |
| @@ -1116,7 +1141,7 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) { | |||
| 1116 | 1141 | ||
| 1117 | // Skip conditional block if condition not met. | 1142 | // Skip conditional block if condition not met. |
| 1118 | if (!cond_met) { | 1143 | if (!cond_met) { |
| 1119 | SkipConditionalBlock(); | 1144 | SkipConditionalBlock(true); |
| 1120 | } | 1145 | } |
| 1121 | } else if (auto save_restore_reg = | 1146 | } else if (auto save_restore_reg = |
| 1122 | std::get_if<SaveRestoreRegisterOpcode>(&cur_opcode.opcode)) { | 1147 | std::get_if<SaveRestoreRegisterOpcode>(&cur_opcode.opcode)) { |
| @@ -1178,6 +1203,10 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) { | |||
| 1178 | // Store a register to a static register. | 1203 | // Store a register to a static register. |
| 1179 | static_registers[rw_static_reg->static_idx] = registers[rw_static_reg->idx]; | 1204 | static_registers[rw_static_reg->static_idx] = registers[rw_static_reg->idx]; |
| 1180 | } | 1205 | } |
| 1206 | } else if (std::holds_alternative<PauseProcessOpcode>(cur_opcode.opcode)) { | ||
| 1207 | // TODO: Pause cheat process | ||
| 1208 | } else if (std::holds_alternative<ResumeProcessOpcode>(cur_opcode.opcode)) { | ||
| 1209 | // TODO: Resume cheat process | ||
| 1181 | } else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) { | 1210 | } else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) { |
| 1182 | // Read value from memory. | 1211 | // Read value from memory. |
| 1183 | u64 log_value = 0; | 1212 | u64 log_value = 0; |
diff --git a/src/core/memory/dmnt_cheat_vm.h b/src/core/memory/dmnt_cheat_vm.h index 641cb09c4..32797dcd7 100644 --- a/src/core/memory/dmnt_cheat_vm.h +++ b/src/core/memory/dmnt_cheat_vm.h | |||
| @@ -42,12 +42,16 @@ enum class CheatVmOpcodeType : u32 { | |||
| 42 | DoubleExtendedWidth = 0xF0, | 42 | DoubleExtendedWidth = 0xF0, |
| 43 | 43 | ||
| 44 | // Double-extended width opcodes. | 44 | // Double-extended width opcodes. |
| 45 | PauseProcess = 0xFF0, | ||
| 46 | ResumeProcess = 0xFF1, | ||
| 45 | DebugLog = 0xFFF, | 47 | DebugLog = 0xFFF, |
| 46 | }; | 48 | }; |
| 47 | 49 | ||
| 48 | enum class MemoryAccessType : u32 { | 50 | enum class MemoryAccessType : u32 { |
| 49 | MainNso = 0, | 51 | MainNso = 0, |
| 50 | Heap = 1, | 52 | Heap = 1, |
| 53 | Alias = 2, | ||
| 54 | Aslr = 3, | ||
| 51 | }; | 55 | }; |
| 52 | 56 | ||
| 53 | enum class ConditionalComparisonType : u32 { | 57 | enum class ConditionalComparisonType : u32 { |
| @@ -131,7 +135,9 @@ struct BeginConditionalOpcode { | |||
| 131 | VmInt value{}; | 135 | VmInt value{}; |
| 132 | }; | 136 | }; |
| 133 | 137 | ||
| 134 | struct EndConditionalOpcode {}; | 138 | struct EndConditionalOpcode { |
| 139 | bool is_else; | ||
| 140 | }; | ||
| 135 | 141 | ||
| 136 | struct ControlLoopOpcode { | 142 | struct ControlLoopOpcode { |
| 137 | bool start_loop{}; | 143 | bool start_loop{}; |
| @@ -222,6 +228,10 @@ struct ReadWriteStaticRegisterOpcode { | |||
| 222 | u32 idx{}; | 228 | u32 idx{}; |
| 223 | }; | 229 | }; |
| 224 | 230 | ||
| 231 | struct PauseProcessOpcode {}; | ||
| 232 | |||
| 233 | struct ResumeProcessOpcode {}; | ||
| 234 | |||
| 225 | struct DebugLogOpcode { | 235 | struct DebugLogOpcode { |
| 226 | u32 bit_width{}; | 236 | u32 bit_width{}; |
| 227 | u32 log_id{}; | 237 | u32 log_id{}; |
| @@ -244,8 +254,8 @@ struct CheatVmOpcode { | |||
| 244 | PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode, | 254 | PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode, |
| 245 | PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode, | 255 | PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode, |
| 246 | BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode, | 256 | BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode, |
| 247 | SaveRestoreRegisterMaskOpcode, ReadWriteStaticRegisterOpcode, DebugLogOpcode, | 257 | SaveRestoreRegisterMaskOpcode, ReadWriteStaticRegisterOpcode, PauseProcessOpcode, |
| 248 | UnrecognizedInstruction> | 258 | ResumeProcessOpcode, DebugLogOpcode, UnrecognizedInstruction> |
| 249 | opcode{}; | 259 | opcode{}; |
| 250 | }; | 260 | }; |
| 251 | 261 | ||
| @@ -296,7 +306,7 @@ private: | |||
| 296 | std::array<std::size_t, NumRegisters> loop_tops{}; | 306 | std::array<std::size_t, NumRegisters> loop_tops{}; |
| 297 | 307 | ||
| 298 | bool DecodeNextOpcode(CheatVmOpcode& out); | 308 | bool DecodeNextOpcode(CheatVmOpcode& out); |
| 299 | void SkipConditionalBlock(); | 309 | void SkipConditionalBlock(bool is_if); |
| 300 | void ResetState(); | 310 | void ResetState(); |
| 301 | 311 | ||
| 302 | // For implementing the DebugLog opcode. | 312 | // For implementing the DebugLog opcode. |