mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
dmnt-cheat: Implement remaining VM opcodes
This commit is contained in:
parent
a3fc2c95b8
commit
bc6ad53018
4 changed files with 135 additions and 8 deletions
|
@ -77,6 +77,36 @@ void DmntCheatManager::ContinueCheatProcess() {
|
|||
}
|
||||
}
|
||||
|
||||
Result DmntCheatManager::ReadCheatProcessMemoryForVm(u64 proc_addr, void *out_data, size_t size) {
|
||||
if (HasActiveCheatProcess()) {
|
||||
return svcReadDebugProcessMemory(out_data, g_cheat_process_debug_hnd, proc_addr, size);
|
||||
}
|
||||
|
||||
/* TODO: Return value... */
|
||||
return 0x20F;
|
||||
}
|
||||
|
||||
Result DmntCheatManager::WriteCheatProcessMemoryForVm(u64 proc_addr, const void *data, size_t size) {
|
||||
if (HasActiveCheatProcess()) {
|
||||
return svcWriteDebugProcessMemory(g_cheat_process_debug_hnd, data, proc_addr, size);
|
||||
}
|
||||
|
||||
/* TODO: Return value... */
|
||||
return 0x20F;
|
||||
}
|
||||
|
||||
Result DmntCheatManager::ReadCheatProcessMemory(u64 proc_addr, void *out_data, size_t size) {
|
||||
std::scoped_lock<HosMutex> lk(g_cheat_lock);
|
||||
|
||||
return ReadCheatProcessMemoryForVm(proc_addr, out_data, size);
|
||||
}
|
||||
|
||||
Result DmntCheatManager::WriteCheatProcessMemory(u64 proc_addr, const void *data, size_t size) {
|
||||
std::scoped_lock<HosMutex> lk(g_cheat_lock);
|
||||
|
||||
return WriteCheatProcessMemoryForVm(proc_addr, data, size);
|
||||
}
|
||||
|
||||
Handle DmntCheatManager::PrepareDebugNextApplication() {
|
||||
Result rc;
|
||||
Handle event_h;
|
||||
|
|
|
@ -30,10 +30,15 @@ class DmntCheatManager {
|
|||
static bool HasActiveCheatProcess();
|
||||
static void CloseActiveCheatProcess();
|
||||
static void ContinueCheatProcess();
|
||||
public:;
|
||||
public:
|
||||
static bool GetHasActiveCheatProcess();
|
||||
static Handle GetCheatProcessEventHandle();
|
||||
static Result GetCheatProcessMetadata(CheatProcessMetadata *out);
|
||||
|
||||
static Result ReadCheatProcessMemoryForVm(u64 proc_addr, void *out_data, size_t size);
|
||||
static Result WriteCheatProcessMemoryForVm(u64 proc_addr, const void *data, size_t size);
|
||||
static Result ReadCheatProcessMemory(u64 proc_addr, void *out_data, size_t size);
|
||||
static Result WriteCheatProcessMemory(u64 proc_addr, const void *data, size_t size);
|
||||
|
||||
static void InitializeCheatManager();
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <switch.h>
|
||||
#include "dmnt_cheat_types.hpp"
|
||||
#include "dmnt_cheat_vm.hpp"
|
||||
#include "dmnt_cheat_manager.hpp"
|
||||
|
||||
bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) {
|
||||
/* TODO: Parse opcodes */
|
||||
|
@ -53,6 +54,16 @@ u64 DmntCheatVm::GetVmInt(VmInt value, u32 bit_width) {
|
|||
}
|
||||
}
|
||||
|
||||
u64 DmntCheatVm::GetCheatProcessAddress(const CheatProcessMetadata* metadata, MemoryAccessType mem_type, u64 rel_address) {
|
||||
switch (mem_type) {
|
||||
case MemoryAccessType_MainNso:
|
||||
default:
|
||||
return metadata->main_nso_extents.base + rel_address;
|
||||
case MemoryAccessType_Heap:
|
||||
return metadata->heap_extents.base + rel_address;
|
||||
}
|
||||
}
|
||||
|
||||
void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) {
|
||||
CheatVmOpcode cur_opcode;
|
||||
u64 kDown = 0;
|
||||
|
@ -70,12 +81,59 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) {
|
|||
switch (cur_opcode.opcode) {
|
||||
case CheatVmOpcodeType_StoreStatic:
|
||||
{
|
||||
/* TODO */
|
||||
/* Calculate address, write value to memory. */
|
||||
u64 dst_address = GetCheatProcessAddress(metadata, cur_opcode.store_static.mem_type, cur_opcode.store_static.rel_address + this->registers[cur_opcode.store_static.offset_register]);
|
||||
u64 dst_value = GetVmInt(cur_opcode.store_static.value, cur_opcode.store_static.bit_width);
|
||||
switch (cur_opcode.store_static.bit_width) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
DmntCheatManager::WriteCheatProcessMemoryForVm(dst_address, &dst_value, cur_opcode.store_static.bit_width);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CheatVmOpcodeType_BeginConditionalBlock:
|
||||
{
|
||||
/* TODO */
|
||||
/* Read value from memory. */
|
||||
u64 src_address = GetCheatProcessAddress(metadata, cur_opcode.begin_cond.mem_type, cur_opcode.begin_cond.rel_address);
|
||||
u64 src_value = 0;
|
||||
switch (cur_opcode.store_static.bit_width) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
DmntCheatManager::ReadCheatProcessMemoryForVm(src_address, &src_value, cur_opcode.begin_cond.bit_width);
|
||||
break;
|
||||
}
|
||||
/* Check against condition. */
|
||||
u64 cond_value = GetVmInt(cur_opcode.begin_cond.value, cur_opcode.begin_cond.bit_width);
|
||||
bool cond_met = false;
|
||||
switch (cur_opcode.begin_cond.cond_type) {
|
||||
case ConditionalComparisonType_GT:
|
||||
cond_met = src_value > cond_value;
|
||||
break;
|
||||
case ConditionalComparisonType_GE:
|
||||
cond_met = src_value >= cond_value;
|
||||
break;
|
||||
case ConditionalComparisonType_LT:
|
||||
cond_met = src_value < cond_value;
|
||||
break;
|
||||
case ConditionalComparisonType_LE:
|
||||
cond_met = src_value <= cond_value;
|
||||
break;
|
||||
case ConditionalComparisonType_EQ:
|
||||
cond_met = src_value == cond_value;
|
||||
break;
|
||||
case ConditionalComparisonType_NE:
|
||||
cond_met = src_value != cond_value;
|
||||
break;
|
||||
}
|
||||
/* Skip conditional block if condition not met. */
|
||||
if (!cond_met) {
|
||||
this->SkipConditionalBlock();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CheatVmOpcodeType_EndConditionalBlock:
|
||||
|
@ -100,12 +158,45 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) {
|
|||
break;
|
||||
case CheatVmOpcodeType_LoadRegisterMemory:
|
||||
{
|
||||
/* TODO */
|
||||
/* Choose source address. */
|
||||
u64 src_address;
|
||||
if (cur_opcode.ldr_memory.load_from_reg) {
|
||||
src_address = this->registers[cur_opcode.ldr_memory.reg_index] + cur_opcode.ldr_memory.rel_address;
|
||||
} else {
|
||||
src_address = GetCheatProcessAddress(metadata, cur_opcode.ldr_memory.mem_type, cur_opcode.ldr_memory.rel_address);
|
||||
}
|
||||
/* Read into register. Gateway only reads on valid bitwidth. */
|
||||
switch (cur_opcode.ldr_memory.bit_width) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
DmntCheatManager::ReadCheatProcessMemoryForVm(src_address, &this->registers[cur_opcode.ldr_memory.reg_index], cur_opcode.ldr_memory.bit_width);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CheatVmOpcodeType_StoreToRegisterAddress:
|
||||
{
|
||||
/* TODO */
|
||||
/* Calculate address. */
|
||||
u64 dst_address = this->registers[cur_opcode.str_regaddr.reg_index];
|
||||
u64 dst_value = cur_opcode.str_regaddr.value;
|
||||
if (cur_opcode.str_regaddr.add_offset_reg) {
|
||||
dst_address += this->registers[cur_opcode.str_regaddr.offset_reg_index];
|
||||
}
|
||||
/* Write value to memory. Gateway only writes on valid bitwidth. */
|
||||
switch (cur_opcode.str_regaddr.bit_width) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
DmntCheatManager::WriteCheatProcessMemoryForVm(dst_address, &dst_value, cur_opcode.str_regaddr.bit_width);
|
||||
break;
|
||||
}
|
||||
/* Increment register if relevant. */
|
||||
if (cur_opcode.str_regaddr.increment_reg) {
|
||||
this->registers[cur_opcode.str_regaddr.reg_index] += cur_opcode.str_regaddr.bit_width;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CheatVmOpcodeType_PerformArithmeticStatic:
|
||||
|
|
|
@ -76,7 +76,7 @@ struct StoreStaticOpcode {
|
|||
u32 bit_width;
|
||||
MemoryAccessType mem_type;
|
||||
u32 offset_register;
|
||||
u64 relative_address;
|
||||
u64 rel_address;
|
||||
VmInt value;
|
||||
};
|
||||
|
||||
|
@ -84,7 +84,7 @@ struct BeginConditionalOpcode {
|
|||
u32 bit_width;
|
||||
MemoryAccessType mem_type;
|
||||
ConditionalComparisonType cond_type;
|
||||
u64 relative_address;
|
||||
u64 rel_address;
|
||||
VmInt value;
|
||||
};
|
||||
|
||||
|
@ -106,7 +106,7 @@ struct LoadRegisterMemoryOpcode {
|
|||
MemoryAccessType mem_type;
|
||||
u32 reg_index;
|
||||
bool load_from_reg;
|
||||
u64 relative_address;
|
||||
u64 rel_address;
|
||||
};
|
||||
|
||||
struct StoreToRegisterAddressOpcode {
|
||||
|
@ -170,6 +170,7 @@ class DmntCheatVm {
|
|||
void SkipConditionalBlock();
|
||||
|
||||
static u64 GetVmInt(VmInt value, u32 bit_width);
|
||||
static u64 GetCheatProcessAddress(const CheatProcessMetadata* metadata, MemoryAccessType mem_type, u64 rel_address);
|
||||
public:
|
||||
DmntCheatVm() { }
|
||||
|
||||
|
|
Loading…
Reference in a new issue