mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-23 04:41:12 +00:00
dmnt-cheat: Implement frozen addresses
This commit is contained in:
parent
7ddb0da5f6
commit
e734a5412a
6 changed files with 175 additions and 13 deletions
|
@ -14,6 +14,7 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#include "dmnt_cheat_manager.hpp"
|
#include "dmnt_cheat_manager.hpp"
|
||||||
#include "dmnt_cheat_vm.hpp"
|
#include "dmnt_cheat_vm.hpp"
|
||||||
|
@ -32,6 +33,9 @@ static Handle g_cheat_process_debug_hnd = 0;
|
||||||
/* Global cheat entry storage. */
|
/* Global cheat entry storage. */
|
||||||
static CheatEntry g_cheat_entries[DmntCheatManager::MaxCheatCount];
|
static CheatEntry g_cheat_entries[DmntCheatManager::MaxCheatCount];
|
||||||
|
|
||||||
|
/* Global frozen address storage. */
|
||||||
|
static std::map<u64, FrozenAddressValue> g_frozen_addresses_map;
|
||||||
|
|
||||||
void DmntCheatManager::CloseActiveCheatProcess() {
|
void DmntCheatManager::CloseActiveCheatProcess() {
|
||||||
if (g_cheat_process_debug_hnd != 0) {
|
if (g_cheat_process_debug_hnd != 0) {
|
||||||
/* Close process resources. */
|
/* Close process resources. */
|
||||||
|
@ -42,6 +46,9 @@ void DmntCheatManager::CloseActiveCheatProcess() {
|
||||||
/* Clear cheat list. */
|
/* Clear cheat list. */
|
||||||
ResetAllCheatEntries();
|
ResetAllCheatEntries();
|
||||||
|
|
||||||
|
/* Clear frozen addresses. */
|
||||||
|
ResetFrozenAddresses();
|
||||||
|
|
||||||
/* Signal to our fans. */
|
/* Signal to our fans. */
|
||||||
g_cheat_process_event->Signal();
|
g_cheat_process_event->Signal();
|
||||||
}
|
}
|
||||||
|
@ -186,6 +193,11 @@ Result DmntCheatManager::QueryCheatProcessMemory(MemoryInfo *mapping, u64 addres
|
||||||
return ResultDmntCheatNotAttached;
|
return ResultDmntCheatNotAttached;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DmntCheatManager::ResetFrozenAddresses() {
|
||||||
|
/* Just clear the map. */
|
||||||
|
g_frozen_addresses_map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void DmntCheatManager::ResetCheatEntry(size_t i) {
|
void DmntCheatManager::ResetCheatEntry(size_t i) {
|
||||||
if (i < DmntCheatManager::MaxCheatCount) {
|
if (i < DmntCheatManager::MaxCheatCount) {
|
||||||
g_cheat_entries[i].enabled = false;
|
g_cheat_entries[i].enabled = false;
|
||||||
|
@ -466,6 +478,102 @@ Result DmntCheatManager::RemoveCheat(u32 cheat_id) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result DmntCheatManager::GetFrozenAddressCount(u64 *out_count) {
|
||||||
|
std::scoped_lock<HosMutex> lk(g_cheat_lock);
|
||||||
|
|
||||||
|
if (!HasActiveCheatProcess()) {
|
||||||
|
return ResultDmntCheatNotAttached;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_count = g_frozen_addresses_map.size();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result DmntCheatManager::GetFrozenAddresses(FrozenAddressEntry *frz_addrs, size_t max_count, u64 *out_count, u64 offset) {
|
||||||
|
std::scoped_lock<HosMutex> lk(g_cheat_lock);
|
||||||
|
|
||||||
|
if (!HasActiveCheatProcess()) {
|
||||||
|
return ResultDmntCheatNotAttached;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 count = 0;
|
||||||
|
*out_count = 0;
|
||||||
|
for (auto const& [address, value] : g_frozen_addresses_map) {
|
||||||
|
if ((*out_count) >= max_count) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
if (count > offset) {
|
||||||
|
const u64 cur_ind = (*out_count)++;
|
||||||
|
frz_addrs[cur_ind].address = address;
|
||||||
|
frz_addrs[cur_ind].value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result DmntCheatManager::GetFrozenAddress(FrozenAddressEntry *frz_addr, u64 address) {
|
||||||
|
std::scoped_lock<HosMutex> lk(g_cheat_lock);
|
||||||
|
|
||||||
|
if (!HasActiveCheatProcess()) {
|
||||||
|
return ResultDmntCheatNotAttached;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto it = g_frozen_addresses_map.find(address);
|
||||||
|
if (it == g_frozen_addresses_map.end()) {
|
||||||
|
return ResultDmntCheatAddressNotFrozen;
|
||||||
|
}
|
||||||
|
|
||||||
|
frz_addr->address = it->first;
|
||||||
|
frz_addr->value = it->second;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result DmntCheatManager::EnableFrozenAddress(u64 address, u64 width) {
|
||||||
|
std::scoped_lock<HosMutex> lk(g_cheat_lock);
|
||||||
|
|
||||||
|
if (!HasActiveCheatProcess()) {
|
||||||
|
return ResultDmntCheatNotAttached;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_frozen_addresses_map.size() >= DmntCheatManager::MaxFrozenAddressCount) {
|
||||||
|
return ResultDmntCheatTooManyFrozenAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto it = g_frozen_addresses_map.find(address);
|
||||||
|
if (it != g_frozen_addresses_map.end()) {
|
||||||
|
return ResultDmntCheatAddressAlreadyFrozen;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result rc;
|
||||||
|
FrozenAddressValue value = {0};
|
||||||
|
value.width = width;
|
||||||
|
if (R_FAILED((rc = ReadCheatProcessMemoryForVm(address, &value.value, width)))) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_frozen_addresses_map[address] = value;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result DmntCheatManager::DisableFrozenAddress(u64 address) {
|
||||||
|
std::scoped_lock<HosMutex> lk(g_cheat_lock);
|
||||||
|
|
||||||
|
if (!HasActiveCheatProcess()) {
|
||||||
|
return ResultDmntCheatNotAttached;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto it = g_frozen_addresses_map.find(address);
|
||||||
|
if (it == g_frozen_addresses_map.end()) {
|
||||||
|
return ResultDmntCheatAddressNotFrozen;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_frozen_addresses_map.erase(address);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Handle DmntCheatManager::PrepareDebugNextApplication() {
|
Handle DmntCheatManager::PrepareDebugNextApplication() {
|
||||||
Result rc;
|
Result rc;
|
||||||
Handle event_h;
|
Handle event_h;
|
||||||
|
@ -691,6 +799,11 @@ void DmntCheatManager::VmThread(void *arg) {
|
||||||
g_cheat_vm->Execute(&g_cheat_process_metadata);
|
g_cheat_vm->Execute(&g_cheat_process_metadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Apply frozen addresses. */
|
||||||
|
for (auto const& [address, value] : g_frozen_addresses_map) {
|
||||||
|
WriteCheatProcessMemoryForVm(address, &value.value, value.width);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
svcSleepThread(0x5000000ul);
|
svcSleepThread(0x5000000ul);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
class DmntCheatManager {
|
class DmntCheatManager {
|
||||||
public:
|
public:
|
||||||
static constexpr size_t MaxCheatCount = 0x80;
|
static constexpr size_t MaxCheatCount = 0x80;
|
||||||
|
static constexpr size_t MaxFrozenAddressCount = 0x80;
|
||||||
private:
|
private:
|
||||||
static Handle PrepareDebugNextApplication();
|
static Handle PrepareDebugNextApplication();
|
||||||
static void OnNewApplicationLaunch();
|
static void OnNewApplicationLaunch();
|
||||||
|
@ -39,6 +40,8 @@ class DmntCheatManager {
|
||||||
static CheatEntry *GetCheatEntryById(size_t i);
|
static CheatEntry *GetCheatEntryById(size_t i);
|
||||||
static bool ParseCheats(const char *cht_txt, size_t len);
|
static bool ParseCheats(const char *cht_txt, size_t len);
|
||||||
static bool LoadCheats(u64 title_id, const u8 *build_id);
|
static bool LoadCheats(u64 title_id, const u8 *build_id);
|
||||||
|
|
||||||
|
static void ResetFrozenAddresses();
|
||||||
public:
|
public:
|
||||||
static bool GetHasActiveCheatProcess();
|
static bool GetHasActiveCheatProcess();
|
||||||
static Handle GetCheatProcessEventHandle();
|
static Handle GetCheatProcessEventHandle();
|
||||||
|
@ -61,5 +64,11 @@ class DmntCheatManager {
|
||||||
static Result AddCheat(u32 *out_id, CheatDefinition *def, bool enabled);
|
static Result AddCheat(u32 *out_id, CheatDefinition *def, bool enabled);
|
||||||
static Result RemoveCheat(u32 cheat_id);
|
static Result RemoveCheat(u32 cheat_id);
|
||||||
|
|
||||||
|
static Result GetFrozenAddressCount(u64 *out_count);
|
||||||
|
static Result GetFrozenAddresses(FrozenAddressEntry *frz_addrs, size_t max_count, u64 *out_count, u64 offset);
|
||||||
|
static Result GetFrozenAddress(FrozenAddressEntry *frz_addr, u64 address);
|
||||||
|
static Result EnableFrozenAddress(u64 address, u64 width);
|
||||||
|
static Result DisableFrozenAddress(u64 address);
|
||||||
|
|
||||||
static void InitializeCheatManager();
|
static void InitializeCheatManager();
|
||||||
};
|
};
|
||||||
|
|
|
@ -143,16 +143,35 @@ Result DmntCheatService::RemoveCheat(u32 cheat_id) {
|
||||||
/* ========================================================================================= */
|
/* ========================================================================================= */
|
||||||
|
|
||||||
Result DmntCheatService::GetFrozenAddressCount(Out<u64> out_count) {
|
Result DmntCheatService::GetFrozenAddressCount(Out<u64> out_count) {
|
||||||
/* TODO */
|
return DmntCheatManager::GetFrozenAddressCount(out_count.GetPointer());
|
||||||
return 0xF601;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DmntCheatService::GetFrozenAddresses(OutBuffer<uintptr_t> addresses, Out<u64> out_count, u64 offset) {
|
Result DmntCheatService::GetFrozenAddresses(OutBuffer<FrozenAddressEntry> frz_addrs, Out<u64> out_count, u64 offset) {
|
||||||
/* TODO */
|
if (frz_addrs.buffer == nullptr) {
|
||||||
return 0xF601;
|
return ResultDmntCheatNullBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DmntCheatService::ToggleAddressFrozen(uintptr_t address) {
|
return DmntCheatManager::GetFrozenAddresses(frz_addrs.buffer, frz_addrs.num_elements, out_count.GetPointer(), offset);
|
||||||
/* TODO */
|
}
|
||||||
return 0xF601;
|
|
||||||
|
Result DmntCheatService::GetFrozenAddress(Out<FrozenAddressEntry> entry, u64 address) {
|
||||||
|
return DmntCheatManager::GetFrozenAddress(entry.GetPointer(), address);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result DmntCheatService::EnableFrozenAddress(u64 address, u64 width) {
|
||||||
|
switch (width) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
case 8:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ResultDmntCheatInvalidFreezeWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DmntCheatManager::EnableFrozenAddress(address, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result DmntCheatService::DisableFrozenAddress(u64 address) {
|
||||||
|
return DmntCheatManager::DisableFrozenAddress(address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,9 @@ enum DmntCheatCmd {
|
||||||
/* Interact with Frozen Addresses */
|
/* Interact with Frozen Addresses */
|
||||||
DmntCheat_Cmd_GetFrozenAddressCount = 65300,
|
DmntCheat_Cmd_GetFrozenAddressCount = 65300,
|
||||||
DmntCheat_Cmd_GetFrozenAddresses = 65301,
|
DmntCheat_Cmd_GetFrozenAddresses = 65301,
|
||||||
DmntCheat_Cmd_ToggleAddressFrozen = 65302,
|
DmntCheat_Cmd_GetFrozenAddress = 65302,
|
||||||
|
DmntCheat_Cmd_EnableFrozenAddress = 65303,
|
||||||
|
DmntCheat_Cmd_DisableFrozenAddress = 65304,
|
||||||
};
|
};
|
||||||
|
|
||||||
class DmntCheatService final : public IServiceObject {
|
class DmntCheatService final : public IServiceObject {
|
||||||
|
@ -69,8 +71,10 @@ class DmntCheatService final : public IServiceObject {
|
||||||
Result RemoveCheat(u32 cheat_id);
|
Result RemoveCheat(u32 cheat_id);
|
||||||
|
|
||||||
Result GetFrozenAddressCount(Out<u64> out_count);
|
Result GetFrozenAddressCount(Out<u64> out_count);
|
||||||
Result GetFrozenAddresses(OutBuffer<uintptr_t> addresses, Out<u64> out_count, u64 offset);
|
Result GetFrozenAddresses(OutBuffer<FrozenAddressEntry> addresses, Out<u64> out_count, u64 offset);
|
||||||
Result ToggleAddressFrozen(uintptr_t address);
|
Result GetFrozenAddress(Out<FrozenAddressEntry> entry, u64 address);
|
||||||
|
Result EnableFrozenAddress(u64 address, u64 width);
|
||||||
|
Result DisableFrozenAddress(u64 address);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||||
|
@ -94,6 +98,8 @@ class DmntCheatService final : public IServiceObject {
|
||||||
|
|
||||||
MakeServiceCommandMeta<DmntCheat_Cmd_GetFrozenAddressCount, &DmntCheatService::GetFrozenAddressCount>(),
|
MakeServiceCommandMeta<DmntCheat_Cmd_GetFrozenAddressCount, &DmntCheatService::GetFrozenAddressCount>(),
|
||||||
MakeServiceCommandMeta<DmntCheat_Cmd_GetFrozenAddresses, &DmntCheatService::GetFrozenAddresses>(),
|
MakeServiceCommandMeta<DmntCheat_Cmd_GetFrozenAddresses, &DmntCheatService::GetFrozenAddresses>(),
|
||||||
MakeServiceCommandMeta<DmntCheat_Cmd_ToggleAddressFrozen, &DmntCheatService::ToggleAddressFrozen>(),
|
MakeServiceCommandMeta<DmntCheat_Cmd_GetFrozenAddress, &DmntCheatService::GetFrozenAddress>(),
|
||||||
|
MakeServiceCommandMeta<DmntCheat_Cmd_EnableFrozenAddress, &DmntCheatService::EnableFrozenAddress>(),
|
||||||
|
MakeServiceCommandMeta<DmntCheat_Cmd_DisableFrozenAddress, &DmntCheatService::DisableFrozenAddress>(),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,3 +46,13 @@ struct CheatEntry {
|
||||||
uint32_t cheat_id;
|
uint32_t cheat_id;
|
||||||
CheatDefinition definition;
|
CheatDefinition definition;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FrozenAddressValue {
|
||||||
|
u64 value;
|
||||||
|
u8 width;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FrozenAddressEntry {
|
||||||
|
u64 address;
|
||||||
|
FrozenAddressValue value;
|
||||||
|
};
|
|
@ -29,3 +29,8 @@ static constexpr Result ResultDmntCheatInvalidBuffer = MAKERESULT(Module_Dmnt, 6
|
||||||
static constexpr Result ResultDmntCheatUnknownChtId = MAKERESULT(Module_Dmnt, 6503);
|
static constexpr Result ResultDmntCheatUnknownChtId = MAKERESULT(Module_Dmnt, 6503);
|
||||||
static constexpr Result ResultDmntCheatOutOfCheats = MAKERESULT(Module_Dmnt, 6504);
|
static constexpr Result ResultDmntCheatOutOfCheats = MAKERESULT(Module_Dmnt, 6504);
|
||||||
static constexpr Result ResultDmntCheatInvalidCheat = MAKERESULT(Module_Dmnt, 6505);
|
static constexpr Result ResultDmntCheatInvalidCheat = MAKERESULT(Module_Dmnt, 6505);
|
||||||
|
|
||||||
|
static constexpr Result ResultDmntCheatInvalidFreezeWidth = MAKERESULT(Module_Dmnt, 6600);
|
||||||
|
static constexpr Result ResultDmntCheatAddressAlreadyFrozen = MAKERESULT(Module_Dmnt, 6601);
|
||||||
|
static constexpr Result ResultDmntCheatAddressNotFrozen = MAKERESULT(Module_Dmnt, 6602);
|
||||||
|
static constexpr Result ResultDmntCheatTooManyFrozenAddresses = MAKERESULT(Module_Dmnt, 6603);
|
Loading…
Reference in a new issue