mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
dmnt: update for new-ipc
This commit is contained in:
parent
89c6fc6437
commit
e5d62025d3
13 changed files with 326 additions and 248 deletions
|
@ -24,15 +24,15 @@ namespace sts::dmnt::cheat {
|
|||
/* ==================================== Meta Commands ==================================== */
|
||||
/* ========================================================================================= */
|
||||
|
||||
void CheatService::HasCheatProcess(Out<bool> out) {
|
||||
void CheatService::HasCheatProcess(sf::Out<bool> out) {
|
||||
out.SetValue(dmnt::cheat::impl::GetHasActiveCheatProcess());
|
||||
}
|
||||
|
||||
void CheatService::GetCheatProcessEvent(Out<CopiedHandle> out_event) {
|
||||
void CheatService::GetCheatProcessEvent(sf::OutCopyHandle out_event) {
|
||||
out_event.SetValue(dmnt::cheat::impl::GetCheatProcessEventHandle());
|
||||
}
|
||||
|
||||
Result CheatService::GetCheatProcessMetadata(Out<CheatProcessMetadata> out_metadata) {
|
||||
Result CheatService::GetCheatProcessMetadata(sf::Out<CheatProcessMetadata> out_metadata) {
|
||||
return dmnt::cheat::impl::GetCheatProcessMetadata(out_metadata.GetPointer());
|
||||
}
|
||||
|
||||
|
@ -48,35 +48,35 @@ namespace sts::dmnt::cheat {
|
|||
/* =================================== Memory Commands =================================== */
|
||||
/* ========================================================================================= */
|
||||
|
||||
Result CheatService::GetCheatProcessMappingCount(Out<u64> out_count) {
|
||||
Result CheatService::GetCheatProcessMappingCount(sf::Out<u64> out_count) {
|
||||
return dmnt::cheat::impl::GetCheatProcessMappingCount(out_count.GetPointer());
|
||||
}
|
||||
|
||||
Result CheatService::GetCheatProcessMappings(OutBuffer<MemoryInfo> mappings, Out<u64> out_count, u64 offset) {
|
||||
if (mappings.buffer == nullptr) {
|
||||
Result CheatService::GetCheatProcessMappings(const sf::OutArray<MemoryInfo> &mappings, sf::Out<u64> out_count, u64 offset) {
|
||||
if (mappings.GetPointer() == nullptr) {
|
||||
return ResultDmntCheatNullBuffer;
|
||||
}
|
||||
|
||||
return dmnt::cheat::impl::GetCheatProcessMappings(mappings.buffer, mappings.num_elements, out_count.GetPointer(), offset);
|
||||
return dmnt::cheat::impl::GetCheatProcessMappings(mappings.GetPointer(), mappings.GetSize(), out_count.GetPointer(), offset);
|
||||
}
|
||||
|
||||
Result CheatService::ReadCheatProcessMemory(OutBuffer<u8> buffer, u64 address, u64 out_size) {
|
||||
if (buffer.buffer == nullptr) {
|
||||
Result CheatService::ReadCheatProcessMemory(const sf::OutBuffer &buffer, u64 address, u64 out_size) {
|
||||
if (buffer.GetPointer() == nullptr) {
|
||||
return ResultDmntCheatNullBuffer;
|
||||
}
|
||||
|
||||
return dmnt::cheat::impl::ReadCheatProcessMemory(address, buffer.buffer, std::min(out_size, buffer.num_elements));
|
||||
return dmnt::cheat::impl::ReadCheatProcessMemory(address, buffer.GetPointer(), std::min(out_size, buffer.GetSize()));
|
||||
}
|
||||
|
||||
Result CheatService::WriteCheatProcessMemory(InBuffer<u8> buffer, u64 address, u64 in_size) {
|
||||
if (buffer.buffer == nullptr) {
|
||||
Result CheatService::WriteCheatProcessMemory(const sf::InBuffer &buffer, u64 address, u64 in_size) {
|
||||
if (buffer.GetPointer() == nullptr) {
|
||||
return ResultDmntCheatNullBuffer;
|
||||
}
|
||||
|
||||
return dmnt::cheat::impl::WriteCheatProcessMemory(address, buffer.buffer, std::min(in_size, buffer.num_elements));
|
||||
return dmnt::cheat::impl::WriteCheatProcessMemory(address, buffer.GetPointer(), std::min(in_size, buffer.GetSize()));
|
||||
}
|
||||
|
||||
Result CheatService::QueryCheatProcessMemory(Out<MemoryInfo> mapping, u64 address) {
|
||||
Result CheatService::QueryCheatProcessMemory(sf::Out<MemoryInfo> mapping, u64 address) {
|
||||
return dmnt::cheat::impl::QueryCheatProcessMemory(mapping.GetPointer(), address);
|
||||
}
|
||||
|
||||
|
@ -84,44 +84,28 @@ namespace sts::dmnt::cheat {
|
|||
/* =================================== Cheat Commands ==================================== */
|
||||
/* ========================================================================================= */
|
||||
|
||||
Result CheatService::GetCheatCount(Out<u64> out_count) {
|
||||
Result CheatService::GetCheatCount(sf::Out<u64> out_count) {
|
||||
return dmnt::cheat::impl::GetCheatCount(out_count.GetPointer());
|
||||
}
|
||||
|
||||
Result CheatService::GetCheats(OutBuffer<CheatEntry> cheats, Out<u64> out_count, u64 offset) {
|
||||
if (cheats.buffer == nullptr) {
|
||||
Result CheatService::GetCheats(const sf::OutArray<CheatEntry> &cheats, sf::Out<u64> out_count, u64 offset) {
|
||||
if (cheats.GetPointer() == nullptr) {
|
||||
return ResultDmntCheatNullBuffer;
|
||||
}
|
||||
|
||||
return dmnt::cheat::impl::GetCheats(cheats.buffer, cheats.num_elements, out_count.GetPointer(), offset);
|
||||
return dmnt::cheat::impl::GetCheats(cheats.GetPointer(), cheats.GetSize(), out_count.GetPointer(), offset);
|
||||
}
|
||||
|
||||
Result CheatService::GetCheatById(OutBuffer<CheatEntry> cheat, u32 cheat_id) {
|
||||
if (cheat.buffer == nullptr) {
|
||||
return ResultDmntCheatNullBuffer;
|
||||
}
|
||||
|
||||
if (cheat.num_elements < 1) {
|
||||
return ResultDmntCheatInvalidBuffer;
|
||||
}
|
||||
|
||||
return dmnt::cheat::impl::GetCheatById(cheat.buffer, cheat_id);
|
||||
Result CheatService::GetCheatById(sf::Out<CheatEntry> cheat, u32 cheat_id) {
|
||||
return dmnt::cheat::impl::GetCheatById(cheat.GetPointer(), cheat_id);
|
||||
}
|
||||
|
||||
Result CheatService::ToggleCheat(u32 cheat_id) {
|
||||
return dmnt::cheat::impl::ToggleCheat(cheat_id);
|
||||
}
|
||||
|
||||
Result CheatService::AddCheat(InBuffer<CheatDefinition> cheat, Out<u32> out_cheat_id, bool enabled) {
|
||||
if (cheat.buffer == nullptr) {
|
||||
return ResultDmntCheatNullBuffer;
|
||||
}
|
||||
|
||||
if (cheat.num_elements < 1) {
|
||||
return ResultDmntCheatInvalidBuffer;
|
||||
}
|
||||
|
||||
return dmnt::cheat::impl::AddCheat(out_cheat_id.GetPointer(), cheat.buffer, enabled);
|
||||
Result CheatService::AddCheat(const CheatDefinition &cheat, sf::Out<u32> out_cheat_id, bool enabled) {
|
||||
return dmnt::cheat::impl::AddCheat(out_cheat_id.GetPointer(), cheat, enabled);
|
||||
}
|
||||
|
||||
Result CheatService::RemoveCheat(u32 cheat_id) {
|
||||
|
@ -132,23 +116,23 @@ namespace sts::dmnt::cheat {
|
|||
/* =================================== Address Commands ================================== */
|
||||
/* ========================================================================================= */
|
||||
|
||||
Result CheatService::GetFrozenAddressCount(Out<u64> out_count) {
|
||||
Result CheatService::GetFrozenAddressCount(sf::Out<u64> out_count) {
|
||||
return dmnt::cheat::impl::GetFrozenAddressCount(out_count.GetPointer());
|
||||
}
|
||||
|
||||
Result CheatService::GetFrozenAddresses(OutBuffer<FrozenAddressEntry> frz_addrs, Out<u64> out_count, u64 offset) {
|
||||
if (frz_addrs.buffer == nullptr) {
|
||||
Result CheatService::GetFrozenAddresses(const sf::OutArray<FrozenAddressEntry> &addresses, sf::Out<u64> out_count, u64 offset) {
|
||||
if (addresses.GetPointer() == nullptr) {
|
||||
return ResultDmntCheatNullBuffer;
|
||||
}
|
||||
|
||||
return dmnt::cheat::impl::GetFrozenAddresses(frz_addrs.buffer, frz_addrs.num_elements, out_count.GetPointer(), offset);
|
||||
return dmnt::cheat::impl::GetFrozenAddresses(addresses.GetPointer(), addresses.GetSize(), out_count.GetPointer(), offset);
|
||||
}
|
||||
|
||||
Result CheatService::GetFrozenAddress(Out<FrozenAddressEntry> entry, u64 address) {
|
||||
Result CheatService::GetFrozenAddress(sf::Out<FrozenAddressEntry> entry, u64 address) {
|
||||
return dmnt::cheat::impl::GetFrozenAddress(entry.GetPointer(), address);
|
||||
}
|
||||
|
||||
Result CheatService::EnableFrozenAddress(Out<u64> out_value, u64 address, u64 width) {
|
||||
Result CheatService::EnableFrozenAddress(sf::Out<u64> out_value, u64 address, u64 width) {
|
||||
switch (width) {
|
||||
case 1:
|
||||
case 2:
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
namespace sts::dmnt::cheat {
|
||||
|
||||
class CheatService final : public IServiceObject {
|
||||
class CheatService final : public sf::IServiceObject {
|
||||
private:
|
||||
enum class CommandId {
|
||||
/* Meta */
|
||||
|
@ -53,55 +53,55 @@ namespace sts::dmnt::cheat {
|
|||
DisableFrozenAddress = 65304,
|
||||
};
|
||||
private:
|
||||
void HasCheatProcess(Out<bool> out);
|
||||
void GetCheatProcessEvent(Out<CopiedHandle> out_event);
|
||||
Result GetCheatProcessMetadata(Out<CheatProcessMetadata> out_metadata);
|
||||
void HasCheatProcess(sf::Out<bool> out);
|
||||
void GetCheatProcessEvent(sf::OutCopyHandle out_event);
|
||||
Result GetCheatProcessMetadata(sf::Out<CheatProcessMetadata> out_metadata);
|
||||
Result ForceOpenCheatProcess();
|
||||
|
||||
Result GetCheatProcessMappingCount(Out<u64> out_count);
|
||||
Result GetCheatProcessMappings(OutBuffer<MemoryInfo> mappings, Out<u64> out_count, u64 offset);
|
||||
Result ReadCheatProcessMemory(OutBuffer<u8> buffer, u64 address, u64 out_size);
|
||||
Result WriteCheatProcessMemory(InBuffer<u8> buffer, u64 address, u64 in_size);
|
||||
Result QueryCheatProcessMemory(Out<MemoryInfo> mapping, u64 address);
|
||||
Result GetCheatProcessMappingCount(sf::Out<u64> out_count);
|
||||
Result GetCheatProcessMappings(const sf::OutArray<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<MemoryInfo> mapping, u64 address);
|
||||
|
||||
Result GetCheatCount(Out<u64> out_count);
|
||||
Result GetCheats(OutBuffer<CheatEntry> cheats, Out<u64> out_count, u64 offset);
|
||||
Result GetCheatById(OutBuffer<CheatEntry> cheat, u32 cheat_id);
|
||||
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(InBuffer<CheatDefinition> cheat, Out<u32> out_cheat_id, bool enabled);
|
||||
Result AddCheat(const CheatDefinition &cheat, sf::Out<u32> out_cheat_id, bool enabled);
|
||||
Result RemoveCheat(u32 cheat_id);
|
||||
|
||||
Result GetFrozenAddressCount(Out<u64> out_count);
|
||||
Result GetFrozenAddresses(OutBuffer<FrozenAddressEntry> addresses, Out<u64> out_count, u64 offset);
|
||||
Result GetFrozenAddress(Out<FrozenAddressEntry> entry, u64 address);
|
||||
Result EnableFrozenAddress(Out<u64> out_value, u64 address, u64 width);
|
||||
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);
|
||||
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, HasCheatProcess),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, GetCheatProcessEvent),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, GetCheatProcessMetadata),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, ForceOpenCheatProcess),
|
||||
MAKE_SERVICE_COMMAND_META(HasCheatProcess),
|
||||
MAKE_SERVICE_COMMAND_META(GetCheatProcessEvent),
|
||||
MAKE_SERVICE_COMMAND_META(GetCheatProcessMetadata),
|
||||
MAKE_SERVICE_COMMAND_META(ForceOpenCheatProcess),
|
||||
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, GetCheatProcessMappingCount),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, GetCheatProcessMappings),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, ReadCheatProcessMemory),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, WriteCheatProcessMemory),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, QueryCheatProcessMemory),
|
||||
MAKE_SERVICE_COMMAND_META(GetCheatProcessMappingCount),
|
||||
MAKE_SERVICE_COMMAND_META(GetCheatProcessMappings),
|
||||
MAKE_SERVICE_COMMAND_META(ReadCheatProcessMemory),
|
||||
MAKE_SERVICE_COMMAND_META(WriteCheatProcessMemory),
|
||||
MAKE_SERVICE_COMMAND_META(QueryCheatProcessMemory),
|
||||
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, GetCheatCount),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, GetCheats),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, GetCheatById),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, ToggleCheat),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, AddCheat),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, RemoveCheat),
|
||||
MAKE_SERVICE_COMMAND_META(GetCheatCount),
|
||||
MAKE_SERVICE_COMMAND_META(GetCheats),
|
||||
MAKE_SERVICE_COMMAND_META(GetCheatById),
|
||||
MAKE_SERVICE_COMMAND_META(ToggleCheat),
|
||||
MAKE_SERVICE_COMMAND_META(AddCheat),
|
||||
MAKE_SERVICE_COMMAND_META(RemoveCheat),
|
||||
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, GetFrozenAddressCount),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, GetFrozenAddresses),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, GetFrozenAddress),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, EnableFrozenAddress),
|
||||
MAKE_SERVICE_COMMAND_META(CheatService, DisableFrozenAddress),
|
||||
MAKE_SERVICE_COMMAND_META(GetFrozenAddressCount),
|
||||
MAKE_SERVICE_COMMAND_META(GetFrozenAddresses),
|
||||
MAKE_SERVICE_COMMAND_META(GetFrozenAddress),
|
||||
MAKE_SERVICE_COMMAND_META(EnableFrozenAddress),
|
||||
MAKE_SERVICE_COMMAND_META(DisableFrozenAddress),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace sts::dmnt::cheat::impl {
|
|||
bool enable_cheats_by_default = true;
|
||||
bool always_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;
|
||||
private:
|
||||
static void DetectLaunchThread(void *_this);
|
||||
|
@ -146,11 +146,11 @@ namespace sts::dmnt::cheat::impl {
|
|||
|
||||
bool HasActiveCheatProcess() {
|
||||
/* Note: This function *MUST* be called only with the cheat lock held. */
|
||||
u64 tmp;
|
||||
os::ProcessId pid;
|
||||
bool has_cheat_process = this->cheat_process_debug_handle != INVALID_HANDLE;
|
||||
has_cheat_process &= R_SUCCEEDED(svcGetProcessId(&tmp, this->cheat_process_debug_handle));
|
||||
has_cheat_process &= R_SUCCEEDED(pm::dmnt::GetApplicationProcessId(&tmp));
|
||||
has_cheat_process &= (tmp == this->cheat_process_metadata.process_id);
|
||||
has_cheat_process &= R_SUCCEEDED(os::GetProcessId(&pid, this->cheat_process_debug_handle));
|
||||
has_cheat_process &= R_SUCCEEDED(pm::dmnt::GetApplicationProcessId(&pid));
|
||||
has_cheat_process &= (pid == this->cheat_process_metadata.process_id);
|
||||
|
||||
if (!has_cheat_process) {
|
||||
this->CloseActiveCheatProcess();
|
||||
|
@ -176,7 +176,7 @@ namespace sts::dmnt::cheat::impl {
|
|||
return h;
|
||||
}
|
||||
|
||||
void StartProcess(u64 process_id) const {
|
||||
void StartProcess(os::ProcessId process_id) const {
|
||||
R_ASSERT(pm::dmnt::StartProcess(process_id));
|
||||
}
|
||||
|
||||
|
@ -404,12 +404,12 @@ namespace sts::dmnt::cheat::impl {
|
|||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AddCheat(u32 *out_id, const CheatDefinition *def, bool enabled) {
|
||||
Result AddCheat(u32 *out_id, const CheatDefinition &def, bool enabled) {
|
||||
std::scoped_lock lk(this->cheat_lock);
|
||||
|
||||
R_TRY(this->EnsureCheatProcess());
|
||||
|
||||
if (def->num_opcodes == 0 || def->num_opcodes > util::size(def->opcodes)) {
|
||||
if (def.num_opcodes == 0 || def.num_opcodes > util::size(def.opcodes)) {
|
||||
return ResultDmntCheatInvalidCheat;
|
||||
}
|
||||
|
||||
|
@ -419,7 +419,7 @@ namespace sts::dmnt::cheat::impl {
|
|||
}
|
||||
|
||||
new_entry->enabled = enabled;
|
||||
new_entry->definition = *def;
|
||||
new_entry->definition = def;
|
||||
|
||||
/* Trigger a VM reload. */
|
||||
this->SetNeedsReloadVm(true);
|
||||
|
@ -630,7 +630,7 @@ namespace sts::dmnt::cheat::impl {
|
|||
if (on_process_launch) {
|
||||
this->StartProcess(this->cheat_process_metadata.process_id);
|
||||
}
|
||||
this->cheat_process_metadata.process_id = 0;
|
||||
this->cheat_process_metadata.process_id = os::ProcessId{};
|
||||
};
|
||||
|
||||
/* Get process handle, use it to learn memory extents. */
|
||||
|
@ -667,7 +667,7 @@ namespace sts::dmnt::cheat::impl {
|
|||
u32 num_modules;
|
||||
|
||||
/* TODO: ldr::dmnt:: */
|
||||
R_ASSERT_IF_NEW_PROCESS(ldrDmntGetModuleInfos(this->cheat_process_metadata.process_id, proc_modules, util::size(proc_modules), &num_modules));
|
||||
R_ASSERT_IF_NEW_PROCESS(ldrDmntGetModuleInfos(static_cast<u64>(this->cheat_process_metadata.process_id), proc_modules, util::size(proc_modules), &num_modules));
|
||||
|
||||
/* All applications must have two modules. */
|
||||
/* Only accept one (which means we're attaching to HBL) */
|
||||
|
@ -696,7 +696,7 @@ namespace sts::dmnt::cheat::impl {
|
|||
}
|
||||
|
||||
/* Open a debug handle. */
|
||||
R_ASSERT_IF_NEW_PROCESS(svcDebugActiveProcess(&this->cheat_process_debug_handle, this->cheat_process_metadata.process_id));
|
||||
R_ASSERT_IF_NEW_PROCESS(svcDebugActiveProcess(&this->cheat_process_debug_handle, static_cast<u64>(this->cheat_process_metadata.process_id)));
|
||||
|
||||
/* Cancel process guard. */
|
||||
proc_guard.Cancel();
|
||||
|
@ -1064,7 +1064,7 @@ namespace sts::dmnt::cheat::impl {
|
|||
return g_cheat_process_manager.ToggleCheat(cheat_id);
|
||||
}
|
||||
|
||||
Result AddCheat(u32 *out_id, const CheatDefinition *def, bool enabled) {
|
||||
Result AddCheat(u32 *out_id, const CheatDefinition &def, bool enabled) {
|
||||
return g_cheat_process_manager.AddCheat(out_id, def, enabled);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace sts::dmnt::cheat::impl {
|
|||
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 AddCheat(u32 *out_id, const CheatDefinition &def, bool enabled);
|
||||
Result RemoveCheat(u32 cheat_id);
|
||||
|
||||
Result GetFrozenAddressCount(u64 *out_count);
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace sts::dmnt::cheat::impl {
|
|||
}
|
||||
|
||||
Result ContinueDebugEvent(Handle debug_handle) {
|
||||
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_300) {
|
||||
if (hos::GetVersion() >= hos::Version_300) {
|
||||
return svcContinueDebugEvent(debug_handle, 5, nullptr, 0);
|
||||
} else {
|
||||
return svcLegacyContinueDebugEvent(debug_handle, 5, 0);
|
||||
|
|
|
@ -30,7 +30,9 @@ extern "C" {
|
|||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
/* TODO: Evaluate how much this can be reduced by. */
|
||||
#define INNER_HEAP_SIZE 0xC0000
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
@ -55,15 +57,17 @@ void __libnx_initheap(void) {
|
|||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
using namespace sts;
|
||||
|
||||
void __appInit(void) {
|
||||
SetFirmwareVersionForLibnx();
|
||||
hos::SetVersionForLibnx();
|
||||
|
||||
DoWithSmSession([&]() {
|
||||
R_ASSERT(pmdmntInitialize());
|
||||
R_ASSERT(pminfoInitialize());
|
||||
R_ASSERT(ldrDmntInitialize());
|
||||
/* TODO: We provide this on every sysver via ro. Do we need a shim? */
|
||||
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_300) {
|
||||
if (hos::GetVersion() >= hos::Version_300) {
|
||||
R_ASSERT(roDmntInitialize());
|
||||
}
|
||||
R_ASSERT(nsdevInitialize());
|
||||
|
@ -94,19 +98,70 @@ void __appExit(void) {
|
|||
pmdmntExit();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||
|
||||
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("dmnt:-");
|
||||
constexpr size_t DebugMonitorMaxSessions = 4;
|
||||
|
||||
constexpr sm::ServiceName CheatServiceName = sm::ServiceName::Encode("dmnt:cht");
|
||||
constexpr size_t CheatMaxSessions = 2;
|
||||
|
||||
/* dmnt:-, dmnt:cht. */
|
||||
constexpr size_t NumServers = 2;
|
||||
constexpr size_t NumSessions = DebugMonitorMaxSessions + CheatMaxSessions;
|
||||
|
||||
sf::hipc::ServerManager<NumServers, ServerOptions, NumSessions> g_server_manager;
|
||||
|
||||
void LoopServerThread(void *arg) {
|
||||
g_server_manager.LoopProcess();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* Nintendo uses four threads. Add a fifth for our cheat service. */
|
||||
static auto s_server_manager = WaitableManager(5);
|
||||
|
||||
/* Create services. */
|
||||
|
||||
/* TODO: Implement rest of dmnt:- in ams.tma development branch. */
|
||||
/* server_manager->AddWaitable(new ServiceServer<DebugMonitorService>("dmnt:-", 4)); */
|
||||
s_server_manager.AddWaitable(new ServiceServer<sts::dmnt::cheat::CheatService>("dmnt:cht", 1));
|
||||
/* R_ASSERT((g_server_manager.RegisterServer<dmnt::cheat::CheatService>(DebugMonitorServiceName, DebugMonitorMaxSessions))); */
|
||||
R_ASSERT((g_server_manager.RegisterServer<dmnt::cheat::CheatService>(CheatServiceName, CheatMaxSessions)));
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
s_server_manager.Process();
|
||||
/* Nintendo loops four threads processing on the manager -- we'll loop an extra fifth for our cheat service. */
|
||||
{
|
||||
constexpr size_t TotalThreads = DebugMonitorMaxSessions + 1;
|
||||
constexpr size_t NumExtraThreads = TotalThreads - 1;
|
||||
static_assert(TotalThreads >= 1, "TotalThreads");
|
||||
|
||||
os::Thread extra_threads[NumExtraThreads];
|
||||
|
||||
/* Initialize threads. */
|
||||
if constexpr (NumExtraThreads > 0) {
|
||||
constexpr size_t ThreadStackSize = 0x4000;
|
||||
const u32 priority = os::GetCurrentThreadPriority();
|
||||
for (size_t i = 0; i < NumExtraThreads; i++) {
|
||||
R_ASSERT(extra_threads[i].Initialize(LoopServerThread, nullptr, ThreadStackSize, priority));
|
||||
}
|
||||
}
|
||||
|
||||
/* Start extra threads. */
|
||||
if constexpr (NumExtraThreads > 0) {
|
||||
for (size_t i = 0; i < NumExtraThreads; i++) {
|
||||
R_ASSERT(extra_threads[i].Start());
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop this thread. */
|
||||
LoopServerThread(nullptr);
|
||||
|
||||
/* Wait for extra threads to finish. */
|
||||
if constexpr (NumExtraThreads > 0) {
|
||||
for (size_t i = 0; i < NumExtraThreads; i++) {
|
||||
R_ASSERT(extra_threads[i].Join());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,46 @@
|
|||
|
||||
namespace sts::dmnt {
|
||||
|
||||
class DebugMonitorService final : public IServiceObject {
|
||||
/* TODO: Move into libstratosphere, eventually. */
|
||||
struct TargetIOFileHandle : sf::LargeData, sf::PrefersMapAliasTransferMode {
|
||||
u64 value;
|
||||
|
||||
constexpr u64 GetValue() const {
|
||||
return this->value;
|
||||
}
|
||||
|
||||
constexpr explicit operator u64() const {
|
||||
return this->value;
|
||||
}
|
||||
|
||||
inline constexpr bool operator==(const TargetIOFileHandle &rhs) const {
|
||||
return this->value == rhs.value;
|
||||
}
|
||||
|
||||
inline constexpr bool operator!=(const TargetIOFileHandle &rhs) const {
|
||||
return this->value != rhs.value;
|
||||
}
|
||||
|
||||
inline constexpr bool operator<(const TargetIOFileHandle &rhs) const {
|
||||
return this->value < rhs.value;
|
||||
}
|
||||
|
||||
inline constexpr bool operator<=(const TargetIOFileHandle &rhs) const {
|
||||
return this->value <= rhs.value;
|
||||
}
|
||||
|
||||
inline constexpr bool operator>(const TargetIOFileHandle &rhs) const {
|
||||
return this->value > rhs.value;
|
||||
}
|
||||
|
||||
inline constexpr bool operator>=(const TargetIOFileHandle &rhs) const {
|
||||
return this->value >= rhs.value;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(std::is_pod<TargetIOFileHandle>::value && sizeof(TargetIOFileHandle) == sizeof(u64), "TargetIOFileHandle");
|
||||
|
||||
class DebugMonitorService final : public sf::IServiceObject {
|
||||
private:
|
||||
enum class CommandId {
|
||||
BreakDebugProcess = 0,
|
||||
|
@ -80,74 +119,74 @@ namespace sts::dmnt {
|
|||
Result BreakDebugProcess(Handle debug_hnd);
|
||||
Result TerminateDebugProcess(Handle debug_hnd);
|
||||
Result CloseHandle(Handle debug_hnd);
|
||||
Result GetProcessId(Out<u64> out_pid, Handle hnd);
|
||||
Result GetProcessHandle(Out<Handle> out_hnd, u64 pid);
|
||||
Result GetProcessId(sf::Out<os::ProcessId> out_pid, Handle hnd);
|
||||
Result GetProcessHandle(sf::Out<Handle> out_hnd, os::ProcessId pid);
|
||||
Result WaitSynchronization(Handle hnd, u64 ns);
|
||||
|
||||
Result TargetIO_FileOpen(OutBuffer<u64> out_hnd, InBuffer<char> path, int open_mode, u32 create_mode);
|
||||
Result TargetIO_FileClose(InBuffer<u64> hnd);
|
||||
Result TargetIO_FileRead(InBuffer<u64> hnd, OutBuffer<u8, BufferType_Type1> out_data, Out<u32> out_read, u64 offset);
|
||||
Result TargetIO_FileWrite(InBuffer<u64> hnd, InBuffer<u8, BufferType_Type1> data, Out<u32> out_written, u64 offset);
|
||||
Result TargetIO_FileSetAttributes(InBuffer<char> path, InBuffer<u8> attributes);
|
||||
Result TargetIO_FileGetInformation(InBuffer<char> path, OutBuffer<u64> out_info, Out<int> is_directory);
|
||||
Result TargetIO_FileSetTime(InBuffer<char> path, u64 create, u64 access, u64 modify);
|
||||
Result TargetIO_FileSetSize(InBuffer<char> path, u64 size);
|
||||
Result TargetIO_FileDelete(InBuffer<char> path);
|
||||
Result TargetIO_FileMove(InBuffer<char> path0, InBuffer<char> path1);
|
||||
Result TargetIO_FileOpen(sf::Out<TargetIOFileHandle> out_hnd, const sf::InBuffer &path, int open_mode, u32 create_mode);
|
||||
Result TargetIO_FileClose(TargetIOFileHandle hnd);
|
||||
Result TargetIO_FileRead(TargetIOFileHandle hnd, const sf::OutNonSecureBuffer &out_data, sf::Out<u32> out_read, u64 offset);
|
||||
Result TargetIO_FileWrite(TargetIOFileHandle hnd, const sf::InNonSecureBuffer &data, sf::Out<u32> out_written, u64 offset);
|
||||
Result TargetIO_FileSetAttributes(const sf::InBuffer &path, const sf::InBuffer &attributes);
|
||||
Result TargetIO_FileGetInformation(const sf::InBuffer &path, const sf::OutArray<u64> &out_info, sf::Out<int> is_directory);
|
||||
Result TargetIO_FileSetTime(const sf::InBuffer &path, u64 create, u64 access, u64 modify);
|
||||
Result TargetIO_FileSetSize(const sf::InBuffer &input, u64 size);
|
||||
Result TargetIO_FileDelete(const sf::InBuffer &path);
|
||||
Result TargetIO_FileMove(const sf::InBuffer &src_path, const sf::InBuffer &dst_path);
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, BreakDebugProcess),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, TerminateDebugProcess),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, CloseHandle),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, LoadImage),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, GetProcessId),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, GetProcessHandle),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, WaitSynchronization),
|
||||
//MAKE_SERVICE_COMMAND_META(DebugMonitorService, GetDebugEvent),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, GetProcessModuleInfo),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, GetProcessList),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, GetThreadList),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, GetDebugThreadContext),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, ContinueDebugEvent),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, ReadDebugProcessMemory),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, WriteDebugProcessMemory),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, SetDebugThreadContext),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, GetDebugThreadParam),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, InitializeThreadInfo),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, SetHardwareBreakPoint),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, QueryDebugProcessMemory),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, GetProcessMemoryDetails),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, AttachByProgramId),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, AttachOnLaunch),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, GetDebugMonitorProcessId),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, GetJitDebugProcessList),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, CreateCoreDump),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, GetAllDebugThreadInfo),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_FileOpen),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_FileClose),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_FileRead),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_FileWrite),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_FileSetAttributes),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_FileGetInformation),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_FileSetTime),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_FileSetSize),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_FileDelete),
|
||||
MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_FileMove),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_DirectoryCreate),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_DirectoryDelete),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_DirectoryRename),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_DirectoryGetCount),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_DirectoryOpen),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_DirectoryGetNext),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_DirectoryClose),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_GetFreeSpace),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, TargetIO_GetVolumeInformation),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, InitiateCoreDump),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, ContinueCoreDump),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, AddTTYToCoreDump),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, AddImageToCoreDump),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, CloseCoreDump),
|
||||
// MAKE_SERVICE_COMMAND_META(DebugMonitorService, CancelAttach),
|
||||
MAKE_SERVICE_COMMAND_META(BreakDebugProcess),
|
||||
MAKE_SERVICE_COMMAND_META(TerminateDebugProcess),
|
||||
MAKE_SERVICE_COMMAND_META(CloseHandle),
|
||||
// MAKE_SERVICE_COMMAND_META(LoadImage),
|
||||
MAKE_SERVICE_COMMAND_META(GetProcessId),
|
||||
MAKE_SERVICE_COMMAND_META(GetProcessHandle),
|
||||
MAKE_SERVICE_COMMAND_META(WaitSynchronization),
|
||||
//MAKE_SERVICE_COMMAND_META(GetDebugEvent),
|
||||
// MAKE_SERVICE_COMMAND_META(GetProcessModuleInfo),
|
||||
// MAKE_SERVICE_COMMAND_META(GetProcessList),
|
||||
// MAKE_SERVICE_COMMAND_META(GetThreadList),
|
||||
// MAKE_SERVICE_COMMAND_META(GetDebugThreadContext),
|
||||
// MAKE_SERVICE_COMMAND_META(ContinueDebugEvent),
|
||||
// MAKE_SERVICE_COMMAND_META(ReadDebugProcessMemory),
|
||||
// MAKE_SERVICE_COMMAND_META(WriteDebugProcessMemory),
|
||||
// MAKE_SERVICE_COMMAND_META(SetDebugThreadContext),
|
||||
// MAKE_SERVICE_COMMAND_META(GetDebugThreadParam),
|
||||
// MAKE_SERVICE_COMMAND_META(InitializeThreadInfo),
|
||||
// MAKE_SERVICE_COMMAND_META(SetHardwareBreakPoint),
|
||||
// MAKE_SERVICE_COMMAND_META(QueryDebugProcessMemory),
|
||||
// MAKE_SERVICE_COMMAND_META(GetProcessMemoryDetails),
|
||||
// MAKE_SERVICE_COMMAND_META(AttachByProgramId),
|
||||
// MAKE_SERVICE_COMMAND_META(AttachOnLaunch),
|
||||
// MAKE_SERVICE_COMMAND_META(GetDebugMonitorProcessId),
|
||||
// MAKE_SERVICE_COMMAND_META(GetJitDebugProcessList),
|
||||
// MAKE_SERVICE_COMMAND_META(CreateCoreDump),
|
||||
// MAKE_SERVICE_COMMAND_META(GetAllDebugThreadInfo),
|
||||
MAKE_SERVICE_COMMAND_META(TargetIO_FileOpen),
|
||||
MAKE_SERVICE_COMMAND_META(TargetIO_FileClose),
|
||||
MAKE_SERVICE_COMMAND_META(TargetIO_FileRead),
|
||||
MAKE_SERVICE_COMMAND_META(TargetIO_FileWrite),
|
||||
MAKE_SERVICE_COMMAND_META(TargetIO_FileSetAttributes),
|
||||
MAKE_SERVICE_COMMAND_META(TargetIO_FileGetInformation),
|
||||
MAKE_SERVICE_COMMAND_META(TargetIO_FileSetTime),
|
||||
MAKE_SERVICE_COMMAND_META(TargetIO_FileSetSize),
|
||||
MAKE_SERVICE_COMMAND_META(TargetIO_FileDelete),
|
||||
MAKE_SERVICE_COMMAND_META(TargetIO_FileMove),
|
||||
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryCreate),
|
||||
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryDelete),
|
||||
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryRename),
|
||||
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryGetCount),
|
||||
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryOpen),
|
||||
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryGetNext),
|
||||
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryClose),
|
||||
// MAKE_SERVICE_COMMAND_META(TargetIO_GetFreeSpace),
|
||||
// MAKE_SERVICE_COMMAND_META(TargetIO_GetVolumeInformation),
|
||||
// MAKE_SERVICE_COMMAND_META(InitiateCoreDump),
|
||||
// MAKE_SERVICE_COMMAND_META(ContinueCoreDump),
|
||||
// MAKE_SERVICE_COMMAND_META(AddTTYToCoreDump),
|
||||
// MAKE_SERVICE_COMMAND_META(AddImageToCoreDump),
|
||||
// MAKE_SERVICE_COMMAND_META(CloseCoreDump),
|
||||
// MAKE_SERVICE_COMMAND_META(CancelAttach),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -34,13 +34,13 @@ namespace sts::dmnt {
|
|||
return svcCloseHandle(debug_hnd);
|
||||
}
|
||||
|
||||
Result DebugMonitorService::GetProcessId(Out<u64> out_pid, Handle hnd) {
|
||||
Result DebugMonitorService::GetProcessId(sf::Out<os::ProcessId> out_pid, Handle hnd) {
|
||||
/* Nintendo discards the output of this command, but we will return it. */
|
||||
return svcGetProcessId(out_pid.GetPointer(), hnd);
|
||||
return svcGetProcessId(reinterpret_cast<u64 *>(out_pid.GetPointer()), hnd);
|
||||
}
|
||||
|
||||
Result DebugMonitorService::GetProcessHandle(Out<Handle> out_hnd, u64 pid) {
|
||||
R_TRY_CATCH(svcDebugActiveProcess(out_hnd.GetPointer(), pid)) {
|
||||
Result DebugMonitorService::GetProcessHandle(sf::Out<Handle> out_hnd, os::ProcessId pid) {
|
||||
R_TRY_CATCH(svcDebugActiveProcess(out_hnd.GetPointer(), static_cast<u64>(pid))) {
|
||||
R_CATCH(ResultKernelAlreadyExists) {
|
||||
return ResultDebugAlreadyAttached;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,17 @@
|
|||
#include <unordered_map>
|
||||
#include "dmnt_service.hpp"
|
||||
|
||||
namespace std {
|
||||
|
||||
template<>
|
||||
struct hash<sts::dmnt::TargetIOFileHandle> {
|
||||
u64 operator()(sts::dmnt::TargetIOFileHandle const &handle) const noexcept {
|
||||
return handle.GetValue();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace sts::dmnt {
|
||||
|
||||
namespace {
|
||||
|
@ -36,7 +47,7 @@ namespace sts::dmnt {
|
|||
|
||||
os::Mutex g_file_handle_lock;
|
||||
u64 g_cur_fd;
|
||||
std::unordered_map<u64, FsFile> g_file_handles;
|
||||
std::unordered_map<TargetIOFileHandle, FsFile> g_file_handles;
|
||||
|
||||
Result EnsureSdInitialized() {
|
||||
std::scoped_lock lk(g_sd_lock);
|
||||
|
@ -49,15 +60,15 @@ namespace sts::dmnt {
|
|||
return ResultSuccess;
|
||||
}
|
||||
|
||||
u64 GetNewFileHandle(FsFile f) {
|
||||
TargetIOFileHandle GetNewFileHandle(FsFile f) {
|
||||
std::scoped_lock lk(g_file_handle_lock);
|
||||
|
||||
u64 fd = g_cur_fd++;
|
||||
TargetIOFileHandle fd = { .value = g_cur_fd++ };
|
||||
g_file_handles[fd] = f;
|
||||
return fd;
|
||||
}
|
||||
|
||||
Result GetFileByHandle(FsFile *out, u64 handle) {
|
||||
Result GetFileByHandle(FsFile *out, TargetIOFileHandle handle) {
|
||||
std::scoped_lock lk(g_file_handle_lock);
|
||||
|
||||
if (g_file_handles.find(handle) != g_file_handles.end()) {
|
||||
|
@ -68,7 +79,7 @@ namespace sts::dmnt {
|
|||
return ResultFsInvalidArgument;
|
||||
}
|
||||
|
||||
Result CloseFileByHandle(u64 handle) {
|
||||
Result CloseFileByHandle(TargetIOFileHandle handle) {
|
||||
std::scoped_lock lk(g_file_handle_lock);
|
||||
|
||||
if (g_file_handles.find(handle) != g_file_handles.end()) {
|
||||
|
@ -80,18 +91,18 @@ namespace sts::dmnt {
|
|||
return ResultFsInvalidArgument;
|
||||
}
|
||||
|
||||
void FixPath(char *dst, size_t dst_size, InBuffer<char> &path) {
|
||||
void FixPath(char *dst, size_t dst_size, const sf::InBuffer &path) {
|
||||
dst[dst_size - 1] = 0;
|
||||
strncpy(dst, "/", dst_size - 1);
|
||||
|
||||
const char *src = path.buffer;
|
||||
const char *src = reinterpret_cast<const char *>(path.GetPointer());
|
||||
size_t src_idx = 0;
|
||||
size_t dst_idx = 1;
|
||||
while (src_idx < path.num_elements && (src[src_idx] == '/' || src[src_idx] == '\\')) {
|
||||
while (src_idx < path.GetSize() && (src[src_idx] == '/' || src[src_idx] == '\\')) {
|
||||
src_idx++;
|
||||
}
|
||||
|
||||
while (src_idx < path.num_elements && dst_idx < dst_size - 1 && src[src_idx] != 0) {
|
||||
while (src_idx < path.GetSize() && dst_idx < dst_size - 1 && src[src_idx] != 0) {
|
||||
if (src[src_idx] == '\\') {
|
||||
dst[dst_idx] = '/';
|
||||
} else {
|
||||
|
@ -109,12 +120,7 @@ namespace sts::dmnt {
|
|||
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileOpen(OutBuffer<u64> out_hnd, InBuffer<char> path, int open_mode, u32 create_mode) {
|
||||
if (out_hnd.num_elements != 1) {
|
||||
/* Serialization error. */
|
||||
return ResultKernelConnectionClosed;
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileOpen(sf::Out<TargetIOFileHandle> out_hnd, const sf::InBuffer &path, int open_mode, u32 create_mode) {
|
||||
R_TRY(EnsureSdInitialized());
|
||||
|
||||
char fs_path[FS_MAX_PATH];
|
||||
|
@ -144,84 +150,66 @@ namespace sts::dmnt {
|
|||
|
||||
/* Cancel guard, output file handle. */
|
||||
file_guard.Cancel();
|
||||
out_hnd[0] = GetNewFileHandle(f);
|
||||
out_hnd.SetValue(GetNewFileHandle(f));
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileClose(InBuffer<u64> hnd) {
|
||||
if (hnd.num_elements != 1) {
|
||||
/* Serialization error. */
|
||||
return ResultKernelConnectionClosed;
|
||||
}
|
||||
|
||||
return CloseFileByHandle(hnd[0]);
|
||||
Result DebugMonitorService::TargetIO_FileClose(TargetIOFileHandle hnd) {
|
||||
return CloseFileByHandle(hnd);
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileRead(InBuffer<u64> hnd, OutBuffer<u8, BufferType_Type1> out_data, Out<u32> out_read, u64 offset) {
|
||||
if (hnd.num_elements != 1) {
|
||||
/* Serialization error. */
|
||||
return ResultKernelConnectionClosed;
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileRead(TargetIOFileHandle hnd, const sf::OutNonSecureBuffer &out_data, sf::Out<u32> out_read, u64 offset) {
|
||||
FsFile f;
|
||||
size_t read = 0;
|
||||
|
||||
R_TRY(GetFileByHandle(&f, hnd[0]));
|
||||
R_TRY(fsFileRead(&f, offset, out_data.buffer, out_data.num_elements, FS_READOPTION_NONE, &read));
|
||||
R_TRY(GetFileByHandle(&f, hnd));
|
||||
R_TRY(fsFileRead(&f, offset, out_data.GetPointer(), out_data.GetSize(), FsReadOption_None, &read));
|
||||
|
||||
out_read.SetValue(static_cast<u32>(read));
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileWrite(InBuffer<u64> hnd, InBuffer<u8, BufferType_Type1> data, Out<u32> out_written, u64 offset) {
|
||||
if (hnd.num_elements != 1) {
|
||||
/* Serialization error. */
|
||||
return ResultKernelConnectionClosed;
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileWrite(TargetIOFileHandle hnd, const sf::InNonSecureBuffer &data, sf::Out<u32> out_written, u64 offset) {
|
||||
FsFile f;
|
||||
|
||||
R_TRY(GetFileByHandle(&f, hnd[0]));
|
||||
R_TRY(fsFileWrite(&f, offset, data.buffer, data.num_elements, FS_WRITEOPTION_NONE));
|
||||
R_TRY(GetFileByHandle(&f, hnd));
|
||||
R_TRY(fsFileWrite(&f, offset, data.GetPointer(), data.GetSize(), FsWriteOption_None));
|
||||
|
||||
out_written.SetValue(data.num_elements);
|
||||
out_written.SetValue(data.GetSize());
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileSetAttributes(InBuffer<char> path, InBuffer<u8> attributes) {
|
||||
Result DebugMonitorService::TargetIO_FileSetAttributes(const sf::InBuffer &path, const sf::InBuffer &attributes) {
|
||||
/* I don't really know why this command exists, Horizon doesn't allow you to set any attributes. */
|
||||
/* N just returns ResultSuccess unconditionally here. */
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileGetInformation(InBuffer<char> path, OutBuffer<u64> out_info, Out<int> is_directory) {
|
||||
if (out_info.num_elements != 4) {
|
||||
/* Serialization error. */
|
||||
return ResultKernelConnectionClosed;
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileGetInformation(const sf::InBuffer &path, const sf::OutArray<u64> &out_info, sf::Out<int> is_directory) {
|
||||
R_TRY(EnsureSdInitialized());
|
||||
|
||||
char fs_path[FS_MAX_PATH];
|
||||
FixPath(fs_path, sizeof(fs_path), path);
|
||||
|
||||
for (size_t i = 0; i < out_info.num_elements; i++) {
|
||||
for (size_t i = 0; i < out_info.GetSize(); i++) {
|
||||
out_info[i] = 0;
|
||||
}
|
||||
is_directory.SetValue(0);
|
||||
|
||||
FsFile f;
|
||||
if (R_SUCCEEDED(fsFsOpenFile(&g_sd_fs, fs_path, FS_OPEN_READ, &f))) {
|
||||
if (R_SUCCEEDED(fsFsOpenFile(&g_sd_fs, fs_path, FsOpenMode_Read, &f))) {
|
||||
ON_SCOPE_EXIT { fsFileClose(&f); };
|
||||
|
||||
/* N doesn't check this return code. */
|
||||
fsFileGetSize(&f, &out_info[0]);
|
||||
if (out_info.GetSize() > 0) {
|
||||
fsFileGetSize(&f, &out_info[0]);
|
||||
}
|
||||
|
||||
/* TODO: N does not call fsFsGetFileTimestampRaw here, but we possibly could. */
|
||||
} else {
|
||||
FsDir dir;
|
||||
R_TRY(fsFsOpenDirectory(&g_sd_fs, fs_path, FS_DIROPEN_FILE | FS_DIROPEN_DIRECTORY, &dir));
|
||||
R_TRY(fsFsOpenDirectory(&g_sd_fs, fs_path, FsDirOpenMode_ReadFiles | FsDirOpenMode_ReadDirs, &dir));
|
||||
fsDirClose(&dir);
|
||||
is_directory.SetValue(1);
|
||||
}
|
||||
|
@ -229,35 +217,33 @@ namespace sts::dmnt {
|
|||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileSetTime(InBuffer<char> path, u64 create, u64 access, u64 modify) {
|
||||
Result DebugMonitorService::TargetIO_FileSetTime(const sf::InBuffer &path, u64 create, u64 access, u64 modify) {
|
||||
/* This is another function that doesn't really need to exist, because Horizon doesn't let you set anything. */
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileSetSize(InBuffer<char> input, u64 size) {
|
||||
Result DebugMonitorService::TargetIO_FileSetSize(const sf::InBuffer &input, u64 size) {
|
||||
/* Why does this function take in a path and not a file handle? */
|
||||
R_TRY(EnsureSdInitialized());
|
||||
|
||||
/* We will try to be better than N, here. N only treats input as a path. */
|
||||
if (input.num_elements == sizeof(u64)) {
|
||||
FsFile f;
|
||||
if (R_SUCCEEDED(GetFileByHandle(&f, reinterpret_cast<u64 *>(input.buffer)[0]))) {
|
||||
FsFile f;
|
||||
if (input.GetSize() == sizeof(TargetIOFileHandle)) {
|
||||
if (R_SUCCEEDED(GetFileByHandle(&f, *reinterpret_cast<const TargetIOFileHandle *>(input.GetPointer())))) {
|
||||
return fsFileSetSize(&f, size);
|
||||
}
|
||||
}
|
||||
|
||||
R_TRY(EnsureSdInitialized());
|
||||
|
||||
char fs_path[FS_MAX_PATH];
|
||||
FixPath(fs_path, sizeof(fs_path), input);
|
||||
|
||||
FsFile f;
|
||||
R_TRY(fsFsOpenFile(&g_sd_fs, fs_path, FS_OPEN_WRITE, &f));
|
||||
R_TRY(fsFsOpenFile(&g_sd_fs, fs_path, FsOpenMode_Write, &f));
|
||||
ON_SCOPE_EXIT { fsFileClose(&f); };
|
||||
|
||||
return fsFileSetSize(&f, size);
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileDelete(InBuffer<char> path) {
|
||||
Result DebugMonitorService::TargetIO_FileDelete(const sf::InBuffer &path) {
|
||||
R_TRY(EnsureSdInitialized());
|
||||
|
||||
char fs_path[FS_MAX_PATH];
|
||||
|
@ -266,15 +252,15 @@ namespace sts::dmnt {
|
|||
return fsFsDeleteFile(&g_sd_fs, fs_path);
|
||||
}
|
||||
|
||||
Result DebugMonitorService::TargetIO_FileMove(InBuffer<char> path0, InBuffer<char> path1) {
|
||||
Result DebugMonitorService::TargetIO_FileMove(const sf::InBuffer &src_path, const sf::InBuffer &dst_path) {
|
||||
R_TRY(EnsureSdInitialized());
|
||||
|
||||
char fs_path0[FS_MAX_PATH];
|
||||
char fs_path1[FS_MAX_PATH];
|
||||
FixPath(fs_path0, sizeof(fs_path0), path0);
|
||||
FixPath(fs_path1, sizeof(fs_path1), path1);
|
||||
char fs_src_path[FS_MAX_PATH];
|
||||
char fs_dst_path[FS_MAX_PATH];
|
||||
FixPath(fs_src_path, sizeof(fs_src_path), src_path);
|
||||
FixPath(fs_dst_path, sizeof(fs_dst_path), dst_path);
|
||||
|
||||
return fsFsRenameFile(&g_sd_fs, fs_path0, fs_path1);
|
||||
return fsFsRenameFile(&g_sd_fs, fs_src_path, fs_dst_path);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -132,7 +132,6 @@ namespace {
|
|||
constexpr size_t PrivateMaxSessions = 4;
|
||||
|
||||
/* fatal:u, fatal:p. */
|
||||
/* TODO: Consider max sessions enforcement? */
|
||||
constexpr size_t NumServers = 2;
|
||||
constexpr size_t NumSessions = UserMaxSessions + PrivateMaxSessions;
|
||||
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../os/os_common_types.hpp"
|
||||
#include "../ncm/ncm_types.hpp"
|
||||
#include "../sf/sf_buffer_tags.hpp"
|
||||
|
||||
namespace sts::dmnt::cheat {
|
||||
|
||||
|
@ -26,7 +28,7 @@ namespace sts::dmnt::cheat {
|
|||
u64 size;
|
||||
};
|
||||
|
||||
u64 process_id;
|
||||
os::ProcessId process_id;
|
||||
ncm::TitleId title_id;
|
||||
MemoryRegionExtents main_nso_extents;
|
||||
MemoryRegionExtents heap_extents;
|
||||
|
@ -37,18 +39,21 @@ namespace sts::dmnt::cheat {
|
|||
|
||||
static_assert(std::is_pod<CheatProcessMetadata>::value && sizeof(CheatProcessMetadata) == 0x70, "CheatProcessMetadata definition!");
|
||||
|
||||
struct CheatDefinition {
|
||||
struct CheatDefinition : sf::LargeData, sf::PrefersMapAliasTransferMode {
|
||||
char readable_name[0x40];
|
||||
uint32_t num_opcodes;
|
||||
uint32_t opcodes[0x100];
|
||||
};
|
||||
|
||||
struct CheatEntry {
|
||||
struct CheatEntry : sf::LargeData, sf::PrefersMapAliasTransferMode {
|
||||
bool enabled;
|
||||
uint32_t cheat_id;
|
||||
CheatDefinition definition;
|
||||
};
|
||||
|
||||
static_assert(std::is_pod<CheatDefinition>::value, "CheatDefinition");
|
||||
static_assert(std::is_pod<CheatEntry>::value, "CheatEntry");
|
||||
|
||||
struct FrozenAddressValue {
|
||||
u64 value;
|
||||
u8 width;
|
||||
|
|
|
@ -46,10 +46,14 @@ namespace sts::os {
|
|||
|
||||
inline constexpr const ProcessId InvalidProcessId = ProcessId::Invalid;
|
||||
|
||||
NX_INLINE Result GetProcessId(os::ProcessId *out, ::Handle process_handle) {
|
||||
return svcGetProcessId(&out->value, process_handle);
|
||||
}
|
||||
|
||||
NX_INLINE ProcessId GetCurrentProcessId() {
|
||||
u64 current_process_id = 0;
|
||||
R_ASSERT(svcGetProcessId(¤t_process_id, CUR_PROCESS_HANDLE));
|
||||
return os::ProcessId{current_process_id};
|
||||
os::ProcessId current_process_id;
|
||||
R_ASSERT(GetProcessId(¤t_process_id, CUR_PROCESS_HANDLE));
|
||||
return current_process_id;
|
||||
}
|
||||
|
||||
inline constexpr bool operator==(const ProcessId &lhs, const ProcessId &rhs) {
|
||||
|
|
|
@ -52,4 +52,10 @@ namespace sts::os {
|
|||
}
|
||||
};
|
||||
|
||||
NX_INLINE u32 GetCurrentThreadPriority() {
|
||||
u32 prio;
|
||||
R_ASSERT(svcGetThreadPriority(&prio, CUR_THREAD_HANDLE));
|
||||
return prio;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue