Compare commits

..

1 Commits

Author SHA1 Message Date
243031aed7 no message 2020-07-06 23:58:53 +02:00
45 changed files with 614 additions and 901 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:
-- Nintendo Homebrew: https://discord.gg/MjzatM8
--
-- Rosalina feature requests go here: https://github.com/LumaTeam/Luma3DS/issues/752
-- Rosalina feature requests go here: https://github.com/AuroraWright/Luma3DS/issues/752
--
-- Also check the Wiki (https://github.com/LumaTeam/Luma3DS/wiki) before making an issue.
-- Also check the Wiki (https://github.com/AuroraWright/Luma3DS/wiki) before making an issue.
--
-- For GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: use https://github.com/MechanicalDragon0687/TWLFix-CFW and update your system.
-- If you're using an emu/redNAND try installing anything on it to sysNAND.
-- Please make sure to read "Enable game patching" https://github.com/LumaTeam/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/AuroraWright/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable game patching" option(s).
--
-- Luma updaters that don't support Boot9Strap/Sighax won't work.
-- This is due to support for non-B9S/Sighax entrypoints being dropped.
@ -21,7 +21,7 @@ about: Use this to report bugs you encounter with Luma3DS. Make sure you upload
-- Please fill in the placeholders.-->
**System model:**
[New 2DS XL, New 3DS XL, New 3DS, Old 2DS, Old 3DS XL, Old 3DS]
[e.g. 2DS, New 3DS, Old 3DS]
**SysNAND version (+emu/redNAND version if applicable):**
@ -34,7 +34,7 @@ about: Use this to report bugs you encounter with Luma3DS. Make sure you upload
**Luma3DS version:**
[e.g. v10.2 stable or if using non-releases specify the commit like this https://github.com/LumaTeam/Luma3DS/commit/0543c208fd154e6326ea5da8cbf66ffcbdef010c]
[e.g. v10.1.3 stable or if using non-releases specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/0543c208fd154e6326ea5da8cbf66ffcbdef010c]
**Luma3DS configuration/options:**
@ -50,7 +50,7 @@ Splash duration: ( )
PIN lock: ( )
New 3DS CPU: ( )
<!--This option is only available on New 3DS (XL)/New 2DS XL.-->
<!--This option is only available for New 3DS/2DS.-->
--
@ -70,13 +70,12 @@ Show NAND or user string in System Settings: ( )
Show GBA boot screen in patched AGB_FIRM: ( )
Patch Arm9 access: ( )
Set developer UNITINFO: ( )
Disable Arm11 exception handlers: ( )
Enable Rosalina on SAFE_FIRM: ( )
<!--This option is only available on New 3DS (XL)/New 2DS XL.-->
--

4
.gitignore vendored
View File

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

View File

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

View File

@ -2,10 +2,9 @@
*Noob-proof (N)3DS "Custom Firmware", with 3GX plugins support*
### 3GX Plugin Edition
This edition of **Luma3DS** allows the loading of **.3GX plugins** in Luma3DS, which are otherwise officially unsupported.
**Warning!** This was a quick, unstable hotfix I published to get things to work while waiting for official updates. The official firmware has now been updated to include 3gx plugins too. Do NOT use this fork.
This edition of **Luma3DS** allows the loading of **.3GX plugins** in Luma3DS, which are otherwise officially unsupported.
#
### How to install this Edition
1. download the latest `boot.firm` from [the releases page](https://github.com/mind-overflow/Luma3DS-3GX/releases/latest)

View File

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

View File

@ -0,0 +1,190 @@
#!/usr/bin/env python
# Requires Python >= 3.2 or >= 2.7
# 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 of GPLv3 applies 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.
__author__ = "TuxSH"
__copyright__ = "Copyright (c) 2016-2020 TuxSH"
__license__ = "GPLv3"
__version__ = "v1.2"
"""
Parses Luma3DS exception dumps
"""
import argparse
from struct import unpack_from
import os
import subprocess
# Source of hexdump: https://gist.github.com/ImmortalPC/c340564823f283fe530b
# Credits for hexdump go to the original authors
# Slightly edited by TuxSH
def hexdump(addr, src, length=16, sep='.' ):
'''
@brief Return {src} in hex dump.
@param[in] length {Int} Nb Bytes by row.
@param[in] sep {Char} For the text part, {sep} will be used for non ASCII char.
@return {Str} The hexdump
@note Full support for python2 and python3 !
'''
result = []
# Python3 support
try:
xrange(0,1)
except NameError:
xrange = range
for i in xrange(0, len(src), length):
subSrc = src[i:i+length]
hexa = ''
isMiddle = False
for h in xrange(0,len(subSrc)):
if h == length/2:
hexa += ' '
h = subSrc[h]
if not isinstance(h, int):
h = ord(h)
h = hex(h).replace('0x','')
if len(h) == 1:
h = '0'+h
hexa += h+' '
hexa = hexa.strip(' ')
text = ''
for c in subSrc:
if not isinstance(c, int):
c = ord(c)
if 0x20 <= c < 0x7F:
text += chr(c)
else:
text += sep
result.append(('%08x: %-'+str(length*(2+1)+1)+'s |%s|') % (addr + i, hexa, text))
return '\n'.join(result)
def makeRegisterLine(A, rA, B, rB):
return "{0:<15}{1:<20}{2:<15}{3:<20}".format(A, "{0:08x}".format(rA), B, "{0:08x}".format(rB))
handledExceptionNames = ("FIQ", "undefined instruction", "prefetch abort", "data abort")
registerNames = tuple("r{0}".format(i) for i in range(13)) + ("sp", "lr", "pc", "cpsr") + ("dfsr", "ifsr", "far") + ("fpexc", "fpinst", "fpinst2")
svcBreakReasons = ("(svcBreak: panic)", "(svcBreak: assertion failed)", "(svcBreak: user-related)")
faultStatusSources = {
0b1:'Alignment', 0b100:'Instruction cache maintenance operation fault',
0b1100:'External Abort on translation - First-level', 0b1110:'External Abort on translation - Second-level',
0b101:'Translation - Section', 0b111:'Translation - Page', 0b11:'Access bit - Section', 0b110:'Access bit - Page',
0b1001:'Domain - Section', 0b1011:'Domain - Page', 0b1101:'Permission - Section', 0b1111:'Permission - Page',
0b1000:'Precise External Abort', 0b10110:'Imprecise External Abort', 0b10:'Debug event'
}
def main(args=None):
parser = argparse.ArgumentParser(description="Parse Luma3DS exception dumps")
parser.add_argument("filename")
args = parser.parse_args()
data = b""
with open(args.filename, "rb") as f: data = f.read()
if unpack_from("<2I", data) != (0xdeadc0de, 0xdeadcafe):
raise SystemExit("Invalid file format")
version, processor, exceptionType, _, nbRegisters, codeDumpSize, stackDumpSize, additionalDataSize = unpack_from("<8I", data, 8)
nbRegisters //= 4
if version < (1 << 16) | 2:
raise SystemExit("Incompatible format version, please use the appropriate parser.")
registers = unpack_from("<{0}I".format(nbRegisters), data, 40)
codeOffset = 40 + 4 * nbRegisters
codeDump = data[codeOffset : codeOffset + codeDumpSize]
stackOffset = codeOffset + codeDumpSize
stackDump = data[stackOffset : stackOffset + stackDumpSize]
addtionalDataOffset = stackOffset + stackDumpSize
additionalData = data[addtionalDataOffset : addtionalDataOffset + additionalDataSize]
if processor == 9: print("Processor: Arm9")
else: print("Processor: Arm11 (core {0})".format(processor >> 16))
typeDetailsStr = ""
if exceptionType == 2:
if (registers[16] & 0x20) == 0 and codeDumpSize >= 4:
instr = unpack_from("<I", codeDump[-4:])[0]
if instr == 0xe12fff7e:
typeDetailsStr = " (kernel panic)"
elif instr == 0xef00003c:
typeDetailsStr = " " + (svcBreakReasons[registers[0]] if registers[0] < 3 else "(svcBreak)")
elif (registers[16] & 0x20) == 1 and codeDumpSize >= 2:
instr = unpack_from("<I", codeDump[-4:])[0]
if instr == 0xdf3c:
typeDetailsStr = " " + (svcBreakReasons[registers[0]] if registers[0] < 3 else "(svcBreak)")
elif processor != 9 and (registers[20] & 0x80000000) != 0:
typeDetailsStr = " (VFP exception)"
print("Exception type: {0}{1}".format("unknown" if exceptionType >= len(handledExceptionNames) else handledExceptionNames[exceptionType], typeDetailsStr))
if processor == 11 and exceptionType >= 2:
xfsr = registers[18] if exceptionType == 2 else registers[17]
print("Fault status: " + faultStatusSources[xfsr & 0xf])
if additionalDataSize != 0:
print("Current process: {0} ({1:016x})".format(additionalData[:8].decode("ascii"), unpack_from("<Q", additionalData, 8)[0]))
print("\nRegister dump:\n")
for i in range(0, nbRegisters - (nbRegisters % 2), 2):
if i == 16: print("")
print(makeRegisterLine(registerNames[i], registers[i], registerNames[i+1], registers[i+1]))
if nbRegisters % 2 == 1: print("{0:<15}{1:<20}".format(registerNames[nbRegisters - 1], "{0:08x}".format(registers[nbRegisters - 1])))
if processor == 11 and exceptionType == 3:
print("{0:<15}{1:<20}Access type: {2}".format("FAR", "{0:08x}".format(registers[19]), "Write" if registers[17] & (1 << 11) != 0 else "Read"))
thumb = registers[16] & 0x20 != 0
addr = registers[15] - codeDumpSize / 2 + (2 if thumb else 4)
print("\nCode dump:\n")
objdump_res = ""
try:
path = os.path.join(os.environ["DEVKITARM"], "bin", "arm-none-eabi-objdump")
if os.name == "nt" and path[0] == '/':
path = ''.join(('c:', path[0], path[5:]))
objdump_res = subprocess.check_output((
path, "-marm", "-b", "binary",
"--adjust-vma="+hex(addr - codeOffset), "--start-address="+hex(addr),
"--stop-address="+hex(addr + codeDumpSize), "-D", "-z", "-M",
"reg-names-std" + (",force-thumb" if thumb else ""), args.filename
)).decode("utf-8")
objdump_res = '\n'.join(objdump_res[objdump_res.find('<.data+'):].split('\n')[1:])
except: objdump_res = ""
print(objdump_res if objdump_res != "" else hexdump(addr, codeDump))
print("\nStack dump:\n")
print(hexdump(registers[13], stackDump))
if __name__ == "__main__":
main()

View File

@ -0,0 +1,13 @@
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,12 +36,11 @@ void executeFunctionOnCores(SGI0Handler_t func, u8 targetList, u8 targetListFilt
void KScheduler__TriggerCrossCoreInterrupt(KScheduler *this);
void KThread__DebugReschedule(KThread *this, bool lock);
bool rosalinaThreadLockPredicate(KThread *thread, u32 mask);
bool rosalinaThreadLockPredicate(KThread *thread);
void rosalinaRescheduleThread(KThread *thread, bool lock);
void rosalinaLockThreads(u32 mask);
void rosalinaUnlockThreads(u32 mask);
void rosalinaLockThread(KThread *thread);
void rosalinaLockAllThreads(void);
void rosalinaUnlockAllThreads(void);
// Taken from ctrulib:
@ -50,11 +49,6 @@ static inline void __dsb(void)
__asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (0) : "memory");
}
static inline void __dmb(void)
{
__asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 5" :: [val] "r" (0) : "memory");
}
static inline void __clrex(void)
{
__asm__ __volatile__("clrex" ::: "memory");

View File

@ -89,7 +89,7 @@ void signalSvcReturn(u8 *pageEnd)
void postprocessSvc(void)
{
KThread *currentThread = currentCoreContext->objectContext.currentThread;
if(!currentThread->shallTerminate && rosalinaThreadLockPredicate(currentThread, rosalinaState & 5))
if(!currentThread->shallTerminate && rosalinaThreadLockPredicate(currentThread))
rosalinaRescheduleThread(currentThread, true);
officialPostProcessSvc();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,28 +0,0 @@
/* 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.
# Usage
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`.
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`.
# Credits
@fincs

View File

@ -218,9 +218,8 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const
programInfoUpdate = (launchFlags & PMLAUNCHFLAG_USE_UPDATE_TITLE) ? programInfoUpdate : programInfo;
TRY(registerProgram(&programHandle, programInfo, programInfoUpdate));
u32 coreVer = OS_KernelConfig->kernel_syscore_ver;
res = LOADER_GetProgramInfo(exheaderInfo, programHandle);
res = R_SUCCEEDED(res) && coreVer == 2 && exheaderInfo->aci.local_caps.core_info.core_version != coreVer ? (Result)0xC8A05800 : res;
res = R_SUCCEEDED(res) && SYSCOREVER == 2 && exheaderInfo->aci.local_caps.core_info.core_version != SYSCOREVER ? (Result)0xC8A05800 : res;
if (R_FAILED(res)) {
LOADER_UnregisterProgram(programHandle);
@ -228,7 +227,7 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const
}
// Change APPMEMALLOC if needed
if (IS_N3DS && OS_KernelConfig->app_memtype == 6 && (launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION) != 0) {
if (IS_N3DS && APPMEMTYPE == 6 && (launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION) != 0) {
u32 limitMb;
SystemMode n3dsSystemMode = exheaderInfo->aci.local_caps.core_info.n3ds_system_mode;
bool forceO3dsAppMem = (launchFlags & PMLAUNCHFLAG_FORCE_USE_O3DS_APP_MEM) != 0;
@ -333,11 +332,9 @@ Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFla
u32 tidh = (u32)(programInfo->programId >> 32);
u32 tidl = (u32)programInfo->programId;
u32 coreVer = OS_KernelConfig->kernel_syscore_ver;
if (coreVer == 2 && (tidh == 0x00040030 || tidh == 0x00040130) && (tidl & 0xFF) != coreVer) {
if ((tidh == 0x00040030 || tidh == 0x00040130) && (tidl & 0xFF) != SYSCOREVER) {
// Panic if launching SAFE_MODE sysmodules or applets (note: exheader syscorever check above only done for applications in official PM)
// Official PM also hardcodes SYSCOREVER = 2 here.
// NATIVE_FIRM-only.
panic(4);
}
@ -523,8 +520,8 @@ Result autolaunchSysmodules(void)
FS_ProgramInfo programInfo = { .mediaType = MEDIATYPE_NAND };
// Launch NS
if (OS_KernelConfig->ns_tid != 0) {
programInfo.programId = OS_KernelConfig->ns_tid;
if (NSTID != 0) {
programInfo.programId = NSTID;
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);
if (g_manager.runningApplicationData != NULL && process->handle == g_manager.runningApplicationData->handle) {
if (IS_N3DS && OS_KernelConfig->app_memtype == 6) {
if (IS_N3DS && APPMEMTYPE == 6) {
assertSuccess(resetAppMemLimit());
}
g_manager.runningApplicationData = NULL;

View File

@ -252,8 +252,7 @@ static ReslimitValues *fixupReslimitValues(void)
// Note: we lie in the reslimit and make as if neither KExt nor Roslina existed, to avoid breakage
u32 appmemalloc = OS_KernelConfig->memregion_sz[0];
u32 sysmemalloc = OS_KernelConfig->memregion_sz[1] + (hasKExt() ? getStolenSystemMemRegionSize() : 0);
u32 sysmemalloc = SYSMEMALLOC + (hasKExt() ? getStolenSystemMemRegionSize() : 0);
ReslimitValues *values = !IS_N3DS ? g_o3dsReslimitValues : g_n3dsReslimitValues;
static const u32 minAppletMemAmount = 0x1200000;
@ -262,7 +261,7 @@ static ReslimitValues *fixupReslimitValues(void)
u32 baseRegionSize = !IS_N3DS ? 0x1400000 : 0x2000000;
if (sysmemalloc < minAppletMemAmount) {
values[1][0] = sysmemalloc - minAppletMemAmount / 3;
values[1][0] = SYSMEMALLOC - minAppletMemAmount / 3;
values[2][0] = 0;
values[3][0] = baseRegionSize + otherMinOvercommitAmount;
} else {
@ -272,8 +271,8 @@ static ReslimitValues *fixupReslimitValues(void)
values[3][0] = baseRegionSize + (otherMinOvercommitAmount + excess / 4);
}
values[0][0] = appmemalloc;
g_defaultAppMemLimit = appmemalloc;
values[0][0] = APPMEMALLOC;
g_defaultAppMemLimit = APPMEMALLOC;
return values;
}

View File

@ -8,7 +8,13 @@
#define REG32(reg) (*(vu32 *)reg)
#define REG64(reg) (*(vu64 *)reg)
#define IS_N3DS (OS_KernelConfig->app_memtype >= 6) // APPMEMTYPE. Hacky but doesn't use APT
#define NSTID REG64(0x1FF80008)
#define SYSCOREVER REG32(0x1FF80010)
#define APPMEMTYPE REG32(0x1FF80030)
#define APPMEMALLOC REG32(0x1FF80040)
#define SYSMEMALLOC REG32(0x1FF80044)
#define IS_N3DS (*(vu32 *)0x1FF80030 >= 6) // APPMEMTYPE. Hacky but doesn't use APT
#define N3DS_TID_MASK 0xF0000000ULL
#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.
# Usage
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/.
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/.
# Credits
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)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit,--section-start,.text=0x14000000
LIBS := -lm -lctru
LIBS := -lctru
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing

View File

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

View File

@ -1,28 +0,0 @@
/* 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

@ -1,33 +0,0 @@
/*
* 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,8 +32,6 @@ extern Menu screenFiltersMenu;
extern int screenFiltersCurrentTemperature;
void ScreenFiltersMenu_RestoreCct(void);
void ScreenFiltersMenu_SetDefault(void); // 6500K (default)
void ScreenFiltersMenu_SetAquarium(void); // 10000K

View File

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

View File

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

View File

@ -277,7 +277,7 @@ void Draw_CreateBitmapHeader(u8 *dst, u32 width, u32 heigth)
Draw_WriteUnaligned(dst + 0x22, 3 * width * heigth, 4);
}
static inline void Draw_ConvertPixelToBGR8(u8 *dst, const u8 *src, GSPGPU_FramebufferFormat srcFormat)
static inline void Draw_ConvertPixelToBGR8(u8 *dst, const u8 *src, GSPGPU_FramebufferFormats srcFormat)
{
u8 red, green, blue;
switch(srcFormat)
@ -354,7 +354,7 @@ static void Draw_ConvertFrameBufferLinesKernel(const FrameBufferConvertArgs *arg
{
static const u8 formatSizes[] = { 4, 3, 2, 2, 2 };
GSPGPU_FramebufferFormat fmt = args->top ? (GSPGPU_FramebufferFormat)(GPU_FB_TOP_FMT & 7) : (GSPGPU_FramebufferFormat)(GPU_FB_BOTTOM_FMT & 7);
GSPGPU_FramebufferFormats fmt = args->top ? (GSPGPU_FramebufferFormats)(GPU_FB_TOP_FMT & 7) : (GSPGPU_FramebufferFormats)(GPU_FB_BOTTOM_FMT & 7);
u32 width = args->width;
u32 stride = args->top ? GPU_FB_TOP_STRIDE : GPU_FB_BOTTOM_STRIDE;

View File

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

View File

@ -177,248 +177,6 @@ void inputRedirectionThreadMain(void)
void hidCodePatchFunc(void);
void irCodePatchFunc(void);
static Result InputRedirection_DoUndoIrPatches(Handle processHandle, bool doPatch)
{
static u32* hookLoc = NULL;
static u32* syncLoc = NULL;
static u32* cppFlagLoc = NULL;
static u32 origIrSync = 0;
static u32 origCppFlag = 0;
static bool patchPrepared = false;
static u32 irOrigReadingCode[5] = {
0xE5940000, // ldr r0, [r4]
0xE1A01005, // mov r1, r5
0xE3A03005, // mov r3, #5
0xE3A02011, // mov r2, #17
0x00000000 // (bl i2c_read_raw goes here)
};
static u32 irHook[] = {
0xE5940000, // ldr r0, [r4]
0xE1A01005, // mov r1, r5
0xE59FC000, // ldr r12, [pc] (actually +8)
0xE12FFF3C, // blx r12
0x00000000 // irCodePhys goes here
};
static u32 syncHookCode[] = {
0xE5900000, // ldr r0, [r0]
0xEF000024, // svc 0x24
0xE3A00000, // mov r0, #0
0xE51FF004, // ldr pc, [pc, #-4]
0x00000000, // (return address goes here)
};
// Find offsets for required patches
s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
u32 totalSize;
Result res;
svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data
svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
svcGetProcessInfo(&startAddress, processHandle, 0x10005);
res = svcMapProcessMemoryEx(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)
{
if(!inputRedirectionEnabled)
@ -437,46 +195,209 @@ Result InputRedirection_Disable(s64 timeout)
Result InputRedirection_DoOrUndoPatches(void)
{
s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
u32 totalSize;
Handle processHandle;
Result res = OpenProcessByName("hid", &processHandle);
static bool hidPatched = false;
static bool irPatched = false;
Handle hidProcHandle = 0, irProcHandle = 0;
// Prevent hid and ir from running, in any case
svcKernelSetState(0x10000, 4);
Result res = OpenProcessByName("hid", &hidProcHandle);
if (R_FAILED(res))
goto cleanup;
res = OpenProcessByName("ir", &irProcHandle);
if (R_FAILED(res))
goto cleanup;
if(R_SUCCEEDED(res))
{
res = InputRedirection_DoUndoHidPatches(hidProcHandle, !hidPatched);
if (R_SUCCEEDED(res))
hidPatched = !hidPatched;
}
svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data
svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
svcGetProcessInfo(&startAddress, processHandle, 0x10005);
res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (u32) startAddress, totalSize);
if(R_SUCCEEDED(res))
{
static const u32 hidOrigRegisterAndValue[] = { 0x1EC46000, 0x4001 };
static const u32 hidOrigCode[] = {
0xE92D4070, // push {r4-r6, lr}
0xE1A05001, // mov r5, r1
0xEE1D4F70, // mrc p15, 0, r4, c13, c0, 3
0xE3A01801, // mov r1, #0x10000
0xE5A41080, // str r1, [r4,#0x80]!
};
static u32 *hidRegPatchOffsets[2];
static u32 *hidPatchJumpLoc;
if(hidPatched)
{
memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode));
hidPatched = false;
}
else
{
u32 hidDataPhys = (u32)PA_FROM_VA_PTR(hidData);
u32 hidCodePhys = (u32)PA_FROM_VA_PTR(&hidCodePatchFunc);
u32 hidHook[] = {
0xE59F3004, // ldr r3, [pc, #4]
0xE59FC004, // ldr r12, [pc, #4]
0xE12FFF1C, // bx r12
hidDataPhys,
hidCodePhys,
};
u32 *off = (u32 *)memsearch((u8 *)0x00100000, &hidOrigRegisterAndValue, totalSize, sizeof(hidOrigRegisterAndValue));
if(off == NULL)
{
svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
return -1;
}
u32 *off2 = (u32 *)memsearch((u8 *)off + sizeof(hidOrigRegisterAndValue), &hidOrigRegisterAndValue, totalSize - ((u32)off - 0x00100000), sizeof(hidOrigRegisterAndValue));
if(off2 == NULL)
{
svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
return -2;
}
u32 *off3 = (u32 *)memsearch((u8 *)0x00100000, &hidOrigCode, totalSize, sizeof(hidOrigCode));
if(off3 == NULL)
{
svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
return -3;
}
hidRegPatchOffsets[0] = off;
hidRegPatchOffsets[1] = off2;
hidPatchJumpLoc = off3;
*off = *off2 = hidDataPhys;
memcpy(off3, &hidHook, sizeof(hidHook));
hidPatched = true;
}
}
res = svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
}
svcCloseHandle(processHandle);
res = OpenProcessByName("ir", &processHandle);
if(R_SUCCEEDED(res) && GET_VERSION_MINOR(osGetKernelVersion()) >= 44)
{
res = InputRedirection_DoUndoIrPatches(irProcHandle, !irPatched);
if (R_SUCCEEDED(res))
irPatched = !irPatched;
else if (!irPatched)
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))
{
InputRedirection_DoUndoHidPatches(hidProcHandle, false);
hidPatched = false;
static bool useOldSyncCode;
static u32 irOrigReadingCode[5] = {
0xE5940000, // ldr r0, [r4]
0xE1A01005, // mov r1, r5
0xE3A03005, // mov r3, #5
0xE3A02011, // mov r2, #17
0x00000000 // (bl i2c_read_raw goes here)
};
static const u32 irOrigWaitSyncCode[] = {
0xEF000024, // svc 0x24 (WaitSynchronization)
0xE1B01FA0, // movs r1, r0, lsr#31
0xE1A0A000, // mov r10, r0
}, irOrigWaitSyncCodeOld[] = {
0xE0AC6000, // adc r6, r12, r0
0xE5D70000, // ldrb r0, [r7]
}; // pattern for 8.1
static const u32 irOrigCppFlagCode[] = {
0xE3550000, // cmp r5, #0
0xE3A0B080, // mov r11, #0x80
};
static u32 *irHookLoc, *irWaitSyncLoc, *irCppFlagLoc;
if(irPatched)
{
memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode));
if(useOldSyncCode)
memcpy(irWaitSyncLoc, &irOrigWaitSyncCodeOld, sizeof(irOrigWaitSyncCodeOld));
else
memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode));
memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode));
irPatched = false;
}
else
{
u32 irDataPhys = (u32)PA_FROM_VA_PTR(irData);
u32 irCodePhys = (u32)PA_FROM_VA_PTR(&irCodePatchFunc);
u32 irHook[] = {
0xE5940000, // ldr r0, [r4]
0xE1A01005, // mov r1, r5
0xE59FC000, // ldr r12, [pc] (actually +8)
0xE12FFF3C, // blx r12
irCodePhys,
};
u32 *off = (u32 *)memsearch((u8 *)0x00100000, &irOrigReadingCode, totalSize, sizeof(irOrigReadingCode) - 4);
if(off == NULL)
{
svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
return -4;
}
u32 *off2 = (u32 *)memsearch((u8 *)0x00100000, &irOrigWaitSyncCode, totalSize, sizeof(irOrigWaitSyncCode));
if(off2 == NULL)
{
off2 = (u32 *)memsearch((u8 *)0x00100000, &irOrigWaitSyncCodeOld, totalSize, sizeof(irOrigWaitSyncCodeOld));
if(off2 == NULL)
{
svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
return -5;
}
useOldSyncCode = true;
}
else
useOldSyncCode = false;
u32 *off3 = (u32 *)memsearch((u8 *)0x00100000, &irOrigCppFlagCode, totalSize, sizeof(irOrigCppFlagCode));
if(off3 == NULL)
{
svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
return -6;
}
*(void **)(irCodePhys + 8) = decodeArmBranch(off + 4);
*(void **)(irCodePhys + 12) = (void*)irDataPhys;
irHookLoc = off;
irWaitSyncLoc = off2;
irCppFlagLoc = off3;
irOrigReadingCode[4] = off[4]; // Copy the branch.
memcpy(irHookLoc, &irHook, sizeof(irHook));
// This "NOP"s out a WaitSynchronisation1 (on the event bound to the 'IR' interrupt) or the check of a previous one
*irWaitSyncLoc = 0xE3A00000; // mov r0, #0
// This NOPs out a flag check in ir:user's CPP emulation
*irCppFlagLoc = 0xE3150000; // tst r5, #0
irPatched = true;
}
}
res = svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, totalSize);
}
svcCloseHandle(processHandle);
cleanup:
svcKernelSetState(0x10000, 4);
svcCloseHandle(hidProcHandle);
svcCloseHandle(irProcHandle);
return res;
}

View File

@ -1,122 +0,0 @@
/*
* 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,15 +83,13 @@ void initSystem(void)
isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0;
svcGetSystemInfo(&out, 0x10000, 0x100);
Luma_SharedConfig->hbldr_3dsx_tid = out == 0 ? HBLDR_DEFAULT_3DSX_TID : (u64)out;
Luma_SharedConfig->use_hbldr = true;
HBLDR_3DSX_TID = out == 0 ? HBLDR_DEFAULT_3DSX_TID : (u64)out;
svcGetSystemInfo(&out, 0x10000, 0x101);
menuCombo = out == 0 ? DEFAULT_MENU_COMBO : (u32)out;
miscellaneousMenu.items[0].title = Luma_SharedConfig->hbldr_3dsx_tid == HBLDR_DEFAULT_3DSX_TID ?
"Switch the hb. title to the current app." :
"Switch the hb. title to hblauncher_loader";
miscellaneousMenu.items[0].title = HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID ? "Switch the hb. title to the current app." :
"Switch the hb. title to hblauncher_loader";
for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL))
{
@ -106,9 +104,6 @@ void initSystem(void)
if (R_FAILED(fsInit()))
svcBreak(USERBREAK_PANIC);
if (R_FAILED(FSUSER_SetPriority(-16)))
svcBreak(USERBREAK_PANIC);
// **** DO NOT init services that don't come from KIPs here ****
// Instead, init the service only where it's actually init (then deinit it).
@ -136,53 +131,11 @@ static void handleTermNotification(u32 notificationId)
(void)notificationId;
}
static void handleSleepNotification(u32 notificationId)
{
ptmSysmInit();
s32 ackValue = ptmSysmGetNotificationAckValue(notificationId);
switch (notificationId)
{
case PTMNOTIFID_SLEEP_REQUESTED:
menuShouldExit = true;
PTMSYSM_ReplyToSleepQuery(miniSocEnabled); // deny sleep request if we have network stuff running
break;
case PTMNOTIFID_GOING_TO_SLEEP:
case PTMNOTIFID_SLEEP_ALLOWED:
case PTMNOTIFID_FULLY_WAKING_UP:
case PTMNOTIFID_HALF_AWAKE:
PTMSYSM_NotifySleepPreparationComplete(ackValue);
break;
case PTMNOTIFID_SLEEP_DENIED:
case PTMNOTIFID_FULLY_AWAKE:
menuShouldExit = false;
break;
default:
break;
}
ptmSysmExit();
}
static void handleShellNotification(u32 notificationId)
{
if (notificationId == 0x213) {
// Shell opened
// Note that this notification is fired on system init
ScreenFiltersMenu_RestoreCct();
menuShouldExit = false;
} else {
// Shell closed
menuShouldExit = true;
}
}
static void handlePreTermNotification(u32 notificationId)
{
(void)notificationId;
// Might be subject to a race condition, but heh.
miniSocUnlockState(true);
// Disable input redirection
InputRedirection_Disable(100 * 1000 * 1000LL);
@ -227,19 +180,11 @@ static const ServiceManagerServiceEntry services[] = {
};
static const ServiceManagerNotificationEntry notifications[] = {
{ 0x100 , handleTermNotification },
{ PTMNOTIFID_SLEEP_REQUESTED, handleSleepNotification },
{ PTMNOTIFID_SLEEP_DENIED, handleSleepNotification },
{ PTMNOTIFID_SLEEP_ALLOWED, handleSleepNotification },
{ PTMNOTIFID_GOING_TO_SLEEP, handleSleepNotification },
{ PTMNOTIFID_FULLY_WAKING_UP, handleSleepNotification },
{ PTMNOTIFID_FULLY_AWAKE, handleSleepNotification },
{ PTMNOTIFID_HALF_AWAKE, handleSleepNotification },
{ 0x213, handleShellNotification },
{ 0x214, handleShellNotification },
{ 0x1000, handleNextApplicationDebuggedByForce },
{ 0x2000, handlePreTermNotification },
{ 0x3000, handleRestartHbAppNotification },
{ 0x100 , handleTermNotification },
//{ 0x103 , handlePreTermNotification }, // Sleep mode entry <=== causes issues
{ 0x1000, handleNextApplicationDebuggedByForce },
{ 0x2000, handlePreTermNotification },
{ 0x3000, handleRestartHbAppNotification },
{ 0x000, NULL },
};

View File

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

View File

@ -40,7 +40,6 @@
#include "memory.h"
#include "fmt.h"
#include "process_patches.h"
#include "luminance.h"
Menu rosalinaMenu = {
"Rosalina menu",
@ -65,11 +64,7 @@ Menu rosalinaMenu = {
bool rosalinaMenuShouldShowDebugInfo(void)
{
// Don't show on release builds
s64 out;
svcGetSystemInfo(&out, 0x10000, 0x200);
return out == 0;
return true;
}
void RosalinaMenu_ShowDebugInfo(void)
@ -124,8 +119,8 @@ void RosalinaMenu_ShowCredits(void)
Draw_DrawString(10, posY, COLOR_WHITE,
(
"Special thanks to:\n"
" fincs, WinterMute, mtheall, piepie62,\n"
" Luma3DS contributors, libctru contributors,\n"
" Bond697, WinterMute, piepie62, yifanlu\n"
" Luma3DS contributors, ctrulib contributors,\n"
" other people"
));
@ -145,7 +140,7 @@ void RosalinaMenu_Reboot(void)
do
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Reboot");
Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina menu");
Draw_DrawString(10, 30, COLOR_WHITE, "Press A to reboot, press B to go back.");
Draw_FlushFramebuffer();
Draw_Unlock();
@ -163,103 +158,107 @@ void RosalinaMenu_Reboot(void)
while(!menuShouldExit);
}
static u32 gspPatchAddrN3ds, gspPatchValuesN3ds[2];
static bool gspPatchDoneN3ds;
static Result RosalinaMenu_PatchN3dsGspForBrightness(u32 size)
{
u32 *off = (u32 *)0x00100000;
u32 *end = (u32 *)(0x00100000 + size);
for (; off < end && (off[0] != 0xE92D4030 || off[1] != 0xE1A04000 || off[2] != 0xE2805C01 || off[3] != 0xE5D0018C); off++);
if (off >= end) {
return -1;
}
gspPatchAddrN3ds = (u32)off;
gspPatchValuesN3ds[0] = off[26];
gspPatchValuesN3ds[1] = off[50];
// NOP brightness changing in GSP
off[26] = 0xE1A00000;
off[50] = 0xE1A00000;
return 0;
}
static Result RosalinaMenu_RevertN3dsGspPatch(u32 size)
{
(void)size;
u32 *off = (u32 *)gspPatchAddrN3ds;
off[26] = gspPatchValuesN3ds[0];
off[50] = gspPatchValuesN3ds[1];
return 0;
}
void RosalinaMenu_ChangeScreenBrightness(void)
{
Result patchResult = 0;
if (isN3DS && !gspPatchDoneN3ds)
{
patchResult = PatchProcessByName("gsp", RosalinaMenu_PatchN3dsGspForBrightness);
gspPatchDoneN3ds = R_SUCCEEDED(patchResult);
}
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
Draw_Unlock();
// gsp:LCD GetLuminance is stubbed on O3DS so we have to implement it ourselves... damn it.
// Assume top and bottom screen luminances are the same (should be; if not, we'll set them to the same values).
u32 luminance = getCurrentLuminance(false);
u32 minLum = getMinLuminancePreset();
u32 maxLum = getMaxLuminancePreset();
do
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Screen brightness");
u32 posY = 30;
posY = Draw_DrawFormattedString(
10,
posY,
COLOR_WHITE,
"Current luminance: %lu (min. %lu, max. %lu)\n\n",
luminance,
minLum,
maxLum
);
posY = Draw_DrawString(10, posY, COLOR_WHITE, "Controls: Up/Down for +-1, Right/Left for +-10.\n");
posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press A to start, B to exit.\n\n");
// Assume the current brightness for both screens are the same.
s32 brightness = (s32)(LCD_TOP_BRIGHTNESS & 0xFF);
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina menu");
u32 posY = 30;
posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Current brightness (0..255): %3lu\n\n", brightness);
if (R_SUCCEEDED(patchResult))
{
posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press Up/Down for +-1, Right/Left for +-10.\n");
posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press Y to revert the GSP patch and exit.\n\n");
posY = Draw_DrawString(10, posY, COLOR_RED, "WARNING: \n");
posY = Draw_DrawString(10, posY, COLOR_WHITE, " * avoid using values far higher than the presets.\n");
posY = Draw_DrawString(10, posY, COLOR_WHITE, " * normal brightness mngmt. is now broken on N3DS.\nYou'll need to press Y to revert");
}
else
Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Failed to patch GSP (0x%08lx).", (u32)patchResult);
posY = Draw_DrawString(10, posY, COLOR_RED, "WARNING: \n");
posY = Draw_DrawString(10, posY, COLOR_WHITE, " * value will be limited by the presets.\n");
posY = Draw_DrawString(10, posY, COLOR_WHITE, " * bottom framebuffer will be restored until\nyou exit.");
Draw_FlushFramebuffer();
Draw_Unlock();
u32 pressed = waitInputWithTimeout(1000);
if (pressed & KEY_A)
break;
if ((pressed & DIRECTIONAL_KEYS) && R_SUCCEEDED(patchResult))
{
if (pressed & KEY_UP)
brightness += 1;
else if (pressed & KEY_DOWN)
brightness -= 1;
else if (pressed & KEY_RIGHT)
brightness += 10;
else if (pressed & KEY_LEFT)
brightness -= 10;
if (pressed & KEY_B)
brightness = brightness < 0 ? 0 : brightness;
brightness = brightness > 255 ? 255 : brightness;
LCD_TOP_BRIGHTNESS = (u32)brightness;
LCD_BOT_BRIGHTNESS = (u32)brightness;
}
else if ((pressed & KEY_Y) && gspPatchDoneN3ds)
{
patchResult = PatchProcessByName("gsp", RosalinaMenu_RevertN3dsGspPatch);
gspPatchDoneN3ds = !R_SUCCEEDED(patchResult);
return;
}
else if (pressed & KEY_B)
return;
}
while (!menuShouldExit);
Draw_Lock();
Draw_RestoreFramebuffer();
Draw_FreeFramebufferCache();
svcKernelSetState(0x10000, 2); // unblock gsp
gspLcdInit(); // assume it doesn't fail. If it does, brightness won't change, anyway.
// gsp:LCD will normalize the brightness between top/bottom screen, handle PWM, etc.
s32 lum = (s32)luminance;
do
{
u32 pressed = waitInputWithTimeout(1000);
if (pressed & DIRECTIONAL_KEYS)
{
if (pressed & KEY_UP)
lum += 1;
else if (pressed & KEY_DOWN)
lum -= 1;
else if (pressed & KEY_RIGHT)
lum += 10;
else if (pressed & KEY_LEFT)
lum -= 10;
lum = lum < (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.
@ -272,7 +271,7 @@ void RosalinaMenu_PowerOff(void) // Soft shutdown.
do
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Power off");
Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina menu");
Draw_DrawString(10, 30, COLOR_WHITE, "Press A to power off, press B to go back.");
Draw_FlushFramebuffer();
Draw_Unlock();

View File

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

View File

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

View File

@ -32,29 +32,26 @@
#include "redshift/redshift.h"
#include "redshift/colorramp.h"
typedef union {
struct {
u8 r;
u8 g;
u8 b;
u8 z;
};
u32 raw;
typedef struct {
u8 r;
u8 g;
u8 b;
u8 z;
} Pixel;
static u16 g_c[0x600];
static Pixel g_px[0x400];
int screenFiltersCurrentTemperature = -1;
int screenFiltersCurrentTemperature = 6500;
static void ScreenFiltersMenu_WriteLut(const Pixel* lut)
static void ScreenFiltersMenu_WriteLut(const u32* 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;
GPU_FB_TOP_COL_LUT_ELEM = *lut;
GPU_FB_BOTTOM_COL_LUT_ELEM = *lut;
lut++;
}
}
@ -87,7 +84,7 @@ static void ScreenFiltersMenu_ApplyColorSettings(color_setting_t* cs)
g_px[i].b = *(g_c + i + 0x200) >> 8;
} while(++i);
ScreenFiltersMenu_WriteLut(g_px);
ScreenFiltersMenu_WriteLut((u32*)g_px);
}
static void ScreenFiltersMenu_SetCct(int cct)
@ -104,6 +101,7 @@ static void ScreenFiltersMenu_SetCct(int cct)
ScreenFiltersMenu_ApplyColorSettings(&cs);
}
Menu screenFiltersMenu = {
"Screen filters menu",
{
@ -116,7 +114,7 @@ Menu screenFiltersMenu = {
{ "[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 },
{ "[2700K] Ember", METHOD, .method = &ScreenFiltersMenu_SetEmber },
{},
}
};
@ -128,20 +126,6 @@ void ScreenFiltersMenu_Set##name(void)\
ScreenFiltersMenu_SetCct(temp);\
}
void ScreenFiltersMenu_RestoreCct(void)
{
// Not initialized: return
if (screenFiltersCurrentTemperature == -1)
return;
// Wait for GSP to restore the CCT table
while (GPU_FB_TOP_COL_LUT_ELEM != g_px[0].raw)
svcSleepThread(10 * 1000 * 1000LL);
svcSleepThread(10 * 1000 * 1000LL);
ScreenFiltersMenu_WriteLut(g_px);
}
DEF_CCT_SETTER(6500, Default)
DEF_CCT_SETTER(10000, Aquarium)

View File

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

View File

@ -1,4 +1,3 @@
/*
* This file is part of Luma3DS.
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
@ -8,16 +7,18 @@
#include "minisoc.h"
#include <sys/socket.h>
#include <3ds.h>
#include <3ds/ipc.h>
#include <3ds/os.h>
#include <3ds/synchronization.h>
#include <3ds/result.h>
#include <string.h>
#include "utils.h"
#include "csvc.h"
s32 miniSocRefCount = 0;
static u32 socContextAddr = 0x08000000;
static u32 socContextSize = 0x60000;
static Handle miniSocHandle;
static Handle miniSocMemHandle;
static bool exclusiveStateEntered = false;
bool miniSocEnabled = false;
@ -55,41 +56,6 @@ static Result SOCU_Shutdown(void)
return cmdbuf[1];
}
// unsafe but what can I do?
void miniSocLockState(void)
{
Result res = 0;
__dmb();
if (!exclusiveStateEntered && isServiceUsable("ndm:u"))
{
ndmuInit();
res = NDMU_EnterExclusiveState(NDM_EXCLUSIVE_STATE_INFRASTRUCTURE);
if (R_SUCCEEDED(res))
res = NDMU_LockState(); // prevents ndm from switching to StreetPass when the lid is closed
exclusiveStateEntered = R_SUCCEEDED(res);
__dmb();
}
}
void miniSocUnlockState(bool force)
{
Result res = 0;
__dmb();
if (exclusiveStateEntered)
{
if (!force)
{
res = NDMU_UnlockState();
if (R_SUCCEEDED(res))
res = NDMU_LeaveExclusiveState();
}
ndmuExit();
exclusiveStateEntered = R_FAILED(res);
__dmb();
}
}
Result miniSocInit(void)
{
if(AtomicPostIncrement(&miniSocRefCount))
@ -123,11 +89,8 @@ Result miniSocInit(void)
ret = SOCU_Initialize(miniSocMemHandle, socContextSize);
if(ret != 0) goto cleanup;
miniSocLockState();
svcKernelSetState(0x10000, 0x10);
svcKernelSetState(0x10000, 2);
miniSocEnabled = true;
return 0;
cleanup:
@ -154,6 +117,7 @@ cleanup:
Result miniSocExitDirect(void)
{
//if (miniSocRefCount != 0) __builtin_trap();
Result ret = 0;
u32 tmp;
@ -168,10 +132,8 @@ Result miniSocExitDirect(void)
svcControlMemory(&tmp, socContextAddr, socContextAddr, socContextSize, MEMOP_FREE, MEMPERM_DONTCARE);
if(ret == 0)
{
miniSocUnlockState(false);
svcKernelSetState(0x10000, 2);
miniSocEnabled = false;
svcKernelSetState(0x10000, 0x10);
}
return ret;
}

View File

@ -3,7 +3,7 @@ Open source replacement of the Arm11 SM system module.
This is licensed under the MIT license.
# Usage
To run this system module, use a recent release or commit of [Luma3DS](https://github.com/LumaTeam/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/AuroraWright/Luma3DS/), build this project and copy sm.cxi to /luma/sysmodules/.
# Credits
Everyone that helped me fix some of stupid bugs I had been making: @fincs, @Hikari-chin, etc.

View File

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

View File

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