Compare commits

...

38 Commits

Author SHA1 Message Date
Lorenzo Dellacà
08110cb125 added "-lm" flag 2020-07-22 22:15:42 +02:00
Lorenzo Dellacà
fd8dd82a8d fixed various build errors 2020-07-22 22:11:32 +02:00
Lorenzo Dellacà
47b5466a6e Merge branch 'master' into 3gx-master
* master:
  rosalina: work around gsp bug
  fix typo in screen filters menu
2020-07-22 19:27:49 +02:00
Lorenzo Dellacà
15342b5030 Merge branch 'master' into 3gx-master
* master:
  removed duplicate include
2020-07-22 19:24:15 +02:00
Lorenzo Dellacà
832c215a2d removed duplicate include 2020-07-22 19:21:59 +02:00
Lorenzo Dellacà
979c59d6f2 Merge commit 'bb07a7334f064c9512bd7e387dab1b9ef9e228cd' into 3gx-master
* commit 'bb07a7334f064c9512bd7e387dab1b9ef9e228cd': (23 commits)
  update gitignore and makefile
  rosalina: ndm + shutdown issue workaround
  rosalina: ndm doesn't exist on SAFE_FIRM
  Update bug-report.md, etc
  rosalina: forgot float suffix in luminance.c
  rosalina: display min/max luminance
  hbloader: allow homebrew to write to the shared config page
  rosalina: minor menu changes
  rosalina/sm: properly interact with ndm
  k11ext: refactor ndm:u workaround
  k11ext: fix oops
  rosalina: properly rewrite luminance-setting menu, etc.
  sysmodules: use libctru configmem defs
  Fix release building (#1454)
  sysmodules: introduce "luma shared config", rewrite ndmu workaround
  rosalina: autoclose menu on sleep mode/shell closed to prevent lockup
  rosalina: prevent disconnect when shell is closed
  rosalina: properly restore screen filters when lid is reopened
  rosalina: prevent sleep mode entry if debugger/input redir is enabled to prevent lockup
  Separate exception dump parser in another repo, add boot.3dsx to release command
  ...

# Conflicts:
#	.gitignore
#	exception_dump_parser/luma3ds_exception_dump_parser/__main__.py
#	sysmodules/rosalina/source/input_redirection.c
#	sysmodules/rosalina/source/menu.c
2020-07-21 11:27:18 +02:00
TuxSH
738a242e3c rosalina: work around gsp bug 2020-07-17 13:50:00 +01:00
TuxSH
5fd6dc6dd4 Merge pull request #1459 from iomintz/patch-1
fix typo in screen filters menu
2020-07-17 11:40:12 +01:00
iomintz
3fd9cacb6d fix typo in screen filters menu
Ember is 1200K, not 2700K.
2020-07-17 08:56:10 +00:00
TuxSH
bb07a7334f update gitignore and makefile 2020-07-16 18:06:14 +01:00
TuxSH
748b771618 rosalina: ndm + shutdown issue workaround 2020-07-16 17:55:31 +01:00
TuxSH
d6e72080d9 rosalina: ndm doesn't exist on SAFE_FIRM 2020-07-16 16:56:59 +01:00
TuxSH
70109fed2c Update bug-report.md, etc 2020-07-16 16:25:56 +01:00
TuxSH
cf36d21daf rosalina: forgot float suffix in luminance.c 2020-07-16 01:24:22 +01:00
TuxSH
781cd85b00 rosalina: display min/max luminance 2020-07-16 00:50:05 +01:00
TuxSH
514537a983 hbloader: allow homebrew to write to the shared config page 2020-07-15 23:04:35 +01:00
TuxSH
184f4587fb rosalina: minor menu changes 2020-07-15 22:24:08 +01:00
TuxSH
e096aaabc4 rosalina/sm: properly interact with ndm 2020-07-15 18:57:53 +01:00
TuxSH
ba26ae0f1c k11ext: refactor ndm:u workaround 2020-07-15 17:33:47 +01:00
TuxSH
786adf0268 k11ext: fix oops 2020-07-15 00:56:25 +01:00
TuxSH
2af05220c2 rosalina: properly rewrite luminance-setting menu, etc. 2020-07-14 22:10:13 +01:00
TuxSH
362c4ffff1 sysmodules: use libctru configmem defs 2020-07-12 21:26:02 +01:00
Death Mask Salesman
95fd4e763b Fix release building (#1454)
`boot.3dsx` is downloaded from a static URL via `curl`.

Fixes #1453
2020-07-12 19:39:03 +01:00
TuxSH
768e587b76 sysmodules: introduce "luma shared config", rewrite ndmu workaround 2020-07-12 19:36:18 +01:00
TuxSH
e3bb1c1b63 rosalina: autoclose menu on sleep mode/shell closed to prevent lockup 2020-07-11 22:04:13 +01:00
TuxSH
4c01bb453c rosalina: prevent disconnect when shell is closed
Fuck ndm, fuck StreetPass
2020-07-11 21:39:36 +01:00
TuxSH
dc67d438dc rosalina: properly restore screen filters when lid is reopened 2020-07-10 22:58:07 +01:00
TuxSH
2d58ec4c86 rosalina: prevent sleep mode entry if debugger/input redir is enabled to prevent lockup 2020-07-09 22:20:29 +01:00
TuxSH
555286ea47 Separate exception dump parser in another repo, add boot.3dsx to release command
https://github.com/LumaTeam/luma3ds_exception_dump_parser
2020-07-09 19:52:55 +01:00
TuxSH
b17eb66d55 rosalina inputredir: Use ir patch from @Nanquitas ; also refactor the code
Fixes #1428, #1438 (I think)
2020-07-08 22:08:57 +01:00
Lorenzo Dellacà
5670062a0f updated .gitignore 2020-07-08 00:44:26 +02:00
TuxSH
9ca52054cf rosalina: bump FS priority 2020-07-07 23:27:26 +01:00
TuxSH
991f51831d kext: add hid/ir thread locking 2020-07-07 23:27:15 +01:00
Lorenzo Dellacà
53ab41e6d0 fixed ARM "undefined instruction" kernel panic when closing games 2020-07-07 00:16:45 +02:00
Lorenzo Dellacà
1176fa8f28 Merge branch 'master' into 3gx-master
* master:
  Change screen filters presets (adding more) menu & print CCT. Fixes #1442.
  rosalina: implement 800px top-screen screenshot, etc. Fixes #1443

# Conflicts:
#	sysmodules/rosalina/source/draw.c
2020-07-06 20:20:27 +02:00
TuxSH
e69f89a0d4 Change screen filters presets (adding more) menu & print CCT. Fixes #1442.
Most new presets come from 8bitwonder
2020-07-05 20:54:27 +01:00
TuxSH
9411a8c186 rosalina: implement 800px top-screen screenshot, etc. Fixes #1443 2020-07-05 18:44:41 +01:00
Lorenzo Dellacà
aa577d0e39 Update README.md 2020-07-04 14:43:01 +02:00
45 changed files with 1039 additions and 520 deletions

View File

@@ -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: -- THIS IS NOT A SUPPORT FORUM! For support go here:
-- Nintendo Homebrew: https://discord.gg/MjzatM8 -- 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. -- 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. -- 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. -- Luma updaters that don't support Boot9Strap/Sighax won't work.
-- This is due to support for non-B9S/Sighax entrypoints being dropped. -- 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.--> -- Please fill in the placeholders.-->
**System model:** **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):** **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:** **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:** **Luma3DS configuration/options:**
@@ -50,7 +50,7 @@ Splash duration: ( )
PIN lock: ( ) PIN lock: ( )
New 3DS CPU: ( ) New 3DS CPU: ( )
<!--This option is only available for New 3DS/2DS.--> <!--This option is only available on New 3DS (XL)/New 2DS XL.-->
-- --
@@ -70,12 +70,13 @@ Show NAND or user string in System Settings: ( )
Show GBA boot screen in patched AGB_FIRM: ( ) Show GBA boot screen in patched AGB_FIRM: ( )
Patch Arm9 access: ( )
Set developer UNITINFO: ( ) Set developer UNITINFO: ( )
Disable Arm11 exception handlers: ( ) Disable Arm11 exception handlers: ( )
Enable Rosalina on SAFE_FIRM: ( )
<!--This option is only available on New 3DS (XL)/New 2DS XL.-->
-- --

4
.gitignore vendored
View File

@@ -13,8 +13,12 @@ exceptions/arm11/build
*.d *.d
*.elf *.elf
*.cxi *.cxi
*.3dsx
.DS_Store .DS_Store
*.dmp *.dmp
.project .project
.cproject .cproject
.settings .settings
.idea/
Luma3DS*.zip

View File

@@ -15,9 +15,10 @@ release: $(NAME)$(REVISION).zip
clean: clean:
@$(foreach dir, $(SUBFOLDERS), $(MAKE) -C $(dir) clean &&) true @$(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*" @zip -r $@ $^ -x "*.DS_Store*" "*__MACOSX*"
boot.firm: $(SUBFOLDERS) boot.firm: $(SUBFOLDERS)
@@ -25,5 +26,9 @@ boot.firm: $(SUBFOLDERS)
-A 0x18180000 -C XDMA XDMA NDMA XDMA -A 0x18180000 -C XDMA XDMA NDMA XDMA
@echo built... $(notdir $@) @echo built... $(notdir $@)
boot.3dsx:
@curl -sSL "https://github.com/fincs/new-hbmenu/releases/latest/download/boot.3dsx" -o "$@"
@echo downloaded... $(notdir $@)
$(SUBFOLDERS): $(SUBFOLDERS):
@$(MAKE) -C $@ all @$(MAKE) -C $@ all

View File

@@ -5,6 +5,7 @@
This edition of **Luma3DS** allows the loading of **.3GX plugins** in Luma3DS, which are otherwise officially unsupported. This edition of **Luma3DS** allows the loading of **.3GX plugins** in Luma3DS, which are otherwise officially unsupported.
#
### How to install this Edition ### How to install this Edition
1. download the latest `boot.firm` from [the releases page](https://github.com/mind-overflow/Luma3DS-3GX/releases/latest) 1. download the latest `boot.firm` from [the releases page](https://github.com/mind-overflow/Luma3DS-3GX/releases/latest)
2. put the downloaded `boot.firm` file in the `root` directory of your SD card (`sd:/boot.firm`), overwriting the official Luma3DS `boot.firm`. 2. put the downloaded `boot.firm` file in the `root` directory of your SD card (`sd:/boot.firm`), overwriting the official Luma3DS `boot.firm`.
@@ -15,6 +16,7 @@ This edition of **Luma3DS** allows the loading of **.3GX plugins** in Luma3DS, w
You successfully installed the 3GX Plugin Loader! Now, proceed to the next step to learn how to install and enable 3GX plugins. You successfully installed the 3GX Plugin Loader! Now, proceed to the next step to learn how to install and enable 3GX plugins.
#
### How to install 3GX plugins ### How to install 3GX plugins
Plugins have to be installed in the `sd:/luma/plugins` folder. Plugins have to be installed in the `sd:/luma/plugins` folder.
Usually, you need to put your specific plugin in the `<TITLEID>` subdirectory, eg: `sd:/luma/plugins/<TITLEID>/<filename>.3gx`. Usually, you need to put your specific plugin in the `<TITLEID>` subdirectory, eg: `sd:/luma/plugins/<TITLEID>/<filename>.3gx`.
@@ -28,6 +30,7 @@ So:
Now you know how to install 3GX plugins! Proceed to the next step to learn how how to enable 3GX plugins. Now you know how to install 3GX plugins! Proceed to the next step to learn how how to enable 3GX plugins.
#
### How to enable 3GX plugins ### How to enable 3GX plugins
1. when booted, press `L + D-Pad Down + Select` to open the Rosalina menu. 1. when booted, press `L + D-Pad Down + Select` to open the Rosalina menu.
2. Press `D-Pad Down` again until `Plugin Loader`, is selected, then press `A` and set it to `[Enabled]`. 2. Press `D-Pad Down` again until `Plugin Loader`, is selected, then press `A` and set it to `[Enabled]`.
@@ -35,6 +38,7 @@ Now you know how to install 3GX plugins! Proceed to the next step to learn how h
Done! You learned to install the 3GX Plugin loader, install 3GX Plugins and enable them. Now, simply launch the game you want to play and press `SELECT` to open up the 3GX menu! Done! You learned to install the 3GX Plugin loader, install 3GX Plugins and enable them. Now, simply launch the game you want to play and press `SELECT` to open up the 3GX menu!
#
### Luma3DS introduction ### Luma3DS introduction
**Luma3DS** is a program to patch the system software of (New) Nintendo (2)3DS handheld consoles "on the fly", adding features such as per-game language settings, debugging capabilities for developers, and removing restrictions enforced by Nintendo such as the region lock. **Luma3DS** is a program to patch the system software of (New) Nintendo (2)3DS handheld consoles "on the fly", adding features such as per-game language settings, debugging capabilities for developers, and removing restrictions enforced by Nintendo such as the region lock.

View File

@@ -34,6 +34,8 @@
#include "buttons.h" #include "buttons.h"
#include "arm9_exception_handlers.h" #include "arm9_exception_handlers.h"
// See https://github.com/LumaTeam/luma3ds_exception_dump_parser
void installArm9Handlers(void) void installArm9Handlers(void)
{ {
vu32 *dstVeneers = (vu32 *)0x08000000; vu32 *dstVeneers = (vu32 *)0x08000000;

View File

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

View File

@@ -36,11 +36,12 @@ void executeFunctionOnCores(SGI0Handler_t func, u8 targetList, u8 targetListFilt
void KScheduler__TriggerCrossCoreInterrupt(KScheduler *this); void KScheduler__TriggerCrossCoreInterrupt(KScheduler *this);
void KThread__DebugReschedule(KThread *this, bool lock); void KThread__DebugReschedule(KThread *this, bool lock);
bool rosalinaThreadLockPredicate(KThread *thread);
bool rosalinaThreadLockPredicate(KThread *thread, u32 mask);
void rosalinaRescheduleThread(KThread *thread, bool lock); void rosalinaRescheduleThread(KThread *thread, bool lock);
void rosalinaLockThread(KThread *thread);
void rosalinaLockAllThreads(void); void rosalinaLockThreads(u32 mask);
void rosalinaUnlockAllThreads(void); void rosalinaUnlockThreads(u32 mask);
// Taken from ctrulib: // 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"); __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) static inline void __clrex(void)
{ {
__asm__ __volatile__("clrex" ::: "memory"); __asm__ __volatile__("clrex" ::: "memory");

View File

@@ -89,7 +89,7 @@ void signalSvcReturn(u8 *pageEnd)
void postprocessSvc(void) void postprocessSvc(void)
{ {
KThread *currentThread = currentCoreContext->objectContext.currentThread; KThread *currentThread = currentCoreContext->objectContext.currentThread;
if(!currentThread->shallTerminate && rosalinaThreadLockPredicate(currentThread)) if(!currentThread->shallTerminate && rosalinaThreadLockPredicate(currentThread, rosalinaState & 5))
rosalinaRescheduleThread(currentThread, true); rosalinaRescheduleThread(currentThread, true);
officialPostProcessSvc(); officialPostProcessSvc();
@@ -118,7 +118,6 @@ void *svcHook(u8 *pageEnd)
KEvent* event = (KEvent *)KProcessHandleTable__ToKAutoObject(handleTableOfProcess(currentProcess), KEvent* event = (KEvent *)KProcessHandleTable__ToKAutoObject(handleTableOfProcess(currentProcess),
KPROCESS_GET_RVALUE(currentProcess, resumeProcessExitEvent)); KPROCESS_GET_RVALUE(currentProcess, resumeProcessExitEvent));
WaitSynchronization1(NULL, currentCoreContext->objectContext.currentThread, (KSynchronizationObject *)event, 10000000000ULL);
((KAutoObject *)event)->vtable->DecrementReferenceCount((KAutoObject *)event); ((KAutoObject *)event)->vtable->DecrementReferenceCount((KAutoObject *)event);
} }
return officialSVCs[0x3]; return officialSVCs[0x3];

View File

@@ -5,8 +5,13 @@
typedef bool (*ThreadPredicate)(KThread *thread); typedef bool (*ThreadPredicate)(KThread *thread);
void rosalinaLockThread(KThread *thread); static void rosalinaLockThread(KThread *thread)
void rosalinaRescheduleThread(KThread *thread, bool lock); {
KThread *syncThread = synchronizationMutex->owner;
if(syncThread == NULL || syncThread != thread)
rosalinaRescheduleThread(thread, true);
}
Result ControlProcess(Handle processHandle, ProcessOp op, u32 varg2, u32 varg3) Result ControlProcess(Handle processHandle, ProcessOp op, u32 varg2, u32 varg3)
{ {

View File

@@ -105,14 +105,22 @@ Result KernelSetStateHook(u32 type, u32 varg1, u32 varg2, u32 varg3)
__ldrex((s32 *)&rosalinaState); __ldrex((s32 *)&rosalinaState);
} }
while(__strex((s32 *)&rosalinaState, (s32)(rosalinaState ^ varg1))); while(__strex((s32 *)&rosalinaState, (s32)(rosalinaState ^ varg1)));
__dmb();
if(rosalinaState & 2) if(rosalinaState & 0x10)
hasStartedRosalinaNetworkFuncsOnce = true; hasStartedRosalinaNetworkFuncsOnce = true;
if(rosalinaState & 1) // 1: all applet/app/dsp/csnd... threads 2: gsp 4: hid/ir
rosalinaLockAllThreads(); for (u32 v = 4; v != 0; v >>= 1)
else if(varg1 & 1) {
rosalinaUnlockAllThreads(); if (varg1 & v)
{
if (rosalinaState & v)
rosalinaLockThreads(v);
else
rosalinaUnlockThreads(v);
}
}
break; break;
} }

View File

@@ -28,9 +28,16 @@
#include "svc/SendSyncRequest.h" #include "svc/SendSyncRequest.h"
#include "ipc.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) 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); KClientSession *clientSession = (KClientSession *)KProcessHandleTable__ToKAutoObject(handleTable, handle);
u32 *cmdbuf = (u32 *)((u8 *)currentCoreContext->objectContext.currentThread->threadLocalStorage + 0x80); u32 *cmdbuf = (u32 *)((u8 *)currentCoreContext->objectContext.currentThread->threadLocalStorage + 0x80);
@@ -47,7 +54,7 @@ Result SendSyncRequestHook(Handle handle)
case 0x10042: case 0x10042:
{ {
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce) if(isNdmuWorkaround(info, pid))
{ {
cmdbuf[0] = 0x10040; cmdbuf[0] = 0x10040;
cmdbuf[1] = 0; cmdbuf[1] = 0;
@@ -87,7 +94,7 @@ Result SendSyncRequestHook(Handle handle)
case 0x20002: case 0x20002:
{ {
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce) if(isNdmuWorkaround(info, pid))
{ {
cmdbuf[0] = 0x20040; cmdbuf[0] = 0x20040;
cmdbuf[1] = 0; cmdbuf[1] = 0;
@@ -129,7 +136,7 @@ Result SendSyncRequestHook(Handle handle)
if(!hasStartedRosalinaNetworkFuncsOnce) if(!hasStartedRosalinaNetworkFuncsOnce)
break; break;
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
skip = info != NULL && strcmp(info->name, "ndm:u") == 0; // SuspendScheduler skip = isNdmuWorkaround(info, pid); // SuspendScheduler
if(skip) if(skip)
cmdbuf[1] = 0; cmdbuf[1] = 0;
break; break;
@@ -140,7 +147,7 @@ Result SendSyncRequestHook(Handle handle)
if(!hasStartedRosalinaNetworkFuncsOnce) if(!hasStartedRosalinaNetworkFuncsOnce)
break; break;
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); 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[0] = 0x90040;
cmdbuf[1] = 0; cmdbuf[1] = 0;

View File

@@ -66,17 +66,12 @@ void KThread__DebugReschedule(KThread *this, bool lock)
KRecursiveLock__Unlock(criticalSectionLock); KRecursiveLock__Unlock(criticalSectionLock);
} }
bool rosalinaThreadLockPredicate(KThread *thread) static void rosalinaLockThread(KThread *thread)
{ {
KProcess *process = thread->ownerProcess; KThread *syncThread = synchronizationMutex->owner;
if(process == NULL)
return false;
u64 titleId = codeSetOfProcess(process)->titleId; if(syncThread == NULL || syncThread != thread)
u32 highTitleId = (u32)(titleId >> 32), lowTitleId = (u32)(titleId & ~0xF0000001); // clear N3DS and SAFE_FIRM bits rosalinaRescheduleThread(thread, true);
return
((rosalinaState & 1) && idOfProcess(process) >= nbSection0Modules &&
(highTitleId != 0x00040130 || (highTitleId == 0x00040130 && (lowTitleId == 0x1A02 || lowTitleId == 0x1C02))));
} }
void rosalinaRescheduleThread(KThread *thread, bool lock) void rosalinaRescheduleThread(KThread *thread, bool lock)
@@ -89,20 +84,45 @@ void rosalinaRescheduleThread(KThread *thread, bool lock)
else else
thread->schedulingMask &= ~0x40; thread->schedulingMask &= ~0x40;
KScheduler__AdjustThread(currentCoreContext->objectContext.currentScheduler, thread, oldSchedulingMask); if (oldSchedulingMask != thread->schedulingMask)
KScheduler__AdjustThread(currentCoreContext->objectContext.currentScheduler, thread, oldSchedulingMask);
KRecursiveLock__Unlock(criticalSectionLock); 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) u64 titleId = codeSetOfProcess(process)->titleId;
rosalinaRescheduleThread(thread, true); 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; 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) for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
{ {
KThread *thread = (KThread *)node->key; KThread *thread = (KThread *)node->key;
if(!rosalinaThreadLockPredicate(thread)) if(!rosalinaThreadLockPredicate(thread, mask))
continue; continue;
if(thread == coreCtxs[thread->coreId].objectContext.currentThread) if(thread == coreCtxs[thread->coreId].objectContext.currentThread)
currentThreadsFound = true; currentThreadsFound = true;
@@ -123,7 +143,7 @@ void rosalinaLockAllThreads(void)
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next) for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
{ {
KThread *thread = (KThread *)node->key; KThread *thread = (KThread *)node->key;
if(!rosalinaThreadLockPredicate(thread)) if(!rosalinaThreadLockPredicate(thread, mask))
continue; continue;
if(!(thread->schedulingMask & 0x40)) if(!(thread->schedulingMask & 0x40))
{ {
@@ -145,7 +165,7 @@ void rosalinaLockAllThreads(void)
KRecursiveLock__Unlock(criticalSectionLock); 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) 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 if((thread->schedulingMask & 0xF) == 2) // thread is terminating
continue; continue;
if(thread->schedulingMask & 0x40) if((thread->schedulingMask & 0x40) && rosalinaThreadLockPredicate(thread, mask))
rosalinaRescheduleThread(thread, false); rosalinaRescheduleThread(thread, false);
} }
} }

View File

@@ -2,8 +2,6 @@
#include <3ds/exheader.h> #include <3ds/exheader.h>
#define HBLDR_3DSX_TID (*(vu64 *)0x1FF81100)
Result hbldrInit(void); Result hbldrInit(void);
void hbldrExit(void); void hbldrExit(void);

View File

@@ -4,6 +4,7 @@
#include "ifile.h" #include "ifile.h"
#include "util.h" #include "util.h"
#include "hbldr.h" #include "hbldr.h"
#include "luma_shared_config.h"
extern u32 config, multiConfig, bootConfig; extern u32 config, multiConfig, bootConfig;
extern bool isN3DS, isSdMode; extern bool isN3DS, isSdMode;
@@ -91,6 +92,11 @@ static int lzss_decompress(u8 *end)
return ret; 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) static Result allocateSharedMem(prog_addrs_t *shared, prog_addrs_t *vaddr, int flags)
{ {
u32 dummy; 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 // 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()); assertSuccess(hbldrInit());
HBLDR_PatchExHeaderInfo(exheaderInfo); HBLDR_PatchExHeaderInfo(exheaderInfo);
@@ -219,7 +222,7 @@ static Result LoadProcess(Handle *process, u64 programHandle)
u64 titleId; u64 titleId;
// make sure the cached info corrosponds to the current programHandle // 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); res = GetProgramInfo(&g_exheaderInfo, programHandle);
g_cached_programHandle = programHandle; g_cached_programHandle = programHandle;
@@ -245,7 +248,7 @@ static Result LoadProcess(Handle *process, u64 programHandle)
titleId = g_exheaderInfo.aci.local_caps.title_id; titleId = g_exheaderInfo.aci.local_caps.title_id;
ExHeader_CodeSetInfo *csi = &g_exheaderInfo.sci.codeset_info; ExHeader_CodeSetInfo *csi = &g_exheaderInfo.sci.codeset_info;
if (titleId == HBLDR_3DSX_TID) if (hbldrIs3dsxTitle(titleId))
{ {
assertSuccess(hbldrInit()); assertSuccess(hbldrInit());
assertSuccess(HBLDR_LoadProcess(&codeset, csi->text.address, flags & 0xF00, titleId, csi->name)); assertSuccess(HBLDR_LoadProcess(&codeset, csi->text.address, flags & 0xF00, titleId, csi->name));
@@ -425,7 +428,7 @@ void loaderHandleCommands(void *ctx)
break; break;
case 4: // GetProgramInfo case 4: // GetProgramInfo
memcpy(&programHandle, &cmdbuf[1], 8); 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); res = GetProgramInfo(&g_exheaderInfo, programHandle);
g_cached_programHandle = R_SUCCEEDED(res) ? programHandle : 0; g_cached_programHandle = R_SUCCEEDED(res) ? programHandle : 0;

View File

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

View File

@@ -3,7 +3,7 @@ Open source replacement of the Arm11 PM system module.
This is licensed under the MIT license. This is licensed under the MIT license.
# Usage # 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 # Credits
@fincs @fincs

View File

@@ -218,8 +218,9 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const
programInfoUpdate = (launchFlags & PMLAUNCHFLAG_USE_UPDATE_TITLE) ? programInfoUpdate : programInfo; programInfoUpdate = (launchFlags & PMLAUNCHFLAG_USE_UPDATE_TITLE) ? programInfoUpdate : programInfo;
TRY(registerProgram(&programHandle, programInfo, programInfoUpdate)); TRY(registerProgram(&programHandle, programInfo, programInfoUpdate));
u32 coreVer = OS_KernelConfig->kernel_syscore_ver;
res = LOADER_GetProgramInfo(exheaderInfo, programHandle); 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)) { if (R_FAILED(res)) {
LOADER_UnregisterProgram(programHandle); LOADER_UnregisterProgram(programHandle);
@@ -227,7 +228,7 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const
} }
// Change APPMEMALLOC if needed // 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; u32 limitMb;
SystemMode n3dsSystemMode = exheaderInfo->aci.local_caps.core_info.n3ds_system_mode; SystemMode n3dsSystemMode = exheaderInfo->aci.local_caps.core_info.n3ds_system_mode;
bool forceO3dsAppMem = (launchFlags & PMLAUNCHFLAG_FORCE_USE_O3DS_APP_MEM) != 0; 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 tidh = (u32)(programInfo->programId >> 32);
u32 tidl = (u32)programInfo->programId; 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) // 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. // Official PM also hardcodes SYSCOREVER = 2 here.
// NATIVE_FIRM-only.
panic(4); panic(4);
} }
@@ -520,8 +523,8 @@ Result autolaunchSysmodules(void)
FS_ProgramInfo programInfo = { .mediaType = MEDIATYPE_NAND }; FS_ProgramInfo programInfo = { .mediaType = MEDIATYPE_NAND };
// Launch NS // Launch NS
if (NSTID != 0) { if (OS_KernelConfig->ns_tid != 0) {
programInfo.programId = NSTID; programInfo.programId = OS_KernelConfig->ns_tid;
TRY(launchTitleImplWrapper(NULL, NULL, &programInfo, &programInfo, PMLAUNCHFLAG_LOAD_DEPENDENCIES)); TRY(launchTitleImplWrapper(NULL, NULL, &programInfo, &programInfo, PMLAUNCHFLAG_LOAD_DEPENDENCIES));
} }

View File

@@ -29,7 +29,7 @@ static void cleanupProcess(ProcessData *process)
ProcessList_Lock(&g_manager.processList); ProcessList_Lock(&g_manager.processList);
if (g_manager.runningApplicationData != NULL && process->handle == g_manager.runningApplicationData->handle) { 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()); assertSuccess(resetAppMemLimit());
} }
g_manager.runningApplicationData = NULL; g_manager.runningApplicationData = NULL;

View File

@@ -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 // 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; ReslimitValues *values = !IS_N3DS ? g_o3dsReslimitValues : g_n3dsReslimitValues;
static const u32 minAppletMemAmount = 0x1200000; static const u32 minAppletMemAmount = 0x1200000;
@@ -261,7 +262,7 @@ static ReslimitValues *fixupReslimitValues(void)
u32 baseRegionSize = !IS_N3DS ? 0x1400000 : 0x2000000; u32 baseRegionSize = !IS_N3DS ? 0x1400000 : 0x2000000;
if (sysmemalloc < minAppletMemAmount) { if (sysmemalloc < minAppletMemAmount) {
values[1][0] = SYSMEMALLOC - minAppletMemAmount / 3; values[1][0] = sysmemalloc - minAppletMemAmount / 3;
values[2][0] = 0; values[2][0] = 0;
values[3][0] = baseRegionSize + otherMinOvercommitAmount; values[3][0] = baseRegionSize + otherMinOvercommitAmount;
} else { } else {
@@ -271,8 +272,8 @@ static ReslimitValues *fixupReslimitValues(void)
values[3][0] = baseRegionSize + (otherMinOvercommitAmount + excess / 4); values[3][0] = baseRegionSize + (otherMinOvercommitAmount + excess / 4);
} }
values[0][0] = APPMEMALLOC; values[0][0] = appmemalloc;
g_defaultAppMemLimit = APPMEMALLOC; g_defaultAppMemLimit = appmemalloc;
return values; return values;
} }

