diff --git a/k11_extension/include/svc/MapProcessMemoryPrivate.h b/k11_extension/include/svc/MapProcessMemoryPrivate.h
new file mode 100644
index 000000000..b82290c7f
--- /dev/null
+++ b/k11_extension/include/svc/MapProcessMemoryPrivate.h
@@ -0,0 +1,34 @@
+/*
+* This file is part of Luma3DS
+* Copyright (C) 2016-2020 Aurora Wright, TuxSH
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that 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 .
+*
+* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
+* * Requiring preservation of specified reasonable legal notices or
+* author attributions in that material or in the Appropriate Legal
+* Notices displayed by works containing it.
+* * Prohibiting misrepresentation of the origin of that material,
+* or requiring that modified versions of such material be marked in
+* reasonable ways as different from the original version.
+*/
+
+#pragma once
+
+#include "utils.h"
+#include "kernel.h"
+#include "svc.h"
+
+Result MapProcessMemoryPrivate(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size);
+Result MapProcessMemoryPrivateWrapper(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size);
diff --git a/k11_extension/source/svc.c b/k11_extension/source/svc.c
index dceb1eeab..f29fda6b9 100644
--- a/k11_extension/source/svc.c
+++ b/k11_extension/source/svc.c
@@ -43,6 +43,7 @@
#include "svc/CustomBackdoor.h"
#include "svc/MapProcessMemoryEx.h"
#include "svc/UnmapProcessMemoryEx.h"
+#include "svc/MapProcessMemoryPrivate.h"
#include "svc/ControlService.h"
#include "svc/ControlProcess.h"
#include "svc/ExitProcess.h"
@@ -98,6 +99,7 @@ void buildAlteredSvcTable(void)
alteredSvcTable[0xA1] = UnmapProcessMemoryEx;
alteredSvcTable[0xA2] = ControlMemoryEx;
alteredSvcTable[0xA3] = ControlMemoryUnsafeWrapper;
+ alteredSvcTable[0xA4] = MapProcessMemoryPrivateWrapper;
alteredSvcTable[0xB0] = ControlService;
alteredSvcTable[0xB1] = CopyHandleWrapper;
diff --git a/k11_extension/source/svc/MapProcessMemoryPrivate.c b/k11_extension/source/svc/MapProcessMemoryPrivate.c
new file mode 100644
index 000000000..c1cf95d67
--- /dev/null
+++ b/k11_extension/source/svc/MapProcessMemoryPrivate.c
@@ -0,0 +1,86 @@
+/*
+* This file is part of Luma3DS
+* Copyright (C) 2016-2020 Aurora Wright, TuxSH
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that 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 .
+*
+* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
+* * Requiring preservation of specified reasonable legal notices or
+* author attributions in that material or in the Appropriate Legal
+* Notices displayed by works containing it.
+* * Prohibiting misrepresentation of the origin of that material,
+* or requiring that modified versions of such material be marked in
+* reasonable ways as different from the original version.
+*/
+
+#include "svc/MapProcessMemoryPrivate.h"
+
+Result MapProcessMemoryPrivate(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size)
+{
+ Result res = 0;
+ u32 sizeInPage = size >> 12;
+ KLinkedList list;
+ KProcess *srcProcess;
+ KProcess *dstProcess;
+ KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
+
+ if (dstProcessHandle == CUR_PROCESS_HANDLE)
+ {
+ dstProcess = currentCoreContext->objectContext.currentProcess;
+ KAutoObject__AddReference((KAutoObject *)dstProcess);
+ }
+ else
+ dstProcess = KProcessHandleTable__ToKProcess(handleTable, dstProcessHandle);
+
+ if (dstProcess == NULL)
+ return 0xD8E007F7;
+
+ if (srcProcessHandle == CUR_PROCESS_HANDLE)
+ {
+ srcProcess = currentCoreContext->objectContext.currentProcess;
+ KAutoObject__AddReference((KAutoObject *)srcProcess);
+ }
+ else
+ srcProcess = KProcessHandleTable__ToKProcess(handleTable, srcProcessHandle);
+
+ if (srcProcess == NULL)
+ {
+ res = 0xD8E007F7;
+ goto exit1;
+ }
+
+ KLinkedList__Initialize(&list);
+
+ res = KProcessHwInfo__GetListOfKBlockInfoForVA(hwInfoOfProcess(srcProcess), &list, vaSrc, sizeInPage);
+
+ if (res >= 0)
+ {
+ // Check if the destination address is free and large enough
+ res = KProcessHwInfo__CheckVaState(hwInfoOfProcess(dstProcess), vaDst, size, 0, 0);
+ if (res == 0)
+ res = KProcessHwInfo__MapListOfKBlockInfo(hwInfoOfProcess(dstProcess), vaDst, &list, 0xBB05, MEMPERM_RW | 0x18, 0);
+ }
+
+ KLinkedList_KBlockInfo__Clear(&list);
+
+ ((KAutoObject *)srcProcess)->vtable->DecrementReferenceCount((KAutoObject *)srcProcess);
+
+exit1:
+ ((KAutoObject *)dstProcess)->vtable->DecrementReferenceCount((KAutoObject *)dstProcess);
+
+ invalidateEntireInstructionCache();
+ flushEntireDataCache();
+
+ return res;
+}
diff --git a/k11_extension/source/svc/wrappers.s b/k11_extension/source/svc/wrappers.s
index 6d07ccde8..cb0cbda21 100644
--- a/k11_extension/source/svc/wrappers.s
+++ b/k11_extension/source/svc/wrappers.s
@@ -122,4 +122,13 @@ MapProcessMemoryExWrapper:
str r4, [sp, #-4]!
bl MapProcessMemoryEx
add sp, #4
+ pop {pc}
+
+.global MapProcessMemoryPrivateWrapper
+.type MapProcessMemoryPrivateWrapper, %function
+MapProcessMemoryPrivateWrapper:
+ push {lr}
+ str r4, [sp, #-4]!
+ bl MapProcessMemoryPrivate
+ add sp, #4
pop {pc}
\ No newline at end of file
diff --git a/sysmodules/rosalina/include/csvc.h b/sysmodules/rosalina/include/csvc.h
index f6d8ce989..d6dad38bd 100644
--- a/sysmodules/rosalina/include/csvc.h
+++ b/sysmodules/rosalina/include/csvc.h
@@ -83,6 +83,16 @@ void svcInvalidateEntireInstructionCache(void);
*/
Result svcMapProcessMemoryEx(Handle dstProcessHandle, u32 destAddress, Handle srcProcessHandle, u32 srcAddress, u32 size);
+/**
+ * @brief Maps a block of process memory, but sets MemState to PRIVATE instead of SHARED.
+ * @param dstProcessHandle Handle of the process to map the memory in (destination)
+ * @param destAddress Start address of the memory block in the destination process
+ * @param srcProcessHandle Handle of the process to map the memory from (source)
+ * @param srcAddress Start address of the memory block in the source process
+ * @param size Size of the block of the memory to map (truncated to a multiple of 0x1000 bytes)
+*/
+Result svcMapProcessMemoryPrivate(Handle dstProcessHandle, u32 destAddress, Handle srcProcessHandle, u32 srcAddress, u32 size);
+
/**
* @brief Unmaps a block of process memory.
* @param process Handle of the process to unmap the memory from
diff --git a/sysmodules/rosalina/source/csvc.s b/sysmodules/rosalina/source/csvc.s
index da6987533..97ba8bf2e 100644
--- a/sysmodules/rosalina/source/csvc.s
+++ b/sysmodules/rosalina/source/csvc.s
@@ -95,6 +95,14 @@ SVC_BEGIN svcFreeMemory
bx lr
SVC_END
+SVC_BEGIN svcMapProcessMemoryPrivate
+ str r4, [sp, #-4]!
+ ldr r4, [sp, #4]
+ svc 0xA4
+ ldr r4, [sp], #4
+ bx lr
+SVC_END
+
SVC_BEGIN svcControlService
svc 0xB0
bx lr
diff --git a/sysmodules/rosalina/source/plugin/memoryblock.c b/sysmodules/rosalina/source/plugin/memoryblock.c
index 8738f1efd..9889d93f8 100644
--- a/sysmodules/rosalina/source/plugin/memoryblock.c
+++ b/sysmodules/rosalina/source/plugin/memoryblock.c
@@ -217,7 +217,16 @@ Result MemoryBlock__MountInProcess(void)
}
// Heap (to be used by the plugin)
- if (R_FAILED((res = svcMapProcessMemoryEx(target, header->heapVA, CUR_PROCESS_HANDLE, (u32)memblock->memblock + header->exeSize, header->heapSize))))
+ if (header->heapSize > 0x500000)
+ {
+ res = svcMapProcessMemoryEx(target, header->heapVA, CUR_PROCESS_HANDLE, (u32)memblock->memblock + header->exeSize, header->heapSize);
+ }
+ else
+ {
+ res = svcMapProcessMemoryPrivate(target, header->heapVA, CUR_PROCESS_HANDLE, (u32)memblock->memblock + header->exeSize, header->heapSize);
+ }
+
+ if (R_FAILED(res))
{
error->message = "Couldn't map heap memory block";
error->code = res;
@@ -230,10 +239,13 @@ Result MemoryBlock__UnmountFromProcess(void)
{
Handle target = PluginLoaderCtx.target;
PluginHeader *header = &PluginLoaderCtx.header;
+ MemoryBlock *memblock = &PluginLoaderCtx.memblock;
Result res = 0;
- res = svcUnmapProcessMemoryEx(target, 0x07000000, header->exeSize);
+ res = svcMapProcessMemoryEx(target, header->heapVA, CUR_PROCESS_HANDLE, (u32) memblock->memblock + header->exeSize, header->heapSize);
+
+ res |= svcUnmapProcessMemoryEx(target, 0x07000000, header->exeSize);
res |= svcUnmapProcessMemoryEx(target, header->heapVA, header->heapSize);
return res;