Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"

This reverts commit 15b7df8ef1.
This commit is contained in:
souldbminersmwc
2025-11-09 16:14:52 -05:00
parent 22ec140738
commit 21a3f953d7
3804 changed files with 435 additions and 570162 deletions

View File

@@ -1,156 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "dmnt_cheat_service.hpp"
#include "impl/dmnt_cheat_api.hpp"
namespace ams::dmnt::cheat {
/* ========================================================================================= */
/* ==================================== Meta Commands ==================================== */
/* ========================================================================================= */
void CheatService::HasCheatProcess(sf::Out<bool> out) {
out.SetValue(dmnt::cheat::impl::GetHasActiveCheatProcess());
}
void CheatService::GetCheatProcessEvent(sf::OutCopyHandle out_event) {
out_event.SetValue(dmnt::cheat::impl::GetCheatProcessEventHandle(), false);
}
Result CheatService::GetCheatProcessMetadata(sf::Out<CheatProcessMetadata> out_metadata) {
R_RETURN(dmnt::cheat::impl::GetCheatProcessMetadata(out_metadata.GetPointer()));
}
Result CheatService::ForceOpenCheatProcess() {
R_UNLESS(R_SUCCEEDED(dmnt::cheat::impl::ForceOpenCheatProcess()), dmnt::cheat::ResultCheatNotAttached());
R_SUCCEED();
}
Result CheatService::PauseCheatProcess() {
R_RETURN(dmnt::cheat::impl::PauseCheatProcess());
}
Result CheatService::ResumeCheatProcess() {
R_RETURN(dmnt::cheat::impl::ResumeCheatProcess());
}
Result CheatService::ForceCloseCheatProcess() {
R_RETURN(dmnt::cheat::impl::ForceCloseCheatProcess());
}
/* ========================================================================================= */
/* =================================== Memory Commands =================================== */
/* ========================================================================================= */
Result CheatService::GetCheatProcessMappingCount(sf::Out<u64> out_count) {
R_RETURN(dmnt::cheat::impl::GetCheatProcessMappingCount(out_count.GetPointer()));
}
Result CheatService::GetCheatProcessMappings(const sf::OutArray<svc::MemoryInfo> &mappings, sf::Out<u64> out_count, u64 offset) {
R_UNLESS(mappings.GetPointer() != nullptr, dmnt::cheat::ResultCheatNullBuffer());
R_RETURN(dmnt::cheat::impl::GetCheatProcessMappings(mappings.GetPointer(), mappings.GetSize(), out_count.GetPointer(), offset));
}
Result CheatService::ReadCheatProcessMemory(const sf::OutBuffer &buffer, u64 address, u64 out_size) {
R_UNLESS(buffer.GetPointer() != nullptr, dmnt::cheat::ResultCheatNullBuffer());
R_RETURN(dmnt::cheat::impl::ReadCheatProcessMemory(address, buffer.GetPointer(), std::min(out_size, buffer.GetSize())));
}
Result CheatService::WriteCheatProcessMemory(const sf::InBuffer &buffer, u64 address, u64 in_size) {
R_UNLESS(buffer.GetPointer() != nullptr, dmnt::cheat::ResultCheatNullBuffer());
R_RETURN(dmnt::cheat::impl::WriteCheatProcessMemory(address, buffer.GetPointer(), std::min(in_size, buffer.GetSize())));
}
Result CheatService::QueryCheatProcessMemory(sf::Out<svc::MemoryInfo> mapping, u64 address) {
R_RETURN(dmnt::cheat::impl::QueryCheatProcessMemory(mapping.GetPointer(), address));
}
/* ========================================================================================= */
/* =================================== Cheat Commands ==================================== */
/* ========================================================================================= */
Result CheatService::GetCheatCount(sf::Out<u64> out_count) {
R_RETURN(dmnt::cheat::impl::GetCheatCount(out_count.GetPointer()));
}
Result CheatService::GetCheats(const sf::OutArray<CheatEntry> &cheats, sf::Out<u64> out_count, u64 offset) {
R_UNLESS(cheats.GetPointer() != nullptr, dmnt::cheat::ResultCheatNullBuffer());
R_RETURN(dmnt::cheat::impl::GetCheats(cheats.GetPointer(), cheats.GetSize(), out_count.GetPointer(), offset));
}
Result CheatService::GetCheatById(sf::Out<CheatEntry> cheat, u32 cheat_id) {
R_RETURN(dmnt::cheat::impl::GetCheatById(cheat.GetPointer(), cheat_id));
}
Result CheatService::ToggleCheat(u32 cheat_id) {
R_RETURN(dmnt::cheat::impl::ToggleCheat(cheat_id));
}
Result CheatService::AddCheat(const CheatDefinition &cheat, sf::Out<u32> out_cheat_id, bool enabled) {
R_RETURN(dmnt::cheat::impl::AddCheat(out_cheat_id.GetPointer(), cheat, enabled));
}
Result CheatService::RemoveCheat(u32 cheat_id) {
R_RETURN(dmnt::cheat::impl::RemoveCheat(cheat_id));
}
Result CheatService::ReadStaticRegister(sf::Out<u64> out, u8 which) {
R_RETURN(dmnt::cheat::impl::ReadStaticRegister(out.GetPointer(), which));
}
Result CheatService::WriteStaticRegister(u8 which, u64 value) {
R_RETURN(dmnt::cheat::impl::WriteStaticRegister(which, value));
}
Result CheatService::ResetStaticRegisters() {
R_RETURN(dmnt::cheat::impl::ResetStaticRegisters());
}
Result CheatService::SetMasterCheat(const CheatDefinition &cheat) {
R_RETURN(dmnt::cheat::impl::SetMasterCheat(cheat));
}
/* ========================================================================================= */
/* =================================== Address Commands ================================== */
/* ========================================================================================= */
Result CheatService::GetFrozenAddressCount(sf::Out<u64> out_count) {
R_RETURN(dmnt::cheat::impl::GetFrozenAddressCount(out_count.GetPointer()));
}
Result CheatService::GetFrozenAddresses(const sf::OutArray<FrozenAddressEntry> &addresses, sf::Out<u64> out_count, u64 offset) {
R_UNLESS(addresses.GetPointer() != nullptr, dmnt::cheat::ResultCheatNullBuffer());
R_RETURN(dmnt::cheat::impl::GetFrozenAddresses(addresses.GetPointer(), addresses.GetSize(), out_count.GetPointer(), offset));
}
Result CheatService::GetFrozenAddress(sf::Out<FrozenAddressEntry> entry, u64 address) {
R_RETURN(dmnt::cheat::impl::GetFrozenAddress(entry.GetPointer(), address));
}
Result CheatService::EnableFrozenAddress(sf::Out<u64> out_value, u64 address, u64 width) {
/* Width needs to be a power of two <= 8. */
R_UNLESS(width > 0, dmnt::cheat::ResultFrozenAddressInvalidWidth());
R_UNLESS(width <= sizeof(u64), dmnt::cheat::ResultFrozenAddressInvalidWidth());
R_UNLESS((width & (width - 1)) == 0, dmnt::cheat::ResultFrozenAddressInvalidWidth());
R_RETURN(dmnt::cheat::impl::EnableFrozenAddress(out_value.GetPointer(), address, width));
}
Result CheatService::DisableFrozenAddress(u64 address) {
R_RETURN(dmnt::cheat::impl::DisableFrozenAddress(address));
}
}

