diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md
index 11d093b..fd79937 100644
--- a/.github/ISSUE_TEMPLATE/bug-report.md
+++ b/.github/ISSUE_TEMPLATE/bug-report.md
@@ -7,13 +7,13 @@ about: Use this to report bugs you encounter with Luma3DS. Make sure you upload
-- THIS IS NOT A SUPPORT FORUM! For support go here:
-- Nintendo Homebrew: https://discord.gg/MjzatM8
--
--- Rosalina feature requests go here: https://github.com/AuroraWright/Luma3DS/issues/752
+-- Rosalina feature requests go here: https://github.com/LumaTeam/Luma3DS/issues/752
--
--- Also check the Wiki (https://github.com/AuroraWright/Luma3DS/wiki) before making an issue.
+-- Also check the Wiki (https://github.com/LumaTeam/Luma3DS/wiki) before making an issue.
--
-- For GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: use https://github.com/MechanicalDragon0687/TWLFix-CFW and update your system.
-- If you're using an emu/redNAND try installing anything on it to sysNAND.
--- Please make sure to read "Enable game patching" https://github.com/AuroraWright/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable game patching" option(s).
+-- Please make sure to read "Enable game patching" https://github.com/LumaTeam/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable game patching" option(s).
--
-- Luma updaters that don't support Boot9Strap/Sighax won't work.
-- This is due to support for non-B9S/Sighax entrypoints being dropped.
@@ -21,7 +21,7 @@ about: Use this to report bugs you encounter with Luma3DS. Make sure you upload
-- Please fill in the placeholders.-->
**System model:**
-[e.g. 2DS, New 3DS, Old 3DS]
+[New 2DS XL, New 3DS XL, New 3DS, Old 2DS, Old 3DS XL, Old 3DS]
**SysNAND version (+emu/redNAND version if applicable):**
@@ -34,7 +34,7 @@ about: Use this to report bugs you encounter with Luma3DS. Make sure you upload
**Luma3DS version:**
-[e.g. v10.1.3 stable or if using non-releases specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/0543c208fd154e6326ea5da8cbf66ffcbdef010c]
+[e.g. v10.2 stable or if using non-releases specify the commit like this https://github.com/LumaTeam/Luma3DS/commit/0543c208fd154e6326ea5da8cbf66ffcbdef010c]
**Luma3DS configuration/options:**
@@ -50,7 +50,7 @@ Splash duration: ( )
PIN lock: ( )
New 3DS CPU: ( )
-
+
--
@@ -70,12 +70,13 @@ Show NAND or user string in System Settings: ( )
Show GBA boot screen in patched AGB_FIRM: ( )
-Patch Arm9 access: ( )
-
Set developer UNITINFO: ( )
Disable Arm11 exception handlers: ( )
+Enable Rosalina on SAFE_FIRM: ( )
+
+
--
diff --git a/.gitignore b/.gitignore
index e9a1bf2..8705440 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,9 +13,12 @@ exceptions/arm11/build
*.d
*.elf
*.cxi
+*.3dsx
.DS_Store
*.dmp
.project
.cproject
.settings
.idea/
+
+Luma3DS*.zip
diff --git a/Makefile b/Makefile
index 7dae32d..54c3153 100644
--- a/Makefile
+++ b/Makefile
@@ -15,9 +15,10 @@ release: $(NAME)$(REVISION).zip
clean:
@$(foreach dir, $(SUBFOLDERS), $(MAKE) -C $(dir) clean &&) true
- @rm -rf *.firm *.zip
+ @rm -rf *.firm *.zip *.3dsx
-$(NAME)$(REVISION).zip: boot.firm exception_dump_parser
+# boot.3dsx comes from https://github.com/fincs/new-hbmenu/releases
+$(NAME)$(REVISION).zip: boot.firm boot.3dsx
@zip -r $@ $^ -x "*.DS_Store*" "*__MACOSX*"
boot.firm: $(SUBFOLDERS)
@@ -25,5 +26,9 @@ boot.firm: $(SUBFOLDERS)
-A 0x18180000 -C XDMA XDMA NDMA XDMA
@echo built... $(notdir $@)
+boot.3dsx:
+ @curl -sSL "https://github.com/fincs/new-hbmenu/releases/latest/download/boot.3dsx" -o "$@"
+ @echo downloaded... $(notdir $@)
+
$(SUBFOLDERS):
@$(MAKE) -C $@ all
diff --git a/arm9/source/exceptions.c b/arm9/source/exceptions.c
index ca45a77..e21bb03 100644
--- a/arm9/source/exceptions.c
+++ b/arm9/source/exceptions.c
@@ -34,6 +34,8 @@
#include "buttons.h"
#include "arm9_exception_handlers.h"
+// See https://github.com/LumaTeam/luma3ds_exception_dump_parser
+
void installArm9Handlers(void)
{
vu32 *dstVeneers = (vu32 *)0x08000000;
diff --git a/exception_dump_parser/luma3ds_exception_dump_parser/__init__.py b/exception_dump_parser/luma3ds_exception_dump_parser/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/exception_dump_parser/setup.py b/exception_dump_parser/setup.py
deleted file mode 100644
index 13a6915..0000000
--- a/exception_dump_parser/setup.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from setuptools import setup, find_packages
-
-setup(
- name='luma3ds_exception_dump_parser',
- version='1.2',
- url='https://github.com/AuroraWright/Luma3DS',
- author='TuxSH',
- license='GPLv3',
- description='Parses Luma3DS exception dumps',
- install_requires=[''],
- packages=find_packages(),
- entry_points={'console_scripts': ['luma3ds_exception_dump_parser=luma3ds_exception_dump_parser.__main__:main']},
-)
diff --git a/k11_extension/include/synchronization.h b/k11_extension/include/synchronization.h
index 32635a7..b577e2e 100644
--- a/k11_extension/include/synchronization.h
+++ b/k11_extension/include/synchronization.h
@@ -36,11 +36,12 @@ void executeFunctionOnCores(SGI0Handler_t func, u8 targetList, u8 targetListFilt
void KScheduler__TriggerCrossCoreInterrupt(KScheduler *this);
void KThread__DebugReschedule(KThread *this, bool lock);
-bool rosalinaThreadLockPredicate(KThread *thread);
+
+bool rosalinaThreadLockPredicate(KThread *thread, u32 mask);
void rosalinaRescheduleThread(KThread *thread, bool lock);
-void rosalinaLockThread(KThread *thread);
-void rosalinaLockAllThreads(void);
-void rosalinaUnlockAllThreads(void);
+
+void rosalinaLockThreads(u32 mask);
+void rosalinaUnlockThreads(u32 mask);
// Taken from ctrulib:
@@ -49,6 +50,11 @@ static inline void __dsb(void)
__asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (0) : "memory");
}
+static inline void __dmb(void)
+{
+ __asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 5" :: [val] "r" (0) : "memory");
+}
+
static inline void __clrex(void)
{
__asm__ __volatile__("clrex" ::: "memory");
diff --git a/k11_extension/source/svc.c b/k11_extension/source/svc.c
index 3a21430..722c301 100644
--- a/k11_extension/source/svc.c
+++ b/k11_extension/source/svc.c
@@ -89,7 +89,7 @@ void signalSvcReturn(u8 *pageEnd)
void postprocessSvc(void)
{
KThread *currentThread = currentCoreContext->objectContext.currentThread;
- if(!currentThread->shallTerminate && rosalinaThreadLockPredicate(currentThread))
+ if(!currentThread->shallTerminate && rosalinaThreadLockPredicate(currentThread, rosalinaState & 5))
rosalinaRescheduleThread(currentThread, true);
officialPostProcessSvc();
diff --git a/k11_extension/source/svc/KernelSetState.c b/k11_extension/source/svc/KernelSetState.c
index 7f8679f..8533735 100644
--- a/k11_extension/source/svc/KernelSetState.c
+++ b/k11_extension/source/svc/KernelSetState.c
@@ -105,14 +105,22 @@ Result KernelSetStateHook(u32 type, u32 varg1, u32 varg2, u32 varg3)
__ldrex((s32 *)&rosalinaState);
}
while(__strex((s32 *)&rosalinaState, (s32)(rosalinaState ^ varg1)));
+ __dmb();
- if(rosalinaState & 2)
+ if(rosalinaState & 0x10)
hasStartedRosalinaNetworkFuncsOnce = true;
- if(rosalinaState & 1)
- rosalinaLockAllThreads();
- else if(varg1 & 1)
- rosalinaUnlockAllThreads();
+ // 1: all applet/app/dsp/csnd... threads 2: gsp 4: hid/ir
+ for (u32 v = 4; v != 0; v >>= 1)
+ {
+ if (varg1 & v)
+ {
+ if (rosalinaState & v)
+ rosalinaLockThreads(v);
+ else
+ rosalinaUnlockThreads(v);
+ }
+ }
break;
}
diff --git a/k11_extension/source/svc/SendSyncRequest.c b/k11_extension/source/svc/SendSyncRequest.c
index 0834254..507b32e 100644
--- a/k11_extension/source/svc/SendSyncRequest.c
+++ b/k11_extension/source/svc/SendSyncRequest.c
@@ -28,9 +28,16 @@
#include "svc/SendSyncRequest.h"
#include "ipc.h"
+static inline bool isNdmuWorkaround(const SessionInfo *info, u32 pid)
+{
+ return info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce && pid >= nbSection0Modules;
+}
+
Result SendSyncRequestHook(Handle handle)
{
- KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
+ KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
+ KProcessHandleTable *handleTable = handleTableOfProcess(currentProcess);
+ u32 pid = idOfProcess(currentProcess);
KClientSession *clientSession = (KClientSession *)KProcessHandleTable__ToKAutoObject(handleTable, handle);
u32 *cmdbuf = (u32 *)((u8 *)currentCoreContext->objectContext.currentThread->threadLocalStorage + 0x80);
@@ -47,7 +54,7 @@ Result SendSyncRequestHook(Handle handle)
case 0x10042:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
- if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce)
+ if(isNdmuWorkaround(info, pid))
{
cmdbuf[0] = 0x10040;
cmdbuf[1] = 0;
@@ -87,7 +94,7 @@ Result SendSyncRequestHook(Handle handle)
case 0x20002:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
- if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce)
+ if(isNdmuWorkaround(info, pid))
{
cmdbuf[0] = 0x20040;
cmdbuf[1] = 0;
@@ -129,7 +136,7 @@ Result SendSyncRequestHook(Handle handle)
if(!hasStartedRosalinaNetworkFuncsOnce)
break;
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
- skip = info != NULL && strcmp(info->name, "ndm:u") == 0; // SuspendScheduler
+ skip = isNdmuWorkaround(info, pid); // SuspendScheduler
if(skip)
cmdbuf[1] = 0;
break;
@@ -140,7 +147,7 @@ Result SendSyncRequestHook(Handle handle)
if(!hasStartedRosalinaNetworkFuncsOnce)
break;
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
- if(info != NULL && strcmp(info->name, "ndm:u") == 0) // ResumeScheduler
+ if(isNdmuWorkaround(info, pid)) // ResumeScheduler
{
cmdbuf[0] = 0x90040;
cmdbuf[1] = 0;
diff --git a/k11_extension/source/synchronization.c b/k11_extension/source/synchronization.c
index eb88c6a..4b00072 100644
--- a/k11_extension/source/synchronization.c
+++ b/k11_extension/source/synchronization.c
@@ -66,17 +66,12 @@ void KThread__DebugReschedule(KThread *this, bool lock)
KRecursiveLock__Unlock(criticalSectionLock);
}
-bool rosalinaThreadLockPredicate(KThread *thread)
+static void rosalinaLockThread(KThread *thread)
{
- KProcess *process = thread->ownerProcess;
- if(process == NULL)
- return false;
+ KThread *syncThread = synchronizationMutex->owner;
- u64 titleId = codeSetOfProcess(process)->titleId;
- u32 highTitleId = (u32)(titleId >> 32), lowTitleId = (u32)(titleId & ~0xF0000001); // clear N3DS and SAFE_FIRM bits
- return
- ((rosalinaState & 1) && idOfProcess(process) >= nbSection0Modules &&
- (highTitleId != 0x00040130 || (highTitleId == 0x00040130 && (lowTitleId == 0x1A02 || lowTitleId == 0x1C02))));
+ if(syncThread == NULL || syncThread != thread)
+ rosalinaRescheduleThread(thread, true);
}
void rosalinaRescheduleThread(KThread *thread, bool lock)
@@ -89,20 +84,45 @@ void rosalinaRescheduleThread(KThread *thread, bool lock)
else
thread->schedulingMask &= ~0x40;
- KScheduler__AdjustThread(currentCoreContext->objectContext.currentScheduler, thread, oldSchedulingMask);
+ if (oldSchedulingMask != thread->schedulingMask)
+ KScheduler__AdjustThread(currentCoreContext->objectContext.currentScheduler, thread, oldSchedulingMask);
KRecursiveLock__Unlock(criticalSectionLock);
}
-void rosalinaLockThread(KThread *thread)
+bool rosalinaThreadLockPredicate(KThread *thread, u32 mask)
{
- KThread *syncThread = synchronizationMutex->owner;
+ KProcess *process = thread->ownerProcess;
+ if(process == NULL || idOfProcess(process) < nbSection0Modules)
+ return false;
- if(syncThread == NULL || syncThread != thread)
- rosalinaRescheduleThread(thread, true);
+ u64 titleId = codeSetOfProcess(process)->titleId;
+ u32 highTitleId = (u32)(titleId >> 32), lowTitleId = (u32)(titleId & ~0xF0000001); // clear N3DS and SAFE_FIRM bits
+
+ if (mask & 1)
+ {
+ if (highTitleId != 0x00040130) // non-sysmodules
+ return true;
+ else
+ return lowTitleId == 0x1A02 || lowTitleId == 0x2702; // dsp, csnd
+ }
+ if (mask & 2)
+ {
+ if (highTitleId != 0x00040130) // non-sysmodules
+ false;
+ return lowTitleId == 0x1C02; // gsp
+ }
+ if (mask & 4)
+ {
+ if (highTitleId != 0x00040130) // non-sysmodules
+ return false;
+ return lowTitleId == 0x1D02 || lowTitleId == 0x3302;
+ }
+
+ return false;
}
-void rosalinaLockAllThreads(void)
+void rosalinaLockThreads(u32 mask)
{
bool currentThreadsFound = false;
@@ -110,7 +130,7 @@ void rosalinaLockAllThreads(void)
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
{
KThread *thread = (KThread *)node->key;
- if(!rosalinaThreadLockPredicate(thread))
+ if(!rosalinaThreadLockPredicate(thread, mask))
continue;
if(thread == coreCtxs[thread->coreId].objectContext.currentThread)
currentThreadsFound = true;
@@ -123,7 +143,7 @@ void rosalinaLockAllThreads(void)
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
{
KThread *thread = (KThread *)node->key;
- if(!rosalinaThreadLockPredicate(thread))
+ if(!rosalinaThreadLockPredicate(thread, mask))
continue;
if(!(thread->schedulingMask & 0x40))
{
@@ -145,7 +165,7 @@ void rosalinaLockAllThreads(void)
KRecursiveLock__Unlock(criticalSectionLock);
}
-void rosalinaUnlockAllThreads(void)
+void rosalinaUnlockThreads(u32 mask)
{
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
{
@@ -154,7 +174,7 @@ void rosalinaUnlockAllThreads(void)
if((thread->schedulingMask & 0xF) == 2) // thread is terminating
continue;
- if(thread->schedulingMask & 0x40)
+ if((thread->schedulingMask & 0x40) && rosalinaThreadLockPredicate(thread, mask))
rosalinaRescheduleThread(thread, false);
}
}
diff --git a/sysmodules/loader/source/hbldr.h b/sysmodules/loader/source/hbldr.h
index 34e22c4..4da0c12 100644
--- a/sysmodules/loader/source/hbldr.h
+++ b/sysmodules/loader/source/hbldr.h
@@ -2,8 +2,6 @@
#include <3ds/exheader.h>
-#define HBLDR_3DSX_TID (*(vu64 *)0x1FF81100)
-
Result hbldrInit(void);
void hbldrExit(void);
diff --git a/sysmodules/loader/source/loader.c b/sysmodules/loader/source/loader.c
index 26aaf4b..dc4f55e 100644
--- a/sysmodules/loader/source/loader.c
+++ b/sysmodules/loader/source/loader.c
@@ -4,6 +4,7 @@
#include "ifile.h"
#include "util.h"
#include "hbldr.h"
+#include "luma_shared_config.h"
extern u32 config, multiConfig, bootConfig;
extern bool isN3DS, isSdMode;
@@ -91,6 +92,11 @@ static int lzss_decompress(u8 *end)
return ret;
}
+static inline bool hbldrIs3dsxTitle(u64 tid)
+{
+ return Luma_SharedConfig->use_hbldr && tid == Luma_SharedConfig->hbldr_3dsx_tid;
+}
+
static Result allocateSharedMem(prog_addrs_t *shared, prog_addrs_t *vaddr, int flags)
{
u32 dummy;
@@ -184,11 +190,8 @@ static Result GetProgramInfo(ExHeader_Info *exheaderInfo, u64 programHandle)
}
}
- s64 nbSection0Modules;
- svcGetSystemInfo(&nbSection0Modules, 26, 0);
-
// Tweak 3dsx placeholder title exheaderInfo
- if (nbSection0Modules == 6 && exheaderInfo->aci.local_caps.title_id == HBLDR_3DSX_TID)
+ if (hbldrIs3dsxTitle(exheaderInfo->aci.local_caps.title_id))
{
assertSuccess(hbldrInit());
HBLDR_PatchExHeaderInfo(exheaderInfo);
@@ -219,7 +222,7 @@ static Result LoadProcess(Handle *process, u64 programHandle)
u64 titleId;
// make sure the cached info corrosponds to the current programHandle
- if (g_cached_programHandle != programHandle || g_exheaderInfo.aci.local_caps.title_id == HBLDR_3DSX_TID)
+ if (g_cached_programHandle != programHandle || hbldrIs3dsxTitle(g_exheaderInfo.aci.local_caps.title_id))
{
res = GetProgramInfo(&g_exheaderInfo, programHandle);
g_cached_programHandle = programHandle;
@@ -245,7 +248,7 @@ static Result LoadProcess(Handle *process, u64 programHandle)
titleId = g_exheaderInfo.aci.local_caps.title_id;
ExHeader_CodeSetInfo *csi = &g_exheaderInfo.sci.codeset_info;
- if (titleId == HBLDR_3DSX_TID)
+ if (hbldrIs3dsxTitle(titleId))
{
assertSuccess(hbldrInit());
assertSuccess(HBLDR_LoadProcess(&codeset, csi->text.address, flags & 0xF00, titleId, csi->name));
@@ -425,7 +428,7 @@ void loaderHandleCommands(void *ctx)
break;
case 4: // GetProgramInfo
memcpy(&programHandle, &cmdbuf[1], 8);
- if (programHandle != g_cached_programHandle || g_exheaderInfo.aci.local_caps.title_id == HBLDR_3DSX_TID)
+ if (programHandle != g_cached_programHandle || hbldrIs3dsxTitle(g_exheaderInfo.aci.local_caps.title_id))
{
res = GetProgramInfo(&g_exheaderInfo, programHandle);
g_cached_programHandle = R_SUCCEEDED(res) ? programHandle : 0;
diff --git a/sysmodules/loader/source/luma_shared_config.h b/sysmodules/loader/source/luma_shared_config.h
new file mode 100644
index 0000000..f956a83
--- /dev/null
+++ b/sysmodules/loader/source/luma_shared_config.h
@@ -0,0 +1,28 @@
+/* This paricular file is licensed under the following terms: */
+
+/*
+* This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable
+* for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it
+* and redistribute it freely, subject to the following restrictions:
+*
+* The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
+* If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+*
+* Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+* This notice may not be removed or altered from any source distribution.
+*/
+
+#pragma once
+
+#include <3ds/types.h>
+
+/// Luma shared config type.
+typedef struct LumaSharedConfig {
+ u64 hbldr_3dsx_tid; ///< Title ID to use for 3DSX loading.
+ bool use_hbldr; ///< Whether or not Loader should use hb:ldr (Rosalina writes 1).
+} LumaSharedConfig;
+
+/// Luma shared config.
+#define Luma_SharedConfig ((volatile LumaSharedConfig *)(OS_SHAREDCFG_VADDR + 0x800))
diff --git a/sysmodules/pm/README.md b/sysmodules/pm/README.md
index 64b7ee4..ecf4f64 100644
--- a/sysmodules/pm/README.md
+++ b/sysmodules/pm/README.md
@@ -3,7 +3,7 @@ Open source replacement of the Arm11 PM system module.
This is licensed under the MIT license.
# Usage
-To run this system module, use a recent release or commit of [Luma3DS](https://github.com/AuroraWright/Luma3DS/), build this project and copy the generated CXI file to `/luma/sysmodules/pm.cxi`.
+To run this system module, use a recent release or commit of [Luma3DS](https://github.com/LumaTeam/Luma3DS/), build this project and copy the generated CXI file to `/luma/sysmodules/pm.cxi`.
# Credits
@fincs
diff --git a/sysmodules/pm/source/launch.c b/sysmodules/pm/source/launch.c
index be6accf..efc40a4 100644
--- a/sysmodules/pm/source/launch.c
+++ b/sysmodules/pm/source/launch.c
@@ -218,8 +218,9 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const
programInfoUpdate = (launchFlags & PMLAUNCHFLAG_USE_UPDATE_TITLE) ? programInfoUpdate : programInfo;
TRY(registerProgram(&programHandle, programInfo, programInfoUpdate));
+ u32 coreVer = OS_KernelConfig->kernel_syscore_ver;
res = LOADER_GetProgramInfo(exheaderInfo, programHandle);
- res = R_SUCCEEDED(res) && SYSCOREVER == 2 && exheaderInfo->aci.local_caps.core_info.core_version != SYSCOREVER ? (Result)0xC8A05800 : res;
+ res = R_SUCCEEDED(res) && coreVer == 2 && exheaderInfo->aci.local_caps.core_info.core_version != coreVer ? (Result)0xC8A05800 : res;
if (R_FAILED(res)) {
LOADER_UnregisterProgram(programHandle);
@@ -227,7 +228,7 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const
}
// Change APPMEMALLOC if needed
- if (IS_N3DS && APPMEMTYPE == 6 && (launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION) != 0) {
+ if (IS_N3DS && OS_KernelConfig->app_memtype == 6 && (launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION) != 0) {
u32 limitMb;
SystemMode n3dsSystemMode = exheaderInfo->aci.local_caps.core_info.n3ds_system_mode;
bool forceO3dsAppMem = (launchFlags & PMLAUNCHFLAG_FORCE_USE_O3DS_APP_MEM) != 0;
@@ -332,9 +333,11 @@ Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFla
u32 tidh = (u32)(programInfo->programId >> 32);
u32 tidl = (u32)programInfo->programId;
- if ((tidh == 0x00040030 || tidh == 0x00040130) && (tidl & 0xFF) != SYSCOREVER) {
+ u32 coreVer = OS_KernelConfig->kernel_syscore_ver;
+ if (coreVer == 2 && (tidh == 0x00040030 || tidh == 0x00040130) && (tidl & 0xFF) != coreVer) {
// Panic if launching SAFE_MODE sysmodules or applets (note: exheader syscorever check above only done for applications in official PM)
// Official PM also hardcodes SYSCOREVER = 2 here.
+ // NATIVE_FIRM-only.
panic(4);
}
@@ -520,8 +523,8 @@ Result autolaunchSysmodules(void)
FS_ProgramInfo programInfo = { .mediaType = MEDIATYPE_NAND };
// Launch NS
- if (NSTID != 0) {
- programInfo.programId = NSTID;
+ if (OS_KernelConfig->ns_tid != 0) {
+ programInfo.programId = OS_KernelConfig->ns_tid;
TRY(launchTitleImplWrapper(NULL, NULL, &programInfo, &programInfo, PMLAUNCHFLAG_LOAD_DEPENDENCIES));
}
diff --git a/sysmodules/pm/source/process_monitor.c b/sysmodules/pm/source/process_monitor.c
index cf65958..c2847d6 100644
--- a/sysmodules/pm/source/process_monitor.c
+++ b/sysmodules/pm/source/process_monitor.c
@@ -29,7 +29,7 @@ static void cleanupProcess(ProcessData *process)
ProcessList_Lock(&g_manager.processList);
if (g_manager.runningApplicationData != NULL && process->handle == g_manager.runningApplicationData->handle) {
- if (IS_N3DS && APPMEMTYPE == 6) {
+ if (IS_N3DS && OS_KernelConfig->app_memtype == 6) {
assertSuccess(resetAppMemLimit());
}
g_manager.runningApplicationData = NULL;
diff --git a/sysmodules/pm/source/reslimit.c b/sysmodules/pm/source/reslimit.c
index 824c1aa..4dad971 100644
--- a/sysmodules/pm/source/reslimit.c
+++ b/sysmodules/pm/source/reslimit.c
@@ -252,7 +252,8 @@ static ReslimitValues *fixupReslimitValues(void)
// Note: we lie in the reslimit and make as if neither KExt nor Roslina existed, to avoid breakage
- u32 sysmemalloc = SYSMEMALLOC + (hasKExt() ? getStolenSystemMemRegionSize() : 0);
+ u32 appmemalloc = OS_KernelConfig->memregion_sz[0];
+ u32 sysmemalloc = OS_KernelConfig->memregion_sz[1] + (hasKExt() ? getStolenSystemMemRegionSize() : 0);
ReslimitValues *values = !IS_N3DS ? g_o3dsReslimitValues : g_n3dsReslimitValues;
static const u32 minAppletMemAmount = 0x1200000;
@@ -261,7 +262,7 @@ static ReslimitValues *fixupReslimitValues(void)
u32 baseRegionSize = !IS_N3DS ? 0x1400000 : 0x2000000;
if (sysmemalloc < minAppletMemAmount) {
- values[1][0] = SYSMEMALLOC - minAppletMemAmount / 3;
+ values[1][0] = sysmemalloc - minAppletMemAmount / 3;
values[2][0] = 0;
values[3][0] = baseRegionSize + otherMinOvercommitAmount;
} else {
@@ -271,8 +272,8 @@ static ReslimitValues *fixupReslimitValues(void)
values[3][0] = baseRegionSize + (otherMinOvercommitAmount + excess / 4);
}
- values[0][0] = APPMEMALLOC;
- g_defaultAppMemLimit = APPMEMALLOC;
+ values[0][0] = appmemalloc;
+ g_defaultAppMemLimit = appmemalloc;
return values;
}
diff --git a/sysmodules/pm/source/util.h b/sysmodules/pm/source/util.h
index 0a3cf20..4618a4c 100644
--- a/sysmodules/pm/source/util.h
+++ b/sysmodules/pm/source/util.h
@@ -8,13 +8,7 @@
#define REG32(reg) (*(vu32 *)reg)
#define REG64(reg) (*(vu64 *)reg)
-#define NSTID REG64(0x1FF80008)
-#define SYSCOREVER REG32(0x1FF80010)
-#define APPMEMTYPE REG32(0x1FF80030)
-#define APPMEMALLOC REG32(0x1FF80040)
-#define SYSMEMALLOC REG32(0x1FF80044)
-
-#define IS_N3DS (*(vu32 *)0x1FF80030 >= 6) // APPMEMTYPE. Hacky but doesn't use APT
+#define IS_N3DS (OS_KernelConfig->app_memtype >= 6) // APPMEMTYPE. Hacky but doesn't use APT
#define N3DS_TID_MASK 0xF0000000ULL
#define N3DS_TID_BIT 0x20000000ULL
diff --git a/sysmodules/pxi/README.md b/sysmodules/pxi/README.md
index 2687003..37a2768 100644
--- a/sysmodules/pxi/README.md
+++ b/sysmodules/pxi/README.md
@@ -3,7 +3,7 @@ Open source replacement of the Arm11 PXI system module.
This is licensed under the MIT license.
# Usage
-To run this system module, use a recent release or commit of [Luma3DS](https://github.com/AuroraWright/Luma3DS/) and copy pxi.cxi to /luma/sysmodules/.
+To run this system module, use a recent release or commit of [Luma3DS](https://github.com/LumaTeam/Luma3DS/) and copy pxi.cxi to /luma/sysmodules/.
# Credits
This list is not complete at all:
diff --git a/sysmodules/rosalina/include/hbloader.h b/sysmodules/rosalina/include/hbloader.h
index a6fb94d..b2fbcca 100644
--- a/sysmodules/rosalina/include/hbloader.h
+++ b/sysmodules/rosalina/include/hbloader.h
@@ -31,7 +31,6 @@
#include "MyThread.h"
#define HBLDR_DEFAULT_3DSX_TID 0x000400000D921E00ULL
-#define HBLDR_3DSX_TID (*(vu64 *)0x1FF81100)
void HBLDR_RestartHbApplication(void *p);
void HBLDR_HandleCommands(void *ctx);
diff --git a/sysmodules/rosalina/include/luma_shared_config.h b/sysmodules/rosalina/include/luma_shared_config.h
new file mode 100644
index 0000000..b63c433
--- /dev/null
+++ b/sysmodules/rosalina/include/luma_shared_config.h
@@ -0,0 +1,30 @@
+/* This paricular file is licensed under the following terms: */
+
+/*
+* This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable
+* for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it
+* and redistribute it freely, subject to the following restrictions:
+*
+* The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
+* If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+*
+* Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+* This notice may not be removed or altered from any source distribution.
+*/
+
+#pragma once
+
+#include <3ds/types.h>
+
+#include <3ds/types.h>
+
+/// Luma shared config type.
+typedef struct LumaSharedConfig {
+ u64 hbldr_3dsx_tid; ///< Title ID to use for 3DSX loading.
+ bool use_hbldr; ///< Whether or not Loader should use hb:ldr (Rosalina writes 1).
+} LumaSharedConfig;
+
+/// Luma shared config.
+#define Luma_SharedConfig ((volatile LumaSharedConfig *)(OS_SHAREDCFG_VADDR + 0x800))
diff --git a/sysmodules/rosalina/include/luminance.h b/sysmodules/rosalina/include/luminance.h
new file mode 100644
index 0000000..1b48036
--- /dev/null
+++ b/sysmodules/rosalina/include/luminance.h
@@ -0,0 +1,33 @@
+/*
+* 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 <3ds/types.h>
+
+u32 getMinLuminancePreset(void);
+u32 getMaxLuminancePreset(void);
+u32 getCurrentLuminance(bool top);
diff --git a/sysmodules/rosalina/include/menus/screen_filters.h b/sysmodules/rosalina/include/menus/screen_filters.h
index 72323b9..d624cb4 100644
--- a/sysmodules/rosalina/include/menus/screen_filters.h
+++ b/sysmodules/rosalina/include/menus/screen_filters.h
@@ -32,6 +32,8 @@ extern Menu screenFiltersMenu;
extern int screenFiltersCurrentTemperature;
+void ScreenFiltersMenu_RestoreCct(void);
+
void ScreenFiltersMenu_SetDefault(void); // 6500K (default)
void ScreenFiltersMenu_SetAquarium(void); // 10000K
diff --git a/sysmodules/rosalina/include/minisoc.h b/sysmodules/rosalina/include/minisoc.h
index 6040bc8..c735171 100644
--- a/sysmodules/rosalina/include/minisoc.h
+++ b/sysmodules/rosalina/include/minisoc.h
@@ -21,6 +21,10 @@
extern bool miniSocEnabled;
Result miniSocInit(void);
+
+void miniSocLockState(void);
+void miniSocUnlockState(bool force);
+
Result miniSocExitDirect(void);
Result miniSocExit(void);
diff --git a/sysmodules/rosalina/include/utils.h b/sysmodules/rosalina/include/utils.h
index bb84620..333f085 100644
--- a/sysmodules/rosalina/include/utils.h
+++ b/sysmodules/rosalina/include/utils.h
@@ -31,6 +31,7 @@
#include <3ds/result.h>
#include <3ds/ipc.h>
#include "csvc.h"
+#include "luma_shared_config.h"
// For accessing physmem uncached (and directly)
#define PA_PTR(addr) (void *)((u32)(addr) | 1 << 31)
diff --git a/sysmodules/rosalina/source/hbloader.c b/sysmodules/rosalina/source/hbloader.c
index d3f2775..6c45478 100644
--- a/sysmodules/rosalina/source/hbloader.c
+++ b/sysmodules/rosalina/source/hbloader.c
@@ -36,9 +36,6 @@
#include "gdb/server.h"
#include "pmdbgext.h"
-#define SYSCOREVER (*(vu32 *)0x1FF80010)
-#define APPMEMTYPE (*(vu32 *)0x1FF80030)
-
extern GDBContext *nextApplicationGdbCtx;
extern GDBServer gdbServer;
@@ -148,7 +145,7 @@ static const u32 kernelCaps[] =
0xFF81FF78, // RW static mapping: 0x1FF78000
0xFF91F000, // RO static mapping: 0x1F000000
0xFF91F600, // RO static mapping: 0x1F600000
- 0xFF002101, // Exflags: APPLICATION memtype + "Allow debug" + "Access core2"
+ 0xFF002109, // Exflags: APPLICATION memtype + "Shared page writing" + "Allow debug" + "Access core2"
0xFE000200, // Handle table size: 0x200
};
@@ -310,21 +307,22 @@ void HBLDR_HandleCommands(void *ctx)
memcpy(&exhi->sci.codeset_info.stack_size, &stacksize, 4);
memset(&exhi->sci.dependencies, 0, sizeof(exhi->sci.dependencies));
- if (SYSCOREVER == 2)
+ u32 coreVer = OS_KernelConfig->kernel_syscore_ver;
+ if (coreVer == 2)
memcpy(exhi->sci.dependencies, dependencyListNativeFirm, sizeof(dependencyListNativeFirm));
- else if (SYSCOREVER == 3)
+ else if (coreVer == 3)
memcpy(exhi->sci.dependencies, dependencyListSafeFirm, sizeof(dependencyListSafeFirm));
ExHeader_Arm11SystemLocalCapabilities* localcaps0 = &exhi->aci.local_caps;
- localcaps0->core_info.core_version = SYSCOREVER;
+ localcaps0->core_info.core_version = coreVer;
localcaps0->core_info.use_cpu_clockrate_804MHz = false;
localcaps0->core_info.enable_l2c = false;
localcaps0->core_info.ideal_processor = 0;
localcaps0->core_info.affinity_mask = BIT(0);
localcaps0->core_info.priority = 0x30;
- u32 appmemtype = APPMEMTYPE;
+ u32 appmemtype = OS_KernelConfig->app_memtype;
localcaps0->core_info.o3ds_system_mode = appmemtype < 6 ? (SystemMode)appmemtype : SYSMODE_O3DS_PROD;
localcaps0->core_info.n3ds_system_mode = appmemtype >= 6 ? (SystemMode)(appmemtype - 6 + 1) : SYSMODE_N3DS_PROD;
@@ -334,7 +332,7 @@ void HBLDR_HandleCommands(void *ctx)
// See the big comment in sysmodules/pm/source/reslimit.c for technical details.
localcaps0->reslimits[0] = BIT(7) | 89;
- //localcaps0->storage_info.fs_access_info = 0xFFFFFFFF; // Give access to everything
+ localcaps0->storage_info.fs_access_info = 0xFFFFFFFF; // Give access to everything
localcaps0->storage_info.no_romfs = true;
localcaps0->storage_info.use_extended_savedata_access = true; // Whatever
@@ -351,7 +349,7 @@ void HBLDR_HandleCommands(void *ctx)
// Set kernel release version to the current kernel version
kcaps0->descriptors[0] = 0xFC000000 | (osGetKernelVersion() >> 16);
- if (GET_VERSION_MINOR(osGetKernelVersion()) >= 50 && SYSCOREVER == 2) // 9.6+ NFIRM
+ if (GET_VERSION_MINOR(osGetKernelVersion()) >= 50 && coreVer == 2) // 9.6+ NFIRM
{
u64 lastdep = sizeof(dependencyListNativeFirm)/8;
exhi->sci.dependencies[lastdep++] = 0x0004013000004002ULL; // nfc
diff --git a/sysmodules/rosalina/source/input_redirection.c b/sysmodules/rosalina/source/input_redirection.c
index 33d4443..9174c48 100644
--- a/sysmodules/rosalina/source/input_redirection.c
+++ b/sysmodules/rosalina/source/input_redirection.c
@@ -177,6 +177,248 @@ void inputRedirectionThreadMain(void)
void hidCodePatchFunc(void);
void irCodePatchFunc(void);
+static Result InputRedirection_DoUndoIrPatches(Handle processHandle, bool doPatch)
+{
+ static u32* hookLoc = NULL;
+ static u32* syncLoc = NULL;
+ static u32* cppFlagLoc = NULL;
+ static u32 origIrSync = 0;
+ static u32 origCppFlag = 0;
+
+ static bool patchPrepared = false;
+
+ static u32 irOrigReadingCode[5] = {
+ 0xE5940000, // ldr r0, [r4]
+ 0xE1A01005, // mov r1, r5
+ 0xE3A03005, // mov r3, #5
+ 0xE3A02011, // mov r2, #17
+ 0x00000000 // (bl i2c_read_raw goes here)
+ };
+
+ static u32 irHook[] = {
+ 0xE5940000, // ldr r0, [r4]
+ 0xE1A01005, // mov r1, r5
+ 0xE59FC000, // ldr r12, [pc] (actually +8)
+ 0xE12FFF3C, // blx r12
+ 0x00000000 // irCodePhys goes here
+ };
+
+ static u32 syncHookCode[] = {
+ 0xE5900000, // ldr r0, [r0]
+ 0xEF000024, // svc 0x24
+ 0xE3A00000, // mov r0, #0
+ 0xE51FF004, // ldr pc, [pc, #-4]
+ 0x00000000, // (return address goes here)
+ };
+
+ // Find offsets for required patches
+ s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
+ u32 totalSize;
+ Result res;
+
+ svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data
+ svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
+ svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
+
+ totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
+
+ svcGetProcessInfo(&startAddress, processHandle, 0x10005);
+ res = svcMapProcessMemoryEx(processHandle, 0x00100000, (u32) startAddress, totalSize);
+
+ if(R_SUCCEEDED(res) && !patchPrepared)
+ {
+ static const u32 irOrigWaitSyncCode[] = {
+ 0xEF000024, // svc 0x24 (WaitSynchronization)
+ 0xE1B01FA0, // movs r1, r0, lsr#31
+ 0xE1A0A000, // mov r10, r0
+ }, irOrigWaitSyncCodeOld[] = {
+ 0xE0AC6000, // adc r6, r12, r0
+ 0xE5D70000, // ldrb r0, [r7]
+ }; // pattern for 8.1
+
+ static const u32 irOrigCppFlagCode[] = {
+ 0xE3550000, // cmp r5, #0
+ 0xE3A0B080, // mov r11, #0x80
+ };
+
+ svcGetProcessInfo(&startAddress, processHandle, 0x10005);
+ res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (u32) startAddress, totalSize);
+ u32 irDataPhys = (u32)PA_FROM_VA_PTR(irData);
+ u32 irCodePhys = (u32)PA_FROM_VA_PTR(&irCodePatchFunc);
+
+ u32 *off = (u32 *)memsearch((u8 *)0x00100000, &irOrigReadingCode, totalSize, sizeof(irOrigReadingCode) - 4);
+ if(off == NULL)
+ {
+ svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
+ return -1;
+ }
+
+ u32 *off2 = (u32 *)memsearch((u8 *)0x00100000, &irOrigWaitSyncCode, totalSize, sizeof(irOrigWaitSyncCode));
+ if(off2 == NULL)
+ {
+ off2 = (u32 *)memsearch((u8 *)0x00100000, &irOrigWaitSyncCodeOld, totalSize, sizeof(irOrigWaitSyncCodeOld));
+ if(off2 == NULL)
+ {
+ svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
+ return -2;
+ }
+ }
+
+ u32 *off3 = (u32 *)memsearch((u8 *)0x00100000, &irOrigCppFlagCode, totalSize, sizeof(irOrigCppFlagCode));
+ if(off3 == NULL)
+ {
+ svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
+ return -3;
+ }
+
+ origIrSync = *off2;
+ origCppFlag = *off3;
+
+ *(void **)(irCodePhys + 8) = decodeArmBranch(off + 4);
+ *(void **)(irCodePhys + 12) = (void*)irDataPhys;
+
+ irHook[4] = irCodePhys;
+ irOrigReadingCode[4] = off[4]; // Copy the branch.
+ syncHookCode[4] = (u32)off2 + 4; // Hook return address
+
+ hookLoc = PA_FROM_VA_PTR(off);
+ syncLoc = PA_FROM_VA_PTR(off2);
+ cppFlagLoc = PA_FROM_VA_PTR(off3);
+
+ patchPrepared = true;
+ }
+
+ if (R_SUCCEEDED(res))
+ {
+ if (doPatch)
+ {
+ memcpy(hookLoc, &irHook, sizeof(irHook));
+
+ // We keep the WaitSynchronization1 to avoid general slowdown because of the high cpu load
+ if (*syncLoc == 0xEF000024) // svc 0x24 (WaitSynchronization)
+ {
+ syncLoc[-1] = 0xE51FF004;
+ syncLoc[0] = (u32)PA_FROM_VA_PTR(&syncHookCode);
+ }
+ else
+ {
+ // This "NOP"s out a WaitSynchronisation1 (on the event bound to the 'IR' interrupt) or the check of a previous one
+ *syncLoc = 0xE3A00000; // mov r0, #0
+ }
+
+ // This NOPs out a flag check in ir:user's CPP emulation
+ *cppFlagLoc = 0xE3150000; // tst r5, #0
+ }
+ else
+ {
+ memcpy(hookLoc, irOrigReadingCode, sizeof(irOrigReadingCode));
+
+ if (*syncLoc == 0xE3A00000)
+ *syncLoc = origIrSync;
+ else
+ {
+ syncLoc[-1] = 0xE5900000; // ldr r0, [r0]
+ syncLoc[0] = 0xEF000024; // svc 0x24
+ }
+
+ *cppFlagLoc = origCppFlag;
+ }
+ }
+
+ svcInvalidateEntireInstructionCache();
+ svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
+
+ return res;
+}
+
+static Result InputRedirection_DoUndoHidPatches(Handle processHandle, bool doPatches)
+{
+ static const u32 hidOrigRegisterAndValue[] = { 0x1EC46000, 0x4001 };
+ static const u32 hidOrigCode[] = {
+ 0xE92D4070, // push {r4-r6, lr}
+ 0xE1A05001, // mov r5, r1
+ 0xEE1D4F70, // mrc p15, 0, r4, c13, c0, 3
+ 0xE3A01801, // mov r1, #0x10000
+ 0xE5A41080, // str r1, [r4,#0x80]!
+ };
+
+ static bool patchPrepared = false;
+ static u32 *hidRegPatchOffsets[2];
+ static u32 *hidPatchJumpLoc;
+
+ // Find offsets for required patches
+ s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
+ u32 totalSize;
+ Result res;
+
+ svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data
+ svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
+ svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
+
+ totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
+
+ svcGetProcessInfo(&startAddress, processHandle, 0x10005);
+ res = svcMapProcessMemoryEx(processHandle, 0x00100000, (u32) startAddress, totalSize);
+
+ if (R_SUCCEEDED(res) && !patchPrepared)
+ {
+ u32 *off = (u32 *)memsearch((u8 *)0x00100000, &hidOrigRegisterAndValue, totalSize, sizeof(hidOrigRegisterAndValue));
+ if(off == NULL)
+ {
+ svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
+ return -1;
+ }
+
+ u32 *off2 = (u32 *)memsearch((u8 *)off + sizeof(hidOrigRegisterAndValue), &hidOrigRegisterAndValue, totalSize - ((u32)off - 0x00100000), sizeof(hidOrigRegisterAndValue));
+ if(off2 == NULL)
+ {
+ svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
+ return -2;
+ }
+
+ u32 *off3 = (u32 *)memsearch((u8 *)0x00100000, &hidOrigCode, totalSize, sizeof(hidOrigCode));
+ if(off3 == NULL)
+ {
+ svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
+ return -3;
+ }
+
+ hidRegPatchOffsets[0] = off;
+ hidRegPatchOffsets[1] = off2;
+ hidPatchJumpLoc = off3;
+
+ patchPrepared = true;
+ }
+
+ if(R_SUCCEEDED(res))
+ {
+ if (doPatches)
+ {
+ u32 hidDataPhys = (u32)PA_FROM_VA_PTR(hidData);
+ u32 hidCodePhys = (u32)PA_FROM_VA_PTR(&hidCodePatchFunc);
+ u32 hidHook[] = {
+ 0xE59F3004, // ldr r3, [pc, #4]
+ 0xE59FC004, // ldr r12, [pc, #4]
+ 0xE12FFF1C, // bx r12
+ hidDataPhys,
+ hidCodePhys,
+ };
+
+ *hidRegPatchOffsets[0] = *hidRegPatchOffsets[1] = hidDataPhys;
+ memcpy(hidPatchJumpLoc, &hidHook, sizeof(hidHook));
+ }
+ else
+ {
+ memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
+ memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
+ memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode));
+ }
+ }
+
+ svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
+ return res;
+}
+
Result InputRedirection_Disable(s64 timeout)
{
if(!inputRedirectionEnabled)
@@ -195,209 +437,46 @@ Result InputRedirection_Disable(s64 timeout)
Result InputRedirection_DoOrUndoPatches(void)
{
- s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
- u32 totalSize;
- Handle processHandle;
-
- Result res = OpenProcessByName("hid", &processHandle);
static bool hidPatched = false;
static bool irPatched = false;
+ Handle hidProcHandle = 0, irProcHandle = 0;
+
+ // Prevent hid and ir from running, in any case
+
+ svcKernelSetState(0x10000, 4);
+
+ Result res = OpenProcessByName("hid", &hidProcHandle);
+ if (R_FAILED(res))
+ goto cleanup;
+
+ res = OpenProcessByName("ir", &irProcHandle);
+ if (R_FAILED(res))
+ goto cleanup;
+
if(R_SUCCEEDED(res))
{
- svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data
- svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
- svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
-
- totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
-
- svcGetProcessInfo(&startAddress, processHandle, 0x10005);
- res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (u32) startAddress, totalSize);
-
- if(R_SUCCEEDED(res))
- {
- static const u32 hidOrigRegisterAndValue[] = { 0x1EC46000, 0x4001 };
- static const u32 hidOrigCode[] = {
- 0xE92D4070, // push {r4-r6, lr}
- 0xE1A05001, // mov r5, r1
- 0xEE1D4F70, // mrc p15, 0, r4, c13, c0, 3
- 0xE3A01801, // mov r1, #0x10000
- 0xE5A41080, // str r1, [r4,#0x80]!
- };
-
- static u32 *hidRegPatchOffsets[2];
- static u32 *hidPatchJumpLoc;
-
- if(hidPatched)
- {
- memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
- memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
- memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode));
- hidPatched = false;
- }
- else
- {
- u32 hidDataPhys = (u32)PA_FROM_VA_PTR(hidData);
- u32 hidCodePhys = (u32)PA_FROM_VA_PTR(&hidCodePatchFunc);
- u32 hidHook[] = {
- 0xE59F3004, // ldr r3, [pc, #4]
- 0xE59FC004, // ldr r12, [pc, #4]
- 0xE12FFF1C, // bx r12
- hidDataPhys,
- hidCodePhys,
- };
-
- u32 *off = (u32 *)memsearch((u8 *)0x00100000, &hidOrigRegisterAndValue, totalSize, sizeof(hidOrigRegisterAndValue));
- if(off == NULL)
- {
- svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
- return -1;
- }
-
- u32 *off2 = (u32 *)memsearch((u8 *)off + sizeof(hidOrigRegisterAndValue), &hidOrigRegisterAndValue, totalSize - ((u32)off - 0x00100000), sizeof(hidOrigRegisterAndValue));
- if(off2 == NULL)
- {
- svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
- return -2;
- }
-
- u32 *off3 = (u32 *)memsearch((u8 *)0x00100000, &hidOrigCode, totalSize, sizeof(hidOrigCode));
- if(off3 == NULL)
- {
- svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
- return -3;
- }
-
- hidRegPatchOffsets[0] = off;
- hidRegPatchOffsets[1] = off2;
- hidPatchJumpLoc = off3;
-
- *off = *off2 = hidDataPhys;
- memcpy(off3, &hidHook, sizeof(hidHook));
- hidPatched = true;
- }
- }
-
- res = svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
+ res = InputRedirection_DoUndoHidPatches(hidProcHandle, !hidPatched);
+ if (R_SUCCEEDED(res))
+ hidPatched = !hidPatched;
}
- svcCloseHandle(processHandle);
- res = OpenProcessByName("ir", &processHandle);
if(R_SUCCEEDED(res) && GET_VERSION_MINOR(osGetKernelVersion()) >= 44)
{
- svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data
- svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
- svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
-
- totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
-
- svcGetProcessInfo(&startAddress, processHandle, 0x10005);
- res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (u32) startAddress, totalSize);
-
- if(R_SUCCEEDED(res))
+ res = InputRedirection_DoUndoIrPatches(irProcHandle, !irPatched);
+ if (R_SUCCEEDED(res))
+ irPatched = !irPatched;
+ else if (!irPatched)
{
- static bool useOldSyncCode;
- static u32 irOrigReadingCode[5] = {
- 0xE5940000, // ldr r0, [r4]
- 0xE1A01005, // mov r1, r5
- 0xE3A03005, // mov r3, #5
- 0xE3A02011, // mov r2, #17
- 0x00000000 // (bl i2c_read_raw goes here)
- };
-
- static const u32 irOrigWaitSyncCode[] = {
- 0xEF000024, // svc 0x24 (WaitSynchronization)
- 0xE1B01FA0, // movs r1, r0, lsr#31
- 0xE1A0A000, // mov r10, r0
- }, irOrigWaitSyncCodeOld[] = {
- 0xE0AC6000, // adc r6, r12, r0
- 0xE5D70000, // ldrb r0, [r7]
- }; // pattern for 8.1
-
- static const u32 irOrigCppFlagCode[] = {
- 0xE3550000, // cmp r5, #0
- 0xE3A0B080, // mov r11, #0x80
- };
-
- static u32 *irHookLoc, *irWaitSyncLoc, *irCppFlagLoc;
-
- if(irPatched)
- {
- memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode));
- if(useOldSyncCode)
- memcpy(irWaitSyncLoc, &irOrigWaitSyncCodeOld, sizeof(irOrigWaitSyncCodeOld));
- else
- memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode));
- memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode));
-
- irPatched = false;
- }
- else
- {
- u32 irDataPhys = (u32)PA_FROM_VA_PTR(irData);
- u32 irCodePhys = (u32)PA_FROM_VA_PTR(&irCodePatchFunc);
-
- u32 irHook[] = {
- 0xE5940000, // ldr r0, [r4]
- 0xE1A01005, // mov r1, r5
- 0xE59FC000, // ldr r12, [pc] (actually +8)
- 0xE12FFF3C, // blx r12
- irCodePhys,
- };
-
- u32 *off = (u32 *)memsearch((u8 *)0x00100000, &irOrigReadingCode, totalSize, sizeof(irOrigReadingCode) - 4);
- if(off == NULL)
- {
- svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
- return -4;
- }
-
- u32 *off2 = (u32 *)memsearch((u8 *)0x00100000, &irOrigWaitSyncCode, totalSize, sizeof(irOrigWaitSyncCode));
- if(off2 == NULL)
- {
- off2 = (u32 *)memsearch((u8 *)0x00100000, &irOrigWaitSyncCodeOld, totalSize, sizeof(irOrigWaitSyncCodeOld));
- if(off2 == NULL)
- {
- svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
- return -5;
- }
-
- useOldSyncCode = true;
- }
- else
- useOldSyncCode = false;
-
- u32 *off3 = (u32 *)memsearch((u8 *)0x00100000, &irOrigCppFlagCode, totalSize, sizeof(irOrigCppFlagCode));
- if(off3 == NULL)
- {
- svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
- return -6;
- }
-
- *(void **)(irCodePhys + 8) = decodeArmBranch(off + 4);
- *(void **)(irCodePhys + 12) = (void*)irDataPhys;
-
- irHookLoc = off;
- irWaitSyncLoc = off2;
- irCppFlagLoc = off3;
-
- irOrigReadingCode[4] = off[4]; // Copy the branch.
-
- memcpy(irHookLoc, &irHook, sizeof(irHook));
-
- // This "NOP"s out a WaitSynchronisation1 (on the event bound to the 'IR' interrupt) or the check of a previous one
- *irWaitSyncLoc = 0xE3A00000; // mov r0, #0
-
- // This NOPs out a flag check in ir:user's CPP emulation
- *irCppFlagLoc = 0xE3150000; // tst r5, #0
-
- irPatched = true;
- }
+ InputRedirection_DoUndoHidPatches(hidProcHandle, false);
+ hidPatched = false;
}
-
- res = svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
}
- svcCloseHandle(processHandle);
+cleanup:
+ svcKernelSetState(0x10000, 4);
+
+ svcCloseHandle(hidProcHandle);
+ svcCloseHandle(irProcHandle);
return res;
}
diff --git a/sysmodules/rosalina/source/luminance.c b/sysmodules/rosalina/source/luminance.c
new file mode 100644
index 0000000..cc12787
--- /dev/null
+++ b/sysmodules/rosalina/source/luminance.c
@@ -0,0 +1,122 @@
+/*
+* 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 <3ds.h>
+#include
+#include "luminance.h"
+#include "utils.h"
+
+extern bool isN3DS;
+
+typedef struct BlPwmData
+{
+ float coeffs[3][3];
+ u8 numLevels;
+ u8 unk;
+ u16 luminanceLevels[7];
+ u16 brightnessMax;
+ u16 brightnessMin;
+} BlPwmData;
+
+// Calibration, with (dubious) default values as fallback
+static BlPwmData s_blPwmData = {
+ .coeffs = {
+ { 0.00111639f, 1.41412f, 0.07178809f },
+ { 0.000418169f, 0.66567f, 0.06098654f },
+ { 0.00208543f, 1.55639f, 0.0385939f }
+ },
+ .numLevels = 5,
+ .unk = 0,
+ .luminanceLevels = { 20, 43, 73, 95, 117, 172, 172 },
+ .brightnessMax = 512,
+ .brightnessMin = 13,
+};
+
+static inline float getPwmRatio(u32 brightnessMax, u32 pwmCnt)
+{
+ u32 val = (pwmCnt & 0x10000) ? pwmCnt & 0x3FF : 511; // check pwm enabled flag
+ return (float)brightnessMax / (val + 1);
+}
+
+// nn's asm has rounding errors (originally at 10^-3)
+static inline u32 luminanceToBrightness(u32 luminance, const float coeffs[3], u32 minLuminance, float pwmRatio)
+{
+ float x = (float)luminance;
+ float y = coeffs[0]*x*x + coeffs[1]*x + coeffs[2];
+ y = (y <= minLuminance ? (float)minLuminance : y) / pwmRatio;
+
+ return (u32)(y + 0.5f);
+}
+
+static inline u32 brightnessToLuminance(u32 brightness, const float coeffs[3], float pwmRatio)
+{
+ // Find polynomial root of ax^2 + bx + c = y
+
+ float y = (float)brightness * pwmRatio;
+ float a = coeffs[0];
+ float b = coeffs[1];
+ float c = coeffs[2] - y;
+
+ float x0 = (-b + sqrtf(b*b - 4.0f*a*c)) / (a + a);
+
+ return (u32)(x0 + 0.5f);
+}
+
+static void readCalibration(void)
+{
+ static bool calibRead = false;
+
+ if (!calibRead) {
+ cfguInit();
+ calibRead = R_SUCCEEDED(CFG_GetConfigInfoBlk8(sizeof(BlPwmData), 0x50002, &s_blPwmData));
+ cfguExit();
+ }
+}
+
+u32 getMinLuminancePreset(void)
+{
+ readCalibration();
+ return s_blPwmData.luminanceLevels[0];
+}
+
+u32 getMaxLuminancePreset(void)
+{
+ readCalibration();
+ return s_blPwmData.luminanceLevels[s_blPwmData.numLevels - 1];
+}
+
+u32 getCurrentLuminance(bool top)
+{
+ u32 regbase = top ? 0x10202200 : 0x10202A00;
+
+ readCalibration();
+
+ const float *coeffs = s_blPwmData.coeffs[top ? (isN3DS ? 2 : 1) : 0];
+ u32 brightness = REG32(regbase + 0x40);
+ float ratio = getPwmRatio(s_blPwmData.brightnessMax, REG32(regbase + 0x44));
+
+ return brightnessToLuminance(brightness, coeffs, ratio);
+}
diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c
index dbb2664..f07f6c8 100644
--- a/sysmodules/rosalina/source/main.c
+++ b/sysmodules/rosalina/source/main.c
@@ -83,13 +83,15 @@ void initSystem(void)
isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0;
svcGetSystemInfo(&out, 0x10000, 0x100);
- HBLDR_3DSX_TID = out == 0 ? HBLDR_DEFAULT_3DSX_TID : (u64)out;
+ Luma_SharedConfig->hbldr_3dsx_tid = out == 0 ? HBLDR_DEFAULT_3DSX_TID : (u64)out;
+ Luma_SharedConfig->use_hbldr = true;
svcGetSystemInfo(&out, 0x10000, 0x101);
menuCombo = out == 0 ? DEFAULT_MENU_COMBO : (u32)out;
- miscellaneousMenu.items[0].title = HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID ? "Switch the hb. title to the current app." :
- "Switch the hb. title to hblauncher_loader";
+ miscellaneousMenu.items[0].title = Luma_SharedConfig->hbldr_3dsx_tid == HBLDR_DEFAULT_3DSX_TID ?
+ "Switch the hb. title to the current app." :
+ "Switch the hb. title to hblauncher_loader";
for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL))
{
@@ -104,6 +106,9 @@ void initSystem(void)
if (R_FAILED(fsInit()))
svcBreak(USERBREAK_PANIC);
+ if (R_FAILED(FSUSER_SetPriority(-16)))
+ svcBreak(USERBREAK_PANIC);
+
// **** DO NOT init services that don't come from KIPs here ****
// Instead, init the service only where it's actually init (then deinit it).
@@ -131,11 +136,53 @@ static void handleTermNotification(u32 notificationId)
(void)notificationId;
}
+static void handleSleepNotification(u32 notificationId)
+{
+ ptmSysmInit();
+ s32 ackValue = ptmSysmGetNotificationAckValue(notificationId);
+ switch (notificationId)
+ {
+ case PTMNOTIFID_SLEEP_REQUESTED:
+ menuShouldExit = true;
+ PTMSYSM_ReplyToSleepQuery(miniSocEnabled); // deny sleep request if we have network stuff running
+ break;
+ case PTMNOTIFID_GOING_TO_SLEEP:
+ case PTMNOTIFID_SLEEP_ALLOWED:
+ case PTMNOTIFID_FULLY_WAKING_UP:
+ case PTMNOTIFID_HALF_AWAKE:
+ PTMSYSM_NotifySleepPreparationComplete(ackValue);
+ break;
+ case PTMNOTIFID_SLEEP_DENIED:
+ case PTMNOTIFID_FULLY_AWAKE:
+ menuShouldExit = false;
+ break;
+ default:
+ break;
+ }
+ ptmSysmExit();
+}
+
+static void handleShellNotification(u32 notificationId)
+{
+ if (notificationId == 0x213) {
+ // Shell opened
+ // Note that this notification is fired on system init
+ ScreenFiltersMenu_RestoreCct();
+ menuShouldExit = false;
+ } else {
+ // Shell closed
+ menuShouldExit = true;
+ }
+
+}
+
static void handlePreTermNotification(u32 notificationId)
{
(void)notificationId;
// Might be subject to a race condition, but heh.
+ miniSocUnlockState(true);
+
// Disable input redirection
InputRedirection_Disable(100 * 1000 * 1000LL);
@@ -180,11 +227,19 @@ static const ServiceManagerServiceEntry services[] = {
};
static const ServiceManagerNotificationEntry notifications[] = {
- { 0x100 , handleTermNotification },
- //{ 0x103 , handlePreTermNotification }, // Sleep mode entry <=== causes issues
- { 0x1000, handleNextApplicationDebuggedByForce },
- { 0x2000, handlePreTermNotification },
- { 0x3000, handleRestartHbAppNotification },
+ { 0x100 , handleTermNotification },
+ { PTMNOTIFID_SLEEP_REQUESTED, handleSleepNotification },
+ { PTMNOTIFID_SLEEP_DENIED, handleSleepNotification },
+ { PTMNOTIFID_SLEEP_ALLOWED, handleSleepNotification },
+ { PTMNOTIFID_GOING_TO_SLEEP, handleSleepNotification },
+ { PTMNOTIFID_FULLY_WAKING_UP, handleSleepNotification },
+ { PTMNOTIFID_FULLY_AWAKE, handleSleepNotification },
+ { PTMNOTIFID_HALF_AWAKE, handleSleepNotification },
+ { 0x213, handleShellNotification },
+ { 0x214, handleShellNotification },
+ { 0x1000, handleNextApplicationDebuggedByForce },
+ { 0x2000, handlePreTermNotification },
+ { 0x3000, handleRestartHbAppNotification },
{ 0x000, NULL },
};
diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c
index 40c5f55..a8addf6 100644
--- a/sysmodules/rosalina/source/menu.c
+++ b/sysmodules/rosalina/source/menu.c
@@ -193,6 +193,7 @@ void menuThreadMain(void)
while(!preTerminationRequested)
{
+ svcSleepThread(50 * 1000 * 1000LL);
if (menuShouldExit)
continue;
@@ -226,13 +227,13 @@ void menuEnter(void)
if(!menuShouldExit && menuRefCount == 0)
{
menuRefCount++;
- svcKernelSetState(0x10000, 1);
+ svcKernelSetState(0x10000, 2 | 1);
svcSleepThread(5 * 1000 * 100LL);
if (R_FAILED(Draw_AllocateFramebufferCache(FB_BOTTOM_SIZE)))
{
// Oops
menuRefCount = 0;
- svcKernelSetState(0x10000, 1);
+ svcKernelSetState(0x10000, 2 | 1);
svcSleepThread(5 * 1000 * 100LL);
}
else
@@ -250,7 +251,7 @@ void menuLeave(void)
{
Draw_RestoreFramebuffer();
Draw_FreeFramebufferCache();
- svcKernelSetState(0x10000, 1);
+ svcKernelSetState(0x10000, 2 | 1);
}
Draw_Unlock();
}
diff --git a/sysmodules/rosalina/source/menus.c b/sysmodules/rosalina/source/menus.c
index 642d4b2..08b6ae8 100644
--- a/sysmodules/rosalina/source/menus.c
+++ b/sysmodules/rosalina/source/menus.c
@@ -40,6 +40,7 @@
#include "memory.h"
#include "fmt.h"
#include "process_patches.h"
+#include "luminance.h"
Menu rosalinaMenu = {
"Rosalina menu",
@@ -64,7 +65,11 @@ Menu rosalinaMenu = {
bool rosalinaMenuShouldShowDebugInfo(void)
{
- return true;
+ // Don't show on release builds
+
+ s64 out;
+ svcGetSystemInfo(&out, 0x10000, 0x200);
+ return out == 0;
}
void RosalinaMenu_ShowDebugInfo(void)
@@ -119,8 +124,8 @@ void RosalinaMenu_ShowCredits(void)
Draw_DrawString(10, posY, COLOR_WHITE,
(
"Special thanks to:\n"
- " Bond697, WinterMute, piepie62, yifanlu\n"
- " Luma3DS contributors, ctrulib contributors,\n"
+ " fincs, WinterMute, mtheall, piepie62,\n"
+ " Luma3DS contributors, libctru contributors,\n"
" other people"
));
@@ -140,7 +145,7 @@ void RosalinaMenu_Reboot(void)
do
{
Draw_Lock();
- Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina menu");
+ Draw_DrawString(10, 10, COLOR_TITLE, "Reboot");
Draw_DrawString(10, 30, COLOR_WHITE, "Press A to reboot, press B to go back.");
Draw_FlushFramebuffer();
Draw_Unlock();
@@ -158,107 +163,102 @@ void RosalinaMenu_Reboot(void)
while(!menuShouldExit);
}
-static u32 gspPatchAddrN3ds, gspPatchValuesN3ds[2];
-static bool gspPatchDoneN3ds;
-
-static Result RosalinaMenu_PatchN3dsGspForBrightness(u32 size)
-{
- u32 *off = (u32 *)0x00100000;
- u32 *end = (u32 *)(0x00100000 + size);
-
- for (; off < end && (off[0] != 0xE92D4030 || off[1] != 0xE1A04000 || off[2] != 0xE2805C01 || off[3] != 0xE5D0018C); off++);
-
- if (off >= end) {
- return -1;
- }
-
- gspPatchAddrN3ds = (u32)off;
- gspPatchValuesN3ds[0] = off[26];
- gspPatchValuesN3ds[1] = off[50];
-
- // NOP brightness changing in GSP
- off[26] = 0xE1A00000;
- off[50] = 0xE1A00000;
-
- return 0;
-}
-static Result RosalinaMenu_RevertN3dsGspPatch(u32 size)
-{
- (void)size;
-
- u32 *off = (u32 *)gspPatchAddrN3ds;
- off[26] = gspPatchValuesN3ds[0];
- off[50] = gspPatchValuesN3ds[1];
-
- return 0;
-}
-
void RosalinaMenu_ChangeScreenBrightness(void)
{
- Result patchResult = 0;
- if (isN3DS && !gspPatchDoneN3ds)
- {
- patchResult = PatchProcessByName("gsp", RosalinaMenu_PatchN3dsGspForBrightness);
- gspPatchDoneN3ds = R_SUCCEEDED(patchResult);
- }
-
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
Draw_Unlock();
+ // gsp:LCD GetLuminance is stubbed on O3DS so we have to implement it ourselves... damn it.
+ // Assume top and bottom screen luminances are the same (should be; if not, we'll set them to the same values).
+ u32 luminance = getCurrentLuminance(false);
+ u32 minLum = getMinLuminancePreset();
+ u32 maxLum = getMaxLuminancePreset();
+
do
{
- // Assume the current brightness for both screens are the same.
- s32 brightness = (s32)(LCD_TOP_BRIGHTNESS & 0xFF);
-
Draw_Lock();
- Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina menu");
+ Draw_DrawString(10, 10, COLOR_TITLE, "Screen brightness");
u32 posY = 30;
- posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Current brightness (0..255): %3lu\n\n", brightness);
- if (R_SUCCEEDED(patchResult))
- {
- posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press Up/Down for +-1, Right/Left for +-10.\n");
- posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press Y to revert the GSP patch and exit.\n\n");
-
- posY = Draw_DrawString(10, posY, COLOR_RED, "WARNING: \n");
- posY = Draw_DrawString(10, posY, COLOR_WHITE, " * avoid using values far higher than the presets.\n");
- posY = Draw_DrawString(10, posY, COLOR_WHITE, " * normal brightness mngmt. is now broken on N3DS.\nYou'll need to press Y to revert");
- }
- else
- Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Failed to patch GSP (0x%08lx).", (u32)patchResult);
+ posY = Draw_DrawFormattedString(
+ 10,
+ posY,
+ COLOR_WHITE,
+ "Current luminance: %lu (min. %lu, max. %lu)\n\n",
+ luminance,
+ minLum,
+ maxLum
+ );
+ posY = Draw_DrawString(10, posY, COLOR_WHITE, "Controls: Up/Down for +-1, Right/Left for +-10.\n");
+ posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press A to start, B to exit.\n\n");
+ posY = Draw_DrawString(10, posY, COLOR_RED, "WARNING: \n");
+ posY = Draw_DrawString(10, posY, COLOR_WHITE, " * value will be limited by the presets.\n");
+ posY = Draw_DrawString(10, posY, COLOR_WHITE, " * bottom framebuffer will be restored until\nyou exit.");
Draw_FlushFramebuffer();
Draw_Unlock();
u32 pressed = waitInputWithTimeout(1000);
- if ((pressed & DIRECTIONAL_KEYS) && R_SUCCEEDED(patchResult))
- {
- if (pressed & KEY_UP)
- brightness += 1;
- else if (pressed & KEY_DOWN)
- brightness -= 1;
- else if (pressed & KEY_RIGHT)
- brightness += 10;
- else if (pressed & KEY_LEFT)
- brightness -= 10;
+ if (pressed & KEY_A)
+ break;
- brightness = brightness < 0 ? 0 : brightness;
- brightness = brightness > 255 ? 255 : brightness;
- LCD_TOP_BRIGHTNESS = (u32)brightness;
- LCD_BOT_BRIGHTNESS = (u32)brightness;
- }
- else if ((pressed & KEY_Y) && gspPatchDoneN3ds)
- {
- patchResult = PatchProcessByName("gsp", RosalinaMenu_RevertN3dsGspPatch);
- gspPatchDoneN3ds = !R_SUCCEEDED(patchResult);
- return;
- }
- else if (pressed & KEY_B)
+ if (pressed & KEY_B)
return;
}
while (!menuShouldExit);
+
+ Draw_Lock();
+
+ Draw_RestoreFramebuffer();
+ Draw_FreeFramebufferCache();
+
+ svcKernelSetState(0x10000, 2); // unblock gsp
+ gspLcdInit(); // assume it doesn't fail. If it does, brightness won't change, anyway.
+
+ // gsp:LCD will normalize the brightness between top/bottom screen, handle PWM, etc.
+
+ s32 lum = (s32)luminance;
+
+ do
+ {
+ u32 pressed = waitInputWithTimeout(1000);
+ if (pressed & DIRECTIONAL_KEYS)
+ {
+ if (pressed & KEY_UP)
+ lum += 1;
+ else if (pressed & KEY_DOWN)
+ lum -= 1;
+ else if (pressed & KEY_RIGHT)
+ lum += 10;
+ else if (pressed & KEY_LEFT)
+ lum -= 10;
+
+ lum = lum < 0 ? 0 : lum;
+
+ // We need to call gsp here because updating the active duty LUT is a bit tedious (plus, GSP has internal state).
+ // This is actually SetLuminance:
+ GSPLCD_SetBrightnessRaw(BIT(GSP_SCREEN_TOP) | BIT(GSP_SCREEN_BOTTOM), lum);
+ }
+
+ if (pressed & KEY_B)
+ break;
+ }
+ while (!menuShouldExit);
+
+ gspLcdExit();
+ svcKernelSetState(0x10000, 2); // block gsp again
+
+ if (R_FAILED(Draw_AllocateFramebufferCache(FB_BOTTOM_SIZE)))
+ {
+ // Shouldn't happen
+ __builtin_trap();
+ }
+ else
+ Draw_SetupFramebuffer();
+
+ Draw_Unlock();
}
void RosalinaMenu_PowerOff(void) // Soft shutdown.
@@ -271,7 +271,7 @@ void RosalinaMenu_PowerOff(void) // Soft shutdown.
do
{
Draw_Lock();
- Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina menu");
+ Draw_DrawString(10, 10, COLOR_TITLE, "Power off");
Draw_DrawString(10, 30, COLOR_WHITE, "Press A to power off, press B to go back.");
Draw_FlushFramebuffer();
Draw_Unlock();
diff --git a/sysmodules/rosalina/source/menus/debugger.c b/sysmodules/rosalina/source/menus/debugger.c
index 70bf67a..0a00ebf 100644
--- a/sysmodules/rosalina/source/menus/debugger.c
+++ b/sysmodules/rosalina/source/menus/debugger.c
@@ -102,7 +102,6 @@ Result debuggerDisable(s64 timeout)
svcCloseHandle(dummy);
PMDBG_DebugNextApplicationByForce(false);
nextApplicationGdbCtx = NULL;
- svcKernelSetState(0x10000, 2);
}
return res;
diff --git a/sysmodules/rosalina/source/menus/miscellaneous.c b/sysmodules/rosalina/source/menus/miscellaneous.c
index c4e66af..579bd78 100644
--- a/sysmodules/rosalina/source/menus/miscellaneous.c
+++ b/sysmodules/rosalina/source/menus/miscellaneous.c
@@ -55,7 +55,7 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void)
Result res;
char failureReason[64];
- if(HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID)
+ if(Luma_SharedConfig->hbldr_3dsx_tid == HBLDR_DEFAULT_3DSX_TID)
{
FS_ProgramInfo progInfo;
u32 pid;
@@ -63,7 +63,7 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void)
res = PMDBG_GetCurrentAppInfo(&progInfo, &pid, &launchFlags);
if(R_SUCCEEDED(res))
{
- HBLDR_3DSX_TID = progInfo.programId;
+ Luma_SharedConfig->hbldr_3dsx_tid = progInfo.programId;
miscellaneousMenu.items[0].title = "Switch the hb. title to hblauncher_loader";
}
else
@@ -75,7 +75,7 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void)
else
{
res = 0;
- HBLDR_3DSX_TID = HBLDR_DEFAULT_3DSX_TID;
+ Luma_SharedConfig->hbldr_3dsx_tid = HBLDR_DEFAULT_3DSX_TID;
miscellaneousMenu.items[0].title = "Switch the hb. title to the current app.";
}
@@ -205,7 +205,7 @@ Result SaveSettings(void)
configData.config = config;
configData.multiConfig = multiConfig;
configData.bootConfig = bootConfig;
- configData.hbldr3dsxTitleId = HBLDR_3DSX_TID;
+ configData.hbldr3dsxTitleId = Luma_SharedConfig->hbldr_3dsx_tid;
configData.rosalinaMenuCombo = menuCombo;
configData.rosalinaFlags = PluginLoader__IsEnabled();
@@ -331,7 +331,21 @@ void MiscellaneousMenu_InputRedirection(void)
else
{
if(res == 0)
- Draw_DrawString(10, 30, COLOR_WHITE, "InputRedirection stopped successfully.");
+ {
+ u32 posY = 30;
+ posY = Draw_DrawString(10, posY, COLOR_WHITE, "InputRedirection stopped successfully.\n\n");
+ if (isN3DS)
+ {
+ posY = Draw_DrawString(
+ 10,
+ posY,
+ COLOR_WHITE,
+ "This might cause a key press to be repeated in\n"
+ "Home Menu for no reason.\n\n"
+ "Just pressing ZL/ZR on the console is enough to fix\nthis.\n"
+ );
+ }
+ }
else
Draw_DrawString(10, 30, COLOR_WHITE, buf);
}
diff --git a/sysmodules/rosalina/source/menus/screen_filters.c b/sysmodules/rosalina/source/menus/screen_filters.c
index 7fe3f9e..1d3d257 100644
--- a/sysmodules/rosalina/source/menus/screen_filters.c
+++ b/sysmodules/rosalina/source/menus/screen_filters.c
@@ -32,26 +32,29 @@
#include "redshift/redshift.h"
#include "redshift/colorramp.h"
-typedef struct {
- u8 r;
- u8 g;
- u8 b;
- u8 z;
+typedef union {
+ struct {
+ u8 r;
+ u8 g;
+ u8 b;
+ u8 z;
+ };
+ u32 raw;
} Pixel;
static u16 g_c[0x600];
static Pixel g_px[0x400];
-int screenFiltersCurrentTemperature = 6500;
+int screenFiltersCurrentTemperature = -1;
-static void ScreenFiltersMenu_WriteLut(const u32* lut)
+static void ScreenFiltersMenu_WriteLut(const Pixel* lut)
{
GPU_FB_TOP_COL_LUT_INDEX = 0;
GPU_FB_BOTTOM_COL_LUT_INDEX = 0;
for (int i = 0; i <= 255; i++) {
- GPU_FB_TOP_COL_LUT_ELEM = *lut;
- GPU_FB_BOTTOM_COL_LUT_ELEM = *lut;
+ GPU_FB_TOP_COL_LUT_ELEM = lut->raw;
+ GPU_FB_BOTTOM_COL_LUT_ELEM = lut->raw;
lut++;
}
}
@@ -84,7 +87,7 @@ static void ScreenFiltersMenu_ApplyColorSettings(color_setting_t* cs)
g_px[i].b = *(g_c + i + 0x200) >> 8;
} while(++i);
- ScreenFiltersMenu_WriteLut((u32*)g_px);
+ ScreenFiltersMenu_WriteLut(g_px);
}
static void ScreenFiltersMenu_SetCct(int cct)
@@ -101,7 +104,6 @@ static void ScreenFiltersMenu_SetCct(int cct)
ScreenFiltersMenu_ApplyColorSettings(&cs);
}
-
Menu screenFiltersMenu = {
"Screen filters menu",
{
@@ -126,6 +128,20 @@ void ScreenFiltersMenu_Set##name(void)\
ScreenFiltersMenu_SetCct(temp);\
}
+void ScreenFiltersMenu_RestoreCct(void)
+{
+ // Not initialized: return
+ if (screenFiltersCurrentTemperature == -1)
+ return;
+
+ // Wait for GSP to restore the CCT table
+ while (GPU_FB_TOP_COL_LUT_ELEM != g_px[0].raw)
+ svcSleepThread(10 * 1000 * 1000LL);
+
+ svcSleepThread(10 * 1000 * 1000LL);
+ ScreenFiltersMenu_WriteLut(g_px);
+}
+
DEF_CCT_SETTER(6500, Default)
DEF_CCT_SETTER(10000, Aquarium)
diff --git a/sysmodules/rosalina/source/menus/sysconfig.c b/sysmodules/rosalina/source/menus/sysconfig.c
index 4a357dd..babf15b 100644
--- a/sysmodules/rosalina/source/menus/sysconfig.c
+++ b/sysmodules/rosalina/source/menus/sysconfig.c
@@ -35,10 +35,10 @@
Menu sysconfigMenu = {
"System configuration menu",
{
+ { "Control Wireless connection", METHOD, .method = &SysConfigMenu_ControlWifi },
{ "Toggle LEDs", METHOD, .method = &SysConfigMenu_ToggleLEDs },
{ "Toggle Wireless", METHOD, .method = &SysConfigMenu_ToggleWireless },
{ "Toggle Power Button", METHOD, .method=&SysConfigMenu_TogglePowerButton },
- { "Control Wireless connection", METHOD, .method = &SysConfigMenu_ControlWifi },
{},
}
};
diff --git a/sysmodules/rosalina/source/minisoc.c b/sysmodules/rosalina/source/minisoc.c
index d52d48c..252c81d 100644
--- a/sysmodules/rosalina/source/minisoc.c
+++ b/sysmodules/rosalina/source/minisoc.c
@@ -1,3 +1,4 @@
+
/*
* This file is part of Luma3DS.
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
@@ -7,18 +8,16 @@
#include "minisoc.h"
#include
-#include <3ds/ipc.h>
-#include <3ds/os.h>
-#include <3ds/synchronization.h>
-#include <3ds/result.h>
+#include <3ds.h>
#include
-#include "csvc.h"
+#include "utils.h"
s32 miniSocRefCount = 0;
static u32 socContextAddr = 0x08000000;
static u32 socContextSize = 0x60000;
static Handle miniSocHandle;
static Handle miniSocMemHandle;
+static bool exclusiveStateEntered = false;
bool miniSocEnabled = false;
@@ -56,6 +55,41 @@ static Result SOCU_Shutdown(void)
return cmdbuf[1];
}
+// unsafe but what can I do?
+void miniSocLockState(void)
+{
+ Result res = 0;
+ __dmb();
+ if (!exclusiveStateEntered && isServiceUsable("ndm:u"))
+ {
+ ndmuInit();
+ res = NDMU_EnterExclusiveState(NDM_EXCLUSIVE_STATE_INFRASTRUCTURE);
+ if (R_SUCCEEDED(res))
+ res = NDMU_LockState(); // prevents ndm from switching to StreetPass when the lid is closed
+ exclusiveStateEntered = R_SUCCEEDED(res);
+ __dmb();
+ }
+}
+
+void miniSocUnlockState(bool force)
+{
+ Result res = 0;
+
+ __dmb();
+ if (exclusiveStateEntered)
+ {
+ if (!force)
+ {
+ res = NDMU_UnlockState();
+ if (R_SUCCEEDED(res))
+ res = NDMU_LeaveExclusiveState();
+ }
+ ndmuExit();
+ exclusiveStateEntered = R_FAILED(res);
+ __dmb();
+ }
+}
+
Result miniSocInit(void)
{
if(AtomicPostIncrement(&miniSocRefCount))
@@ -89,8 +123,11 @@ Result miniSocInit(void)
ret = SOCU_Initialize(miniSocMemHandle, socContextSize);
if(ret != 0) goto cleanup;
- svcKernelSetState(0x10000, 2);
+ miniSocLockState();
+
+ svcKernelSetState(0x10000, 0x10);
miniSocEnabled = true;
+
return 0;
cleanup:
@@ -117,7 +154,6 @@ cleanup:
Result miniSocExitDirect(void)
{
- //if (miniSocRefCount != 0) __builtin_trap();
Result ret = 0;
u32 tmp;
@@ -132,8 +168,10 @@ Result miniSocExitDirect(void)
svcControlMemory(&tmp, socContextAddr, socContextAddr, socContextSize, MEMOP_FREE, MEMPERM_DONTCARE);
if(ret == 0)
{
- svcKernelSetState(0x10000, 2);
+ miniSocUnlockState(false);
+
miniSocEnabled = false;
+ svcKernelSetState(0x10000, 0x10);
}
return ret;
}
diff --git a/sysmodules/sm/README.md b/sysmodules/sm/README.md
index b63f514..34a8318 100644
--- a/sysmodules/sm/README.md
+++ b/sysmodules/sm/README.md
@@ -3,7 +3,7 @@ Open source replacement of the Arm11 SM system module.
This is licensed under the MIT license.
# Usage
-To run this system module, use a recent release or commit of [Luma3DS](https://github.com/AuroraWright/Luma3DS/), build this project and copy sm.cxi to /luma/sysmodules/.
+To run this system module, use a recent release or commit of [Luma3DS](https://github.com/LumaTeam/Luma3DS/), build this project and copy sm.cxi to /luma/sysmodules/.
# Credits
Everyone that helped me fix some of stupid bugs I had been making: @fincs, @Hikari-chin, etc.
diff --git a/sysmodules/sm/source/notifications.c b/sysmodules/sm/source/notifications.c
index 7a69004..07f2694 100644
--- a/sysmodules/sm/source/notifications.c
+++ b/sysmodules/sm/source/notifications.c
@@ -8,6 +8,18 @@ This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for
#include "notifications.h"
#include "processes.h"
+#include
+
+static bool isNotificationInhibited(const ProcessData *processData, u32 notificationId)
+{
+ (void)processData;
+ switch(notificationId)
+ {
+ default:
+ return false;
+ }
+}
+
static bool doPublishNotification(ProcessData *processData, u32 notificationId, u32 flags)
{
if((flags & 1) && processData->nbPendingNotifications != 0) // only send if not already pending
@@ -126,7 +138,7 @@ Result PublishToSubscriber(u32 notificationId, u32 flags)
{
for(ProcessData *node = processDataInUseList.first; node != NULL; node = node->next)
{
- if(!node->notificationEnabled)
+ if(!node->notificationEnabled || isNotificationInhibited(node, notificationId))
continue;
u16 i;
@@ -146,7 +158,7 @@ Result PublishAndGetSubscriber(u32 *pidCount, u32 *pidList, u32 notificationId,
u32 nb = 0;
for(ProcessData *node = processDataInUseList.first; node != NULL; node = node->next)
{
- if(!node->notificationEnabled)
+ if(!node->notificationEnabled || isNotificationInhibited(node, notificationId))
continue;
u16 i;
diff --git a/sysmodules/sm/source/notifications.h b/sysmodules/sm/source/notifications.h
index 42b640f..40855e7 100644
--- a/sysmodules/sm/source/notifications.h
+++ b/sysmodules/sm/source/notifications.h
@@ -17,3 +17,5 @@ Result PublishToSubscriber(u32 notificationId, u32 flags);
Result PublishAndGetSubscriber(u32 *pidCount, u32 *pidList, u32 notificationId, u32 flags);
Result PublishToProcess(Handle process, u32 notificationId);
Result PublishToAll(u32 notificationId);
+
+Result AddToNdmuWorkaroundCount(s32 count);