diff --git a/stratosphere/dmnt/source/dmnt_debug_monitor.cpp b/stratosphere/dmnt/source/dmnt_debug_monitor.cpp
deleted file mode 100644
index 2e287e6..0000000
--- a/stratosphere/dmnt/source/dmnt_debug_monitor.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2018 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 .
- */
-
-#include
-#include "dmnt_debug_monitor.hpp"
-
-Result DebugMonitorService::BreakDebugProcess(Handle debug_hnd) {
- /* Nintendo discards the output of this command, but we will return it. */
- return svcBreakDebugProcess(debug_hnd);
-}
-
-Result DebugMonitorService::TerminateDebugProcess(Handle debug_hnd) {
- /* Nintendo discards the output of this command, but we will return it. */
- return svcTerminateDebugProcess(debug_hnd);
-}
-
-Result DebugMonitorService::CloseHandle(Handle debug_hnd) {
- /* Nintendo discards the output of this command, but we will return it. */
- /* This command is, entertainingly, also pretty unsafe in general... */
- return svcCloseHandle(debug_hnd);
-}
-
-Result DebugMonitorService::GetProcessId(Out out_pid, Handle hnd) {
- /* Nintendo discards the output of this command, but we will return it. */
- return svcGetProcessId(out_pid.GetPointer(), hnd);
-}
-
-Result DebugMonitorService::GetProcessHandle(Out out_hnd, u64 pid) {
- Result rc = svcDebugActiveProcess(out_hnd.GetPointer(), pid);
- if (rc == 0xF401) {
- rc = 0x4B7;
- }
- return rc;
-}
-
-Result DebugMonitorService::WaitSynchronization(Handle hnd, u64 ns) {
- /* Nintendo discards the output of this command, but we will return it. */
- return svcWaitSynchronizationSingle(hnd, ns);
-}
diff --git a/stratosphere/dmnt/source/dmnt_debug_monitor.hpp b/stratosphere/dmnt/source/dmnt_debug_monitor.hpp
deleted file mode 100644
index bd73d4a..0000000
--- a/stratosphere/dmnt/source/dmnt_debug_monitor.hpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2018 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 .
- */
-
-#pragma once
-#include
-#include
-
-enum DmntCmd {
- DebugMonitor_Cmd_BreakDebugProcess = 0,
- DebugMonitor_Cmd_TerminateDebugProcess = 1,
- DebugMonitor_Cmd_CloseHandle = 2,
- DebugMonitor_Cmd_LoadImage = 3,
- DebugMonitor_Cmd_GetProcessId = 4,
- DebugMonitor_Cmd_GetProcessHandle = 5,
- DebugMonitor_Cmd_WaitSynchronization = 6,
- DebugMonitor_Cmd_GetDebugEvent = 7,
- DebugMonitor_Cmd_GetProcessModuleInfo = 8,
- DebugMonitor_Cmd_GetProcessList = 9,
- DebugMonitor_Cmd_GetThreadList = 10,
- DebugMonitor_Cmd_GetDebugThreadContext = 11,
- DebugMonitor_Cmd_ContinueDebugEvent = 12,
- DebugMonitor_Cmd_ReadDebugProcessMemory = 13,
- DebugMonitor_Cmd_WriteDebugProcessMemory = 14,
- DebugMonitor_Cmd_SetDebugThreadContext = 15,
- DebugMonitor_Cmd_GetDebugThreadParam = 16,
- DebugMonitor_Cmd_InitializeThreadInfo = 17,
- DebugMonitor_Cmd_SetHardwareBreakPoint = 18,
- DebugMonitor_Cmd_QueryDebugProcessMemory = 19,
- DebugMonitor_Cmd_GetProcessMemoryDetails = 20,
- DebugMonitor_Cmd_AttachByProgramId = 21,
- DebugMonitor_Cmd_AttachOnLaunch = 22,
- DebugMonitor_Cmd_GetDebugMonitorProcessId = 23,
- DebugMonitor_Cmd_GetJitDebugProcessList = 25,
- DebugMonitor_Cmd_CreateCoreDump = 26,
- DebugMonitor_Cmd_GetAllDebugThreadInfo = 27,
- DebugMonitor_Cmd_TargetIO_FileOpen = 29,
- DebugMonitor_Cmd_TargetIO_FileClose = 30,
- DebugMonitor_Cmd_TargetIO_FileRead = 31,
- DebugMonitor_Cmd_TargetIO_FileWrite = 32,
- DebugMonitor_Cmd_TargetIO_FileSetAttributes = 33,
- DebugMonitor_Cmd_TargetIO_FileGetInformation = 34,
- DebugMonitor_Cmd_TargetIO_FileSetTime = 35,
- DebugMonitor_Cmd_TargetIO_FileSetSize = 36,
- DebugMonitor_Cmd_TargetIO_FileDelete = 37,
- DebugMonitor_Cmd_TargetIO_FileMove = 38,
- DebugMonitor_Cmd_TargetIO_DirectoryCreate = 39,
- DebugMonitor_Cmd_TargetIO_DirectoryDelete = 40,
- DebugMonitor_Cmd_TargetIO_DirectoryRename = 41,
- DebugMonitor_Cmd_TargetIO_DirectoryGetCount = 42,
- DebugMonitor_Cmd_TargetIO_DirectoryOpen = 43,
- DebugMonitor_Cmd_TargetIO_DirectoryGetNext = 44,
- DebugMonitor_Cmd_TargetIO_DirectoryClose = 45,
- DebugMonitor_Cmd_TargetIO_GetFreeSpace = 46,
- DebugMonitor_Cmd_TargetIO_GetVolumeInformation = 47,
- DebugMonitor_Cmd_InitiateCoreDump = 48,
- DebugMonitor_Cmd_ContinueCoreDump = 49,
- DebugMonitor_Cmd_AddTTYToCoreDump = 50,
- DebugMonitor_Cmd_AddImageToCoreDump = 51,
- DebugMonitor_Cmd_CloseCoreDump = 52,
- DebugMonitor_Cmd_CancelAttach = 53,
-};
-
-class DebugMonitorService final : public IServiceObject {
- private:
- Result BreakDebugProcess(Handle debug_hnd);
- Result TerminateDebugProcess(Handle debug_hnd);
- Result CloseHandle(Handle debug_hnd);
- Result GetProcessId(Out out_pid, Handle hnd);
- Result GetProcessHandle(Out out_hnd, u64 pid);
- Result WaitSynchronization(Handle hnd, u64 ns);
- public:
- DEFINE_SERVICE_DISPATCH_TABLE {
- MakeServiceCommandMeta(),
- MakeServiceCommandMeta(),
- MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- MakeServiceCommandMeta(),
- MakeServiceCommandMeta(),
- MakeServiceCommandMeta(),
- //MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- // MakeServiceCommandMeta(),
- };
-};
diff --git a/stratosphere/dmnt/source/dmnt_main.cpp b/stratosphere/dmnt/source/dmnt_main.cpp
index dbf9366..fc4917f 100644
--- a/stratosphere/dmnt/source/dmnt_main.cpp
+++ b/stratosphere/dmnt/source/dmnt_main.cpp
@@ -23,7 +23,7 @@
#include
#include
-#include "dmnt_debug_monitor.hpp"
+#include "dmnt_service.hpp"
extern "C" {
extern u32 __start__;
diff --git a/stratosphere/dmnt/source/dmnt_service.hpp b/stratosphere/dmnt/source/dmnt_service.hpp
new file mode 100644
index 0000000..4959657
--- /dev/null
+++ b/stratosphere/dmnt/source/dmnt_service.hpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2018 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 .
+ */
+
+#pragma once
+#include
+#include
+
+enum DmntCmd {
+ DebugMonitor_Cmd_BreakDebugProcess = 0,
+ DebugMonitor_Cmd_TerminateDebugProcess = 1,
+ DebugMonitor_Cmd_CloseHandle = 2,
+ DebugMonitor_Cmd_LoadImage = 3,
+ DebugMonitor_Cmd_GetProcessId = 4,
+ DebugMonitor_Cmd_GetProcessHandle = 5,
+ DebugMonitor_Cmd_WaitSynchronization = 6,
+ DebugMonitor_Cmd_GetDebugEvent = 7,
+ DebugMonitor_Cmd_GetProcessModuleInfo = 8,
+ DebugMonitor_Cmd_GetProcessList = 9,
+ DebugMonitor_Cmd_GetThreadList = 10,
+ DebugMonitor_Cmd_GetDebugThreadContext = 11,
+ DebugMonitor_Cmd_ContinueDebugEvent = 12,
+ DebugMonitor_Cmd_ReadDebugProcessMemory = 13,
+ DebugMonitor_Cmd_WriteDebugProcessMemory = 14,
+ DebugMonitor_Cmd_SetDebugThreadContext = 15,
+ DebugMonitor_Cmd_GetDebugThreadParam = 16,
+ DebugMonitor_Cmd_InitializeThreadInfo = 17,
+ DebugMonitor_Cmd_SetHardwareBreakPoint = 18,
+ DebugMonitor_Cmd_QueryDebugProcessMemory = 19,
+ DebugMonitor_Cmd_GetProcessMemoryDetails = 20,
+ DebugMonitor_Cmd_AttachByProgramId = 21,
+ DebugMonitor_Cmd_AttachOnLaunch = 22,
+ DebugMonitor_Cmd_GetDebugMonitorProcessId = 23,
+ DebugMonitor_Cmd_GetJitDebugProcessList = 25,
+ DebugMonitor_Cmd_CreateCoreDump = 26,
+ DebugMonitor_Cmd_GetAllDebugThreadInfo = 27,
+ DebugMonitor_Cmd_TargetIO_FileOpen = 29,
+ DebugMonitor_Cmd_TargetIO_FileClose = 30,
+ DebugMonitor_Cmd_TargetIO_FileRead = 31,
+ DebugMonitor_Cmd_TargetIO_FileWrite = 32,
+ DebugMonitor_Cmd_TargetIO_FileSetAttributes = 33,
+ DebugMonitor_Cmd_TargetIO_FileGetInformation = 34,
+ DebugMonitor_Cmd_TargetIO_FileSetTime = 35,
+ DebugMonitor_Cmd_TargetIO_FileSetSize = 36,
+ DebugMonitor_Cmd_TargetIO_FileDelete = 37,
+ DebugMonitor_Cmd_TargetIO_FileMove = 38,
+ DebugMonitor_Cmd_TargetIO_DirectoryCreate = 39,
+ DebugMonitor_Cmd_TargetIO_DirectoryDelete = 40,
+ DebugMonitor_Cmd_TargetIO_DirectoryRename = 41,
+ DebugMonitor_Cmd_TargetIO_DirectoryGetCount = 42,
+ DebugMonitor_Cmd_TargetIO_DirectoryOpen = 43,
+ DebugMonitor_Cmd_TargetIO_DirectoryGetNext = 44,
+ DebugMonitor_Cmd_TargetIO_DirectoryClose = 45,
+ DebugMonitor_Cmd_TargetIO_GetFreeSpace = 46,
+ DebugMonitor_Cmd_TargetIO_GetVolumeInformation = 47,
+ DebugMonitor_Cmd_InitiateCoreDump = 48,
+ DebugMonitor_Cmd_ContinueCoreDump = 49,
+ DebugMonitor_Cmd_AddTTYToCoreDump = 50,
+ DebugMonitor_Cmd_AddImageToCoreDump = 51,
+ DebugMonitor_Cmd_CloseCoreDump = 52,
+ DebugMonitor_Cmd_CancelAttach = 53,
+};
+
+class DebugMonitorService final : public IServiceObject {
+ private:
+ Result BreakDebugProcess(Handle debug_hnd);
+ Result TerminateDebugProcess(Handle debug_hnd);
+ Result CloseHandle(Handle debug_hnd);
+ Result GetProcessId(Out out_pid, Handle hnd);
+ Result GetProcessHandle(Out out_hnd, u64 pid);
+ Result WaitSynchronization(Handle hnd, u64 ns);
+
+ Result TargetIO_FileOpen(OutBuffer out_hnd, InBuffer path, int open_mode, u32 create_mode);
+ Result TargetIO_FileClose(InBuffer hnd);
+ Result TargetIO_FileRead(InBuffer hnd, OutBuffer out_data, Out out_read, u64 offset);
+ Result TargetIO_FileWrite(InBuffer hnd, InBuffer data, Out out_written, u64 offset);
+ public:
+ DEFINE_SERVICE_DISPATCH_TABLE {
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ //MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ // MakeServiceCommandMeta(),
+ };
+};
diff --git a/stratosphere/dmnt/source/dmnt_service_debug.cpp b/stratosphere/dmnt/source/dmnt_service_debug.cpp
new file mode 100644
index 0000000..2c384a9
--- /dev/null
+++ b/stratosphere/dmnt/source/dmnt_service_debug.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018 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 .
+ */
+
+#include
+#include "dmnt_service.hpp"
+
+Result DebugMonitorService::BreakDebugProcess(Handle debug_hnd) {
+ /* Nintendo discards the output of this command, but we will return it. */
+ return svcBreakDebugProcess(debug_hnd);
+}
+
+Result DebugMonitorService::TerminateDebugProcess(Handle debug_hnd) {
+ /* Nintendo discards the output of this command, but we will return it. */
+ return svcTerminateDebugProcess(debug_hnd);
+}
+
+Result DebugMonitorService::CloseHandle(Handle debug_hnd) {
+ /* Nintendo discards the output of this command, but we will return it. */
+ /* This command is, entertainingly, also pretty unsafe in general... */
+ return svcCloseHandle(debug_hnd);
+}
+
+Result DebugMonitorService::GetProcessId(Out out_pid, Handle hnd) {
+ /* Nintendo discards the output of this command, but we will return it. */
+ return svcGetProcessId(out_pid.GetPointer(), hnd);
+}
+
+Result DebugMonitorService::GetProcessHandle(Out out_hnd, u64 pid) {
+ Result rc = svcDebugActiveProcess(out_hnd.GetPointer(), pid);
+ if (rc == 0xF401) {
+ rc = 0x4B7;
+ }
+ return rc;
+}
+
+Result DebugMonitorService::WaitSynchronization(Handle hnd, u64 ns) {
+ /* Nintendo discards the output of this command, but we will return it. */
+ return svcWaitSynchronizationSingle(hnd, ns);
+}
diff --git a/stratosphere/dmnt/source/dmnt_service_target_io.cpp b/stratosphere/dmnt/source/dmnt_service_target_io.cpp
new file mode 100644
index 0000000..15f8e08
--- /dev/null
+++ b/stratosphere/dmnt/source/dmnt_service_target_io.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2018 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 .
+ */
+
+#include
+#include
+#include "dmnt_service.hpp"
+
+enum TIOCreateOption : u32 {
+ TIOCreateOption_CreateNew = 1,
+ TIOCreateOption_CreateAlways = 2,
+ TIOCreateOption_OpenExisting = 3,
+ TIOCreateOption_OpenAlways = 4,
+ TIOCreateOption_ResetSize = 5,
+};
+
+/* Nintendo uses actual pointers as file handles. We'll add a layer of indirection... */
+static bool g_sd_initialized = false;
+static HosMutex g_sd_lock;
+static FsFileSystem g_sd_fs;
+
+static HosMutex g_file_handle_lock;
+static u64 g_cur_fd = 0;
+static std::unordered_map g_file_handles;
+
+static Result EnsureSdInitialized() {
+ std::scoped_lock lk(g_sd_lock);
+ if (g_sd_initialized) {
+ return 0;
+ }
+
+ Result rc = fsMountSdcard(&g_sd_fs);
+ if (R_SUCCEEDED(rc)) {
+ g_sd_initialized = true;
+ }
+ return rc;
+}
+
+static u64 GetFileHandle(FsFile f) {
+ std::scoped_lock lk(g_file_handle_lock);
+
+ u64 fd = g_cur_fd++;
+ g_file_handles[fd] = f;
+ return fd;
+}
+
+static Result GetFileByHandle(FsFile *out, u64 handle) {
+ std::scoped_lock lk(g_file_handle_lock);
+ if (g_file_handles.find(handle) != g_file_handles.end()) {
+ *out = g_file_handles[handle];
+ return 0;
+ }
+ return 0x2EE202;
+}
+
+static Result CloseFileByHandle(u64 handle) {
+ std::scoped_lock lk(g_file_handle_lock);
+ if (g_file_handles.find(handle) != g_file_handles.end()) {
+ fsFileClose(&g_file_handles[handle]);
+ g_file_handles.erase(handle);
+ return 0;
+ }
+ return 0x2EE202;
+}
+
+static void FixPath(char *dst, size_t dst_size, InBuffer &path) {
+ dst[dst_size - 1] = 0;
+ strncpy(dst, "/", dst_size - 1);
+
+ const char *src = path.buffer;
+ size_t src_idx = 0;
+ size_t dst_idx = 1;
+ while (src_idx < path.num_elements && (src[src_idx] == '/' || src[src_idx] == '\\')) {
+ src_idx++;
+ }
+
+ while (src_idx < path.num_elements && dst_idx < dst_size - 1 && src[src_idx] != 0) {
+ if (src[src_idx] == '\\') {
+ dst[dst_idx] = '/';
+ } else {
+ dst[dst_idx] = src[src_idx];
+ }
+
+ src_idx++;
+ dst_idx++;
+ }
+
+ if (dst_idx < dst_size) {
+ dst[dst_idx] = 0;
+ }
+}
+
+Result DebugMonitorService::TargetIO_FileOpen(OutBuffer out_hnd, InBuffer path, int open_mode, u32 create_mode) {
+ if (out_hnd.num_elements != 1) {
+ return 0xF601;
+ }
+
+ Result rc = EnsureSdInitialized();
+ if (R_FAILED(rc)) {
+ return rc;
+ }
+
+ char fs_path[FS_MAX_PATH];
+
+ FixPath(fs_path, sizeof(fs_path), path);
+
+ if (create_mode == TIOCreateOption_CreateAlways) {
+ fsFsDeleteFile(&g_sd_fs, fs_path);
+ rc = fsFsCreateFile(&g_sd_fs, fs_path, 0, 0);
+ } else if (create_mode == TIOCreateOption_CreateNew) {
+ rc = fsFsCreateFile(&g_sd_fs, fs_path, 0, 0);
+ }
+
+ if (R_FAILED(rc)) {
+ return rc;
+ }
+
+ FsFile f;
+ rc = fsFsOpenFile(&g_sd_fs, fs_path, open_mode, &f);
+ if (R_FAILED(rc)) {
+ if (create_mode == TIOCreateOption_OpenAlways) {
+ fsFsCreateFile(&g_sd_fs, fs_path, 0, 0);
+ rc = fsFsOpenFile(&g_sd_fs, fs_path, open_mode, &f);
+ }
+ }
+
+ if (R_SUCCEEDED(rc)) {
+ if (create_mode == TIOCreateOption_ResetSize) {
+ rc = fsFileSetSize(&f, 0);
+ }
+ if (R_SUCCEEDED(rc)) {
+ out_hnd[0] = GetFileHandle(f);
+ } else {
+ fsFileClose(&f);
+ }
+ }
+
+ return rc;
+}
+
+Result DebugMonitorService::TargetIO_FileClose(InBuffer hnd) {
+ if (hnd.num_elements != 1) {
+ return 0xF601;
+ }
+
+ return CloseFileByHandle(hnd[0]);
+}
+
+Result DebugMonitorService::TargetIO_FileRead(InBuffer hnd, OutBuffer out_data, Out out_read, u64 offset) {
+ if (hnd.num_elements != 1) {
+ return 0xF601;
+ }
+
+ FsFile f;
+ Result rc = GetFileByHandle(&f, hnd[0]);
+ if (R_FAILED(rc)) {
+ return rc;
+ }
+
+ size_t read = 0;
+ rc = fsFileRead(&f, offset, out_data.buffer, out_data.num_elements, &read);
+ out_read.SetValue(static_cast(read));
+ return rc;
+}
+
+Result DebugMonitorService::TargetIO_FileWrite(InBuffer hnd, InBuffer data, Out out_written, u64 offset) {
+ if (hnd.num_elements != 1) {
+ return 0xF601;
+ }
+
+ FsFile f;
+ Result rc = GetFileByHandle(&f, hnd[0]);
+ if (R_FAILED(rc)) {
+ return rc;
+ }
+
+ rc = fsFileWrite(&f, offset, data.buffer, data.num_elements);
+ if (R_SUCCEEDED(rc)) {
+ out_written.SetValue(data.num_elements);
+ }
+
+ return rc;
+}