dmnt-cheat: add clear to save/restore reg

This commit is contained in:
Michael Scire 2019-04-05 14:16:07 -07:00
parent 2f1f56307d
commit c7ffcad74e
2 changed files with 47 additions and 22 deletions

View file

@ -192,13 +192,13 @@ void DmntCheatVm::LogOpcode(const CheatVmOpcode *opcode) {
this->LogToDebugFile("Opcode: Save or Restore Register\n"); this->LogToDebugFile("Opcode: Save or Restore Register\n");
this->LogToDebugFile("Dst Idx: %x\n", opcode->save_restore_reg.dst_index); 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("Src Idx: %x\n", opcode->save_restore_reg.src_index);
this->LogToDebugFile("Is Save: %d\n", opcode->save_restore_reg.is_save); this->LogToDebugFile("Op Type: %d\n", opcode->save_restore_reg.op_type);
break; break;
case CheatVmOpcodeType_SaveRestoreRegisterMask: case CheatVmOpcodeType_SaveRestoreRegisterMask:
this->LogToDebugFile("Opcode: Save or Restore Register Mask\n"); this->LogToDebugFile("Opcode: Save or Restore Register Mask\n");
this->LogToDebugFile("Is Save: %d\n", opcode->save_restore_regmask.is_save); this->LogToDebugFile("Op Type: %d\n", opcode->save_restore_regmask.op_type);
for (size_t i = 0; i < NumRegisters; i++) { for (size_t i = 0; i < NumRegisters; i++) {
this->LogToDebugFile("Act[%02x]: %d\n", i, opcode->save_restore_regmask.should_save_or_restore[i]); this->LogToDebugFile("Act[%02x]: %d\n", i, opcode->save_restore_regmask.should_operate[i]);
} }
break; break;
default: default:
@ -481,22 +481,22 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) {
/* C1 = opcode 0xC1 */ /* C1 = opcode 0xC1 */
/* D = destination index. */ /* D = destination index. */
/* S = source index. */ /* S = source index. */
/* x = 1 if saving a register, 0 if restoring a register. */ /* x = 2 if clearing saved value, 1 if saving a register, 0 if restoring a register. */
/* NOTE: If we add more save slots later, current encoding is backwards compatible. */ /* 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.dst_index = (first_dword >> 16) & 0xF;
opcode.save_restore_reg.src_index = (first_dword >> 8) & 0xF; opcode.save_restore_reg.src_index = (first_dword >> 8) & 0xF;
opcode.save_restore_reg.is_save = ((first_dword >> 4) & 0xF) != 0; opcode.save_restore_reg.op_type = (SaveRestoreRegisterOpType)((first_dword >> 4) & 0xF);
} }
break; break;
case CheatVmOpcodeType_SaveRestoreRegisterMask: case CheatVmOpcodeType_SaveRestoreRegisterMask:
{ {
/* C2x0XXXX */ /* C2x0XXXX */
/* C2 = opcode 0xC2 */ /* C2 = opcode 0xC2 */
/* x = 1 if saving, 0 if restoring. */ /* x = 2 if clearing saved value, 1 if saving, 0 if restoring. */
/* X = 16-bit bitmask, bit i --> save or restore register i. */ /* X = 16-bit bitmask, bit i --> save or restore register i. */
opcode.save_restore_regmask.is_save = ((first_dword >> 20) & 0xF) != 0; opcode.save_restore_regmask.op_type = (SaveRestoreRegisterOpType)((first_dword >> 20) & 0xF);
for (size_t i = 0; i < NumRegisters; i++) { for (size_t i = 0; i < NumRegisters; i++) {
opcode.save_restore_regmask.should_save_or_restore[i] = (first_dword & (1u << i)) != 0; opcode.save_restore_regmask.should_operate[i] = (first_dword & (1u << i)) != 0;
} }
} }
break; break;
@ -1009,25 +1009,44 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) {
break; break;
case CheatVmOpcodeType_SaveRestoreRegister: case CheatVmOpcodeType_SaveRestoreRegister:
/* Save or restore a register. */ /* Save or restore a register. */
if (cur_opcode.save_restore_reg.is_save) { switch (cur_opcode.save_restore_reg.op_type) {
this->saved_values[cur_opcode.save_restore_reg.dst_index] = this->registers[cur_opcode.save_restore_reg.src_index]; case SaveRestoreRegisterOpType_Clear:
} else { this->saved_values[cur_opcode.save_restore_reg.dst_index] = 0ul;
this->registers[cur_opcode.save_restore_reg.dst_index] = this->saved_values[cur_opcode.save_restore_reg.src_index]; break;
case SaveRestoreRegisterOpType_Save:
this->saved_values[cur_opcode.save_restore_reg.dst_index] = this->registers[cur_opcode.save_restore_reg.src_index];
break;
case SaveRestoreRegisterOpType_Restore:
default:
this->registers[cur_opcode.save_restore_reg.dst_index] = this->saved_values[cur_opcode.save_restore_reg.src_index];
break;
} }
break; break;
case CheatVmOpcodeType_SaveRestoreRegisterMask: case CheatVmOpcodeType_SaveRestoreRegisterMask:
/* Save or restore register mask. */ /* Save or restore register mask. */
if (cur_opcode.save_restore_reg.op_type == SaveRestoreRegisterOpType_Clear) {
for (size_t i = 0; i < NumRegisters; i++) {
if (cur_opcode.save_restore_regmask.should_operate[i]) {
this->saved_values[i] = 0;
}
}
break;
}
u64 *src; u64 *src;
u64 *dst; u64 *dst;
if (cur_opcode.save_restore_regmask.is_save) { switch (cur_opcode.save_restore_regmask.op_type) {
src = this->registers; case SaveRestoreRegisterOpType_Save:
dst = this->saved_values; src = this->registers;
} else { dst = this->saved_values;
src = this->registers; break;
dst = this->saved_values; case SaveRestoreRegisterOpType_Restore:
default:
src = this->registers;
dst = this->saved_values;
break;
} }
for (size_t i = 0; i < NumRegisters; i++) { for (size_t i = 0; i < NumRegisters; i++) {
if (cur_opcode.save_restore_regmask.should_save_or_restore[i]) { if (cur_opcode.save_restore_regmask.should_operate[i]) {
dst[i] = src[i]; dst[i] = src[i];
} }
} }

View file

@ -95,6 +95,12 @@ enum CompareRegisterValueType : u32 {
CompareRegisterValueType_OtherRegister = 5, CompareRegisterValueType_OtherRegister = 5,
}; };
enum SaveRestoreRegisterOpType : u32 {
SaveRestoreRegisterOpType_Restore = 0,
SaveRestoreRegisterOpType_Save = 1,
SaveRestoreRegisterOpType_Clear = 2,
};
union VmInt { union VmInt {
u8 bit8; u8 bit8;
u16 bit16; u16 bit16;
@ -196,12 +202,12 @@ struct BeginRegisterConditionalOpcode {
struct SaveRestoreRegisterOpcode { struct SaveRestoreRegisterOpcode {
u32 dst_index; u32 dst_index;
u32 src_index; u32 src_index;
bool is_save; SaveRestoreRegisterOpType op_type;
}; };
struct SaveRestoreRegisterMaskOpcode { struct SaveRestoreRegisterMaskOpcode {
bool is_save; SaveRestoreRegisterOpType op_type;
bool should_save_or_restore[0x10]; bool should_operate[0x10];
}; };
struct CheatVmOpcode { struct CheatVmOpcode {