View File

@@ -1,88 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#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, 65006, Result, ForceCloseCheatProcess, (), ()) \
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<svc::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<svc::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, 65209, Result, SetMasterCheat, (const dmnt::cheat::CheatDefinition &cheat), (cheat)) \
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, 0x00000000)
namespace ams::dmnt::cheat {
class CheatService {
public:
void HasCheatProcess(sf::Out<bool> out);
void GetCheatProcessEvent(sf::OutCopyHandle out_event);
Result GetCheatProcessMetadata(sf::Out<CheatProcessMetadata> out_metadata);
Result ForceOpenCheatProcess();
Result PauseCheatProcess();
Result ResumeCheatProcess();
Result ForceCloseCheatProcess();
Result GetCheatProcessMappingCount(sf::Out<u64> out_count);
Result GetCheatProcessMappings(const sf::OutArray<svc::MemoryInfo> &mappings, sf::Out<u64> out_count, u64 offset);
Result ReadCheatProcessMemory(const sf::OutBuffer &buffer, u64 address, u64 out_size);
Result WriteCheatProcessMemory(const sf::InBuffer &buffer, u64 address, u64 in_size);
Result QueryCheatProcessMemory(sf::Out<svc::MemoryInfo> mapping, u64 address);
Result GetCheatCount(sf::Out<u64> out_count);
Result GetCheats(const sf::OutArray<CheatEntry> &cheats, sf::Out<u64> out_count, u64 offset);
Result GetCheatById(sf::Out<CheatEntry> cheat, u32 cheat_id);
Result ToggleCheat(u32 cheat_id);
Result AddCheat(const CheatDefinition &cheat, sf::Out<u32> out_cheat_id, bool enabled);
Result RemoveCheat(u32 cheat_id);
Result ReadStaticRegister(sf::Out<u64> out, u8 which);
Result WriteStaticRegister(u8 which, u64 value);
Result ResetStaticRegisters();
Result SetMasterCheat(const CheatDefinition &cheat);
Result GetFrozenAddressCount(sf::Out<u64> out_count);
Result GetFrozenAddresses(const sf::OutArray<FrozenAddressEntry> &addresses, sf::Out<u64> out_count, u64 offset);
Result GetFrozenAddress(sf::Out<FrozenAddressEntry> entry, u64 address);
Result EnableFrozenAddress(sf::Out<u64> out_value, u64 address, u64 width);
Result DisableFrozenAddress(u64 address);
};
static_assert(impl::IsICheatInterface<CheatService>);
}

