diff options
| -rw-r--r-- | src/core/memory/dmnt_cheat_vm.cpp | 28 | ||||
| -rw-r--r-- | src/core/memory/dmnt_cheat_vm.h | 14 |
2 files changed, 41 insertions, 1 deletions
diff --git a/src/core/memory/dmnt_cheat_vm.cpp b/src/core/memory/dmnt_cheat_vm.cpp index fb9f36bfd..0faebe951 100644 --- a/src/core/memory/dmnt_cheat_vm.cpp +++ b/src/core/memory/dmnt_cheat_vm.cpp | |||
| @@ -190,6 +190,15 @@ void DmntCheatVm::LogOpcode(const CheatVmOpcode& opcode) { | |||
| 190 | callbacks->CommandLog( | 190 | callbacks->CommandLog( |
| 191 | fmt::format("Act[{:02X}]: {:d}", i, save_restore_regmask->should_operate[i])); | 191 | fmt::format("Act[{:02X}]: {:d}", i, save_restore_regmask->should_operate[i])); |
| 192 | } | 192 | } |
| 193 | } else if (auto rw_static_reg = std::get_if<ReadWriteStaticRegisterOpcode>(&opcode.opcode)) { | ||
| 194 | callbacks->CommandLog("Opcode: Read/Write Static Register"); | ||
| 195 | if (rw_static_reg->static_idx < NumReadableStaticRegisters) { | ||
| 196 | callbacks->CommandLog("Op Type: ReadStaticRegister"); | ||
| 197 | } else { | ||
| 198 | callbacks->CommandLog("Op Type: WriteStaticRegister"); | ||
| 199 | } | ||
| 200 | callbacks->CommandLog(fmt::format("Reg Idx {:X}", rw_static_reg->idx)); | ||
| 201 | callbacks->CommandLog(fmt::format("Stc Idx {:X}", rw_static_reg->static_idx)); | ||
| 193 | } else if (auto debug_log = std::get_if<DebugLogOpcode>(&opcode.opcode)) { | 202 | } else if (auto debug_log = std::get_if<DebugLogOpcode>(&opcode.opcode)) { |
| 194 | callbacks->CommandLog("Opcode: Debug Log"); | 203 | callbacks->CommandLog("Opcode: Debug Log"); |
| 195 | callbacks->CommandLog(fmt::format("Bit Width: {:X}", debug_log->bit_width)); | 204 | callbacks->CommandLog(fmt::format("Bit Width: {:X}", debug_log->bit_width)); |
| @@ -544,6 +553,16 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 544 | } | 553 | } |
| 545 | opcode.opcode = save_restore_regmask; | 554 | opcode.opcode = save_restore_regmask; |
| 546 | } break; | 555 | } break; |
| 556 | case CheatVmOpcodeType::ReadWriteStaticRegister: { | ||
| 557 | ReadWriteStaticRegisterOpcode rw_static_reg{}; | ||
| 558 | // C3000XXx | ||
| 559 | // C3 = opcode 0xC3. | ||
| 560 | // XX = static register index. | ||
| 561 | // x = register index. | ||
| 562 | rw_static_reg.static_idx = ((first_dword >> 4) & 0xFF); | ||
| 563 | rw_static_reg.idx = (first_dword & 0xF); | ||
| 564 | opcode.opcode = rw_static_reg; | ||
| 565 | } break; | ||
| 547 | case CheatVmOpcodeType::DebugLog: { | 566 | case CheatVmOpcodeType::DebugLog: { |
| 548 | DebugLogOpcode debug_log{}; | 567 | DebugLogOpcode debug_log{}; |
| 549 | // FFFTIX## | 568 | // FFFTIX## |
| @@ -667,6 +686,7 @@ void DmntCheatVm::ResetState() { | |||
| 667 | registers.fill(0); | 686 | registers.fill(0); |
| 668 | saved_values.fill(0); | 687 | saved_values.fill(0); |
| 669 | loop_tops.fill(0); | 688 | loop_tops.fill(0); |
| 689 | static_registers.fill(0); | ||
| 670 | instruction_ptr = 0; | 690 | instruction_ptr = 0; |
| 671 | condition_depth = 0; | 691 | condition_depth = 0; |
| 672 | decode_success = true; | 692 | decode_success = true; |
| @@ -1153,6 +1173,14 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) { | |||
| 1153 | } | 1173 | } |
| 1154 | } | 1174 | } |
| 1155 | } | 1175 | } |
| 1176 | } else if (auto rw_static_reg = std::get_if<ReadWriteStaticRegisterOpcode>(&cur_opcode.opcode)) { | ||
| 1177 | if (rw_static_reg->static_idx < NumReadableStaticRegisters) { | ||
| 1178 | // Load a register with a static register. | ||
| 1179 | registers[rw_static_reg->idx] = static_registers[rw_static_reg->static_idx]; | ||
| 1180 | } else { | ||
| 1181 | // Store a register to a static register. | ||
| 1182 | static_registers[rw_static_reg->static_idx] = registers[rw_static_reg->idx]; | ||
| 1183 | } | ||
| 1156 | } else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) { | 1184 | } else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) { |
| 1157 | // Read value from memory. | 1185 | // Read value from memory. |
| 1158 | u64 log_value = 0; | 1186 | u64 log_value = 0; |
diff --git a/src/core/memory/dmnt_cheat_vm.h b/src/core/memory/dmnt_cheat_vm.h index 8351fd798..21b86b72c 100644 --- a/src/core/memory/dmnt_cheat_vm.h +++ b/src/core/memory/dmnt_cheat_vm.h | |||
| @@ -56,6 +56,7 @@ enum class CheatVmOpcodeType : u32 { | |||
| 56 | BeginRegisterConditionalBlock = 0xC0, | 56 | BeginRegisterConditionalBlock = 0xC0, |
| 57 | SaveRestoreRegister = 0xC1, | 57 | SaveRestoreRegister = 0xC1, |
| 58 | SaveRestoreRegisterMask = 0xC2, | 58 | SaveRestoreRegisterMask = 0xC2, |
| 59 | ReadWriteStaticRegister = 0xC3, | ||
| 59 | 60 | ||
| 60 | // This is a meta entry, and not a real opcode. | 61 | // This is a meta entry, and not a real opcode. |
| 61 | // This is to facilitate multi-nybble instruction decoding. | 62 | // This is to facilitate multi-nybble instruction decoding. |
| @@ -237,6 +238,11 @@ struct SaveRestoreRegisterMaskOpcode { | |||
| 237 | std::array<bool, 0x10> should_operate{}; | 238 | std::array<bool, 0x10> should_operate{}; |
| 238 | }; | 239 | }; |
| 239 | 240 | ||
| 241 | struct ReadWriteStaticRegisterOpcode { | ||
| 242 | u32 static_idx{}; | ||
| 243 | u32 idx{}; | ||
| 244 | }; | ||
| 245 | |||
| 240 | struct DebugLogOpcode { | 246 | struct DebugLogOpcode { |
| 241 | u32 bit_width{}; | 247 | u32 bit_width{}; |
| 242 | u32 log_id{}; | 248 | u32 log_id{}; |
| @@ -259,7 +265,8 @@ struct CheatVmOpcode { | |||
| 259 | PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode, | 265 | PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode, |
| 260 | PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode, | 266 | PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode, |
| 261 | BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode, | 267 | BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode, |
| 262 | SaveRestoreRegisterMaskOpcode, DebugLogOpcode, UnrecognizedInstruction> | 268 | SaveRestoreRegisterMaskOpcode, ReadWriteStaticRegisterOpcode, DebugLogOpcode, |
| 269 | UnrecognizedInstruction> | ||
| 263 | opcode{}; | 270 | opcode{}; |
| 264 | }; | 271 | }; |
| 265 | 272 | ||
| @@ -281,6 +288,10 @@ public: | |||
| 281 | 288 | ||
| 282 | static constexpr std::size_t MaximumProgramOpcodeCount = 0x400; | 289 | static constexpr std::size_t MaximumProgramOpcodeCount = 0x400; |
| 283 | static constexpr std::size_t NumRegisters = 0x10; | 290 | static constexpr std::size_t NumRegisters = 0x10; |
| 291 | static constexpr std::size_t NumReadableStaticRegisters = 0x80; | ||
| 292 | static constexpr std::size_t NumWritableStaticRegisters = 0x80; | ||
| 293 | static constexpr std::size_t NumStaticRegisters = | ||
| 294 | NumReadableStaticRegisters + NumWritableStaticRegisters; | ||
| 284 | 295 | ||
| 285 | explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks); | 296 | explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks); |
| 286 | ~DmntCheatVm(); | 297 | ~DmntCheatVm(); |
| @@ -302,6 +313,7 @@ private: | |||
| 302 | std::array<u32, MaximumProgramOpcodeCount> program{}; | 313 | std::array<u32, MaximumProgramOpcodeCount> program{}; |
| 303 | std::array<u64, NumRegisters> registers{}; | 314 | std::array<u64, NumRegisters> registers{}; |
| 304 | std::array<u64, NumRegisters> saved_values{}; | 315 | std::array<u64, NumRegisters> saved_values{}; |
| 316 | std::array<u64, NumStaticRegisters> static_registers{}; | ||
| 305 | std::array<std::size_t, NumRegisters> loop_tops{}; | 317 | std::array<std::size_t, NumRegisters> loop_tops{}; |
| 306 | 318 | ||
| 307 | bool DecodeNextOpcode(CheatVmOpcode& out); | 319 | bool DecodeNextOpcode(CheatVmOpcode& out); |