mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-26 13:52:21 +00:00
dmnt-cheat: Add Save/Restore register opcode
This commit is contained in:
parent
a0f3183c79
commit
477bee2e4c
2 changed files with 40 additions and 0 deletions
|
@ -188,6 +188,12 @@ void DmntCheatVm::LogOpcode(const CheatVmOpcode *opcode) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CheatVmOpcodeType_SaveRestoreRegister:
|
||||||
|
this->LogToDebugFile("Opcode: Save or Restore Register\n");
|
||||||
|
this->LogToDebugFile("Dst Idx: %x\n", opcode->save_restore_reg.dst_index);
|
||||||
|
this->LogToDebugFile("Src Idx: %x\n", opcode->save_restore_reg.src_index);
|
||||||
|
this->LogToDebugFile("Is Save: %d\n", opcode->save_restore_reg.is_save);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
this->LogToDebugFile("Unknown opcode: %x\n", opcode->opcode);
|
this->LogToDebugFile("Unknown opcode: %x\n", opcode->opcode);
|
||||||
break;
|
break;
|
||||||
|
@ -462,6 +468,19 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CheatVmOpcodeType_SaveRestoreRegister:
|
||||||
|
{
|
||||||
|
/* C10D0Sx0 */
|
||||||
|
/* C1 = opcode 0xC1 */
|
||||||
|
/* D = destination index. */
|
||||||
|
/* S = source index. */
|
||||||
|
/* x = 1 if saving a register, 0 if restoring a register. */
|
||||||
|
/* NOTE: If we add more save slots later, current encoding is backwards compatible. */
|
||||||
|
opcode.save_restore_reg.dst_index = (first_dword >> 16) & 0xF;
|
||||||
|
opcode.save_restore_reg.src_index = (first_dword >> 8) & 0xF;
|
||||||
|
opcode.save_restore_reg.is_save = ((first_dword >> 4) & 0xF) != 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case CheatVmOpcodeType_ExtendedWidth:
|
case CheatVmOpcodeType_ExtendedWidth:
|
||||||
default:
|
default:
|
||||||
/* Unrecognized instruction cannot be decoded. */
|
/* Unrecognized instruction cannot be decoded. */
|
||||||
|
@ -532,6 +551,7 @@ u64 DmntCheatVm::GetCheatProcessAddress(const CheatProcessMetadata* metadata, Me
|
||||||
void DmntCheatVm::ResetState() {
|
void DmntCheatVm::ResetState() {
|
||||||
for (size_t i = 0; i < DmntCheatVm::NumRegisters; i++) {
|
for (size_t i = 0; i < DmntCheatVm::NumRegisters; i++) {
|
||||||
this->registers[i] = 0;
|
this->registers[i] = 0;
|
||||||
|
this->saved_values[i] = 0;
|
||||||
this->loop_tops[i] = 0;
|
this->loop_tops[i] = 0;
|
||||||
}
|
}
|
||||||
this->instruction_ptr = 0;
|
this->instruction_ptr = 0;
|
||||||
|
@ -585,6 +605,10 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) {
|
||||||
for (size_t i = 0; i < NumRegisters; i++) {
|
for (size_t i = 0; i < NumRegisters; i++) {
|
||||||
this->LogToDebugFile("Registers[%02x]: %016lx\n", i, this->registers[i]);
|
this->LogToDebugFile("Registers[%02x]: %016lx\n", i, this->registers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < NumRegisters; i++) {
|
||||||
|
this->LogToDebugFile("SavedRegs[%02x]: %016lx\n", i, this->saved_values[i]);
|
||||||
|
}
|
||||||
this->LogOpcode(&cur_opcode);
|
this->LogOpcode(&cur_opcode);
|
||||||
|
|
||||||
/* Increment conditional depth, if relevant. */
|
/* Increment conditional depth, if relevant. */
|
||||||
|
@ -964,6 +988,14 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CheatVmOpcodeType_SaveRestoreRegister:
|
||||||
|
/* Save or restore a register. */
|
||||||
|
if (cur_opcode.save_restore_reg.is_save) {
|
||||||
|
this->saved_values[cur_opcode.save_restore_reg.dst_index] = this->registers[cur_opcode.save_restore_reg.src_index];
|
||||||
|
} else {
|
||||||
|
this->registers[cur_opcode.save_restore_reg.dst_index] = this->saved_values[cur_opcode.save_restore_reg.src_index];
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* By default, we do a no-op. */
|
/* By default, we do a no-op. */
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -43,6 +43,7 @@ enum CheatVmOpcodeType : u32 {
|
||||||
|
|
||||||
/* Extended width opcodes. */
|
/* Extended width opcodes. */
|
||||||
CheatVmOpcodeType_BeginRegisterConditionalBlock = 0xC0,
|
CheatVmOpcodeType_BeginRegisterConditionalBlock = 0xC0,
|
||||||
|
CheatVmOpcodeType_SaveRestoreRegister = 0xC1,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MemoryAccessType : u32 {
|
enum MemoryAccessType : u32 {
|
||||||
|
@ -191,6 +192,11 @@ struct BeginRegisterConditionalOpcode {
|
||||||
VmInt value;
|
VmInt value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SaveRestoreRegisterOpcode {
|
||||||
|
u32 dst_index;
|
||||||
|
u32 src_index;
|
||||||
|
bool is_save;
|
||||||
|
};
|
||||||
|
|
||||||
struct CheatVmOpcode {
|
struct CheatVmOpcode {
|
||||||
CheatVmOpcodeType opcode;
|
CheatVmOpcodeType opcode;
|
||||||
|
@ -208,6 +214,7 @@ struct CheatVmOpcode {
|
||||||
PerformArithmeticRegisterOpcode perform_math_reg;
|
PerformArithmeticRegisterOpcode perform_math_reg;
|
||||||
StoreRegisterToAddressOpcode str_register;
|
StoreRegisterToAddressOpcode str_register;
|
||||||
BeginRegisterConditionalOpcode begin_reg_cond;
|
BeginRegisterConditionalOpcode begin_reg_cond;
|
||||||
|
SaveRestoreRegisterOpcode save_restore_reg;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -222,6 +229,7 @@ class DmntCheatVm {
|
||||||
bool decode_success = false;
|
bool decode_success = false;
|
||||||
u32 program[MaximumProgramOpcodeCount] = {0};
|
u32 program[MaximumProgramOpcodeCount] = {0};
|
||||||
u64 registers[NumRegisters] = {0};
|
u64 registers[NumRegisters] = {0};
|
||||||
|
u64 saved_values[NumRegisters] = {0};
|
||||||
size_t loop_tops[NumRegisters] = {0};
|
size_t loop_tops[NumRegisters] = {0};
|
||||||
private:
|
private:
|
||||||
bool DecodeNextOpcode(CheatVmOpcode *out);
|
bool DecodeNextOpcode(CheatVmOpcode *out);
|
||||||
|
|
Loading…
Reference in a new issue