aboutsummaryrefslogtreecommitdiff
path: root/src/core/memory/dmnt_cheat_vm.cpp
diff options
context:
space:
mode:
authorVolcaEM <63682805+VolcaEM@users.noreply.github.com>2020-07-15 01:19:22 +0200
committerGitHub <noreply@github.com>2020-07-15 01:19:22 +0200
commitb608acd6881c973710d687bc20722838d8a689cc (patch)
tree76f13616daad96fb35553369c204375d04a716ec /src/core/memory/dmnt_cheat_vm.cpp
parenta0ee597b19482ce4bfc6231ad54666e2a7f894b5 (diff)
dmnt_cheat_vm: Implement opcode 0xC3 (ReadWriteStaticRegister)
This was based on Atmosphére's DMNT Cheat VM: - https://github.com/Atmosphere-NX/Atmosphere/blob/master/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.hpp - https://github.com/Atmosphere-NX/Atmosphere/blob/master/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.cpp From Atmosphére's documentation: "Code type 0xC3 reads or writes a static register with a given register" There are now only two remaining opcodes to implement (PauseProcess and BreakProcess) This is untested because I don't have any experience in testing cheats on yuzu
Diffstat (limited to 'src/core/memory/dmnt_cheat_vm.cpp')
-rw-r--r--src/core/memory/dmnt_cheat_vm.cpp28
1 files changed, 28 insertions, 0 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) {
callbacks->CommandLog(
fmt::format("Act[{:02X}]: {:d}", i, save_restore_regmask->should_operate[i]));
}
+ } else if (auto rw_static_reg = std::get_if<ReadWriteStaticRegisterOpcode>(&opcode.opcode)) {
+ callbacks->CommandLog("Opcode: Read/Write Static Register");
+ if (rw_static_reg->static_idx < NumReadableStaticRegisters) {
+ callbacks->CommandLog("Op Type: ReadStaticRegister");
+ } else {
+ callbacks->CommandLog("Op Type: WriteStaticRegister");
+ }
+ callbacks->CommandLog(fmt::format("Reg Idx {:X}", rw_static_reg->idx));
+ callbacks->CommandLog(fmt::format("Stc Idx {:X}", rw_static_reg->static_idx));
} else if (auto debug_log = std::get_if<DebugLogOpcode>(&opcode.opcode)) {
callbacks->CommandLog("Opcode: Debug Log");
callbacks->CommandLog(fmt::format("Bit Width: {:X}", debug_log->bit_width));
@@ -544,6 +553,16 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
}
opcode.opcode = save_restore_regmask;
} break;
+ case CheatVmOpcodeType::ReadWriteStaticRegister: {
+ ReadWriteStaticRegisterOpcode rw_static_reg{};
+ // C3000XXx
+ // C3 = opcode 0xC3.
+ // XX = static register index.
+ // x = register index.
+ rw_static_reg.static_idx = ((first_dword >> 4) & 0xFF);
+ rw_static_reg.idx = (first_dword & 0xF);
+ opcode.opcode = rw_static_reg;
+ } break;
case CheatVmOpcodeType::DebugLog: {
DebugLogOpcode debug_log{};
// FFFTIX##
@@ -667,6 +686,7 @@ void DmntCheatVm::ResetState() {
registers.fill(0);
saved_values.fill(0);
loop_tops.fill(0);
+ static_registers.fill(0);
instruction_ptr = 0;
condition_depth = 0;
decode_success = true;
@@ -1153,6 +1173,14 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
}
}
}
+ } else if (auto rw_static_reg = std::get_if<ReadWriteStaticRegisterOpcode>(&cur_opcode.opcode)) {
+ if (rw_static_reg->static_idx < NumReadableStaticRegisters) {
+ // Load a register with a static register.
+ registers[rw_static_reg->idx] = static_registers[rw_static_reg->static_idx];
+ } else {
+ // Store a register to a static register.
+ static_registers[rw_static_reg->static_idx] = registers[rw_static_reg->idx];
+ }
} else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) {
// Read value from memory.
u64 log_value = 0;