diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index 1a152a7a5..7f42b2369 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -211,6 +211,14 @@ CheatEntry *DmntCheatManager::GetFreeCheatEntry() { return nullptr; } +CheatEntry *DmntCheatManager::GetCheatEntryById(size_t i) { + if (i < DmntCheatManager::MaxCheatCount) { + return &g_cheat_entries[i]; + } + + return nullptr; +} + bool DmntCheatManager::ParseCheats(const char *s, size_t len) { size_t i = 0; CheatEntry *cur_entry = NULL; @@ -352,6 +360,112 @@ bool DmntCheatManager::LoadCheats(u64 title_id, const u8 *build_id) { return ParseCheats(cht_txt, strlen(cht_txt)); } +Result DmntCheatManager::GetCheatCount(u64 *out_count) { + std::scoped_lock lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + *out_count = 0; + for (size_t i = 0; i < DmntCheatManager::MaxCheatCount; i++) { + if (g_cheat_entries[i].definition.num_opcodes > 0) { + *out_count += 1; + } + } + + return 0; +} + +Result DmntCheatManager::GetCheats(CheatEntry *cheats, size_t max_count, u64 *out_count, u64 offset) { + std::scoped_lock lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + u64 count = 0; + *out_count = 0; + for (size_t i = 0; i < DmntCheatManager::MaxCheatCount && (*out_count) < max_count; i++) { + if (g_cheat_entries[i].definition.num_opcodes > 0) { + count++; + if (count > offset) { + cheats[(*out_count)++] = g_cheat_entries[i]; + } + } + } + + return 0; +} + +Result DmntCheatManager::GetCheatById(CheatEntry *out_cheat, u32 cheat_id) { + std::scoped_lock lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + const CheatEntry *entry = GetCheatEntryById(cheat_id); + if (entry == nullptr || entry->definition.num_opcodes == 0) { + return ResultDmntCheatUnknownChtId; + } + + *out_cheat = *entry; + return 0; +} + +Result DmntCheatManager::ToggleCheat(u32 cheat_id) { + std::scoped_lock lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + CheatEntry *entry = GetCheatEntryById(cheat_id); + if (entry == nullptr || entry->definition.num_opcodes == 0) { + return ResultDmntCheatUnknownChtId; + } + + entry->enabled = !entry->enabled; + return 0; +} + +Result DmntCheatManager::AddCheat(u32 *out_id, CheatDefinition *def, bool enabled) { + std::scoped_lock lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + if (def->num_opcodes == 0 || def->num_opcodes > sizeof(def->opcodes)/sizeof(def->opcodes[0])) { + return ResultDmntCheatInvalidCheat; + } + + CheatEntry *new_entry = GetFreeCheatEntry(); + if (new_entry == nullptr) { + return ResultDmntCheatOutOfCheats; + } + + new_entry->enabled = enabled; + new_entry->definition = *def; + return 0; +} + +Result DmntCheatManager::RemoveCheat(u32 cheat_id) { + std::scoped_lock lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + if (cheat_id >= DmntCheatManager::MaxCheatCount) { + return ResultDmntCheatUnknownChtId; + } + + ResetCheatEntry(cheat_id); + return 0; +} + Handle DmntCheatManager::PrepareDebugNextApplication() { Result rc; Handle event_h; diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp index 99ae85b43..2b8a11dcb 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp @@ -36,6 +36,7 @@ class DmntCheatManager { static void ResetCheatEntry(size_t i); static void ResetAllCheatEntries(); static CheatEntry *GetFreeCheatEntry(); + static CheatEntry *GetCheatEntryById(size_t i); static bool ParseCheats(const char *cht_txt, size_t len); static bool LoadCheats(u64 title_id, const u8 *build_id); public: @@ -53,5 +54,12 @@ class DmntCheatManager { static Result WriteCheatProcessMemory(u64 proc_addr, const void *data, size_t size); static Result QueryCheatProcessMemory(MemoryInfo *mapping, u64 address); + static Result GetCheatCount(u64 *out_count); + static Result GetCheats(CheatEntry *cheats, size_t max_count, u64 *out_count, u64 offset); + static Result GetCheatById(CheatEntry *out_cheat, u32 cheat_id); + static Result ToggleCheat(u32 cheat_id); + static Result AddCheat(u32 *out_id, CheatDefinition *def, bool enabled); + static Result RemoveCheat(u32 cheat_id); + static void InitializeCheatManager(); }; diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.cpp b/stratosphere/dmnt/source/dmnt_cheat_service.cpp index 521a12c85..69abea9c8 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.cpp @@ -18,6 +18,10 @@ #include "dmnt_cheat_service.hpp" #include "dmnt_cheat_manager.hpp" +/* ========================================================================================= */ +/* ==================================== Meta Commands ==================================== */ +/* ========================================================================================= */ + void DmntCheatService::HasCheatProcess(Out out) { out.SetValue(DmntCheatManager::GetHasActiveCheatProcess()); } @@ -40,6 +44,9 @@ Result DmntCheatService::ForceOpenCheatProcess() { return rc; } +/* ========================================================================================= */ +/* =================================== Memory Commands =================================== */ +/* ========================================================================================= */ Result DmntCheatService::GetCheatProcessMappingCount(Out out_count) { return DmntCheatManager::GetCheatProcessMappingCount(out_count.GetPointer()); @@ -83,37 +90,57 @@ Result DmntCheatService::QueryCheatProcessMemory(Out mapping, u64 ad return DmntCheatManager::QueryCheatProcessMemory(mapping.GetPointer(), address); } +/* ========================================================================================= */ +/* =================================== Cheat Commands ==================================== */ +/* ========================================================================================= */ Result DmntCheatService::GetCheatCount(Out out_count) { - /* TODO */ - return 0xF601; + return DmntCheatManager::GetCheatCount(out_count.GetPointer()); } Result DmntCheatService::GetCheats(OutBuffer cheats, Out out_count, u64 offset) { - /* TODO */ - return 0xF601; + if (cheats.buffer == nullptr) { + return ResultDmntCheatNullBuffer; + } + + return DmntCheatManager::GetCheats(cheats.buffer, cheats.num_elements, out_count.GetPointer(), offset); } Result DmntCheatService::GetCheatById(OutBuffer cheat, u32 cheat_id) { - /* TODO */ - return 0xF601; + if (cheat.buffer == nullptr) { + return ResultDmntCheatNullBuffer; + } + + if (cheat.num_elements < 1) { + return ResultDmntCheatInvalidBuffer; + } + + return DmntCheatManager::GetCheatById(cheat.buffer, cheat_id); } Result DmntCheatService::ToggleCheat(u32 cheat_id) { - /* TODO */ - return 0xF601; + return DmntCheatManager::ToggleCheat(cheat_id); } Result DmntCheatService::AddCheat(InBuffer cheat, Out out_cheat_id, bool enabled) { - /* TODO */ - return 0xF601; + if (cheat.buffer == nullptr) { + return ResultDmntCheatNullBuffer; + } + + if (cheat.num_elements < 1) { + return ResultDmntCheatInvalidBuffer; + } + + return DmntCheatManager::AddCheat(out_cheat_id.GetPointer(), cheat.buffer, enabled); } Result DmntCheatService::RemoveCheat(u32 cheat_id) { - /* TODO */ - return 0xF601; + return DmntCheatManager::RemoveCheat(cheat_id); } +/* ========================================================================================= */ +/* =================================== Address Commands ================================== */ +/* ========================================================================================= */ Result DmntCheatService::GetFrozenAddressCount(Out out_count) { /* TODO */ diff --git a/stratosphere/dmnt/source/dmnt_results.hpp b/stratosphere/dmnt/source/dmnt_results.hpp index 5be79a674..752e9de07 100644 --- a/stratosphere/dmnt/source/dmnt_results.hpp +++ b/stratosphere/dmnt/source/dmnt_results.hpp @@ -23,5 +23,9 @@ static constexpr u32 Module_Dmnt = 13; static constexpr Result ResultDmntUnknown = MAKERESULT(Module_Dmnt, 1); static constexpr Result ResultDmntDebuggingDisabled = MAKERESULT(Module_Dmnt, 2); -static constexpr Result ResultDmntCheatNotAttached = MAKERESULT(Module_Dmnt, 6500); -static constexpr Result ResultDmntCheatNullBuffer = MAKERESULT(Module_Dmnt, 6501); \ No newline at end of file +static constexpr Result ResultDmntCheatNotAttached = MAKERESULT(Module_Dmnt, 6500); +static constexpr Result ResultDmntCheatNullBuffer = MAKERESULT(Module_Dmnt, 6501); +static constexpr Result ResultDmntCheatInvalidBuffer = MAKERESULT(Module_Dmnt, 6502); +static constexpr Result ResultDmntCheatUnknownChtId = MAKERESULT(Module_Dmnt, 6503); +static constexpr Result ResultDmntCheatOutOfCheats = MAKERESULT(Module_Dmnt, 6504); +static constexpr Result ResultDmntCheatInvalidCheat = MAKERESULT(Module_Dmnt, 6505); \ No newline at end of file