View File

@@ -8,13 +8,7 @@
#define REG32(reg) (*(vu32 *)reg) #define REG32(reg) (*(vu32 *)reg)
#define REG64(reg) (*(vu64 *)reg) #define REG64(reg) (*(vu64 *)reg)
#define NSTID REG64(0x1FF80008) #define IS_N3DS (OS_KernelConfig->app_memtype >= 6) // APPMEMTYPE. Hacky but doesn't use APT
#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 N3DS_TID_MASK 0xF0000000ULL #define N3DS_TID_MASK 0xF0000000ULL
#define N3DS_TID_BIT 0x20000000ULL #define N3DS_TID_BIT 0x20000000ULL

View File

@@ -3,7 +3,7 @@ Open source replacement of the Arm11 PXI system module.
This is licensed under the MIT license. This is licensed under the MIT license.
# Usage # 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 # Credits
This list is not complete at all: This list is not complete at all:

View File

@@ -40,7 +40,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH) ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit,--section-start,.text=0x14000000 LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit,--section-start,.text=0x14000000
LIBS := -lctru LIBS := -lm -lctru
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing # list of directories containing libraries, this must be the top level containing

View File

@@ -91,7 +91,8 @@ u32 Draw_DrawFormattedString(u32 posX, u32 posY, u32 color, const char *fmt, ...
void Draw_FillFramebuffer(u32 value); void Draw_FillFramebuffer(u32 value);
void Draw_ClearFramebuffer(void); void Draw_ClearFramebuffer(void);
u32 Draw_AllocateFramebufferCache(void); Result Draw_AllocateFramebufferCache(u32 size);
Result Draw_AllocateFramebufferCacheForScreenshot(u32 size);
void Draw_FreeFramebufferCache(void); void Draw_FreeFramebufferCache(void);
void *Draw_GetFramebufferCache(void); void *Draw_GetFramebufferCache(void);
u32 Draw_GetFramebufferCacheSize(void); u32 Draw_GetFramebufferCacheSize(void);
@@ -99,6 +100,8 @@ u32 Draw_SetupFramebuffer(void);
void Draw_RestoreFramebuffer(void); void Draw_RestoreFramebuffer(void);
void Draw_FlushFramebuffer(void); void Draw_FlushFramebuffer(void);
u32 Draw_GetCurrentFramebufferAddress(bool top, bool left); u32 Draw_GetCurrentFramebufferAddress(bool top, bool left);
// Width is actually height as the 3ds screen is rotated 90 degrees
void Draw_GetCurrentScreenInfo(u32 *width, bool *is3d, bool top);
void Draw_CreateBitmapHeader(u8 *dst, u32 width, u32 heigth); void Draw_CreateBitmapHeader(u8 *dst, u32 width, u32 heigth);
void Draw_ConvertFrameBufferLines(u8 *buf, u32 startingLine, u32 numLines, bool top, bool left); void Draw_ConvertFrameBufferLines(u8 *buf, u32 width, u32 startingLine, u32 numLines, bool top, bool left);

View File

@@ -31,7 +31,6 @@
#include "MyThread.h" #include "MyThread.h"
#define HBLDR_DEFAULT_3DSX_TID 0x000400000D921E00ULL #define HBLDR_DEFAULT_3DSX_TID 0x000400000D921E00ULL
#define HBLDR_3DSX_TID (*(vu64 *)0x1FF81100)
void HBLDR_RestartHbApplication(void *p); void HBLDR_RestartHbApplication(void *p);
void HBLDR_HandleCommands(void *ctx); void HBLDR_HandleCommands(void *ctx);

View File

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

View File

@@ -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 <http://www.gnu.org/licenses/>.
*
* 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);