View File

@@ -1,60 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::dmnt::cheat::impl {
void InitializeCheatManager();
bool GetHasActiveCheatProcess();
os::NativeHandle GetCheatProcessEventHandle();
Result GetCheatProcessMetadata(CheatProcessMetadata *out);
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);
Result PauseCheatProcessUnsafe();
Result ResumeCheatProcessUnsafe();
Result GetCheatProcessMappingCount(u64 *out_count);
Result GetCheatProcessMappings(svc::MemoryInfo *mappings, size_t max_count, u64 *out_count, u64 offset);
Result ReadCheatProcessMemory(u64 proc_addr, void *out_data, size_t size);
Result WriteCheatProcessMemory(u64 proc_addr, const void *data, size_t size);
Result QueryCheatProcessMemory(svc::MemoryInfo *mapping, u64 address);
Result GetCheatCount(u64 *out_count);
Result GetCheats(CheatEntry *cheats, size_t max_count, u64 *out_count, u64 offset);
Result GetCheatById(CheatEntry *out_cheat, u32 cheat_id);
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();
Result GetFrozenAddressCount(u64 *out_count);
Result GetFrozenAddresses(FrozenAddressEntry *frz_addrs, size_t max_count, u64 *out_count, u64 offset);
Result GetFrozenAddress(FrozenAddressEntry *frz_addr, u64 address);
Result EnableFrozenAddress(u64 *out_value, u64 address, u64 width);
Result DisableFrozenAddress(u64 address);
}

View File

