dmnt: update for new-ipc

This commit is contained in:
Michael Scire 2019-10-17 21:18:27 -07:00 committed by SciresM
parent 89c6fc6437
commit e5d62025d3
13 changed files with 326 additions and 248 deletions

View file

@ -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:

View file

@ -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),
};
};

View file

@ -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);
}

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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),
};
};

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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(&current_process_id, CUR_PROCESS_HANDLE));
return os::ProcessId{current_process_id};
os::ProcessId current_process_id;
R_ASSERT(GetProcessId(&current_process_id, CUR_PROCESS_HANDLE));
return current_process_id;
}
inline constexpr bool operator==(const ProcessId &lhs, const ProcessId &rhs) {

View file

@ -52,4 +52,10 @@ namespace sts::os {
}
};
NX_INLINE u32 GetCurrentThreadPriority() {
u32 prio;
R_ASSERT(svcGetThreadPriority(&prio, CUR_THREAD_HANDLE));
return prio;
}
}