View File

@@ -32,10 +32,16 @@ extern Menu screenFiltersMenu;
extern int screenFiltersCurrentTemperature; extern int screenFiltersCurrentTemperature;
void screenFiltersSetDisabled(void); void ScreenFiltersMenu_RestoreCct(void);
void screenFiltersReduceBlueLevel1(void);
void screenFiltersReduceBlueLevel2(void); void ScreenFiltersMenu_SetDefault(void); // 6500K (default)
void screenFiltersReduceBlueLevel3(void);
void screenFiltersReduceBlueLevel4(void); void ScreenFiltersMenu_SetAquarium(void); // 10000K
void screenFiltersReduceBlueLevel5(void); void ScreenFiltersMenu_SetOvercastSky(void); // 7500K
void screenFiltersSetTemperature(int temperature); void ScreenFiltersMenu_SetDaylight(void); // 5500K
void ScreenFiltersMenu_SetFluorescent(void); // 4200K
void ScreenFiltersMenu_SetHalogen(void); // 3400K
void ScreenFiltersMenu_SetIncandescent(void); // 2700K
void ScreenFiltersMenu_SetWarmIncandescent(void); // 2300K
void ScreenFiltersMenu_SetCandle(void); // 1900K
void ScreenFiltersMenu_SetEmber(void); // 1200K

