diff --git a/Makefile b/Makefile
index ea746be8..add6a081 100644
--- a/Makefile
+++ b/Makefile
@@ -32,7 +32,7 @@ CFLAGS := -g -Wall -O2 -ffunction-sections \
CFLAGS += $(INCLUDE) -D__SWITCH__
-CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17
+CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -flto -std=gnu++17
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
diff --git a/include/stratosphere/dmnt.hpp b/include/stratosphere/dmnt.hpp
new file mode 100644
index 00000000..62539959
--- /dev/null
+++ b/include/stratosphere/dmnt.hpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2018-2019 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 "dmnt/dmnt_cheat_types.hpp"
diff --git a/include/stratosphere/dmnt/dmnt_cheat_types.hpp b/include/stratosphere/dmnt/dmnt_cheat_types.hpp
new file mode 100644
index 00000000..1edb9192
--- /dev/null
+++ b/include/stratosphere/dmnt/dmnt_cheat_types.hpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2018-2019 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 "../ncm/ncm_types.hpp"
+
+namespace sts::dmnt::cheat {
+
+ struct CheatProcessMetadata {
+ struct MemoryRegionExtents {
+ u64 base;
+ u64 size;
+ };
+
+ u64 process_id;
+ ncm::TitleId title_id;
+ MemoryRegionExtents main_nso_extents;
+ MemoryRegionExtents heap_extents;
+ MemoryRegionExtents alias_extents;
+ MemoryRegionExtents aslr_extents;
+ u8 main_nso_build_id[0x20];
+ };
+
+ static_assert(std::is_pod::value && sizeof(CheatProcessMetadata) == 0x70, "CheatProcessMetadata definition!");
+
+ struct CheatDefinition {
+ char readable_name[0x40];
+ uint32_t num_opcodes;
+ uint32_t opcodes[0x100];
+ };
+
+ struct CheatEntry {
+ bool enabled;
+ uint32_t cheat_id;
+ CheatDefinition definition;
+ };
+
+ struct FrozenAddressValue {
+ u64 value;
+ u8 width;
+ };
+
+ struct FrozenAddressEntry {
+ u64 address;
+ FrozenAddressValue value;
+ };
+
+}
diff --git a/include/stratosphere/hossynch.hpp b/include/stratosphere/hossynch.hpp
index 624dba80..2b654a74 100644
--- a/include/stratosphere/hossynch.hpp
+++ b/include/stratosphere/hossynch.hpp
@@ -224,24 +224,33 @@ class HosSignal {
mutexUnlock(&m);
}
- void Wait() {
+ void Wait(bool reset = false) {
mutexLock(&m);
while (!signaled) {
condvarWait(&cv, &m);
}
+ if (reset) {
+ this->signaled = false;
+ }
+
mutexUnlock(&m);
}
- bool TryWait() {
+ bool TryWait(bool reset = false) {
mutexLock(&m);
+
bool success = signaled;
+ if (reset) {
+ this->signaled = false;
+ }
+
mutexUnlock(&m);
return success;
}
- Result TimedWait(u64 ns) {
+ Result TimedWait(u64 ns, bool reset = false) {
mutexLock(&m);
TimeoutHelper timeout_helper(ns);
@@ -251,6 +260,10 @@ class HosSignal {
}
}
+ if (reset) {
+ this->signaled = false;
+ }
+
mutexUnlock(&m);
return true;
}
diff --git a/include/stratosphere/pm.hpp b/include/stratosphere/pm.hpp
index 92d8eef6..2a8d7976 100644
--- a/include/stratosphere/pm.hpp
+++ b/include/stratosphere/pm.hpp
@@ -20,4 +20,5 @@
#include "pm/pm_types.hpp"
#include "pm/pm_boot_mode_api.hpp"
#include "pm/pm_info_api.hpp"
-#include "pm/pm_shell_api.hpp"
\ No newline at end of file
+#include "pm/pm_shell_api.hpp"
+#include "pm/pm_dmnt_api.hpp"
\ No newline at end of file
diff --git a/include/stratosphere/pm/pm_dmnt_api.hpp b/include/stratosphere/pm/pm_dmnt_api.hpp
new file mode 100644
index 00000000..607b4c43
--- /dev/null
+++ b/include/stratosphere/pm/pm_dmnt_api.hpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018-2019 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 "../ldr.hpp"
+#include "pm_types.hpp"
+
+namespace sts::pm::dmnt {
+
+ /* Debug Monitor API. */
+ Result StartProcess(u64 process_id);
+ Result GetProcessId(u64 *out_process_id, const ncm::TitleId title_id);
+ Result GetApplicationProcessId(u64 *out_process_id);
+ Result HookToCreateApplicationProcess(Handle *out_handle);
+ Result AtmosphereGetProcessInfo(Handle *out_handle, ncm::TitleLocation *out_loc, u64 process_id);
+ Result AtmosphereGetCurrentLimitInfo(u64 *out_current_value, u64 *out_limit_value, ResourceLimitGroup group, LimitableResource resource);
+
+}
diff --git a/source/pm/pm_ams.c b/source/pm/pm_ams.c
index 46882eb0..2e1c1988 100644
--- a/source/pm/pm_ams.c
+++ b/source/pm/pm_ams.c
@@ -94,3 +94,94 @@ Result pminfoAtmosphereHasLaunchedTitle(bool *out, u64 tid) {
return rc;
}
+
+Result pmdmntAtmosphereGetProcessInfo(Handle* out, u64 *tid_out, u8 *sid_out, u64 pid) {
+ IpcCommand c;
+ ipcInitialize(&c);
+ Service *s = pmdmntGetServiceSession();
+
+ struct {
+ u64 magic;
+ u64 cmd_id;
+ u64 pid;
+ } *raw;
+
+ raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
+
+ raw->magic = SFCI_MAGIC;
+ raw->cmd_id = 65000;
+ raw->pid = pid;
+
+ Result rc = serviceIpcDispatch(s);
+
+ if (R_SUCCEEDED(rc)) {
+ IpcParsedCommand r;
+ struct {
+ u64 magic;
+ u64 result;
+ u64 title_id;
+ FsStorageId storage_id;
+ } *resp;
+
+ serviceIpcParse(s, &r, sizeof(*resp));
+ resp = r.Raw;
+
+ rc = resp->result;
+
+ if (R_SUCCEEDED(rc)) {
+ if (out) {
+ *out = r.Handles[0];
+ } else {
+ svcCloseHandle(r.Handles[0]);
+ }
+ if (tid_out) *tid_out = resp->title_id;
+ if (sid_out) *sid_out = resp->storage_id;
+ }
+ }
+
+ return rc;
+}
+
+Result pmdmntAtmosphereGetCurrentLimitInfo(u64 *out_cur, u64 *out_lim, u32 group, u32 resource) {
+ IpcCommand c;
+ ipcInitialize(&c);
+ Service *s = pmdmntGetServiceSession();
+
+ struct {
+ u64 magic;
+ u64 cmd_id;
+ u32 group;
+ u32 resource;
+ } *raw;
+
+ raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
+
+ raw->magic = SFCI_MAGIC;
+ raw->cmd_id = 65001;
+ raw->group = group;
+ raw->resource = resource;
+
+ Result rc = serviceIpcDispatch(s);
+
+ if (R_SUCCEEDED(rc)) {
+ IpcParsedCommand r;
+ struct {
+ u64 magic;
+ u64 result;
+ u64 cur_value;
+ u64 lim_value;
+ } *resp;
+
+ serviceIpcParse(s, &r, sizeof(*resp));
+ resp = r.Raw;
+
+ rc = resp->result;
+
+ if (R_SUCCEEDED(rc)) {
+ if (out_cur) *out_cur = resp->cur_value;
+ if (out_lim) *out_lim = resp->lim_value;
+ }
+ }
+
+ return rc;
+}
diff --git a/source/pm/pm_ams.h b/source/pm/pm_ams.h
index 78bc9ce9..11887971 100644
--- a/source/pm/pm_ams.h
+++ b/source/pm/pm_ams.h
@@ -14,6 +14,9 @@ extern "C" {
Result pminfoAtmosphereGetProcessId(u64 *out_pid, u64 tid);
Result pminfoAtmosphereHasLaunchedTitle(bool *out, u64 tid);
+Result pmdmntAtmosphereGetProcessInfo(Handle *out, u64 *tid_out, u8 *sid_out, u64 pid);
+Result pmdmntAtmosphereGetCurrentLimitInfo(u64 *out_cur, u64 *out_lim, u32 group, u32 resource);
+
#ifdef __cplusplus
}
#endif
\ No newline at end of file
diff --git a/source/pm/pm_dmnt_api.cpp b/source/pm/pm_dmnt_api.cpp
new file mode 100644
index 00000000..2ea35478
--- /dev/null
+++ b/source/pm/pm_dmnt_api.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018-2019 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
+
+#include "pm_ams.h"
+
+namespace sts::pm::dmnt {
+
+ /* Debug Monitor API. */
+ Result StartProcess(u64 process_id) {
+ return pmdmntStartProcess(process_id);
+ }
+
+ Result GetProcessId(u64 *out_process_id, const ncm::TitleId title_id) {
+ return pmdmntGetTitlePid(out_process_id, static_cast(title_id));
+ }
+
+ Result GetApplicationProcessId(u64 *out_process_id) {
+ return pmdmntGetApplicationPid(out_process_id);
+ }
+
+ Result HookToCreateApplicationProcess(Handle *out_handle) {
+ return pmdmntEnableDebugForApplication(out_handle);
+ }
+
+ Result AtmosphereGetProcessInfo(Handle *out_handle, ncm::TitleLocation *out_loc, u64 process_id) {
+ *out_handle = INVALID_HANDLE;
+ *out_loc = {};
+ return pmdmntAtmosphereGetProcessInfo(out_handle, reinterpret_cast(&out_loc->title_id), &out_loc->storage_id, process_id);
+ }
+
+ Result AtmosphereGetCurrentLimitInfo(u64 *out_current_value, u64 *out_limit_value, ResourceLimitGroup group, LimitableResource resource) {
+ *out_current_value = 0;
+ *out_limit_value = 0;
+ return pmdmntAtmosphereGetCurrentLimitInfo(out_current_value, out_limit_value, group, resource);
+ }
+
+}