Add ability to redirect app core1 threads to core2
N3DS-only option. See config.ini for details and context. This should make very demanding games (those which already use 3x clockrate and L2C by default, like Pokémon US/UM) between 5 to 15% faster. Not widely tested, and can potentially break some games and other apps.
This commit is contained in:
parent
ceea6afa05
commit
7b97af473a
Binary file not shown.
@ -62,6 +62,7 @@ static const char *singleOptionIniNamesBoot[] = {
|
||||
"use_emunand_firm_if_r_pressed",
|
||||
"enable_external_firm_and_modules",
|
||||
"enable_game_patching",
|
||||
"app_syscore_threads_on_core_2",
|
||||
"show_system_settings_string",
|
||||
"show_gba_boot_screen",
|
||||
};
|
||||
@ -544,7 +545,8 @@ static size_t saveLumaIniConfigToStr(char *out)
|
||||
(int)CONFIG_VERSIONMAJOR, (int)CONFIG_VERSIONMINOR,
|
||||
(int)CONFIG(AUTOBOOTEMU), (int)CONFIG(USEEMUFIRM),
|
||||
(int)CONFIG(LOADEXTFIRMSANDMODULES), (int)CONFIG(PATCHGAMES),
|
||||
(int)CONFIG(PATCHVERSTRING), (int)CONFIG(SHOWGBABOOT),
|
||||
(int)CONFIG(REDIRECTAPPTHREADS), (int)CONFIG(PATCHVERSTRING),
|
||||
(int)CONFIG(SHOWGBABOOT),
|
||||
|
||||
1 + (int)MULTICONFIG(DEFAULTEMU), 4 - (int)MULTICONFIG(BRIGHTNESS),
|
||||
splashPosStr, (unsigned int)cfg->splashDurationMsec,
|
||||
@ -716,6 +718,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
"( ) Use EmuNAND FIRM if booting with R",
|
||||
"( ) Enable loading external FIRMs and modules",
|
||||
"( ) Enable game patching",
|
||||
"( ) Redirect app. syscore threads to core2",
|
||||
"( ) Show NAND or user string in System Settings",
|
||||
"( ) Show GBA boot screen in patched AGB_FIRM",
|
||||
};
|
||||
@ -793,6 +796,15 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
"for out-of-region games work.\n\n"
|
||||
"Refer to the wiki for instructions.",
|
||||
|
||||
"Redirect app. threads that would spawn\n"
|
||||
"on core1, to core2 (which is an extra\n"
|
||||
"CPU core for applications that usually\n"
|
||||
"remains unused).\n\n"
|
||||
"This improves the performance of very\n"
|
||||
"demanding games (like Pok\x82mon US/UM)\n" // CP437
|
||||
"by about 10%. Can break some games\n"
|
||||
"and other applications.\n",
|
||||
|
||||
"Enable showing the current NAND/FIRM:\n\n"
|
||||
"\t* Sys = SysNAND\n"
|
||||
"\t* Emu = EmuNAND 1\n"
|
||||
@ -839,6 +851,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
{ .visible = nandType == FIRMWARE_EMUNAND },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = ISN3DS },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
};
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
#define CONFIG_FILE "config.bin"
|
||||
#define CONFIG_VERSIONMAJOR 3
|
||||
#define CONFIG_VERSIONMINOR 2
|
||||
#define CONFIG_VERSIONMINOR 3
|
||||
|
||||
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
|
||||
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
|
||||
@ -59,6 +59,7 @@ enum singleOptions
|
||||
USEEMUFIRM,
|
||||
LOADEXTFIRMSANDMODULES,
|
||||
PATCHGAMES,
|
||||
REDIRECTAPPTHREADS,
|
||||
PATCHVERSTRING,
|
||||
SHOWGBABOOT,
|
||||
PATCHUNITINFO,
|
||||
|
@ -30,6 +30,7 @@ enum singleOptions
|
||||
USEEMUFIRM,
|
||||
LOADEXTFIRMSANDMODULES,
|
||||
PATCHGAMES,
|
||||
REDIRECTAPPTHREADS,
|
||||
PATCHVERSTRING,
|
||||
SHOWGBABOOT,
|
||||
PATCHUNITINFO,
|
||||
|
@ -54,6 +54,7 @@ extern void (*KScheduler__AdjustThread)(KScheduler *this, KThread *thread, u32 o
|
||||
extern void (*KScheduler__AttemptSwitchingThreadContext)(KScheduler *this);
|
||||
|
||||
extern Result (*ControlMemory)(u32 *addrOut, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm, bool isLoader);
|
||||
extern Result (*CreateThread)(Handle *outThreadHandle, u32 ep, u32 arg, u32 stackTop, s32 priority, s32 processorId);
|
||||
extern void (*SleepThread)(s64 ns);
|
||||
extern Result (*CloseHandle)(Handle handle);
|
||||
extern Result (*GetHandleInfo)(s64 *out, Handle handle, u32 type);
|
||||
|
@ -1162,7 +1162,7 @@ offsetof(classname##O3DSPre8x, field)))
|
||||
#define KPROCESSHWINFO_GET_RVALUE(obj, field) *(KPROCESSHWINFO_GET_PTR(obj, field))
|
||||
#define KPROCESSHWINFO_GET_RVALUE_TYPE(type, obj, field) *(KPROCESSHWINFO_GET_PTR_TYPE(type, obj, field))
|
||||
|
||||
extern u32 pidOffsetKProcess, hwInfoOffsetKProcess, codeSetOffsetKProcess, handleTableOffsetKProcess, debugOffsetKProcess;
|
||||
extern u32 pidOffsetKProcess, hwInfoOffsetKProcess, codeSetOffsetKProcess, handleTableOffsetKProcess, debugOffsetKProcess, flagsKProcess;
|
||||
|
||||
static inline u32 idOfProcess(KProcess *process)
|
||||
{
|
||||
@ -1195,6 +1195,13 @@ static inline KDebug *debugOfProcess(KProcess *process)
|
||||
return debug;
|
||||
}
|
||||
|
||||
static inline u32 flagsOfProcess(KProcess *process)
|
||||
{
|
||||
u32 flags;
|
||||
memcpy(&flags, (const u8 *)process + flagsKProcess, 4);
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline const char *classNameOfAutoObject(KAutoObject *object)
|
||||
{
|
||||
const char *name;
|
||||
|
32
k11_extension/include/svc/CreateThread.h
Normal file
32
k11_extension/include/svc/CreateThread.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2023 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 "utils.h"
|
||||
#include "kernel.h"
|
||||
#include "svc.h"
|
||||
|
||||
Result CreateThreadHookWrapper(Handle *outThreadHandle, u32 ep, u32 arg, u32 stackTop, s32 priority, s32 processorId);
|
||||
Result CreateThreadHook(Handle *outThreadHandle, u32 ep, u32 arg, u32 stackTop, s32 priority, s32 processorId);
|
@ -50,6 +50,7 @@ void (*KScheduler__AdjustThread)(KScheduler *this, KThread *thread, u32 oldSched
|
||||
void (*KScheduler__AttemptSwitchingThreadContext)(KScheduler *this);
|
||||
|
||||
Result (*ControlMemory)(u32 *addrOut, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm, bool isLoader);
|
||||
Result (*CreateThread)(Handle *outThreadHandle, u32 ep, u32 arg, u32 stackTop, s32 priority, s32 processorId);
|
||||
void (*SleepThread)(s64 ns);
|
||||
Result (*CloseHandle)(Handle handle);
|
||||
Result (*GetHandleInfo)(s64 *out, Handle handle, u32 type);
|
||||
@ -114,4 +115,4 @@ u32 stolenSystemMemRegionSize;
|
||||
vu32 rosalinaState;
|
||||
bool hasStartedRosalinaNetworkFuncsOnce;
|
||||
|
||||
u32 pidOffsetKProcess, hwInfoOffsetKProcess, codeSetOffsetKProcess, handleTableOffsetKProcess, debugOffsetKProcess;
|
||||
u32 pidOffsetKProcess, hwInfoOffsetKProcess, codeSetOffsetKProcess, handleTableOffsetKProcess, debugOffsetKProcess, flagsKProcess;
|
||||
|
@ -127,6 +127,7 @@ void configHook(vu8 *cfgPage)
|
||||
codeSetOffsetKProcess = KPROCESS_OFFSETOF(codeSet);
|
||||
handleTableOffsetKProcess = KPROCESS_OFFSETOF(handleTable);
|
||||
debugOffsetKProcess = KPROCESS_OFFSETOF(debug);
|
||||
flagsKProcess = KPROCESS_OFFSETOF(kernelFlags);
|
||||
}
|
||||
|
||||
static void findUsefulSymbols(void)
|
||||
@ -240,6 +241,7 @@ static void findUsefulSymbols(void)
|
||||
// The official prototype of ControlMemory doesn't have that extra param'
|
||||
ControlMemory = (Result (*)(u32 *, u32, u32, u32, MemOp, MemPerm, bool))
|
||||
decodeArmBranch((u32 *)officialSVCs[0x01] + 5);
|
||||
CreateThread = (Result (*)(Handle *, u32, u32, u32, s32, s32))decodeArmBranch((u32 *)officialSVCs[0x08] + 5);
|
||||
SleepThread = (void (*)(s64))officialSVCs[0x0A];
|
||||
CloseHandle = (Result (*)(Handle))officialSVCs[0x23];
|
||||
GetHandleInfo = (Result (*)(s64 *, Handle, u32))decodeArmBranch((u32 *)officialSVCs[0x29] + 3);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "synchronization.h"
|
||||
#include "svc.h"
|
||||
#include "svc/ControlMemory.h"
|
||||
#include "svc/CreateThread.h"
|
||||
#include "svc/GetHandleInfo.h"
|
||||
#include "svc/GetSystemInfo.h"
|
||||
#include "svc/GetProcessInfo.h"
|
||||
@ -63,6 +64,8 @@ void buildAlteredSvcTable(void)
|
||||
|
||||
alteredSvcTable[0x01] = ControlMemoryHookWrapper;
|
||||
|
||||
if (isN3DS)
|
||||
alteredSvcTable[0x08] = CreateThreadHookWrapper;
|
||||
alteredSvcTable[0x29] = GetHandleInfoHookWrapper;
|
||||
alteredSvcTable[0x2A] = GetSystemInfoHookWrapper;
|
||||
alteredSvcTable[0x2B] = GetProcessInfoHookWrapper;
|
||||
|
37
k11_extension/source/svc/CreateThread.c
Normal file
37
k11_extension/source/svc/CreateThread.c
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2023 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 "svc/CreateThread.h"
|
||||
|
||||
Result CreateThreadHook(Handle *outThreadHandle, u32 ep, u32 arg, u32 stackTop, s32 priority, s32 processorId)
|
||||
{
|
||||
u32 flags = flagsOfProcess(currentCoreContext->objectContext.currentProcess);
|
||||
if (isN3DS && CONFIG(REDIRECTAPPTHREADS) && processorId == 1 && (flags & 0xF00) == 0x100)
|
||||
processorId = 2;
|
||||
|
||||
return CreateThread(outThreadHandle, ep, arg, stackTop, priority, processorId);
|
||||
}
|
||||
|
@ -84,3 +84,16 @@ ControlMemoryEx:
|
||||
ldr r1, [sp, #12]
|
||||
add sp, #20
|
||||
pop {pc}
|
||||
|
||||
.global CreateThreadHookWrapper
|
||||
.type CreateThreadHookWrapper, %function
|
||||
CreateThreadHookWrapper:
|
||||
push {lr}
|
||||
sub sp, #12
|
||||
str r4, [sp, #4]
|
||||
str r0, [sp]
|
||||
add r0, sp, #8
|
||||
bl CreateThreadHook
|
||||
ldr r1, [sp, #8]
|
||||
add sp, sp, #12
|
||||
pop {pc}
|
||||
|
@ -33,6 +33,7 @@ enum singleOptions
|
||||
USEEMUFIRM,
|
||||
LOADEXTFIRMSANDMODULES,
|
||||
PATCHGAMES,
|
||||
REDIRECTAPPTHREADS,
|
||||
PATCHVERSTRING,
|
||||
SHOWGBABOOT,
|
||||
PATCHUNITINFO,
|
||||
|
@ -3,6 +3,23 @@
|
||||
#include "luma.h"
|
||||
#include "util.h"
|
||||
|
||||
u32 config, multiConfig, bootConfig;
|
||||
|
||||
void readLumaConfig(void)
|
||||
{
|
||||
s64 out = 0;
|
||||
bool isLumaWithKext = svcGetSystemInfo(&out, 0x20000, 0) == 1;
|
||||
if (isLumaWithKext)
|
||||
{
|
||||
svcGetSystemInfo(&out, 0x10000, 3);
|
||||
config = (u32)out;
|
||||
svcGetSystemInfo(&out, 0x10000, 4);
|
||||
multiConfig = (u32)out;
|
||||
svcGetSystemInfo(&out, 0x10000, 5);
|
||||
bootConfig = (u32)out;
|
||||
}
|
||||
}
|
||||
|
||||
bool hasKExt(void)
|
||||
{
|
||||
s64 val;
|
||||
|
@ -2,6 +2,42 @@
|
||||
|
||||
#include <3ds/types.h>
|
||||
|
||||
#define CONFIG(a) (((config >> (a)) & 1) != 0)
|
||||
#define MULTICONFIG(a) ((multiConfig >> (2 * (a))) & 3)
|
||||
#define BOOTCONFIG(a, b) ((bootConfig >> (a)) & (b))
|
||||
|
||||
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
|
||||
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
|
||||
#define BOOTCFG_NOFORCEFLAG BOOTCONFIG(6, 1)
|
||||
#define BOOTCFG_NTRCARDBOOT BOOTCONFIG(7, 1)
|
||||
|
||||
enum multiOptions
|
||||
{
|
||||
DEFAULTEMU = 0,
|
||||
BRIGHTNESS,
|
||||
SPLASH,
|
||||
PIN,
|
||||
NEWCPU,
|
||||
AUTOBOOTMODE,
|
||||
};
|
||||
|
||||
enum singleOptions
|
||||
{
|
||||
AUTOBOOTEMU = 0,
|
||||
USEEMUFIRM,
|
||||
LOADEXTFIRMSANDMODULES,
|
||||
PATCHGAMES,
|
||||
REDIRECTAPPTHREADS,
|
||||
PATCHVERSTRING,
|
||||
SHOWGBABOOT,
|
||||
PATCHUNITINFO,
|
||||
DISABLEARM11EXCHANDLERS,
|
||||
ENABLESAFEFIRMROSALINA,
|
||||
};
|
||||
|
||||
extern u32 config, multiConfig, bootConfig;
|
||||
|
||||
void readLumaConfig(void);
|
||||
bool hasKExt(void);
|
||||
u32 getKExtSize(void);
|
||||
u32 getStolenSystemMemRegionSize(void);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "util.h"
|
||||
#include "my_thread.h"
|
||||
#include "service_manager.h"
|
||||
#include "luma.h"
|
||||
|
||||
static MyThread processMonitorThread, taskRunnerThread;
|
||||
static u8 ALIGN(8) processDataBuffer[0x40 * sizeof(ProcessData)] = {0};
|
||||
@ -34,6 +35,7 @@ Result __sync_init(void);
|
||||
void initSystem()
|
||||
{
|
||||
__sync_init();
|
||||
readLumaConfig();
|
||||
//__libc_init_array();
|
||||
|
||||
// Wait for sm
|
||||
|
@ -308,6 +308,11 @@ Result resetAppMemLimit(void)
|
||||
|
||||
Result setAppCpuTimeLimit(s64 limit)
|
||||
{
|
||||
// Prevent apps from enabling preemption on core1 (and kernel will
|
||||
// redirect apps threads from core 1 to 2).
|
||||
if (IS_N3DS && CONFIG(REDIRECTAPPTHREADS))
|
||||
return 0;
|
||||
|
||||
ResourceLimitType category = RESLIMIT_CPUTIME;
|
||||
return svcSetResourceLimitValues(g_manager.reslimits[0], &category, &limit, 1);
|
||||
}
|
||||
|
Binary file not shown.
@ -49,6 +49,7 @@ enum singleOptions
|
||||
USEEMUFIRM,
|
||||
LOADEXTFIRMSANDMODULES,
|
||||
PATCHGAMES,
|
||||
REDIRECTAPPTHREADS,
|
||||
PATCHVERSTRING,
|
||||
SHOWGBABOOT,
|
||||
PATCHUNITINFO,
|
||||
@ -315,7 +316,8 @@ static size_t saveLumaIniConfigToStr(char *out, const CfgData *cfg)
|
||||
(int)cfg->formatVersionMajor, (int)cfg->formatVersionMinor,
|
||||
(int)CONFIG(AUTOBOOTEMU), (int)CONFIG(USEEMUFIRM),
|
||||
(int)CONFIG(LOADEXTFIRMSANDMODULES), (int)CONFIG(PATCHGAMES),
|
||||
(int)CONFIG(PATCHVERSTRING), (int)CONFIG(SHOWGBABOOT),
|
||||
(int)CONFIG(REDIRECTAPPTHREADS), (int)CONFIG(PATCHVERSTRING),
|
||||
(int)CONFIG(SHOWGBABOOT),
|
||||
|
||||
1 + (int)MULTICONFIG(DEFAULTEMU), 4 - (int)MULTICONFIG(BRIGHTNESS),
|
||||
splashPosStr, (unsigned int)cfg->splashDurationMsec,
|
||||
|
Loading…
x
Reference in New Issue
Block a user