View File

@@ -21,6 +21,10 @@
extern bool miniSocEnabled; extern bool miniSocEnabled;
Result miniSocInit(void); Result miniSocInit(void);
void miniSocLockState(void);
void miniSocUnlockState(bool force);
Result miniSocExitDirect(void); Result miniSocExitDirect(void);
Result miniSocExit(void); Result miniSocExit(void);

View File

@@ -31,6 +31,7 @@
#include <3ds/result.h> #include <3ds/result.h>
#include <3ds/ipc.h> #include <3ds/ipc.h>
#include "csvc.h" #include "csvc.h"
#include "luma_shared_config.h"
// For accessing physmem uncached (and directly) // For accessing physmem uncached (and directly)
#define PA_PTR(addr) (void *)((u32)(addr) | 1 << 31) #define PA_PTR(addr) (void *)((u32)(addr) | 1 << 31)

View File

@@ -129,18 +129,19 @@ void Draw_ClearFramebuffer(void)
Draw_FillFramebuffer(0); Draw_FillFramebuffer(0);
} }
u32 Draw_AllocateFramebufferCache(void) Result Draw_AllocateFramebufferCache(u32 size)
{ {
// Try to see how much we can allocate...
// Can't use fbs in FCRAM when Home Menu is active (AXI config related maybe?) // Can't use fbs in FCRAM when Home Menu is active (AXI config related maybe?)
u32 addr = 0x0D000000; u32 addr = 0x0D000000;
u32 tmp; u32 tmp;
u32 minSize = (FB_BOTTOM_SIZE + 0xFFF) & ~0xFFF;
u32 maxSize = (FB_SCREENSHOT_SIZE + 0xFFF) & ~0xFFF;
u32 remaining = (u32)osGetMemRegionFree(MEMREGION_SYSTEM);
u32 size = remaining < maxSize ? remaining : maxSize;
if (size < minSize || R_FAILED(svcControlMemoryEx(&tmp, addr, 0, size, MEMOP_ALLOC, MEMREGION_SYSTEM | MEMPERM_READ | MEMPERM_WRITE, true))) size = (size + 0xFFF) >> 12 << 12; // round-up
if (framebufferCache != NULL)
__builtin_trap();
Result res = svcControlMemoryEx(&tmp, addr, 0, size, MEMOP_ALLOC, MEMREGION_SYSTEM | MEMPERM_READWRITE, true);
if (R_FAILED(res))
{ {
framebufferCache = NULL; framebufferCache = NULL;
framebufferCacheSize = 0; framebufferCacheSize = 0;
@@ -151,13 +152,21 @@ u32 Draw_AllocateFramebufferCache(void)
framebufferCacheSize = size; framebufferCacheSize = size;
} }
return framebufferCacheSize; return res;
}
Result Draw_AllocateFramebufferCacheForScreenshot(u32 size)
{
u32 remaining = (u32)osGetMemRegionFree(MEMREGION_SYSTEM);
u32 sz = remaining < size ? remaining : size;
return Draw_AllocateFramebufferCache(sz);
} }
void Draw_FreeFramebufferCache(void) void Draw_FreeFramebufferCache(void)
{ {
u32 tmp; u32 tmp;
svcControlMemory(&tmp, (u32)framebufferCache, 0, framebufferCacheSize, MEMOP_FREE, 0); if (framebufferCache != NULL)
svcControlMemory(&tmp, (u32)framebufferCache, 0, framebufferCacheSize, MEMOP_FREE, 0);
framebufferCacheSize = 0; framebufferCacheSize = 0;
framebufferCache = NULL; framebufferCache = NULL;
} }
@@ -180,13 +189,19 @@ u32 Draw_SetupFramebuffer(void)
memcpy(framebufferCache, FB_BOTTOM_VRAM_ADDR, FB_BOTTOM_SIZE); memcpy(framebufferCache, FB_BOTTOM_VRAM_ADDR, FB_BOTTOM_SIZE);
Draw_ClearFramebuffer(); Draw_ClearFramebuffer();
Draw_FlushFramebuffer(); Draw_FlushFramebuffer();
u32 format = GPU_FB_BOTTOM_FMT;
gpuSavedFramebufferAddr1 = GPU_FB_BOTTOM_ADDR_1; gpuSavedFramebufferAddr1 = GPU_FB_BOTTOM_ADDR_1;
gpuSavedFramebufferAddr2 = GPU_FB_BOTTOM_ADDR_2; gpuSavedFramebufferAddr2 = GPU_FB_BOTTOM_ADDR_2;
gpuSavedFramebufferFormat = GPU_FB_BOTTOM_FMT; gpuSavedFramebufferFormat = format;
gpuSavedFramebufferStride = GPU_FB_BOTTOM_STRIDE; gpuSavedFramebufferStride = GPU_FB_BOTTOM_STRIDE;
format = (format & ~7) | GSP_RGB565_OES;
format |= 3 << 8; // set VRAM bits
GPU_FB_BOTTOM_ADDR_1 = GPU_FB_BOTTOM_ADDR_2 = FB_BOTTOM_VRAM_PA; GPU_FB_BOTTOM_ADDR_1 = GPU_FB_BOTTOM_ADDR_2 = FB_BOTTOM_VRAM_PA;
GPU_FB_BOTTOM_FMT = (GPU_FB_BOTTOM_FMT & ~7) | GSP_RGB565_OES; GPU_FB_BOTTOM_FMT = format;
GPU_FB_BOTTOM_STRIDE = 240 * 2; GPU_FB_BOTTOM_STRIDE = 240 * 2;
return framebufferCacheSize; return framebufferCacheSize;
@@ -205,7 +220,7 @@ void Draw_RestoreFramebuffer(void)
void Draw_FlushFramebuffer(void) void Draw_FlushFramebuffer(void)
{ {
svcFlushProcessDataCache(CUR_PROCESS_HANDLE, FB_BOTTOM_VRAM_ADDR, FB_BOTTOM_SIZE); svcFlushProcessDataCache(CUR_PROCESS_HANDLE, (u32)FB_BOTTOM_VRAM_ADDR, FB_BOTTOM_SIZE);
} }
u32 Draw_GetCurrentFramebufferAddress(bool top, bool left) u32 Draw_GetCurrentFramebufferAddress(bool top, bool left)
@@ -226,6 +241,21 @@ u32 Draw_GetCurrentFramebufferAddress(bool top, bool left)
} }
} }
void Draw_GetCurrentScreenInfo(u32 *width, bool *is3d, bool top)
{
if (top)
{
bool isNormal2d = (GPU_FB_TOP_FMT & BIT(6)) != 0;
*is3d = (GPU_FB_TOP_FMT & BIT(5)) != 0;
*width = !(*is3d) && !isNormal2d ? 800 : 400;
}
else
{
*is3d = false;
*width = 320;
}
}
static inline void Draw_WriteUnaligned(u8 *dst, u32 tmp, u32 size) static inline void Draw_WriteUnaligned(u8 *dst, u32 tmp, u32 size)
{ {
memcpy(dst, &tmp, size); memcpy(dst, &tmp, size);
@@ -247,7 +277,7 @@ void Draw_CreateBitmapHeader(u8 *dst, u32 width, u32 heigth)
Draw_WriteUnaligned(dst + 0x22, 3 * width * heigth, 4); Draw_WriteUnaligned(dst + 0x22, 3 * width * heigth, 4);
} }
static inline void Draw_ConvertPixelToBGR8(u8 *dst, const u8 *src, GSPGPU_FramebufferFormats srcFormat) static inline void Draw_ConvertPixelToBGR8(u8 *dst, const u8 *src, GSPGPU_FramebufferFormat srcFormat)
{ {
u8 red, green, blue; u8 red, green, blue;
switch(srcFormat) switch(srcFormat)
@@ -313,6 +343,7 @@ static inline void Draw_ConvertPixelToBGR8(u8 *dst, const u8 *src, GSPGPU_Frameb
typedef struct FrameBufferConvertArgs { typedef struct FrameBufferConvertArgs {
u8 *buf; u8 *buf;
u32 width;
u8 startingLine; u8 startingLine;
u8 numLines; u8 numLines;
bool top; bool top;
@@ -323,8 +354,8 @@ static void Draw_ConvertFrameBufferLinesKernel(const FrameBufferConvertArgs *arg
{ {
static const u8 formatSizes[] = { 4, 3, 2, 2, 2 }; static const u8 formatSizes[] = { 4, 3, 2, 2, 2 };
GSPGPU_FramebufferFormats fmt = args->top ? (GSPGPU_FramebufferFormats)(GPU_FB_TOP_FMT & 7) : (GSPGPU_FramebufferFormats)(GPU_FB_BOTTOM_FMT & 7); GSPGPU_FramebufferFormat fmt = args->top ? (GSPGPU_FramebufferFormat)(GPU_FB_TOP_FMT & 7) : (GSPGPU_FramebufferFormat)(GPU_FB_BOTTOM_FMT & 7);
u32 width = args->top ? 400 : 320; u32 width = args->width;
u32 stride = args->top ? GPU_FB_TOP_STRIDE : GPU_FB_BOTTOM_STRIDE; u32 stride = args->top ? GPU_FB_TOP_STRIDE : GPU_FB_BOTTOM_STRIDE;
u32 pa = Draw_GetCurrentFramebufferAddress(args->top, args->left); u32 pa = Draw_GetCurrentFramebufferAddress(args->top, args->left);
@@ -340,8 +371,8 @@ static void Draw_ConvertFrameBufferLinesKernel(const FrameBufferConvertArgs *arg
} }
} }
void Draw_ConvertFrameBufferLines(u8 *buf, u32 startingLine, u32 numLines, bool top, bool left) void Draw_ConvertFrameBufferLines(u8 *buf, u32 width, u32 startingLine, u32 numLines, bool top, bool left)
{ {
FrameBufferConvertArgs args = { buf, (u8)startingLine, (u8)numLines, top, left }; FrameBufferConvertArgs args = { buf, width, (u8)startingLine, (u8)numLines, top, left };
svcCustomBackdoor(Draw_ConvertFrameBufferLinesKernel, &args); svcCustomBackdoor(Draw_ConvertFrameBufferLinesKernel, &args);
} }

View File

@@ -36,9 +36,6 @@
#include "gdb/server.h" #include "gdb/server.h"
#include "pmdbgext.h" #include "pmdbgext.h"
#define SYSCOREVER (*(vu32 *)0x1FF80010)
#define APPMEMTYPE (*(vu32 *)0x1FF80030)
extern GDBContext *nextApplicationGdbCtx; extern GDBContext *nextApplicationGdbCtx;
extern GDBServer gdbServer; extern GDBServer gdbServer;
@@ -148,7 +145,7 @@ static const u32 kernelCaps[] =
0xFF81FF78, // RW static mapping: 0x1FF78000 0xFF81FF78, // RW static mapping: 0x1FF78000
0xFF91F000, // RO static mapping: 0x1F000000 0xFF91F000, // RO static mapping: 0x1F000000
0xFF91F600, // RO static mapping: 0x1F600000 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 0xFE000200, // Handle table size: 0x200
}; };
@@ -310,21 +307,22 @@ void HBLDR_HandleCommands(void *ctx)
memcpy(&exhi->sci.codeset_info.stack_size, &stacksize, 4); memcpy(&exhi->sci.codeset_info.stack_size, &stacksize, 4);
memset(&exhi->sci.dependencies, 0, sizeof(exhi->sci.dependencies)); 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)); memcpy(exhi->sci.dependencies, dependencyListNativeFirm, sizeof(dependencyListNativeFirm));
else if (SYSCOREVER == 3) else if (coreVer == 3)
memcpy(exhi->sci.dependencies, dependencyListSafeFirm, sizeof(dependencyListSafeFirm)); memcpy(exhi->sci.dependencies, dependencyListSafeFirm, sizeof(dependencyListSafeFirm));
ExHeader_Arm11SystemLocalCapabilities* localcaps0 = &exhi->aci.local_caps; 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.use_cpu_clockrate_804MHz = false;
localcaps0->core_info.enable_l2c = false; localcaps0->core_info.enable_l2c = false;
localcaps0->core_info.ideal_processor = 0; localcaps0->core_info.ideal_processor = 0;
localcaps0->core_info.affinity_mask = BIT(0); localcaps0->core_info.affinity_mask = BIT(0);
localcaps0->core_info.priority = 0x30; 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.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; 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. // See the big comment in sysmodules/pm/source/reslimit.c for technical details.
localcaps0->reslimits[0] = BIT(7) | 89; 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.no_romfs = true;
localcaps0->storage_info.use_extended_savedata_access = true; // Whatever 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 // Set kernel release version to the current kernel version
kcaps0->descriptors[0] = 0xFC000000 | (osGetKernelVersion() >> 16); 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; u64 lastdep = sizeof(dependencyListNativeFirm)/8;
exhi->sci.dependencies[lastdep++] = 0x0004013000004002ULL; // nfc exhi->sci.dependencies[lastdep++] = 0x0004013000004002ULL; // nfc

View File

@@ -177,6 +177,248 @@ void inputRedirectionThreadMain(void)
void hidCodePatchFunc(void); void hidCodePatchFunc(void);
void irCodePatchFunc(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(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (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(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (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) Result InputRedirection_Disable(s64 timeout)
{ {
if(!inputRedirectionEnabled) if(!inputRedirectionEnabled)
@@ -195,209 +437,46 @@ Result InputRedirection_Disable(s64 timeout)
Result InputRedirection_DoOrUndoPatches(void) Result InputRedirection_DoOrUndoPatches(void)
{ {
s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
u32 totalSize;
Handle processHandle;
Result res = OpenProcessByName("hid", &processHandle);
static bool hidPatched = false; static bool hidPatched = false;
static bool irPatched = 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)) if(R_SUCCEEDED(res))
{ {
svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data res = InputRedirection_DoUndoHidPatches(hidProcHandle, !hidPatched);
svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003); if (R_SUCCEEDED(res))
svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004); hidPatched = !hidPatched;
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);
} }
svcCloseHandle(processHandle);
res = OpenProcessByName("ir", &processHandle);
if(R_SUCCEEDED(res) && GET_VERSION_MINOR(osGetKernelVersion()) >= 44) if(R_SUCCEEDED(res) && GET_VERSION_MINOR(osGetKernelVersion()) >= 44)
{ {
svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data res = InputRedirection_DoUndoIrPatches(irProcHandle, !irPatched);
svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003); if (R_SUCCEEDED(res))
svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004); irPatched = !irPatched;
else if (!irPatched)
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
svcGetProcessInfo(&startAddress, processHandle, 0x10005);
res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (u32) startAddress, totalSize);
if(R_SUCCEEDED(res))
{ {
static bool useOldSyncCode; InputRedirection_DoUndoHidPatches(hidProcHandle, false);
static u32 irOrigReadingCode[5] = { hidPatched = false;
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;
}
} }
res = svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
} }
svcCloseHandle(processHandle);
cleanup:
svcKernelSetState(0x10000, 4);
svcCloseHandle(hidProcHandle);
svcCloseHandle(irProcHandle);
return res; return res;
} }

View File

@@ -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 <http://www.gnu.org/licenses/>.
*
* 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 <math.h>
#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);
}

View File

@@ -83,13 +83,15 @@ void initSystem(void)
isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0; isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0;
svcGetSystemInfo(&out, 0x10000, 0x100); 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); svcGetSystemInfo(&out, 0x10000, 0x101);
menuCombo = out == 0 ? DEFAULT_MENU_COMBO : (u32)out; 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." : miscellaneousMenu.items[0].title = Luma_SharedConfig->hbldr_3dsx_tid == HBLDR_DEFAULT_3DSX_TID ?
"Switch the hb. title to hblauncher_loader"; "Switch the hb. title to the current app." :
"Switch the hb. title to hblauncher_loader";
for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL)) for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL))
{ {
@@ -104,6 +106,9 @@ void initSystem(void)
if (R_FAILED(fsInit())) if (R_FAILED(fsInit()))
svcBreak(USERBREAK_PANIC); svcBreak(USERBREAK_PANIC);
if (R_FAILED(FSUSER_SetPriority(-16)))
svcBreak(USERBREAK_PANIC);
// **** DO NOT init services that don't come from KIPs here **** // **** DO NOT init services that don't come from KIPs here ****
// Instead, init the service only where it's actually init (then deinit it). // Instead, init the service only where it's actually init (then deinit it).
@@ -131,11 +136,53 @@ static void handleTermNotification(u32 notificationId)
(void)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) static void handlePreTermNotification(u32 notificationId)
{ {
(void)notificationId; (void)notificationId;
// Might be subject to a race condition, but heh. // Might be subject to a race condition, but heh.
miniSocUnlockState(true);
// Disable input redirection // Disable input redirection
InputRedirection_Disable(100 * 1000 * 1000LL); InputRedirection_Disable(100 * 1000 * 1000LL);
@@ -180,11 +227,19 @@ static const ServiceManagerServiceEntry services[] = {
}; };
static const ServiceManagerNotificationEntry notifications[] = { static const ServiceManagerNotificationEntry notifications[] = {
{ 0x100 , handleTermNotification }, { 0x100 , handleTermNotification },
//{ 0x103 , handlePreTermNotification }, // Sleep mode entry <=== causes issues { PTMNOTIFID_SLEEP_REQUESTED, handleSleepNotification },
{ 0x1000, handleNextApplicationDebuggedByForce }, { PTMNOTIFID_SLEEP_DENIED, handleSleepNotification },
{ 0x2000, handlePreTermNotification }, { PTMNOTIFID_SLEEP_ALLOWED, handleSleepNotification },
{ 0x3000, handleRestartHbAppNotification }, { 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 }, { 0x000, NULL },
}; };

View File

@@ -193,6 +193,7 @@ void menuThreadMain(void)
while(!preTerminationRequested) while(!preTerminationRequested)
{ {
svcSleepThread(50 * 1000 * 1000LL);
if (menuShouldExit) if (menuShouldExit)
continue; continue;
@@ -226,17 +227,17 @@ void menuEnter(void)
if(!menuShouldExit && menuRefCount == 0) if(!menuShouldExit && menuRefCount == 0)
{ {
menuRefCount++; menuRefCount++;
svcKernelSetState(0x10000, 1); svcKernelSetState(0x10000, 2 | 1);
svcSleepThread(5 * 1000 * 100LL); svcSleepThread(5 * 1000 * 100LL);
if (Draw_AllocateFramebufferCache() == 0) if (R_FAILED(Draw_AllocateFramebufferCache(FB_BOTTOM_SIZE)))
{ {
// Oops // Oops
menuRefCount = 0; menuRefCount = 0;
svcKernelSetState(0x10000, 1); svcKernelSetState(0x10000, 2 | 1);
svcSleepThread(5 * 1000 * 100LL); svcSleepThread(5 * 1000 * 100LL);
} }
else
Draw_SetupFramebuffer(); Draw_SetupFramebuffer();
} }
Draw_Unlock(); Draw_Unlock();
} }
@@ -250,7 +251,7 @@ void menuLeave(void)
{ {
Draw_RestoreFramebuffer(); Draw_RestoreFramebuffer();
Draw_FreeFramebufferCache(); Draw_FreeFramebufferCache();
svcKernelSetState(0x10000, 1); svcKernelSetState(0x10000, 2 | 1);
} }
Draw_Unlock(); Draw_Unlock();
} }

View File

@@ -40,6 +40,7 @@
#include "memory.h" #include "memory.h"
#include "fmt.h" #include "fmt.h"
#include "process_patches.h" #include "process_patches.h"
#include "luminance.h"
Menu rosalinaMenu = { Menu rosalinaMenu = {
"Rosalina menu", "Rosalina menu",
@@ -64,7 +65,11 @@ Menu rosalinaMenu = {
bool rosalinaMenuShouldShowDebugInfo(void) bool rosalinaMenuShouldShowDebugInfo(void)
{ {
return true; // Don't show on release builds
s64 out;
svcGetSystemInfo(&out, 0x10000, 0x200);
return out == 0;
} }
void RosalinaMenu_ShowDebugInfo(void) void RosalinaMenu_ShowDebugInfo(void)
@@ -119,8 +124,8 @@ void RosalinaMenu_ShowCredits(void)
Draw_DrawString(10, posY, COLOR_WHITE, Draw_DrawString(10, posY, COLOR_WHITE,
( (
"Special thanks to:\n" "Special thanks to:\n"
" Bond697, WinterMute, piepie62, yifanlu\n" " fincs, WinterMute, mtheall, piepie62,\n"
" Luma3DS contributors, ctrulib contributors,\n" " Luma3DS contributors, libctru contributors,\n"
" other people" " other people"
)); ));
@@ -140,7 +145,7 @@ void RosalinaMenu_Reboot(void)
do do
{ {
Draw_Lock(); 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_DrawString(10, 30, COLOR_WHITE, "Press A to reboot, press B to go back.");
Draw_FlushFramebuffer(); Draw_FlushFramebuffer();
Draw_Unlock(); Draw_Unlock();
@@ -158,107 +163,103 @@ void RosalinaMenu_Reboot(void)
while(!menuShouldExit); 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) void RosalinaMenu_ChangeScreenBrightness(void)
{ {
Result patchResult = 0;
if (isN3DS && !gspPatchDoneN3ds)
{
patchResult = PatchProcessByName("gsp", RosalinaMenu_PatchN3dsGspForBrightness);
gspPatchDoneN3ds = R_SUCCEEDED(patchResult);
}
Draw_Lock(); Draw_Lock();
Draw_ClearFramebuffer(); Draw_ClearFramebuffer();
Draw_FlushFramebuffer(); Draw_FlushFramebuffer();
Draw_Unlock(); 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 do
{ {
// Assume the current brightness for both screens are the same.
s32 brightness = (s32)(LCD_TOP_BRIGHTNESS & 0xFF);
Draw_Lock(); Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina menu"); Draw_DrawString(10, 10, COLOR_TITLE, "Screen brightness");
u32 posY = 30; u32 posY = 30;
posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Current brightness (0..255): %3lu\n\n", brightness); posY = Draw_DrawFormattedString(
if (R_SUCCEEDED(patchResult)) 10,
{ posY,
posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press Up/Down for +-1, Right/Left for +-10.\n"); COLOR_WHITE,
posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press Y to revert the GSP patch and exit.\n\n"); "Current luminance: %lu (min. %lu, max. %lu)\n\n",
luminance,
posY = Draw_DrawString(10, posY, COLOR_RED, "WARNING: \n"); minLum,
posY = Draw_DrawString(10, posY, COLOR_WHITE, " * avoid using values far higher than the presets.\n"); maxLum
posY = Draw_DrawString(10, posY, COLOR_WHITE, " * normal brightness mngmt. is now broken on N3DS.\nYou'll need to press Y to revert"); );
} posY = Draw_DrawString(10, posY, COLOR_WHITE, "Controls: Up/Down for +-1, Right/Left for +-10.\n");
else posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press A to start, B to exit.\n\n");
Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Failed to patch GSP (0x%08lx).", (u32)patchResult);
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_FlushFramebuffer();
Draw_Unlock(); Draw_Unlock();
u32 pressed = waitInputWithTimeout(1000); u32 pressed = waitInputWithTimeout(1000);
if ((pressed & DIRECTIONAL_KEYS) && R_SUCCEEDED(patchResult)) if (pressed & KEY_A)
{ break;
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;
brightness = brightness < 0 ? 0 : brightness; if (pressed & KEY_B)
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)
return; return;
} }
while (!menuShouldExit); 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 < (s32)minLum ? (s32)minLum : lum;
lum = lum > (s32)maxLum ? (s32)maxLum : 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. void RosalinaMenu_PowerOff(void) // Soft shutdown.
@@ -271,7 +272,7 @@ void RosalinaMenu_PowerOff(void) // Soft shutdown.
do do
{ {
Draw_Lock(); 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_DrawString(10, 30, COLOR_WHITE, "Press A to power off, press B to go back.");
Draw_FlushFramebuffer(); Draw_FlushFramebuffer();
Draw_Unlock(); Draw_Unlock();
@@ -296,18 +297,20 @@ void RosalinaMenu_PowerOff(void) // Soft shutdown.
static s64 timeSpentConvertingScreenshot = 0; static s64 timeSpentConvertingScreenshot = 0;
static s64 timeSpentWritingScreenshot = 0; static s64 timeSpentWritingScreenshot = 0;
static Result RosalinaMenu_WriteScreenshot(IFile *file, bool top, bool left) static Result RosalinaMenu_WriteScreenshot(IFile *file, u32 width, bool top, bool left)
{ {
u64 total; u64 total;
Result res = 0; Result res = 0;
u32 dimX = top ? 400 : 320; u32 lineSize = 3 * width;
u32 lineSize = 3 * dimX;
u32 remaining = lineSize * 240; u32 remaining = lineSize * 240;
TRY(Draw_AllocateFramebufferCacheForScreenshot(remaining));
u8 *framebufferCache = (u8 *)Draw_GetFramebufferCache(); u8 *framebufferCache = (u8 *)Draw_GetFramebufferCache();
u8 *framebufferCacheEnd = framebufferCache + Draw_GetFramebufferCacheSize(); u8 *framebufferCacheEnd = framebufferCache + Draw_GetFramebufferCacheSize();
u8 *buf = framebufferCache; u8 *buf = framebufferCache;
Draw_CreateBitmapHeader(framebufferCache, dimX, 240); Draw_CreateBitmapHeader(framebufferCache, width, 240);
buf += 54; buf += 54;
u32 y = 0; u32 y = 0;
@@ -318,7 +321,7 @@ static Result RosalinaMenu_WriteScreenshot(IFile *file, bool top, bool left)
u32 available = (u32)(framebufferCacheEnd - buf); u32 available = (u32)(framebufferCacheEnd - buf);
u32 size = available < remaining ? available : remaining; u32 size = available < remaining ? available : remaining;
u32 nlines = size / lineSize; u32 nlines = size / lineSize;
Draw_ConvertFrameBufferLines(buf, y, nlines, top, left); Draw_ConvertFrameBufferLines(buf, width, y, nlines, top, left);
s64 t1 = svcGetSystemTick(); s64 t1 = svcGetSystemTick();
timeSpentConvertingScreenshot += t1 - t0; timeSpentConvertingScreenshot += t1 - t0;
@@ -329,7 +332,10 @@ static Result RosalinaMenu_WriteScreenshot(IFile *file, bool top, bool left)
remaining -= lineSize * nlines; remaining -= lineSize * nlines;
buf = framebufferCache; buf = framebufferCache;
} }
end: return res; end:
Draw_FreeFramebufferCache();
return res;
} }
void RosalinaMenu_TakeScreenshot(void) void RosalinaMenu_TakeScreenshot(void)
@@ -353,9 +359,16 @@ void RosalinaMenu_TakeScreenshot(void)
archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW; archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW;
Draw_Lock(); Draw_Lock();
Draw_RestoreFramebuffer(); Draw_RestoreFramebuffer();
Draw_FreeFramebufferCache();
svcFlushEntireDataCache(); svcFlushEntireDataCache();
bool is3d;
u32 topWidth, bottomWidth; // actually Y-dim
Draw_GetCurrentScreenInfo(&bottomWidth, &is3d, false);
Draw_GetCurrentScreenInfo(&topWidth, &is3d, true);
res = FSUSER_OpenArchive(&archive, archiveId, fsMakePath(PATH_EMPTY, "")); res = FSUSER_OpenArchive(&archive, archiveId, fsMakePath(PATH_EMPTY, ""));
if(R_SUCCEEDED(res)) if(R_SUCCEEDED(res))
{ {
@@ -410,24 +423,28 @@ void RosalinaMenu_TakeScreenshot(void)
sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_top.bmp", year, month, days, hours, minutes, seconds, milliseconds); sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_top.bmp", year, month, days, hours, minutes, seconds, milliseconds);
TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE)); TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE));
TRY(RosalinaMenu_WriteScreenshot(&file, true, true)); TRY(RosalinaMenu_WriteScreenshot(&file, topWidth, true, true));
TRY(IFile_Close(&file)); TRY(IFile_Close(&file));
sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_bot.bmp", year, month, days, hours, minutes, seconds, milliseconds); sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_bot.bmp", year, month, days, hours, minutes, seconds, milliseconds);
TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE)); TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE));
TRY(RosalinaMenu_WriteScreenshot(&file, false, true)); TRY(RosalinaMenu_WriteScreenshot(&file, bottomWidth, false, true));
TRY(IFile_Close(&file)); TRY(IFile_Close(&file));
if((GPU_FB_TOP_FMT & 0x20) && (Draw_GetCurrentFramebufferAddress(true, true) != Draw_GetCurrentFramebufferAddress(true, false))) if(is3d && (Draw_GetCurrentFramebufferAddress(true, true) != Draw_GetCurrentFramebufferAddress(true, false)))
{ {
sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_top_right.bmp", year, month, days, hours, minutes, seconds, milliseconds); sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_top_right.bmp", year, month, days, hours, minutes, seconds, milliseconds);
TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE)); TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE));
TRY(RosalinaMenu_WriteScreenshot(&file, true, false)); TRY(RosalinaMenu_WriteScreenshot(&file, topWidth, true, false));
TRY(IFile_Close(&file)); TRY(IFile_Close(&file));
} }
end: end:
IFile_Close(&file); IFile_Close(&file);
if (R_FAILED(Draw_AllocateFramebufferCache(FB_BOTTOM_SIZE)))
__builtin_trap(); // We're f***ed if this happens
svcFlushEntireDataCache(); svcFlushEntireDataCache();
Draw_SetupFramebuffer(); Draw_SetupFramebuffer();
Draw_Unlock(); Draw_Unlock();

View File

@@ -102,7 +102,6 @@ Result debuggerDisable(s64 timeout)
svcCloseHandle(dummy); svcCloseHandle(dummy);
PMDBG_DebugNextApplicationByForce(false); PMDBG_DebugNextApplicationByForce(false);
nextApplicationGdbCtx = NULL; nextApplicationGdbCtx = NULL;
svcKernelSetState(0x10000, 2);
} }
return res; return res;

View File

@@ -55,7 +55,7 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void)
Result res; Result res;
char failureReason[64]; char failureReason[64];
if(HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID) if(Luma_SharedConfig->hbldr_3dsx_tid == HBLDR_DEFAULT_3DSX_TID)
{ {
FS_ProgramInfo progInfo; FS_ProgramInfo progInfo;
u32 pid; u32 pid;
@@ -63,7 +63,7 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void)
res = PMDBG_GetCurrentAppInfo(&progInfo, &pid, &launchFlags); res = PMDBG_GetCurrentAppInfo(&progInfo, &pid, &launchFlags);
if(R_SUCCEEDED(res)) 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"; miscellaneousMenu.items[0].title = "Switch the hb. title to hblauncher_loader";
} }
else else
@@ -75,7 +75,7 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void)
else else
{ {
res = 0; 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."; miscellaneousMenu.items[0].title = "Switch the hb. title to the current app.";
} }
@@ -205,7 +205,7 @@ Result SaveSettings(void)
configData.config = config; configData.config = config;
configData.multiConfig = multiConfig; configData.multiConfig = multiConfig;
configData.bootConfig = bootConfig; configData.bootConfig = bootConfig;
configData.hbldr3dsxTitleId = HBLDR_3DSX_TID; configData.hbldr3dsxTitleId = Luma_SharedConfig->hbldr_3dsx_tid;
configData.rosalinaMenuCombo = menuCombo; configData.rosalinaMenuCombo = menuCombo;
configData.rosalinaFlags = PluginLoader__IsEnabled(); configData.rosalinaFlags = PluginLoader__IsEnabled();
@@ -331,7 +331,21 @@ void MiscellaneousMenu_InputRedirection(void)
else else
{ {
if(res == 0) 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 else
Draw_DrawString(10, 30, COLOR_WHITE, buf); Draw_DrawString(10, 30, COLOR_WHITE, buf);
} }

View File

@@ -32,33 +32,34 @@
#include "redshift/redshift.h" #include "redshift/redshift.h"
#include "redshift/colorramp.h" #include "redshift/colorramp.h"
#define TEMP_DEFAULT NEUTRAL_TEMP typedef union {
struct {
int screenFiltersCurrentTemperature = TEMP_DEFAULT; u8 r;
u8 g;
void writeLut(u32* lut) u8 b;
{ u8 z;
GPU_FB_TOP_COL_LUT_INDEX = 0; };
GPU_FB_BOTTOM_COL_LUT_INDEX = 0; u32 raw;
for (int i = 0; i <= 255; i++) {
GPU_FB_TOP_COL_LUT_ELEM = *lut;
GPU_FB_BOTTOM_COL_LUT_ELEM = *lut;
lut++;
}
}
typedef struct {
u8 r;
u8 g;
u8 b;
u8 z;
} Pixel; } Pixel;
static u16 g_c[0x600]; static u16 g_c[0x600];
static Pixel g_px[0x400]; static Pixel g_px[0x400];
void applyColorSettings(color_setting_t* cs) int screenFiltersCurrentTemperature = -1;
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->raw;
GPU_FB_BOTTOM_COL_LUT_ELEM = lut->raw;
lut++;
}
}
static void ScreenFiltersMenu_ApplyColorSettings(color_setting_t* cs)
{ {
u8 i = 0; u8 i = 0;
@@ -86,68 +87,69 @@ void applyColorSettings(color_setting_t* cs)
g_px[i].b = *(g_c + i + 0x200) >> 8; g_px[i].b = *(g_c + i + 0x200) >> 8;
} while(++i); } while(++i);
writeLut((u32*)g_px); ScreenFiltersMenu_WriteLut(g_px);
} }
Menu screenFiltersMenu = { static void ScreenFiltersMenu_SetCct(int cct)
"Screen filters menu",
{
{ "Disable", METHOD, .method = &screenFiltersSetDisabled },
{ "Reduce blue light (level 1)", METHOD, .method = &screenFiltersReduceBlueLevel1 },
{ "Reduce blue light (level 2)", METHOD, .method = &screenFiltersReduceBlueLevel2 },
{ "Reduce blue light (level 3)", METHOD, .method = &screenFiltersReduceBlueLevel3 },
{ "Reduce blue light (level 4)", METHOD, .method = &screenFiltersReduceBlueLevel4 },
{ "Reduce blue light (level 5)", METHOD, .method = &screenFiltersReduceBlueLevel5 },
{},
}
};
void screenFiltersSetDisabled(void)
{
screenFiltersCurrentTemperature = TEMP_DEFAULT;
screenFiltersSetTemperature(screenFiltersCurrentTemperature);
}
void screenFiltersReduceBlueLevel1(void)
{
screenFiltersCurrentTemperature = 4300;
screenFiltersSetTemperature(screenFiltersCurrentTemperature);
}
void screenFiltersReduceBlueLevel2(void)
{
screenFiltersCurrentTemperature = 3200;
screenFiltersSetTemperature(screenFiltersCurrentTemperature);
}
void screenFiltersReduceBlueLevel3(void)
{
screenFiltersCurrentTemperature = 2100;
screenFiltersSetTemperature(screenFiltersCurrentTemperature);
}
void screenFiltersReduceBlueLevel4(void)
{
screenFiltersCurrentTemperature = 1550;
screenFiltersSetTemperature(screenFiltersCurrentTemperature);
}
void screenFiltersReduceBlueLevel5(void)
{
screenFiltersCurrentTemperature = 1000;
screenFiltersSetTemperature(screenFiltersCurrentTemperature);
}
void screenFiltersSetTemperature(int temperature)
{ {
color_setting_t cs; color_setting_t cs;
memset(&cs, 0, sizeof(cs)); memset(&cs, 0, sizeof(cs));
cs.temperature = temperature; cs.temperature = cct;
/*cs.gamma[0] = 1.0F; /*cs.gamma[0] = 1.0F;
cs.gamma[1] = 1.0F; cs.gamma[1] = 1.0F;
cs.gamma[2] = 1.0F; cs.gamma[2] = 1.0F;
cs.brightness = 1.0F;*/ cs.brightness = 1.0F;*/
applyColorSettings(&cs); ScreenFiltersMenu_ApplyColorSettings(&cs);
} }
Menu screenFiltersMenu = {
"Screen filters menu",
{
{ "[6500K] Default", METHOD, .method = &ScreenFiltersMenu_SetDefault },
{ "[10000K] Aquarium", METHOD, .method = &ScreenFiltersMenu_SetAquarium },
{ "[7500K] Overcast Sky", METHOD, .method = &ScreenFiltersMenu_SetOvercastSky },
{ "[5500K] Daylight", METHOD, .method = &ScreenFiltersMenu_SetDaylight },
{ "[4200K] Fluorescent", METHOD, .method = &ScreenFiltersMenu_SetFluorescent },
{ "[3400K] Halogen", METHOD, .method = &ScreenFiltersMenu_SetHalogen },
{ "[2700K] Incandescent", METHOD, .method = &ScreenFiltersMenu_SetIncandescent },
{ "[2300K] Warm Incandescent", METHOD, .method = &ScreenFiltersMenu_SetWarmIncandescent },
{ "[1900K] Candle", METHOD, .method = &ScreenFiltersMenu_SetCandle },
{ "[1200K] Ember", METHOD, .method = &ScreenFiltersMenu_SetEmber },
{},
}
};
#define DEF_CCT_SETTER(temp, name)\
void ScreenFiltersMenu_Set##name(void)\
{\
screenFiltersCurrentTemperature = temp;\
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)
DEF_CCT_SETTER(7500, OvercastSky)
DEF_CCT_SETTER(5500, Daylight)
DEF_CCT_SETTER(4200, Fluorescent)
DEF_CCT_SETTER(3400, Halogen)
DEF_CCT_SETTER(2700, Incandescent)
DEF_CCT_SETTER(2300, WarmIncandescent)
DEF_CCT_SETTER(1900, Candle)
DEF_CCT_SETTER(1200, Ember)

View File

@@ -35,10 +35,10 @@
Menu sysconfigMenu = { Menu sysconfigMenu = {
"System configuration menu", "System configuration menu",
{ {
{ "Control Wireless connection", METHOD, .method = &SysConfigMenu_ControlWifi },
{ "Toggle LEDs", METHOD, .method = &SysConfigMenu_ToggleLEDs }, { "Toggle LEDs", METHOD, .method = &SysConfigMenu_ToggleLEDs },
{ "Toggle Wireless", METHOD, .method = &SysConfigMenu_ToggleWireless }, { "Toggle Wireless", METHOD, .method = &SysConfigMenu_ToggleWireless },
{ "Toggle Power Button", METHOD, .method=&SysConfigMenu_TogglePowerButton }, { "Toggle Power Button", METHOD, .method=&SysConfigMenu_TogglePowerButton },
{ "Control Wireless connection", METHOD, .method = &SysConfigMenu_ControlWifi },
{}, {},
} }
}; };

View File

@@ -1,3 +1,4 @@
/* /*
* This file is part of Luma3DS. * This file is part of Luma3DS.
* Copyright (C) 2016-2020 Aurora Wright, TuxSH * Copyright (C) 2016-2020 Aurora Wright, TuxSH
@@ -7,18 +8,16 @@
#include "minisoc.h" #include "minisoc.h"
#include <sys/socket.h> #include <sys/socket.h>
#include <3ds/ipc.h> #include <3ds.h>
#include <3ds/os.h>
#include <3ds/synchronization.h>
#include <3ds/result.h>
#include <string.h> #include <string.h>
#include "csvc.h" #include "utils.h"
s32 miniSocRefCount = 0; s32 miniSocRefCount = 0;
static u32 socContextAddr = 0x08000000; static u32 socContextAddr = 0x08000000;
static u32 socContextSize = 0x60000; static u32 socContextSize = 0x60000;
static Handle miniSocHandle; static Handle miniSocHandle;
static Handle miniSocMemHandle; static Handle miniSocMemHandle;
static bool exclusiveStateEntered = false;
bool miniSocEnabled = false; bool miniSocEnabled = false;
@@ -56,6 +55,41 @@ static Result SOCU_Shutdown(void)
return cmdbuf[1]; 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) Result miniSocInit(void)
{ {
if(AtomicPostIncrement(&miniSocRefCount)) if(AtomicPostIncrement(&miniSocRefCount))
@@ -89,8 +123,11 @@ Result miniSocInit(void)
ret = SOCU_Initialize(miniSocMemHandle, socContextSize); ret = SOCU_Initialize(miniSocMemHandle, socContextSize);
if(ret != 0) goto cleanup; if(ret != 0) goto cleanup;
svcKernelSetState(0x10000, 2); miniSocLockState();
svcKernelSetState(0x10000, 0x10);
miniSocEnabled = true; miniSocEnabled = true;
return 0; return 0;
cleanup: cleanup:
@@ -117,7 +154,6 @@ cleanup:
Result miniSocExitDirect(void) Result miniSocExitDirect(void)
{ {
//if (miniSocRefCount != 0) __builtin_trap();
Result ret = 0; Result ret = 0;
u32 tmp; u32 tmp;
@@ -132,8 +168,10 @@ Result miniSocExitDirect(void)
svcControlMemory(&tmp, socContextAddr, socContextAddr, socContextSize, MEMOP_FREE, MEMPERM_DONTCARE); svcControlMemory(&tmp, socContextAddr, socContextAddr, socContextSize, MEMOP_FREE, MEMPERM_DONTCARE);
if(ret == 0) if(ret == 0)
{ {
svcKernelSetState(0x10000, 2); miniSocUnlockState(false);
miniSocEnabled = false; miniSocEnabled = false;
svcKernelSetState(0x10000, 0x10);
} }
return ret; return ret;
} }

View File

@@ -3,7 +3,7 @@ Open source replacement of the Arm11 SM system module.
This is licensed under the MIT license. This is licensed under the MIT license.
# Usage # 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 # Credits
Everyone that helped me fix some of stupid bugs I had been making: @fincs, @Hikari-chin, etc. Everyone that helped me fix some of stupid bugs I had been making: @fincs, @Hikari-chin, etc.

View File

@@ -8,6 +8,18 @@ This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for
#include "notifications.h" #include "notifications.h"
#include "processes.h" #include "processes.h"
#include <stdatomic.h>
static bool isNotificationInhibited(const ProcessData *processData, u32 notificationId)
{
(void)processData;
switch(notificationId)
{
default:
return false;
}
}
static bool doPublishNotification(ProcessData *processData, u32 notificationId, u32 flags) static bool doPublishNotification(ProcessData *processData, u32 notificationId, u32 flags)
{ {
if((flags & 1) && processData->nbPendingNotifications != 0) // only send if not already pending 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) for(ProcessData *node = processDataInUseList.first; node != NULL; node = node->next)
{ {
if(!node->notificationEnabled) if(!node->notificationEnabled || isNotificationInhibited(node, notificationId))
continue; continue;
u16 i; u16 i;
@@ -146,7 +158,7 @@ Result PublishAndGetSubscriber(u32 *pidCount, u32 *pidList, u32 notificationId,
u32 nb = 0; u32 nb = 0;
for(ProcessData *node = processDataInUseList.first; node != NULL; node = node->next) for(ProcessData *node = processDataInUseList.first; node != NULL; node = node->next)
{ {
if(!node->notificationEnabled) if(!node->notificationEnabled || isNotificationInhibited(node, notificationId))
continue; continue;
u16 i; u16 i;

View File

@@ -17,3 +17,5 @@ Result PublishToSubscriber(u32 notificationId, u32 flags);
Result PublishAndGetSubscriber(u32 *pidCount, u32 *pidList, u32 notificationId, u32 flags); Result PublishAndGetSubscriber(u32 *pidCount, u32 *pidList, u32 notificationId, u32 flags);
Result PublishToProcess(Handle process, u32 notificationId); Result PublishToProcess(Handle process, u32 notificationId);
Result PublishToAll(u32 notificationId); Result PublishToAll(u32 notificationId);
Result AddToNdmuWorkaroundCount(s32 count);