mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-05 19:51:45 +00:00
dmnt-cheat: Add opcode to store register to memory
This commit is contained in:
parent
88a6ef4cd7
commit
8c86074da2
2 changed files with 127 additions and 27 deletions
|
@ -95,15 +95,15 @@ void DmntCheatVm::LogOpcode(const CheatVmOpcode *opcode) {
|
||||||
this->LogToDebugFile("From Reg: %d\n", opcode->ldr_memory.load_from_reg);
|
this->LogToDebugFile("From Reg: %d\n", opcode->ldr_memory.load_from_reg);
|
||||||
this->LogToDebugFile("Rel Addr: %lx\n", opcode->ldr_memory.rel_address);
|
this->LogToDebugFile("Rel Addr: %lx\n", opcode->ldr_memory.rel_address);
|
||||||
break;
|
break;
|
||||||
case CheatVmOpcodeType_StoreToRegisterAddress:
|
case CheatVmOpcodeType_StoreStaticToAddress:
|
||||||
this->LogToDebugFile("Opcode: Store Static to Register Address\n");
|
this->LogToDebugFile("Opcode: Store Static to Address\n");
|
||||||
this->LogToDebugFile("Bit Width: %x\n", opcode->str_regaddr.bit_width);
|
this->LogToDebugFile("Bit Width: %x\n", opcode->str_static.bit_width);
|
||||||
this->LogToDebugFile("Reg Idx: %x\n", opcode->str_regaddr.reg_index);
|
this->LogToDebugFile("Reg Idx: %x\n", opcode->str_static.reg_index);
|
||||||
if (opcode->str_regaddr.add_offset_reg) {
|
if (opcode->str_static.add_offset_reg) {
|
||||||
this->LogToDebugFile("O Reg Idx: %x\n", opcode->str_regaddr.offset_reg_index);
|
this->LogToDebugFile("O Reg Idx: %x\n", opcode->str_static.offset_reg_index);
|
||||||
}
|
}
|
||||||
this->LogToDebugFile("Incr Reg: %d\n", opcode->str_regaddr.increment_reg);
|
this->LogToDebugFile("Incr Reg: %d\n", opcode->str_static.increment_reg);
|
||||||
this->LogToDebugFile("Value: %lx\n", opcode->str_regaddr.value);
|
this->LogToDebugFile("Value: %lx\n", opcode->str_static.value);
|
||||||
break;
|
break;
|
||||||
case CheatVmOpcodeType_PerformArithmeticStatic:
|
case CheatVmOpcodeType_PerformArithmeticStatic:
|
||||||
this->LogToDebugFile("Opcode: Perform Static Arithmetic\n");
|
this->LogToDebugFile("Opcode: Perform Static Arithmetic\n");
|
||||||
|
@ -127,6 +127,23 @@ void DmntCheatVm::LogOpcode(const CheatVmOpcode *opcode) {
|
||||||
this->LogToDebugFile("Src2 Idx: %x\n", opcode->perform_math_reg.src_reg_2_index);
|
this->LogToDebugFile("Src2 Idx: %x\n", opcode->perform_math_reg.src_reg_2_index);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CheatVmOpcodeType_StoreRegisterToAddress:
|
||||||
|
this->LogToDebugFile("Opcode: Store Register to Address\n");
|
||||||
|
this->LogToDebugFile("Bit Width: %x\n", opcode->str_register.bit_width);
|
||||||
|
this->LogToDebugFile("S Reg Idx: %x\n", opcode->str_register.str_reg_index);
|
||||||
|
this->LogToDebugFile("A Reg Idx: %x\n", opcode->str_register.addr_reg_index);
|
||||||
|
this->LogToDebugFile("Incr Reg: %d\n", opcode->str_register.increment_reg);
|
||||||
|
switch (opcode->str_register.ofs_type) {
|
||||||
|
case StoreRegisterOffsetType_None:
|
||||||
|
break;
|
||||||
|
case StoreRegisterOffsetType_Reg:
|
||||||
|
this->LogToDebugFile("O Reg Idx: %x\n", opcode->str_register.ofs_reg_index);
|
||||||
|
break;
|
||||||
|
case StoreRegisterOffsetType_Imm:
|
||||||
|
this->LogToDebugFile("Rel Addr: %lx\n", opcode->str_register.rel_address);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
this->LogToDebugFile("Unknown opcode: %x\n", opcode->opcode);
|
this->LogToDebugFile("Unknown opcode: %x\n", opcode->opcode);
|
||||||
break;
|
break;
|
||||||
|
@ -252,16 +269,16 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) {
|
||||||
opcode.ldr_memory.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword);
|
opcode.ldr_memory.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CheatVmOpcodeType_StoreToRegisterAddress:
|
case CheatVmOpcodeType_StoreStaticToAddress:
|
||||||
{
|
{
|
||||||
/* 6T0RIor0 VVVVVVVV VVVVVVVV */
|
/* 6T0RIor0 VVVVVVVV VVVVVVVV */
|
||||||
/* Read additional words. */
|
/* Read additional words. */
|
||||||
opcode.str_regaddr.bit_width = (first_dword >> 24) & 0xF;
|
opcode.str_static.bit_width = (first_dword >> 24) & 0xF;
|
||||||
opcode.str_regaddr.reg_index = ((first_dword >> 16) & 0xF);
|
opcode.str_static.reg_index = ((first_dword >> 16) & 0xF);
|
||||||
opcode.str_regaddr.increment_reg = ((first_dword >> 12) & 0xF) != 0;
|
opcode.str_static.increment_reg = ((first_dword >> 12) & 0xF) != 0;
|
||||||
opcode.str_regaddr.add_offset_reg = ((first_dword >> 8) & 0xF) != 0;
|
opcode.str_static.add_offset_reg = ((first_dword >> 8) & 0xF) != 0;
|
||||||
opcode.str_regaddr.offset_reg_index = ((first_dword >> 4) & 0xF);
|
opcode.str_static.offset_reg_index = ((first_dword >> 4) & 0xF);
|
||||||
opcode.str_regaddr.value = (((u64)GetNextDword()) << 32ul) | ((u64)GetNextDword());
|
opcode.str_static.value = (((u64)GetNextDword()) << 32ul) | ((u64)GetNextDword());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CheatVmOpcodeType_PerformArithmeticStatic:
|
case CheatVmOpcodeType_PerformArithmeticStatic:
|
||||||
|
@ -297,6 +314,37 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CheatVmOpcodeType_StoreRegisterToAddress:
|
||||||
|
{
|
||||||
|
/* ATSRIOra (aaaaaaaa) */
|
||||||
|
/* A = opcode 10 */
|
||||||
|
/* T = bit width */
|
||||||
|
/* S = src register index */
|
||||||
|
/* R = address register index */
|
||||||
|
/* I = 1 if increment address register, 0 if not increment address register */
|
||||||
|
/* O = offset type, 0 = None, 1 = Register, 2 = Immediate */
|
||||||
|
/* r = offset register (for offset type 1) */
|
||||||
|
/* a = relative address (for offset type 2) */
|
||||||
|
opcode.str_register.bit_width = (first_dword >> 24) & 0xF;
|
||||||
|
opcode.str_register.str_reg_index = ((first_dword >> 20) & 0xF);
|
||||||
|
opcode.str_register.addr_reg_index = ((first_dword >> 16) & 0xF);
|
||||||
|
opcode.str_register.increment_reg = ((first_dword >> 12) & 0xF) != 0;
|
||||||
|
opcode.str_register.ofs_type = (StoreRegisterOffsetType)(((first_dword >> 8) & 0xF));
|
||||||
|
opcode.str_register.ofs_reg_index = ((first_dword >> 4) & 0xF);
|
||||||
|
switch (opcode.str_register.ofs_type) {
|
||||||
|
case StoreRegisterOffsetType_None:
|
||||||
|
case StoreRegisterOffsetType_Reg:
|
||||||
|
/* Nothing more to do */
|
||||||
|
break;
|
||||||
|
case StoreRegisterOffsetType_Imm:
|
||||||
|
opcode.str_register.rel_address = (((u64)(first_dword & 0xF) << 32ul) | ((u64)GetNextDword()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
opcode.str_register.ofs_type = StoreRegisterOffsetType_None;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case CheatVmOpcodeType_ExtendedWidth:
|
case CheatVmOpcodeType_ExtendedWidth:
|
||||||
default:
|
default:
|
||||||
/* Unrecognized instruction cannot be decoded. */
|
/* Unrecognized instruction cannot be decoded. */
|
||||||
|
@ -502,26 +550,26 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CheatVmOpcodeType_StoreToRegisterAddress:
|
case CheatVmOpcodeType_StoreStaticToAddress:
|
||||||
{
|
{
|
||||||
/* Calculate address. */
|
/* Calculate address. */
|
||||||
u64 dst_address = this->registers[cur_opcode.str_regaddr.reg_index];
|
u64 dst_address = this->registers[cur_opcode.str_static.reg_index];
|
||||||
u64 dst_value = cur_opcode.str_regaddr.value;
|
u64 dst_value = cur_opcode.str_static.value;
|
||||||
if (cur_opcode.str_regaddr.add_offset_reg) {
|
if (cur_opcode.str_static.add_offset_reg) {
|
||||||
dst_address += this->registers[cur_opcode.str_regaddr.offset_reg_index];
|
dst_address += this->registers[cur_opcode.str_static.offset_reg_index];
|
||||||
}
|
}
|
||||||
/* Write value to memory. Gateway only writes on valid bitwidth. */
|
/* Write value to memory. Gateway only writes on valid bitwidth. */
|
||||||
switch (cur_opcode.str_regaddr.bit_width) {
|
switch (cur_opcode.str_static.bit_width) {
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
case 4:
|
case 4:
|
||||||
case 8:
|
case 8:
|
||||||
DmntCheatManager::WriteCheatProcessMemoryForVm(dst_address, &dst_value, cur_opcode.str_regaddr.bit_width);
|
DmntCheatManager::WriteCheatProcessMemoryForVm(dst_address, &dst_value, cur_opcode.str_static.bit_width);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Increment register if relevant. */
|
/* Increment register if relevant. */
|
||||||
if (cur_opcode.str_regaddr.increment_reg) {
|
if (cur_opcode.str_static.increment_reg) {
|
||||||
this->registers[cur_opcode.str_regaddr.reg_index] += cur_opcode.str_regaddr.bit_width;
|
this->registers[cur_opcode.str_static.reg_index] += cur_opcode.str_static.bit_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -635,6 +683,39 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) {
|
||||||
this->registers[cur_opcode.perform_math_reg.dst_reg_index] = res_val;
|
this->registers[cur_opcode.perform_math_reg.dst_reg_index] = res_val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CheatVmOpcodeType_StoreRegisterToAddress:
|
||||||
|
{
|
||||||
|
/* Calculate address. */
|
||||||
|
u64 dst_value = this->registers[cur_opcode.str_register.str_reg_index];
|
||||||
|
u64 dst_address = this->registers[cur_opcode.str_register.addr_reg_index];
|
||||||
|
switch (cur_opcode.str_register.ofs_type) {
|
||||||
|
case StoreRegisterOffsetType_None:
|
||||||
|
/* Nothing more to do */
|
||||||
|
break;
|
||||||
|
case StoreRegisterOffsetType_Reg:
|
||||||
|
dst_address += this->registers[cur_opcode.str_register.ofs_reg_index];
|
||||||
|
break;
|
||||||
|
case StoreRegisterOffsetType_Imm:
|
||||||
|
dst_address += cur_opcode.str_register.rel_address;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write value to memory. Write only on valid bitwidth. */
|
||||||
|
switch (cur_opcode.str_register.bit_width) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
case 8:
|
||||||
|
DmntCheatManager::WriteCheatProcessMemoryForVm(dst_address, &dst_value, cur_opcode.str_register.bit_width);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increment register if relevant. */
|
||||||
|
if (cur_opcode.str_register.increment_reg) {
|
||||||
|
this->registers[cur_opcode.str_register.addr_reg_index] += cur_opcode.str_register.bit_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* By default, we do a no-op. */
|
/* By default, we do a no-op. */
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -28,12 +28,13 @@ enum CheatVmOpcodeType : u32 {
|
||||||
CheatVmOpcodeType_ControlLoop = 3,
|
CheatVmOpcodeType_ControlLoop = 3,
|
||||||
CheatVmOpcodeType_LoadRegisterStatic = 4,
|
CheatVmOpcodeType_LoadRegisterStatic = 4,
|
||||||
CheatVmOpcodeType_LoadRegisterMemory = 5,
|
CheatVmOpcodeType_LoadRegisterMemory = 5,
|
||||||
CheatVmOpcodeType_StoreToRegisterAddress = 6,
|
CheatVmOpcodeType_StoreStaticToAddress = 6,
|
||||||
CheatVmOpcodeType_PerformArithmeticStatic = 7,
|
CheatVmOpcodeType_PerformArithmeticStatic = 7,
|
||||||
CheatVmOpcodeType_BeginKeypressConditionalBlock = 8,
|
CheatVmOpcodeType_BeginKeypressConditionalBlock = 8,
|
||||||
|
|
||||||
/* These are not implemented by Gateway's VM. */
|
/* These are not implemented by Gateway's VM. */
|
||||||
CheatVmOpcodeType_PerformArithmeticRegister = 9,
|
CheatVmOpcodeType_PerformArithmeticRegister = 9,
|
||||||
|
CheatVmOpcodeType_StoreRegisterToAddress = 10,
|
||||||
|
|
||||||
/* This is a meta entry, and not a real opcode. */
|
/* This is a meta entry, and not a real opcode. */
|
||||||
/* This is to facilitate multi-nybble instruction decoding in the future. */
|
/* This is to facilitate multi-nybble instruction decoding in the future. */
|
||||||
|
@ -70,6 +71,12 @@ enum RegisterArithmeticType : u32 {
|
||||||
RegisterArithmeticType_None = 9,
|
RegisterArithmeticType_None = 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum StoreRegisterOffsetType : u32 {
|
||||||
|
StoreRegisterOffsetType_None = 0,
|
||||||
|
StoreRegisterOffsetType_Reg = 1,
|
||||||
|
StoreRegisterOffsetType_Imm = 2,
|
||||||
|
};
|
||||||
|
|
||||||
union VmInt {
|
union VmInt {
|
||||||
u8 bit8;
|
u8 bit8;
|
||||||
u16 bit16;
|
u16 bit16;
|
||||||
|
@ -114,7 +121,7 @@ struct LoadRegisterMemoryOpcode {
|
||||||
u64 rel_address;
|
u64 rel_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StoreToRegisterAddressOpcode {
|
struct StoreStaticToAddressOpcode {
|
||||||
u32 bit_width;
|
u32 bit_width;
|
||||||
u32 reg_index;
|
u32 reg_index;
|
||||||
bool increment_reg;
|
bool increment_reg;
|
||||||
|
@ -144,6 +151,17 @@ struct PerformArithmeticRegisterOpcode {
|
||||||
VmInt value;
|
VmInt value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct StoreRegisterToAddressOpcode {
|
||||||
|
u32 bit_width;
|
||||||
|
u32 str_reg_index;
|
||||||
|
u32 addr_reg_index;
|
||||||
|
bool increment_reg;
|
||||||
|
StoreRegisterOffsetType ofs_type;
|
||||||
|
u32 ofs_reg_index;
|
||||||
|
u64 rel_address;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct CheatVmOpcode {
|
struct CheatVmOpcode {
|
||||||
CheatVmOpcodeType opcode;
|
CheatVmOpcodeType opcode;
|
||||||
union {
|
union {
|
||||||
|
@ -153,10 +171,11 @@ struct CheatVmOpcode {
|
||||||
ControlLoopOpcode ctrl_loop;
|
ControlLoopOpcode ctrl_loop;
|
||||||
LoadRegisterStaticOpcode ldr_static;
|
LoadRegisterStaticOpcode ldr_static;
|
||||||
LoadRegisterMemoryOpcode ldr_memory;
|
LoadRegisterMemoryOpcode ldr_memory;
|
||||||
StoreToRegisterAddressOpcode str_regaddr;
|
StoreStaticToAddressOpcode str_static;
|
||||||
PerformArithmeticStaticOpcode perform_math_static;
|
PerformArithmeticStaticOpcode perform_math_static;
|
||||||
BeginKeypressConditionalOpcode begin_keypress_cond;
|
BeginKeypressConditionalOpcode begin_keypress_cond;
|
||||||
PerformArithmeticRegisterOpcode perform_math_reg;
|
PerformArithmeticRegisterOpcode perform_math_reg;
|
||||||
|
StoreRegisterToAddressOpcode str_register;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue