mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-10 07:06:34 +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() {
|
Handle DmntCheatManager::PrepareDebugNextApplication() {
|
||||||
Result rc;
|
Result rc;
|
||||||
Handle event_h;
|
Handle event_h;
|
||||||
|
|
|
@ -30,10 +30,15 @@ class DmntCheatManager {
|
||||||
static bool HasActiveCheatProcess();
|
static bool HasActiveCheatProcess();
|
||||||
static void CloseActiveCheatProcess();
|
static void CloseActiveCheatProcess();
|
||||||
static void ContinueCheatProcess();
|
static void ContinueCheatProcess();
|
||||||
public:;
|
public:
|
||||||
static bool GetHasActiveCheatProcess();
|
static bool GetHasActiveCheatProcess();
|
||||||
static Handle GetCheatProcessEventHandle();
|
static Handle GetCheatProcessEventHandle();
|
||||||
static Result GetCheatProcessMetadata(CheatProcessMetadata *out);
|
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();
|
static void InitializeCheatManager();
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#include "dmnt_cheat_types.hpp"
|
#include "dmnt_cheat_types.hpp"
|
||||||
#include "dmnt_cheat_vm.hpp"
|
#include "dmnt_cheat_vm.hpp"
|
||||||
|
#include "dmnt_cheat_manager.hpp"
|
||||||
|
|
||||||
bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) {
|
bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) {
|
||||||
/* TODO: Parse opcodes */
|
/* 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) {
|
void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) {
|
||||||
CheatVmOpcode cur_opcode;
|
CheatVmOpcode cur_opcode;
|
||||||
u64 kDown = 0;
|
u64 kDown = 0;
|
||||||
|
@ -70,12 +81,59 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) {
|
||||||
switch (cur_opcode.opcode) {
|
switch (cur_opcode.opcode) {
|
||||||
case CheatVmOpcodeType_StoreStatic:
|
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;
|
break;
|
||||||
case CheatVmOpcodeType_BeginConditionalBlock:
|
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;
|
break;
|
||||||
case CheatVmOpcodeType_EndConditionalBlock:
|
case CheatVmOpcodeType_EndConditionalBlock:
|
||||||
|
@ -100,12 +158,45 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) {
|
||||||
break;
|
break;
|
||||||
case CheatVmOpcodeType_LoadRegisterMemory:
|
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;
|
break;
|
||||||
case CheatVmOpcodeType_StoreToRegisterAddress:
|
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;
|
break;
|
||||||
case CheatVmOpcodeType_PerformArithmeticStatic:
|
case CheatVmOpcodeType_PerformArithmeticStatic:
|
||||||
|
|
|
@ -76,7 +76,7 @@ struct StoreStaticOpcode {
|
||||||
u32 bit_width;
|
u32 bit_width;
|
||||||
MemoryAccessType mem_type;
|
MemoryAccessType mem_type;
|
||||||
u32 offset_register;
|
u32 offset_register;
|
||||||
u64 relative_address;
|
u64 rel_address;
|
||||||
VmInt value;
|
VmInt value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ struct BeginConditionalOpcode {
|
||||||
u32 bit_width;
|
u32 bit_width;
|
||||||
MemoryAccessType mem_type;
|
MemoryAccessType mem_type;
|
||||||
ConditionalComparisonType cond_type;
|
ConditionalComparisonType cond_type;
|
||||||
u64 relative_address;
|
u64 rel_address;
|
||||||
VmInt value;
|
VmInt value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ struct LoadRegisterMemoryOpcode {
|
||||||
MemoryAccessType mem_type;
|
MemoryAccessType mem_type;
|
||||||
u32 reg_index;
|
u32 reg_index;
|
||||||
bool load_from_reg;
|
bool load_from_reg;
|
||||||
u64 relative_address;
|
u64 rel_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StoreToRegisterAddressOpcode {
|
struct StoreToRegisterAddressOpcode {
|
||||||
|
@ -170,6 +170,7 @@ class DmntCheatVm {
|
||||||
void SkipConditionalBlock();
|
void SkipConditionalBlock();
|
||||||
|
|
||||||
static u64 GetVmInt(VmInt value, u32 bit_width);
|
static u64 GetVmInt(VmInt value, u32 bit_width);
|
||||||
|
static u64 GetCheatProcessAddress(const CheatProcessMetadata* metadata, MemoryAccessType mem_type, u64 rel_address);
|
||||||
public:
|
public:
|
||||||
DmntCheatVm() { }
|
DmntCheatVm() { }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue