mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-15 01:26:34 +00:00
dmnt: update for new sf semantics
This commit is contained in:
parent
2d7a85d14f
commit
88a99bc68e
3 changed files with 191 additions and 71 deletions
|
@ -16,43 +16,39 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stratosphere.hpp>
|
#include <stratosphere.hpp>
|
||||||
|
|
||||||
|
/* TODO: In libstratosphere, eventually? */
|
||||||
|
#define AMS_DMNT_I_CHEAT_INTERFACE_INTERFACE_INFO(C, H) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65000, void, HasCheatProcess, (sf::Out<bool> out), (out)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65001, void, GetCheatProcessEvent, (sf::OutCopyHandle out_event), (out_event)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65002, Result, GetCheatProcessMetadata, (sf::Out<dmnt::cheat::CheatProcessMetadata> out_metadata), (out_metadata)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65003, Result, ForceOpenCheatProcess, (), ()) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65004, Result, PauseCheatProcess, (), ()) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65005, Result, ResumeCheatProcess, (), ()) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65100, Result, GetCheatProcessMappingCount, (sf::Out<u64> out_count), (out_count)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65101, Result, GetCheatProcessMappings, (const sf::OutArray<MemoryInfo> &mappings, sf::Out<u64> out_count, u64 offset), (mappings, out_count, offset)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65102, Result, ReadCheatProcessMemory, (const sf::OutBuffer &buffer, u64 address, u64 out_size), (buffer, address, out_size)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65103, Result, WriteCheatProcessMemory, (const sf::InBuffer &buffer, u64 address, u64 in_size), (buffer, address, in_size)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65104, Result, QueryCheatProcessMemory, (sf::Out<MemoryInfo> mapping, u64 address), (mapping, address)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65200, Result, GetCheatCount, (sf::Out<u64> out_count), (out_count)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65201, Result, GetCheats, (const sf::OutArray<dmnt::cheat::CheatEntry> &cheats, sf::Out<u64> out_count, u64 offset), (cheats, out_count, offset)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65202, Result, GetCheatById, (sf::Out<dmnt::cheat::CheatEntry> cheat, u32 cheat_id), (cheat, cheat_id)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65203, Result, ToggleCheat, (u32 cheat_id), (cheat_id)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65204, Result, AddCheat, (const dmnt::cheat::CheatDefinition &cheat, sf::Out<u32> out_cheat_id, bool enabled), (cheat, out_cheat_id, enabled)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65205, Result, RemoveCheat, (u32 cheat_id), (cheat_id)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65206, Result, ReadStaticRegister, (sf::Out<u64> out, u8 which), (out, which)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65207, Result, WriteStaticRegister, (u8 which, u64 value), (which, value)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65208, Result, ResetStaticRegisters, (), ()) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65300, Result, GetFrozenAddressCount, (sf::Out<u64> out_count), (out_count)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65301, Result, GetFrozenAddresses, (const sf::OutArray<dmnt::cheat::FrozenAddressEntry> &addresses, sf::Out<u64> out_count, u64 offset), (addresses, out_count, offset)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65302, Result, GetFrozenAddress, (sf::Out<dmnt::cheat::FrozenAddressEntry> entry, u64 address), (entry, address)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65303, Result, EnableFrozenAddress, (sf::Out<u64> out_value, u64 address, u64 width), (out_value, address, width)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65304, Result, DisableFrozenAddress, (u64 address), (address))
|
||||||
|
|
||||||
|
AMS_SF_DEFINE_INTERFACE(ams::dmnt::cheat::impl, ICheatInterface, AMS_DMNT_I_CHEAT_INTERFACE_INTERFACE_INFO)
|
||||||
|
|
||||||
namespace ams::dmnt::cheat {
|
namespace ams::dmnt::cheat {
|
||||||
|
|
||||||
/* TODO: In libstratosphere, eventually? */
|
class CheatService {
|
||||||
namespace impl {
|
|
||||||
|
|
||||||
#define AMS_DMNT_I_CHEAT_INTERFACE_INTERFACE_INFO(C, H) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65000, void, HasCheatProcess, (sf::Out<bool> out)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65001, void, GetCheatProcessEvent, (sf::OutCopyHandle out_event)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65002, Result, GetCheatProcessMetadata, (sf::Out<CheatProcessMetadata> out_metadata)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65003, Result, ForceOpenCheatProcess, ()) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65004, Result, PauseCheatProcess, ()) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65005, Result, ResumeCheatProcess, ()) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65100, Result, GetCheatProcessMappingCount, (sf::Out<u64> out_count)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65101, Result, GetCheatProcessMappings, (const sf::OutArray<MemoryInfo> &mappings, sf::Out<u64> out_count, u64 offset)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65102, Result, ReadCheatProcessMemory, (const sf::OutBuffer &buffer, u64 address, u64 out_size)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65103, Result, WriteCheatProcessMemory, (const sf::InBuffer &buffer, u64 address, u64 in_size)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65104, Result, QueryCheatProcessMemory, (sf::Out<MemoryInfo> mapping, u64 address)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65200, Result, GetCheatCount, (sf::Out<u64> out_count)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65201, Result, GetCheats, (const sf::OutArray<CheatEntry> &cheats, sf::Out<u64> out_count, u64 offset)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65202, Result, GetCheatById, (sf::Out<CheatEntry> cheat, u32 cheat_id)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65203, Result, ToggleCheat, (u32 cheat_id)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65204, Result, AddCheat, (const CheatDefinition &cheat, sf::Out<u32> out_cheat_id, bool enabled)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65205, Result, RemoveCheat, (u32 cheat_id)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65206, Result, ReadStaticRegister, (sf::Out<u64> out, u8 which)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65207, Result, WriteStaticRegister, (u8 which, u64 value)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65208, Result, ResetStaticRegisters, ()) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65300, Result, GetFrozenAddressCount, (sf::Out<u64> out_count)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65301, Result, GetFrozenAddresses, (const sf::OutArray<FrozenAddressEntry> &addresses, sf::Out<u64> out_count, u64 offset)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65302, Result, GetFrozenAddress, (sf::Out<FrozenAddressEntry> entry, u64 address)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65303, Result, EnableFrozenAddress, (sf::Out<u64> out_value, u64 address, u64 width)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 65304, Result, DisableFrozenAddress, (u64 address))
|
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(ICheatInterface, AMS_DMNT_I_CHEAT_INTERFACE_INTERFACE_INFO)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class CheatService final {
|
|
||||||
public:
|
public:
|
||||||
void HasCheatProcess(sf::Out<bool> out);
|
void HasCheatProcess(sf::Out<bool> out);
|
||||||
void GetCheatProcessEvent(sf::OutCopyHandle out_event);
|
void GetCheatProcessEvent(sf::OutCopyHandle out_event);
|
||||||
|
|
|
@ -26,6 +26,58 @@ namespace ams::dmnt::cheat::impl {
|
||||||
constexpr size_t MaxCheatCount = 0x80;
|
constexpr size_t MaxCheatCount = 0x80;
|
||||||
constexpr size_t MaxFrozenAddressCount = 0x80;
|
constexpr size_t MaxFrozenAddressCount = 0x80;
|
||||||
|
|
||||||
|
class FrozenAddressMapEntry : public util::IntrusiveRedBlackTreeBaseNode<FrozenAddressMapEntry> {
|
||||||
|
public:
|
||||||
|
using LightCompareType = u64;
|
||||||
|
private:
|
||||||
|
u64 m_address;
|
||||||
|
FrozenAddressValue m_value;
|
||||||
|
public:
|
||||||
|
constexpr FrozenAddressMapEntry(u64 address, FrozenAddressValue value) : m_address(address), m_value(value) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr u64 GetAddress() const { return m_address; }
|
||||||
|
|
||||||
|
constexpr const FrozenAddressValue &GetValue() const { return m_value; }
|
||||||
|
constexpr FrozenAddressValue &GetValue() { return m_value; }
|
||||||
|
|
||||||
|
static constexpr ALWAYS_INLINE int Compare(const LightCompareType &lval, const FrozenAddressMapEntry &rhs) {
|
||||||
|
const auto rval = rhs.GetAddress();
|
||||||
|
|
||||||
|
if (lval < rval) {
|
||||||
|
return -1;
|
||||||
|
} else if (lval == rval) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr ALWAYS_INLINE int Compare(const FrozenAddressMapEntry &lhs, const FrozenAddressMapEntry &rhs) {
|
||||||
|
return Compare(lhs.GetAddress(), rhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constinit os::SdkMutex g_text_file_buffer_lock;
|
||||||
|
constinit char g_text_file_buffer[64_KB];
|
||||||
|
|
||||||
|
constinit u8 g_frozen_address_map_memory[sizeof(FrozenAddressMapEntry) * MaxFrozenAddressCount];
|
||||||
|
constinit lmem::HeapHandle g_frozen_address_map_heap;
|
||||||
|
|
||||||
|
FrozenAddressMapEntry *AllocateFrozenAddress(u64 address, FrozenAddressValue value) {
|
||||||
|
FrozenAddressMapEntry *entry = static_cast<FrozenAddressMapEntry *>(lmem::AllocateFromUnitHeap(g_frozen_address_map_heap));
|
||||||
|
if (entry != nullptr) {
|
||||||
|
new (entry) FrozenAddressMapEntry(address, value);
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeallocateFrozenAddress(FrozenAddressMapEntry *entry) {
|
||||||
|
entry->~FrozenAddressMapEntry();
|
||||||
|
lmem::FreeToUnitHeap(g_frozen_address_map_heap, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
using FrozenAddressMap = typename util::IntrusiveRedBlackTreeBaseTraits<FrozenAddressMapEntry>::TreeType<FrozenAddressMapEntry>;
|
||||||
|
|
||||||
/* Manager class. */
|
/* Manager class. */
|
||||||
class CheatProcessManager {
|
class CheatProcessManager {
|
||||||
private:
|
private:
|
||||||
|
@ -48,7 +100,7 @@ namespace ams::dmnt::cheat::impl {
|
||||||
bool always_save_cheat_toggles = false;
|
bool always_save_cheat_toggles = false;
|
||||||
bool should_save_cheat_toggles = false;
|
bool should_save_cheat_toggles = false;
|
||||||
CheatEntry cheat_entries[MaxCheatCount] = {};
|
CheatEntry cheat_entries[MaxCheatCount] = {};
|
||||||
std::map<u64, FrozenAddressValue> frozen_addresses_map;
|
FrozenAddressMap frozen_addresses_map = {};
|
||||||
|
|
||||||
alignas(os::MemoryPageSize) u8 detect_thread_stack[ThreadStackSize] = {};
|
alignas(os::MemoryPageSize) u8 detect_thread_stack[ThreadStackSize] = {};
|
||||||
alignas(os::MemoryPageSize) u8 debug_events_thread_stack[ThreadStackSize] = {};
|
alignas(os::MemoryPageSize) u8 debug_events_thread_stack[ThreadStackSize] = {};
|
||||||
|
@ -149,7 +201,14 @@ namespace ams::dmnt::cheat::impl {
|
||||||
this->ResetAllCheatEntries();
|
this->ResetAllCheatEntries();
|
||||||
|
|
||||||
/* Clear frozen addresses. */
|
/* Clear frozen addresses. */
|
||||||
this->frozen_addresses_map.clear();
|
{
|
||||||
|
auto it = this->frozen_addresses_map.begin();
|
||||||
|
while (it != this->frozen_addresses_map.end()) {
|
||||||
|
FrozenAddressMapEntry *entry = std::addressof(*it);
|
||||||
|
it = this->frozen_addresses_map.erase(it);
|
||||||
|
DeallocateFrozenAddress(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Signal to our fans. */
|
/* Signal to our fans. */
|
||||||
this->cheat_process_event.Signal();
|
this->cheat_process_event.Signal();
|
||||||
|
@ -249,7 +308,11 @@ namespace ams::dmnt::cheat::impl {
|
||||||
Result WriteCheatProcessMemoryUnsafe(u64 proc_addr, const void *data, size_t size) {
|
Result WriteCheatProcessMemoryUnsafe(u64 proc_addr, const void *data, size_t size) {
|
||||||
R_TRY(svcWriteDebugProcessMemory(this->GetCheatProcessHandle(), data, proc_addr, size));
|
R_TRY(svcWriteDebugProcessMemory(this->GetCheatProcessHandle(), data, proc_addr, size));
|
||||||
|
|
||||||
for (auto& [address, value] : this->frozen_addresses_map) {
|
for (auto &entry : this->frozen_addresses_map) {
|
||||||
|
/* Get address/value. */
|
||||||
|
const u64 address = entry.GetAddress();
|
||||||
|
auto &value = entry.GetValue();
|
||||||
|
|
||||||
/* Map is ordered, so break when we can. */
|
/* Map is ordered, so break when we can. */
|
||||||
if (address >= proc_addr + size) {
|
if (address >= proc_addr + size) {
|
||||||
break;
|
break;
|
||||||
|
@ -508,7 +571,7 @@ namespace ams::dmnt::cheat::impl {
|
||||||
|
|
||||||
R_TRY(this->EnsureCheatProcess());
|
R_TRY(this->EnsureCheatProcess());
|
||||||
|
|
||||||
*out_count = this->frozen_addresses_map.size();
|
*out_count = std::distance(this->frozen_addresses_map.begin(), this->frozen_addresses_map.end());
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,14 +581,14 @@ namespace ams::dmnt::cheat::impl {
|
||||||
R_TRY(this->EnsureCheatProcess());
|
R_TRY(this->EnsureCheatProcess());
|
||||||
|
|
||||||
u64 total_count = 0, written_count = 0;
|
u64 total_count = 0, written_count = 0;
|
||||||
for (auto const& [address, value] : this->frozen_addresses_map) {
|
for (const auto &entry : this->frozen_addresses_map) {
|
||||||
if (written_count >= max_count) {
|
if (written_count >= max_count) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset <= total_count) {
|
if (offset <= total_count) {
|
||||||
frz_addrs[written_count].address = address;
|
frz_addrs[written_count].address = entry.GetAddress();
|
||||||
frz_addrs[written_count].value = value;
|
frz_addrs[written_count].value = entry.GetValue();
|
||||||
written_count++;
|
written_count++;
|
||||||
}
|
}
|
||||||
total_count++;
|
total_count++;
|
||||||
|
@ -540,11 +603,11 @@ namespace ams::dmnt::cheat::impl {
|
||||||
|
|
||||||
R_TRY(this->EnsureCheatProcess());
|
R_TRY(this->EnsureCheatProcess());
|
||||||
|
|
||||||
const auto it = this->frozen_addresses_map.find(address);
|
const auto it = this->frozen_addresses_map.find_light(address);
|
||||||
R_UNLESS(it != this->frozen_addresses_map.end(), ResultFrozenAddressNotFound());
|
R_UNLESS(it != this->frozen_addresses_map.end(), ResultFrozenAddressNotFound());
|
||||||
|
|
||||||
frz_addr->address = it->first;
|
frz_addr->address = it->GetAddress();
|
||||||
frz_addr->value = it->second;
|
frz_addr->value = it->GetValue();
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,16 +616,17 @@ namespace ams::dmnt::cheat::impl {
|
||||||
|
|
||||||
R_TRY(this->EnsureCheatProcess());
|
R_TRY(this->EnsureCheatProcess());
|
||||||
|
|
||||||
R_UNLESS(this->frozen_addresses_map.size() < MaxFrozenAddressCount, ResultFrozenAddressOutOfResource());
|
const auto it = this->frozen_addresses_map.find_light(address);
|
||||||
|
|
||||||
const auto it = this->frozen_addresses_map.find(address);
|
|
||||||
R_UNLESS(it == this->frozen_addresses_map.end(), ResultFrozenAddressAlreadyExists());
|
R_UNLESS(it == this->frozen_addresses_map.end(), ResultFrozenAddressAlreadyExists());
|
||||||
|
|
||||||
FrozenAddressValue value = {};
|
FrozenAddressValue value = {};
|
||||||
value.width = width;
|
value.width = width;
|
||||||
R_TRY(this->ReadCheatProcessMemoryUnsafe(address, &value.value, width));
|
R_TRY(this->ReadCheatProcessMemoryUnsafe(address, &value.value, width));
|
||||||
|
|
||||||
this->frozen_addresses_map[address] = value;
|
FrozenAddressMapEntry *entry = AllocateFrozenAddress(address, value);
|
||||||
|
R_UNLESS(entry != nullptr, ResultFrozenAddressOutOfResource());
|
||||||
|
|
||||||
|
this->frozen_addresses_map.insert(*entry);
|
||||||
*out_value = value.value;
|
*out_value = value.value;
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -572,10 +636,13 @@ namespace ams::dmnt::cheat::impl {
|
||||||
|
|
||||||
R_TRY(this->EnsureCheatProcess());
|
R_TRY(this->EnsureCheatProcess());
|
||||||
|
|
||||||
const auto it = this->frozen_addresses_map.find(address);
|
const auto it = this->frozen_addresses_map.find_light(address);
|
||||||
R_UNLESS(it != this->frozen_addresses_map.end(), ResultFrozenAddressNotFound());
|
R_UNLESS(it != this->frozen_addresses_map.end(), ResultFrozenAddressNotFound());
|
||||||
|
|
||||||
|
FrozenAddressMapEntry *entry = std::addressof(*it);
|
||||||
this->frozen_addresses_map.erase(it);
|
this->frozen_addresses_map.erase(it);
|
||||||
|
DeallocateFrozenAddress(entry);
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,7 +726,10 @@ namespace ams::dmnt::cheat::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply frozen addresses. */
|
/* Apply frozen addresses. */
|
||||||
for (auto const& [address, value] : this_ptr->frozen_addresses_map) {
|
for (const auto &entry : this_ptr->frozen_addresses_map) {
|
||||||
|
const auto address = entry.GetAddress();
|
||||||
|
const auto &value = entry.GetValue();
|
||||||
|
|
||||||
/* Use Write SVC directly, to avoid the usual frozen address update logic. */
|
/* Use Write SVC directly, to avoid the usual frozen address update logic. */
|
||||||
svcWriteDebugProcessMemory(this_ptr->GetCheatProcessHandle(), &value.value, address, value.width);
|
svcWriteDebugProcessMemory(this_ptr->GetCheatProcessHandle(), &value.value, address, value.width);
|
||||||
}
|
}
|
||||||
|
@ -983,22 +1053,20 @@ namespace ams::dmnt::cheat::impl {
|
||||||
if (R_FAILED(fs::GetFileSize(std::addressof(file_size), file))) {
|
if (R_FAILED(fs::GetFileSize(std::addressof(file_size), file))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (file_size < 0 || file_size >= static_cast<s64>(sizeof(g_text_file_buffer))) {
|
||||||
/* Allocate cheat txt buffer. */
|
|
||||||
char *cht_txt = static_cast<char *>(std::malloc(file_size + 1));
|
|
||||||
if (cht_txt == nullptr) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT { std::free(cht_txt); };
|
|
||||||
|
std::scoped_lock lk(g_text_file_buffer_lock);
|
||||||
|
|
||||||
/* Read cheats into buffer. */
|
/* Read cheats into buffer. */
|
||||||
if (R_FAILED(fs::ReadFile(file, 0, cht_txt, file_size))) {
|
if (R_FAILED(fs::ReadFile(file, 0, g_text_file_buffer, file_size))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cht_txt[file_size] = '\x00';
|
g_text_file_buffer[file_size] = '\x00';
|
||||||
|
|
||||||
/* Parse cheat buffer. */
|
/* Parse cheat buffer. */
|
||||||
return this->ParseCheats(cht_txt, std::strlen(cht_txt));
|
return this->ParseCheats(g_text_file_buffer, std::strlen(g_text_file_buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheatProcessManager::LoadCheatToggles(const ncm::ProgramId program_id) {
|
bool CheatProcessManager::LoadCheatToggles(const ncm::ProgramId program_id) {
|
||||||
|
@ -1022,22 +1090,20 @@ namespace ams::dmnt::cheat::impl {
|
||||||
if (R_FAILED(fs::GetFileSize(std::addressof(file_size), file))) {
|
if (R_FAILED(fs::GetFileSize(std::addressof(file_size), file))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (file_size < 0 || file_size >= static_cast<s64>(sizeof(g_text_file_buffer))) {
|
||||||
/* Allocate toggle txt buffer. */
|
|
||||||
char *tg_txt = static_cast<char *>(std::malloc(file_size + 1));
|
|
||||||
if (tg_txt == nullptr) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT { std::free(tg_txt); };
|
|
||||||
|
std::scoped_lock lk(g_text_file_buffer_lock);
|
||||||
|
|
||||||
/* Read cheats into buffer. */
|
/* Read cheats into buffer. */
|
||||||
if (R_FAILED(fs::ReadFile(file, 0, tg_txt, file_size))) {
|
if (R_FAILED(fs::ReadFile(file, 0, g_text_file_buffer, file_size))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
tg_txt[file_size] = '\x00';
|
g_text_file_buffer[file_size] = '\x00';
|
||||||
|
|
||||||
/* Parse toggle buffer. */
|
/* Parse toggle buffer. */
|
||||||
this->should_save_cheat_toggles = this->ParseCheatToggles(tg_txt, std::strlen(tg_txt));
|
this->should_save_cheat_toggles = this->ParseCheatToggles(g_text_file_buffer, std::strlen(g_text_file_buffer));
|
||||||
return this->should_save_cheat_toggles;
|
return this->should_save_cheat_toggles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1086,6 +1152,9 @@ namespace ams::dmnt::cheat::impl {
|
||||||
/* Initialize the debug events manager (spawning its threads). */
|
/* Initialize the debug events manager (spawning its threads). */
|
||||||
InitializeDebugEventsManager();
|
InitializeDebugEventsManager();
|
||||||
|
|
||||||
|
/* Initialize the frozen address map heap. */
|
||||||
|
g_frozen_address_map_heap = lmem::CreateUnitHeap(g_frozen_address_map_memory, sizeof(g_frozen_address_map_memory), sizeof(FrozenAddressMapEntry), lmem::CreateOption_ThreadSafe);
|
||||||
|
|
||||||
/* Create the cheat process manager (spawning its threads). */
|
/* Create the cheat process manager (spawning its threads). */
|
||||||
new (GetPointer(g_cheat_process_manager)) CheatProcessManager;
|
new (GetPointer(g_cheat_process_manager)) CheatProcessManager;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,14 +24,16 @@ extern "C" {
|
||||||
u32 __nx_applet_type = AppletType_None;
|
u32 __nx_applet_type = AppletType_None;
|
||||||
u32 __nx_fs_num_sessions = 1;
|
u32 __nx_fs_num_sessions = 1;
|
||||||
|
|
||||||
/* TODO: Evaluate how much this can be reduced by. */
|
#define INNER_HEAP_SIZE 0x0
|
||||||
#define INNER_HEAP_SIZE 0x20000
|
|
||||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||||
|
|
||||||
void __libnx_initheap(void);
|
void __libnx_initheap(void);
|
||||||
void __appInit(void);
|
void __appInit(void);
|
||||||
void __appExit(void);
|
void __appExit(void);
|
||||||
|
|
||||||
|
void *__libnx_thread_alloc(size_t size);
|
||||||
|
void __libnx_thread_free(void *mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ams {
|
namespace ams {
|
||||||
|
@ -60,9 +62,32 @@ void __libnx_initheap(void) {
|
||||||
fake_heap_end = (char*)addr + size;
|
fake_heap_end = (char*)addr + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
|
||||||
|
constinit u8 g_fs_heap_memory[4_KB];
|
||||||
|
lmem::HeapHandle g_fs_heap_handle;
|
||||||
|
|
||||||
|
void *AllocateForFs(size_t size) {
|
||||||
|
return lmem::AllocateFromExpHeap(g_fs_heap_handle, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeallocateForFs(void *p, size_t size) {
|
||||||
|
return lmem::FreeToExpHeap(g_fs_heap_handle, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeFsHeap() {
|
||||||
|
g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap_memory, sizeof(g_fs_heap_memory), lmem::CreateOption_None);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void __appInit(void) {
|
void __appInit(void) {
|
||||||
hos::InitializeForStratosphere();
|
hos::InitializeForStratosphere();
|
||||||
|
|
||||||
|
InitializeFsHeap();
|
||||||
|
fs::SetAllocator(AllocateForFs, DeallocateForFs);
|
||||||
|
|
||||||
sm::DoWithSession([&]() {
|
sm::DoWithSession([&]() {
|
||||||
R_ABORT_UNLESS(pmdmntInitialize());
|
R_ABORT_UNLESS(pmdmntInitialize());
|
||||||
R_ABORT_UNLESS(pminfoInitialize());
|
R_ABORT_UNLESS(pminfoInitialize());
|
||||||
|
@ -114,6 +139,8 @@ namespace {
|
||||||
|
|
||||||
sf::hipc::ServerManager<NumServers, ServerOptions, NumSessions> g_server_manager;
|
sf::hipc::ServerManager<NumServers, ServerOptions, NumSessions> g_server_manager;
|
||||||
|
|
||||||
|
constinit sf::UnmanagedServiceObject<dmnt::cheat::impl::ICheatInterface, dmnt::cheat::CheatService> g_cheat_service;
|
||||||
|
|
||||||
void LoopServerThread(void *arg) {
|
void LoopServerThread(void *arg) {
|
||||||
g_server_manager.LoopProcess();
|
g_server_manager.LoopProcess();
|
||||||
}
|
}
|
||||||
|
@ -128,6 +155,34 @@ namespace {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ams {
|
||||||
|
|
||||||
|
void *Malloc(size_t size) {
|
||||||
|
AMS_ABORT("ams::Malloc was called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free(void *ptr) {
|
||||||
|
AMS_ABORT("ams::Free was called");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void *operator new(size_t size) {
|
||||||
|
AMS_ABORT("operator new(size_t) was called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void *p) {
|
||||||
|
AMS_ABORT("operator delete(void *) was called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void *__libnx_thread_alloc(size_t size) {
|
||||||
|
AMS_ABORT("__libnx_thread_alloc was called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void __libnx_thread_free(void *mem) {
|
||||||
|
AMS_ABORT("__libnx_thread_free was called");
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
/* Set thread name. */
|
/* Set thread name. */
|
||||||
|
@ -139,8 +194,8 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
/* Create services. */
|
/* Create services. */
|
||||||
/* TODO: Implement rest of dmnt:- in ams.tma development branch. */
|
/* TODO: Implement rest of dmnt:- in ams.tma development branch. */
|
||||||
/* R_ABORT_UNLESS((g_server_manager.RegisterServer<dmnt::cheat::CheatService>(DebugMonitorServiceName, DebugMonitorMaxSessions))); */
|
/* TODO: register debug service */
|
||||||
R_ABORT_UNLESS((g_server_manager.RegisterServer<dmnt::cheat::impl::ICheatInterface, dmnt::cheat::CheatService>(CheatServiceName, CheatMaxSessions)));
|
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_cheat_service.GetShared(), CheatServiceName, CheatMaxSessions));
|
||||||
|
|
||||||
/* Loop forever, servicing our services. */
|
/* Loop forever, servicing our services. */
|
||||||
/* Nintendo loops four threads processing on the manager -- we'll loop an extra fifth for our cheat service. */
|
/* Nintendo loops four threads processing on the manager -- we'll loop an extra fifth for our cheat service. */
|
||||||
|
|
Loading…
Reference in a new issue