@@ -1,158 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "dmnt_cheat_debug_events_manager.hpp"
/* WORKAROUND: This design prevents a kernel deadlock from occurring on 6.0.0+ */
namespace ams::dmnt::cheat::impl {
namespace {
class DebugEventsManager {
public:
static constexpr size_t NumCores = 4;
static constexpr size_t ThreadStackSize = os::MemoryPageSize;
private:
std::array<uintptr_t, NumCores> m_handle_message_queue_buffers;
std::array<uintptr_t, NumCores> m_result_message_queue_buffers;
std::array<os::MessageQueue, NumCores> m_handle_message_queues;
std::array<os::MessageQueue, NumCores> m_result_message_queues;
std::array<os::ThreadType, NumCores> m_threads;
alignas(os::MemoryPageSize) u8 m_thread_stacks[NumCores][ThreadStackSize];
private:
static void PerCoreThreadFunction(void *_this) {
/* This thread will wait on the appropriate message queue. */
DebugEventsManager *this_ptr = reinterpret_cast<DebugEventsManager *>(_this);
const size_t current_core = svc::GetCurrentProcessorNumber();
while (true) {
/* Receive handle. */
os::NativeHandle debug_handle = this_ptr->WaitReceiveHandle(current_core);
/* Continue events on the correct core. */
Result result = this_ptr->ContinueDebugEvent(debug_handle);
/* Return our result. */
this_ptr->SendContinueResult(current_core, result);
}
}
Result GetTargetCore(size_t *out, const svc::DebugEventInfo &dbg_event, os::NativeHandle debug_handle) {
/* If we don't need to continue on a specific core, use the system core. */
size_t target_core = NumCores - 1;
/* Retrieve correct core for new thread event. */
if (dbg_event.type == svc::DebugEvent_CreateThread) {
u64 out64 = 0;
u32 out32 = 0;
R_TRY_CATCH(svc::GetDebugThreadParam(&out64, &out32, debug_handle, dbg_event.info.create_thread.thread_id, svc::DebugThreadParam_CurrentCore)) {
R_CATCH_RETHROW(svc::ResultProcessTerminated)
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
target_core = out32;
}
/* Set the target core. */
*out = target_core;
R_SUCCEED();
}
void SendHandle(size_t target_core, os::NativeHandle debug_handle) {
m_handle_message_queues[target_core].Send(static_cast<uintptr_t>(debug_handle));
}
os::NativeHandle WaitReceiveHandle(size_t core_id) {
uintptr_t x = 0;
m_handle_message_queues[core_id].Receive(&x);
return static_cast<os::NativeHandle>(x);
}
Result ContinueDebugEvent(os::NativeHandle debug_handle) {
if (hos::GetVersion() >= hos::Version_3_0_0) {
R_RETURN(svc::ContinueDebugEvent(debug_handle, svc::ContinueFlag_ExceptionHandled | svc::ContinueFlag_ContinueAll, nullptr, 0));
} else {
R_RETURN(svc::LegacyContinueDebugEvent(debug_handle, svc::ContinueFlag_ExceptionHandled | svc::ContinueFlag_ContinueAll, 0));
}
}
void SendContinueResult(size_t target_core, Result result) {
m_result_message_queues[target_core].Send(static_cast<uintptr_t>(result.GetValue()));
}
Result GetContinueResult(size_t core_id) {
uintptr_t x = 0;
m_result_message_queues[core_id].Receive(&x);
return static_cast<Result>(x);
}
public:
DebugEventsManager()
: m_handle_message_queues{
os::MessageQueue(std::addressof(m_handle_message_queue_buffers[0]), 1),
os::MessageQueue(std::addressof(m_handle_message_queue_buffers[1]), 1),
os::MessageQueue(std::addressof(m_handle_message_queue_buffers[2]), 1),
os::MessageQueue(std::addressof(m_handle_message_queue_buffers[3]), 1)},
m_result_message_queues{
os::MessageQueue(std::addressof(m_result_message_queue_buffers[0]), 1),
os::MessageQueue(std::addressof(m_result_message_queue_buffers[1]), 1),
os::MessageQueue(std::addressof(m_result_message_queue_buffers[2]), 1),
os::MessageQueue(std::addressof(m_result_message_queue_buffers[3]), 1)},
m_thread_stacks{}
{
for (size_t i = 0; i < NumCores; i++) {
/* Create thread. */
R_ABORT_UNLESS(os::CreateThread(std::addressof(m_threads[i]), PerCoreThreadFunction, this, m_thread_stacks[i], ThreadStackSize, AMS_GET_SYSTEM_THREAD_PRIORITY(dmnt, MultiCoreEventManager), i));
os::SetThreadNamePointer(std::addressof(m_threads[i]), AMS_GET_SYSTEM_THREAD_NAME(dmnt, MultiCoreEventManager));
/* Set core mask. */
os::SetThreadCoreMask(std::addressof(m_threads[i]), i, (1u << i));
/* Start thread. */
os::StartThread(std::addressof(m_threads[i]));
}
}
Result ContinueCheatProcess(os::NativeHandle cheat_dbg_hnd) {
/* Loop getting all debug events. */
svc::DebugEventInfo d;
size_t target_core = NumCores - 1;
while (R_SUCCEEDED(svc::GetDebugEvent(std::addressof(d), cheat_dbg_hnd))) {
if (d.type == svc::DebugEvent_CreateThread) {
R_TRY(GetTargetCore(std::addressof(target_core), d, cheat_dbg_hnd));
}
}
/* Send handle to correct core, wait for continue to finish. */
this->SendHandle(target_core, cheat_dbg_hnd);
R_RETURN(this->GetContinueResult(target_core));
}
};
/* Manager global. */
util::TypedStorage<DebugEventsManager> g_events_manager;
}
void InitializeDebugEventsManager() {
util::ConstructAt(g_events_manager);
}
Result ContinueCheatProcess(os::NativeHandle cheat_dbg_hnd) {
R_RETURN(GetReference(g_events_manager).ContinueCheatProcess(cheat_dbg_hnd));
}
}

View File

@@ -1,25 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::dmnt::cheat::impl {
void InitializeDebugEventsManager();
Result ContinueCheatProcess(os::NativeHandle cheat_dbg_hnd);
}

View File

@@ -1,350 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::dmnt::cheat::impl {
enum CheatVmOpcodeType : u32 {
CheatVmOpcodeType_StoreStatic = 0,
CheatVmOpcodeType_BeginConditionalBlock = 1,
CheatVmOpcodeType_EndConditionalBlock = 2,
CheatVmOpcodeType_ControlLoop = 3,
CheatVmOpcodeType_LoadRegisterStatic = 4,
CheatVmOpcodeType_LoadRegisterMemory = 5,
CheatVmOpcodeType_StoreStaticToAddress = 6,
CheatVmOpcodeType_PerformArithmeticStatic = 7,
CheatVmOpcodeType_BeginKeypressConditionalBlock = 8,
/* These are not implemented by Gateway's VM. */
CheatVmOpcodeType_PerformArithmeticRegister = 9,
CheatVmOpcodeType_StoreRegisterToAddress = 10,
CheatVmOpcodeType_Reserved11 = 11,
/* This is a meta entry, and not a real opcode. */
/* This is to facilitate multi-nybble instruction decoding. */
CheatVmOpcodeType_ExtendedWidth = 12,
/* Extended width opcodes. */
CheatVmOpcodeType_BeginRegisterConditionalBlock = 0xC0,
CheatVmOpcodeType_SaveRestoreRegister = 0xC1,
CheatVmOpcodeType_SaveRestoreRegisterMask = 0xC2,
CheatVmOpcodeType_ReadWriteStaticRegister = 0xC3,
CheatVmOpcodeType_BeginExtendedKeypressConditionalBlock = 0xC4,
/* This is a meta entry, and not a real opcode. */
/* This is to facilitate multi-nybble instruction decoding. */
CheatVmOpcodeType_DoubleExtendedWidth = 0xF0,
/* Double-extended width opcodes. */
CheatVmOpcodeType_PauseProcess = 0xFF0,
CheatVmOpcodeType_ResumeProcess = 0xFF1,
CheatVmOpcodeType_DebugLog = 0xFFF,
};
enum MemoryAccessType : u32 {
MemoryAccessType_MainNso = 0,
MemoryAccessType_Heap = 1,
MemoryAccessType_Alias = 2,
MemoryAccessType_Aslr = 3,
MemoryAccessType_NonRelative = 4,
};
enum ConditionalComparisonType : u32 {
ConditionalComparisonType_GT = 1,
ConditionalComparisonType_GE = 2,
ConditionalComparisonType_LT = 3,
ConditionalComparisonType_LE = 4,
ConditionalComparisonType_EQ = 5,
ConditionalComparisonType_NE = 6,
};
enum RegisterArithmeticType : u32 {
RegisterArithmeticType_Addition = 0,
RegisterArithmeticType_Subtraction = 1,
RegisterArithmeticType_Multiplication = 2,
RegisterArithmeticType_LeftShift = 3,
RegisterArithmeticType_RightShift = 4,
/* These are not supported by Gateway's VM. */
RegisterArithmeticType_LogicalAnd = 5,
RegisterArithmeticType_LogicalOr = 6,
RegisterArithmeticType_LogicalNot = 7,
RegisterArithmeticType_LogicalXor = 8,
RegisterArithmeticType_None = 9,
RegisterArithmeticType_FloatAddition = 10,
RegisterArithmeticType_FloatSubtraction = 11,
RegisterArithmeticType_FloatMultiplication = 12,
RegisterArithmeticType_FloatDivision = 13,
};
enum StoreRegisterOffsetType : u32 {
StoreRegisterOffsetType_None = 0,
StoreRegisterOffsetType_Reg = 1,
StoreRegisterOffsetType_Imm = 2,
StoreRegisterOffsetType_MemReg = 3,
StoreRegisterOffsetType_MemImm = 4,
StoreRegisterOffsetType_MemImmReg = 5,
};
enum CompareRegisterValueType : u32 {
CompareRegisterValueType_MemoryRelAddr = 0,
CompareRegisterValueType_MemoryOfsReg = 1,
CompareRegisterValueType_RegisterRelAddr = 2,
CompareRegisterValueType_RegisterOfsReg = 3,
CompareRegisterValueType_StaticValue = 4,
CompareRegisterValueType_OtherRegister = 5,
};
enum SaveRestoreRegisterOpType : u32 {
SaveRestoreRegisterOpType_Restore = 0,
SaveRestoreRegisterOpType_Save = 1,
SaveRestoreRegisterOpType_ClearSaved = 2,
SaveRestoreRegisterOpType_ClearRegs = 3,
};
enum DebugLogValueType : u32 {
DebugLogValueType_MemoryRelAddr = 0,
DebugLogValueType_MemoryOfsReg = 1,
DebugLogValueType_RegisterRelAddr = 2,
DebugLogValueType_RegisterOfsReg = 3,
DebugLogValueType_RegisterValue = 4,
};
union VmInt {
u8 bit8;
u16 bit16;
u32 bit32;
u64 bit64;
};
struct StoreStaticOpcode {
u32 bit_width;
MemoryAccessType mem_type;
u32 offset_register;
u64 rel_address;
VmInt value;
};
struct BeginConditionalOpcode {
u32 bit_width;
MemoryAccessType mem_type;
ConditionalComparisonType cond_type;
bool include_ofs_reg;
u32 ofs_reg_index;
u64 rel_address;
VmInt value;
};
struct EndConditionalOpcode {
bool is_else;
};
struct ControlLoopOpcode {
bool start_loop;
u32 reg_index;
u32 num_iters;
};
struct LoadRegisterStaticOpcode {
u32 reg_index;
u64 value;
};
struct LoadRegisterMemoryOpcode {
u32 bit_width;
MemoryAccessType mem_type;
u32 reg_index;
u8 load_from_reg;
u8 offset_register;
u64 rel_address;
};
struct StoreStaticToAddressOpcode {
u32 bit_width;
u32 reg_index;
bool increment_reg;
bool add_offset_reg;
u32 offset_reg_index;
u64 value;
};
struct PerformArithmeticStaticOpcode {
u32 bit_width;
u32 reg_index;
RegisterArithmeticType math_type;
u32 value;
};
struct BeginKeypressConditionalOpcode {
u32 key_mask;
};
struct BeginExtendedKeypressConditionalOpcode {
u64 key_mask;
bool auto_repeat;
};
struct PerformArithmeticRegisterOpcode {
u32 bit_width;
RegisterArithmeticType math_type;
u32 dst_reg_index;
u32 src_reg_1_index;
u32 src_reg_2_index;
bool has_immediate;
VmInt value;
};
struct StoreRegisterToAddressOpcode {
u32 bit_width;
u32 str_reg_index;
u32 addr_reg_index;
bool increment_reg;
StoreRegisterOffsetType ofs_type;
MemoryAccessType mem_type;
u32 ofs_reg_index;
u64 rel_address;
};
struct BeginRegisterConditionalOpcode {
u32 bit_width;
ConditionalComparisonType cond_type;
u32 val_reg_index;
CompareRegisterValueType comp_type;
MemoryAccessType mem_type;
u32 addr_reg_index;
u32 other_reg_index;
u32 ofs_reg_index;
u64 rel_address;
VmInt value;
};
struct SaveRestoreRegisterOpcode {
u32 dst_index;
u32 src_index;
SaveRestoreRegisterOpType op_type;
};
struct SaveRestoreRegisterMaskOpcode {
SaveRestoreRegisterOpType op_type;
bool should_operate[0x10];
};
struct ReadWriteStaticRegisterOpcode {
u32 static_idx;
u32 idx;
};
struct DebugLogOpcode {
u32 bit_width;
u32 log_id;
DebugLogValueType val_type;
MemoryAccessType mem_type;
u32 addr_reg_index;
u32 val_reg_index;
u32 ofs_reg_index;
u64 rel_address;
};
struct CheatVmOpcode {
CheatVmOpcodeType opcode;
bool begin_conditional_block;
union {
StoreStaticOpcode store_static;
BeginConditionalOpcode begin_cond;
EndConditionalOpcode end_cond;
ControlLoopOpcode ctrl_loop;
LoadRegisterStaticOpcode ldr_static;
LoadRegisterMemoryOpcode ldr_memory;
StoreStaticToAddressOpcode str_static;
PerformArithmeticStaticOpcode perform_math_static;
BeginKeypressConditionalOpcode begin_keypress_cond;
BeginExtendedKeypressConditionalOpcode begin_ext_keypress_cond;
PerformArithmeticRegisterOpcode perform_math_reg;
StoreRegisterToAddressOpcode str_register;
BeginRegisterConditionalOpcode begin_reg_cond;
SaveRestoreRegisterOpcode save_restore_reg;
SaveRestoreRegisterMaskOpcode save_restore_regmask;
ReadWriteStaticRegisterOpcode rw_static_reg;
DebugLogOpcode debug_log;
};
};
class CheatVirtualMachine {
public:
constexpr static size_t MaximumProgramOpcodeCount = 0x400;
constexpr static size_t NumRegisters = 0x10;
constexpr static size_t NumReadableStaticRegisters = 0x80;
constexpr static size_t NumWritableStaticRegisters = 0x80;
constexpr static size_t NumStaticRegisters = NumReadableStaticRegisters + NumWritableStaticRegisters;
private:
size_t m_num_opcodes = 0;
size_t m_instruction_ptr = 0;
size_t m_condition_depth = 0;
bool m_decode_success = false;
u32 m_program[MaximumProgramOpcodeCount] = {0};
u64 m_registers[NumRegisters] = {0};
u64 m_saved_values[NumRegisters] = {0};
u64 m_static_registers[NumStaticRegisters] = {0};
size_t m_loop_tops[NumRegisters] = {0};
private:
bool DecodeNextOpcode(CheatVmOpcode *out);
void SkipConditionalBlock(bool is_if);
void ResetState();
/* For implementing the DebugLog opcode. */
void DebugLog(u32 log_id, u64 value);
/* For debugging. These will be IFDEF'd out normally. */
void OpenDebugLogFile();
void CloseDebugLogFile();
void LogToDebugFile(const char *format, ...);
void LogOpcode(const CheatVmOpcode *opcode);
static u64 GetVmInt(VmInt value, u32 bit_width);
static u64 GetCheatProcessAddress(const CheatProcessMetadata* metadata, MemoryAccessType mem_type, u64 rel_address);
public:
constexpr CheatVirtualMachine() = default;
size_t GetProgramSize() {
return m_num_opcodes;
}
bool LoadProgram(const CheatEntry *cheats, size_t num_cheats);
void Execute(const CheatProcessMetadata *metadata);
u64 GetStaticRegister(size_t which) const {
return m_static_registers[which];
}
void SetStaticRegister(size_t which, u64 value) {
m_static_registers[which] = value;
}
void ResetStaticRegisters() {
std::memset(m_static_registers, 0, sizeof(m_static_registers));
}
#ifdef DMNT_CHEAT_VM_DEBUG_LOG
private:
fs::FileHandle m_debug_log_file = {};
s64 m_debug_log_file_offset = 0;
bool m_has_debug_log_file = false;
char m_debug_log_format_buf[0x100] = {0};
#endif
};
}