From 389c3b6baa36e8e5b7e0430cf618953bef2aca3c Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 21 Jul 2021 19:21:58 -0700 Subject: [PATCH] dmnt: various cheat changes/suggestions that have been cooking a while --- docs/features/cheats.md | 8 +++-- .../libstratosphere/source/dmnt/dmntcht.c | 11 ++++++ .../libstratosphere/source/dmnt/dmntcht.h | 2 ++ .../dmnt/source/cheat/dmnt_cheat_service.cpp | 8 +++++ .../dmnt/source/cheat/dmnt_cheat_service.hpp | 4 +++ .../dmnt/source/cheat/impl/dmnt_cheat_api.cpp | 35 +++++++++++++++++++ .../dmnt/source/cheat/impl/dmnt_cheat_api.hpp | 2 ++ .../dmnt/source/cheat/impl/dmnt_cheat_vm.cpp | 4 +++ .../dmnt/source/cheat/impl/dmnt_cheat_vm.hpp | 4 ++- 9 files changed, 74 insertions(+), 4 deletions(-) diff --git a/docs/features/cheats.md b/docs/features/cheats.md index 2937cd956..aaab58d57 100644 --- a/docs/features/cheats.md +++ b/docs/features/cheats.md @@ -19,6 +19,8 @@ This behavior ensures that cheat codes are only loaded when the user would want In cases where `dmnt` has not activated the cheat manager, but the user wants to make it do so anyway, the cheat manager's service API provides a `ForceOpenCheatProcess` command that homebrew can use. This command will cause the cheat manager to try to force itself to attach to the process. +In cases where `dmnt` has activated the cheat manager, but the user wants to use an alternate debugger, the cheat manager's service API provides a `ForceCloseCheatProcess` command that homebrew can use. This command will cause the cheat manager to detach itself from the process. + By default, all cheat codes listed in the loaded .txt file will be toggled on. This is configurable by the user by editing the `atmosphere!dmnt_cheats_enabled_by_default` [system setting](configurations.md). Users may use homebrew programs to toggle cheats on and off at runtime via the cheat manager's service API. @@ -47,7 +49,7 @@ Code type 0x0 allows writing a static value to a memory address. `0TMR00AA AAAAAAAA VVVVVVVV (VVVVVVVV)` + T: Width of memory write (1, 2, 4, or 8 bytes). -+ M: Memory region to write to (0 = Main NSO, 1 = Heap). ++ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr). + R: Register to use as an offset from memory region base. + A: Immediate offset to use from memory region base. + V: Value to write. @@ -63,7 +65,7 @@ If the condition is not met, all instructions until the appropriate conditional `1TMC00AA AAAAAAAA VVVVVVVV (VVVVVVVV)` + T: Width of memory write (1, 2, 4, or 8 bytes). -+ M: Memory region to write to (0 = Main NSO, 1 = Heap). ++ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr). + C: Condition to use, see below. + A: Immediate offset to use from memory region base. + V: Value to compare to. @@ -120,7 +122,7 @@ Code type 0x5 allows loading a value from memory into a register, either using a `5TMR00AA AAAAAAAA` + T: Width of memory read (1, 2, 4, or 8 bytes). -+ M: Memory region to write to (0 = Main NSO, 1 = Heap). ++ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr). + R: Register to load value into. + A: Immediate offset to use from memory region base. diff --git a/libraries/libstratosphere/source/dmnt/dmntcht.c b/libraries/libstratosphere/source/dmnt/dmntcht.c index dd5faaa12..9fa5e8435 100644 --- a/libraries/libstratosphere/source/dmnt/dmntcht.c +++ b/libraries/libstratosphere/source/dmnt/dmntcht.c @@ -74,6 +74,10 @@ Result dmntchtResumeCheatProcess(void) { return _dmntchtCmdVoid(&g_dmntchtSrv, 65005); } +Result dmntchtForceCloseCheatProcess(void) { + return _dmntchtCmdVoid(&g_dmntchtSrv, 65006); +} + static Result _dmntchtGetCount(u64 *out_count, u32 cmd_id) { return serviceDispatchOut(&g_dmntchtSrv, cmd_id, *out_count); } @@ -171,6 +175,13 @@ Result dmntchtResetStaticRegisters() { return _dmntchtCmdVoid(&g_dmntchtSrv, 65208); } +Result dmntchtSetMasterCheat(DmntCheatDefinition *cheat_def) { + return serviceDispatch(&g_dmntchtSrv, 65209, + .buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias | SfBufferAttr_FixedSize }, + .buffers = { { cheat_def, sizeof(*cheat_def) } }, + ); +} + Result dmntchtGetFrozenAddressCount(u64 *out_count) { return _dmntchtGetCount(out_count, 65300); } diff --git a/libraries/libstratosphere/source/dmnt/dmntcht.h b/libraries/libstratosphere/source/dmnt/dmntcht.h index 62f895736..859297782 100644 --- a/libraries/libstratosphere/source/dmnt/dmntcht.h +++ b/libraries/libstratosphere/source/dmnt/dmntcht.h @@ -66,6 +66,7 @@ Result dmntchtHasCheatProcess(bool *out); Result dmntchtGetCheatProcessEvent(Event *event); Result dmntchtGetCheatProcessMetadata(DmntCheatProcessMetadata *out_metadata); Result dmntchtForceOpenCheatProcess(void); +Result dmntchtForceCloseCheatProcess(void); Result dmntchtGetCheatProcessMappingCount(u64 *out_count); Result dmntchtGetCheatProcessMappings(MemoryInfo *buffer, u64 max_count, u64 offset, u64 *out_count); @@ -84,6 +85,7 @@ Result dmntchtRemoveCheat(u32 cheat_id); Result dmntchtReadStaticRegister(u64 *out, u8 which); Result dmntchtWriteStaticRegister(u8 which, u64 value); Result dmntchtResetStaticRegisters(); +Result dmntchtSetMasterCheat(DmntCheatDefinition *cheat); Result dmntchtGetFrozenAddressCount(u64 *out_count); Result dmntchtGetFrozenAddresses(DmntFrozenAddressEntry *buffer, u64 max_count, u64 offset, u64 *out_count); diff --git a/stratosphere/dmnt/source/cheat/dmnt_cheat_service.cpp b/stratosphere/dmnt/source/cheat/dmnt_cheat_service.cpp index b3856f441..7fa8c24b0 100644 --- a/stratosphere/dmnt/source/cheat/dmnt_cheat_service.cpp +++ b/stratosphere/dmnt/source/cheat/dmnt_cheat_service.cpp @@ -48,6 +48,10 @@ namespace ams::dmnt::cheat { return dmnt::cheat::impl::ResumeCheatProcess(); } + Result CheatService::ForceCloseCheatProcess() { + return dmnt::cheat::impl::ForceCloseCheatProcess(); + } + /* ========================================================================================= */ /* =================================== Memory Commands =================================== */ /* ========================================================================================= */ @@ -116,6 +120,10 @@ namespace ams::dmnt::cheat { return dmnt::cheat::impl::ResetStaticRegisters(); } + Result CheatService::SetMasterCheat(const CheatDefinition &cheat) { + return dmnt::cheat::impl::SetMasterCheat(cheat); + } + /* ========================================================================================= */ /* =================================== Address Commands ================================== */ /* ========================================================================================= */ diff --git a/stratosphere/dmnt/source/cheat/dmnt_cheat_service.hpp b/stratosphere/dmnt/source/cheat/dmnt_cheat_service.hpp index 492368aee..d4d9ab48f 100644 --- a/stratosphere/dmnt/source/cheat/dmnt_cheat_service.hpp +++ b/stratosphere/dmnt/source/cheat/dmnt_cheat_service.hpp @@ -24,6 +24,7 @@ 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, 65006, Result, ForceCloseCheatProcess, (), ()) \ AMS_SF_METHOD_INFO(C, H, 65100, Result, GetCheatProcessMappingCount, (sf::Out out_count), (out_count)) \ AMS_SF_METHOD_INFO(C, H, 65101, Result, GetCheatProcessMappings, (const sf::OutArray &mappings, sf::Out 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)) \ @@ -38,6 +39,7 @@ AMS_SF_METHOD_INFO(C, H, 65206, Result, ReadStaticRegister, (sf::Out 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, 65209, Result, SetMasterCheat, (const dmnt::cheat::CheatDefinition &cheat), (cheat)) \ AMS_SF_METHOD_INFO(C, H, 65300, Result, GetFrozenAddressCount, (sf::Out out_count), (out_count)) \ AMS_SF_METHOD_INFO(C, H, 65301, Result, GetFrozenAddresses, (const sf::OutArray &addresses, sf::Out out_count, u64 offset), (addresses, out_count, offset)) \ AMS_SF_METHOD_INFO(C, H, 65302, Result, GetFrozenAddress, (sf::Out entry, u64 address), (entry, address)) \ @@ -56,6 +58,7 @@ namespace ams::dmnt::cheat { Result ForceOpenCheatProcess(); Result PauseCheatProcess(); Result ResumeCheatProcess(); + Result ForceCloseCheatProcess(); Result GetCheatProcessMappingCount(sf::Out out_count); Result GetCheatProcessMappings(const sf::OutArray &mappings, sf::Out out_count, u64 offset); @@ -72,6 +75,7 @@ namespace ams::dmnt::cheat { Result ReadStaticRegister(sf::Out out, u8 which); Result WriteStaticRegister(u8 which, u64 value); Result ResetStaticRegisters(); + Result SetMasterCheat(const CheatDefinition &cheat); Result GetFrozenAddressCount(sf::Out out_count); Result GetFrozenAddresses(const sf::OutArray &addresses, sf::Out out_count, u64 offset); diff --git a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp index aca817b8c..832ebc0ac 100644 --- a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp +++ b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp @@ -301,6 +301,11 @@ namespace ams::dmnt::cheat::impl { return this->AttachToApplicationProcess(false); } + Result ForceCloseCheatProcess() { + this->CloseActiveCheatProcess(); + return ResultSuccess(); + } + Result ReadCheatProcessMemoryUnsafe(u64 proc_addr, void *out_data, size_t size) { return svcReadDebugProcessMemory(out_data, this->GetCheatProcessHandle(), proc_addr, size); } @@ -520,6 +525,9 @@ namespace ams::dmnt::cheat::impl { /* Trigger a VM reload. */ this->SetNeedsReloadVm(true); + /* Set output id. */ + *out_id = new_entry->cheat_id; + return ResultSuccess(); } @@ -537,6 +545,25 @@ namespace ams::dmnt::cheat::impl { return ResultSuccess(); } + Result SetMasterCheat(const CheatDefinition &def) { + std::scoped_lock lk(this->cheat_lock); + + R_TRY(this->EnsureCheatProcess()); + + R_UNLESS(def.num_opcodes != 0, ResultCheatInvalid()); + R_UNLESS(def.num_opcodes <= util::size(def.opcodes), ResultCheatInvalid()); + + CheatEntry *master_entry = this->cheat_entries + 0; + + master_entry->enabled = true; + master_entry->definition = def; + + /* Trigger a VM reload. */ + this->SetNeedsReloadVm(true); + + return ResultSuccess(); + } + Result ReadStaticRegister(u64 *out, size_t which) { std::scoped_lock lk(this->cheat_lock); @@ -1187,6 +1214,10 @@ namespace ams::dmnt::cheat::impl { return GetReference(g_cheat_process_manager).ResumeCheatProcess(); } + Result ForceCloseCheatProcess() { + return GetReference(g_cheat_process_manager).ForceCloseCheatProcess(); + } + Result ReadCheatProcessMemoryUnsafe(u64 process_addr, void *out_data, size_t size) { return GetReference(g_cheat_process_manager).ReadCheatProcessMemoryUnsafe(process_addr, out_data, size); } @@ -1247,6 +1278,10 @@ namespace ams::dmnt::cheat::impl { return GetReference(g_cheat_process_manager).RemoveCheat(cheat_id); } + Result SetMasterCheat(const CheatDefinition &def) { + return GetReference(g_cheat_process_manager).SetMasterCheat(def); + } + Result ReadStaticRegister(u64 *out, size_t which) { return GetReference(g_cheat_process_manager).ReadStaticRegister(out, which); } diff --git a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.hpp b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.hpp index 0940f2700..7f0196560 100644 --- a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.hpp +++ b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.hpp @@ -26,6 +26,7 @@ namespace ams::dmnt::cheat::impl { Result ForceOpenCheatProcess(); Result PauseCheatProcess(); Result ResumeCheatProcess(); + Result ForceCloseCheatProcess(); Result ReadCheatProcessMemoryUnsafe(u64 process_addr, void *out_data, size_t size); Result WriteCheatProcessMemoryUnsafe(u64 process_addr, void *data, size_t size); @@ -45,6 +46,7 @@ namespace ams::dmnt::cheat::impl { Result ToggleCheat(u32 cheat_id); Result AddCheat(u32 *out_id, const CheatDefinition &def, bool enabled); Result RemoveCheat(u32 cheat_id); + Result SetMasterCheat(const CheatDefinition &def); Result ReadStaticRegister(u64 *out, size_t which); Result WriteStaticRegister(size_t which, u64 value); Result ResetStaticRegisters(); diff --git a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.cpp index 0b521ceea..8d4241b7c 100644 --- a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.cpp @@ -721,6 +721,10 @@ namespace ams::dmnt::cheat::impl { return metadata->main_nso_extents.base + rel_address; case MemoryAccessType_Heap: return metadata->heap_extents.base + rel_address; + case MemoryAccessType_Alias: + return metadata->alias_extents.base + rel_address; + case MemoryAccessType_Aslr: + return metadata->aslr_extents.base + rel_address; } } diff --git a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.hpp index 66dcb6721..3273c4700 100644 --- a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.hpp +++ b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.hpp @@ -56,7 +56,9 @@ namespace ams::dmnt::cheat::impl { enum MemoryAccessType : u32 { MemoryAccessType_MainNso = 0, - MemoryAccessType_Heap = 1, + MemoryAccessType_Heap = 1, + MemoryAccessType_Alias = 2, + MemoryAccessType_Aslr = 3, }; enum ConditionalComparisonType : u32 {