diff --git a/sysmodules/loader/source/hbldr.h b/sysmodules/loader/source/hbldr.h index 34e22c4..4da0c12 100644 --- a/sysmodules/loader/source/hbldr.h +++ b/sysmodules/loader/source/hbldr.h @@ -2,8 +2,6 @@ #include <3ds/exheader.h> -#define HBLDR_3DSX_TID (*(vu64 *)0x1FF81100) - Result hbldrInit(void); void hbldrExit(void); diff --git a/sysmodules/loader/source/loader.c b/sysmodules/loader/source/loader.c index d9f1dfc..d0d8a28 100644 --- a/sysmodules/loader/source/loader.c +++ b/sysmodules/loader/source/loader.c @@ -4,6 +4,7 @@ #include "ifile.h" #include "util.h" #include "hbldr.h" +#include "luma_shared_config.h" extern u32 config, multiConfig, bootConfig; extern bool isN3DS, isSdMode; @@ -91,6 +92,11 @@ static int lzss_decompress(u8 *end) return ret; } +static inline bool hbldrIs3dsxTitle(u64 tid) +{ + return Luma_SharedConfig->use_hbldr && tid == Luma_SharedConfig->hbldr_3dsx_tid; +} + static Result allocateSharedMem(prog_addrs_t *shared, prog_addrs_t *vaddr, int flags) { u32 dummy; @@ -169,11 +175,8 @@ static Result GetProgramInfo(ExHeader_Info *exheaderInfo, u64 programHandle) } } - s64 nbSection0Modules; - svcGetSystemInfo(&nbSection0Modules, 26, 0); - // Tweak 3dsx placeholder title exheaderInfo - if (nbSection0Modules == 6 && exheaderInfo->aci.local_caps.title_id == HBLDR_3DSX_TID) + if (hbldrIs3dsxTitle(exheaderInfo->aci.local_caps.title_id)) { assertSuccess(hbldrInit()); HBLDR_PatchExHeaderInfo(exheaderInfo); @@ -204,7 +207,7 @@ static Result LoadProcess(Handle *process, u64 programHandle) u64 titleId; // make sure the cached info corrosponds to the current programHandle - if (g_cached_programHandle != programHandle || g_exheaderInfo.aci.local_caps.title_id == HBLDR_3DSX_TID) + if (g_cached_programHandle != programHandle || hbldrIs3dsxTitle(g_exheaderInfo.aci.local_caps.title_id)) { res = GetProgramInfo(&g_exheaderInfo, programHandle); g_cached_programHandle = programHandle; @@ -230,7 +233,7 @@ static Result LoadProcess(Handle *process, u64 programHandle) titleId = g_exheaderInfo.aci.local_caps.title_id; ExHeader_CodeSetInfo *csi = &g_exheaderInfo.sci.codeset_info; - if (titleId == HBLDR_3DSX_TID) + if (hbldrIs3dsxTitle(titleId)) { assertSuccess(hbldrInit()); assertSuccess(HBLDR_LoadProcess(&codeset, csi->text.address, flags & 0xF00, titleId, csi->name)); @@ -377,7 +380,7 @@ void loaderHandleCommands(void *ctx) break; case 4: // GetProgramInfo memcpy(&programHandle, &cmdbuf[1], 8); - if (programHandle != g_cached_programHandle || g_exheaderInfo.aci.local_caps.title_id == HBLDR_3DSX_TID) + if (programHandle != g_cached_programHandle || hbldrIs3dsxTitle(g_exheaderInfo.aci.local_caps.title_id)) { res = GetProgramInfo(&g_exheaderInfo, programHandle); g_cached_programHandle = R_SUCCEEDED(res) ? programHandle : 0; diff --git a/sysmodules/loader/source/luma_shared_config.h b/sysmodules/loader/source/luma_shared_config.h new file mode 100644 index 0000000..f956a83 --- /dev/null +++ b/sysmodules/loader/source/luma_shared_config.h @@ -0,0 +1,28 @@ +/* This paricular file is licensed under the following terms: */ + +/* +* This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable +* for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it +* and redistribute it freely, subject to the following restrictions: +* +* The origin of this software must not be misrepresented; you must not claim that you wrote the original software. +* If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +* +* Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +* This notice may not be removed or altered from any source distribution. +*/ + +#pragma once + +#include <3ds/types.h> + +/// Luma shared config type. +typedef struct LumaSharedConfig { + u64 hbldr_3dsx_tid; ///< Title ID to use for 3DSX loading. + bool use_hbldr; ///< Whether or not Loader should use hb:ldr (Rosalina writes 1). +} LumaSharedConfig; + +/// Luma shared config. +#define Luma_SharedConfig ((volatile LumaSharedConfig *)(OS_SHAREDCFG_VADDR + 0x800)) diff --git a/sysmodules/rosalina/include/hbloader.h b/sysmodules/rosalina/include/hbloader.h index a6fb94d..b2fbcca 100644 --- a/sysmodules/rosalina/include/hbloader.h +++ b/sysmodules/rosalina/include/hbloader.h @@ -31,7 +31,6 @@ #include "MyThread.h" #define HBLDR_DEFAULT_3DSX_TID 0x000400000D921E00ULL -#define HBLDR_3DSX_TID (*(vu64 *)0x1FF81100) void HBLDR_RestartHbApplication(void *p); void HBLDR_HandleCommands(void *ctx); diff --git a/sysmodules/rosalina/include/luma_shared_config.h b/sysmodules/rosalina/include/luma_shared_config.h new file mode 100644 index 0000000..b63c433 --- /dev/null +++ b/sysmodules/rosalina/include/luma_shared_config.h @@ -0,0 +1,30 @@ +/* This paricular file is licensed under the following terms: */ + +/* +* This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable +* for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it +* and redistribute it freely, subject to the following restrictions: +* +* The origin of this software must not be misrepresented; you must not claim that you wrote the original software. +* If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +* +* Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +* This notice may not be removed or altered from any source distribution. +*/ + +#pragma once + +#include <3ds/types.h> + +#include <3ds/types.h> + +/// Luma shared config type. +typedef struct LumaSharedConfig { + u64 hbldr_3dsx_tid; ///< Title ID to use for 3DSX loading. + bool use_hbldr; ///< Whether or not Loader should use hb:ldr (Rosalina writes 1). +} LumaSharedConfig; + +/// Luma shared config. +#define Luma_SharedConfig ((volatile LumaSharedConfig *)(OS_SHAREDCFG_VADDR + 0x800)) diff --git a/sysmodules/rosalina/include/minisoc.h b/sysmodules/rosalina/include/minisoc.h index 9a97878..6040bc8 100644 --- a/sysmodules/rosalina/include/minisoc.h +++ b/sysmodules/rosalina/include/minisoc.h @@ -17,8 +17,6 @@ #define _REENT_ONLY #include -#define ROSALINA_PREVENT_DISCONNECT (*(volatile bool*)0x1FF81108) - #define SYNC_ERROR ENODEV extern bool miniSocEnabled; diff --git a/sysmodules/rosalina/include/utils.h b/sysmodules/rosalina/include/utils.h index 8c1a6a1..6155308 100644 --- a/sysmodules/rosalina/include/utils.h +++ b/sysmodules/rosalina/include/utils.h @@ -30,6 +30,7 @@ #include <3ds/srv.h> #include <3ds/result.h> #include "csvc.h" +#include "luma_shared_config.h" // For accessing physmem uncached (and directly) #define PA_PTR(addr) (void *)((u32)(addr) | 1 << 31) diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c index d0c3e7b..390f09d 100644 --- a/sysmodules/rosalina/source/main.c +++ b/sysmodules/rosalina/source/main.c @@ -82,13 +82,15 @@ void initSystem(void) isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0; svcGetSystemInfo(&out, 0x10000, 0x100); - HBLDR_3DSX_TID = out == 0 ? HBLDR_DEFAULT_3DSX_TID : (u64)out; + Luma_SharedConfig->hbldr_3dsx_tid = out == 0 ? HBLDR_DEFAULT_3DSX_TID : (u64)out; + Luma_SharedConfig->use_hbldr = true; svcGetSystemInfo(&out, 0x10000, 0x101); menuCombo = out == 0 ? DEFAULT_MENU_COMBO : (u32)out; - miscellaneousMenu.items[0].title = HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID ? "Switch the hb. title to the current app." : - "Switch the hb. title to hblauncher_loader"; + miscellaneousMenu.items[0].title = Luma_SharedConfig->hbldr_3dsx_tid == HBLDR_DEFAULT_3DSX_TID ? + "Switch the hb. title to the current app." : + "Switch the hb. title to hblauncher_loader"; for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL)) { @@ -141,7 +143,7 @@ static void handleSleepNotification(u32 notificationId) { case PTMNOTIFID_SLEEP_REQUESTED: menuShouldExit = true; - PTMSYSM_ReplyToSleepQuery(ROSALINA_PREVENT_DISCONNECT); // deny sleep request if we have network stuff running + PTMSYSM_ReplyToSleepQuery(miniSocEnabled); // deny sleep request if we have network stuff running break; case PTMNOTIFID_GOING_TO_SLEEP: case PTMNOTIFID_SLEEP_ALLOWED: diff --git a/sysmodules/rosalina/source/menus/miscellaneous.c b/sysmodules/rosalina/source/menus/miscellaneous.c index 809275b..64f9882 100644 --- a/sysmodules/rosalina/source/menus/miscellaneous.c +++ b/sysmodules/rosalina/source/menus/miscellaneous.c @@ -54,7 +54,7 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void) Result res; char failureReason[64]; - if(HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID) + if(Luma_SharedConfig->hbldr_3dsx_tid == HBLDR_DEFAULT_3DSX_TID) { FS_ProgramInfo progInfo; u32 pid; @@ -62,7 +62,7 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void) res = PMDBG_GetCurrentAppInfo(&progInfo, &pid, &launchFlags); if(R_SUCCEEDED(res)) { - HBLDR_3DSX_TID = progInfo.programId; + Luma_SharedConfig->hbldr_3dsx_tid = progInfo.programId; miscellaneousMenu.items[0].title = "Switch the hb. title to hblauncher_loader"; } else @@ -74,7 +74,7 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void) else { res = 0; - HBLDR_3DSX_TID = HBLDR_DEFAULT_3DSX_TID; + Luma_SharedConfig->hbldr_3dsx_tid = HBLDR_DEFAULT_3DSX_TID; miscellaneousMenu.items[0].title = "Switch the hb. title to the current app."; } @@ -202,7 +202,7 @@ void MiscellaneousMenu_SaveSettings(void) configData.config = config; configData.multiConfig = multiConfig; configData.bootConfig = bootConfig; - configData.hbldr3dsxTitleId = HBLDR_3DSX_TID; + configData.hbldr3dsxTitleId = Luma_SharedConfig->hbldr_3dsx_tid; configData.rosalinaMenuCombo = menuCombo; FS_ArchiveID archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW; diff --git a/sysmodules/rosalina/source/minisoc.c b/sysmodules/rosalina/source/minisoc.c index 2cf5c68..4d698be 100644 --- a/sysmodules/rosalina/source/minisoc.c +++ b/sysmodules/rosalina/source/minisoc.c @@ -7,12 +7,9 @@ #include "minisoc.h" #include -#include <3ds/ipc.h> -#include <3ds/os.h> -#include <3ds/synchronization.h> -#include <3ds/result.h> +#include <3ds.h> #include -#include "csvc.h" +#include "utils.h" s32 miniSocRefCount = 0; static u32 socContextAddr = 0x08000000; @@ -24,6 +21,22 @@ bool miniSocEnabled = false; s32 _net_convert_error(s32 sock_retval); +// To prevent ndm:u from disconnecting us +static Result srvExtAddToNdmuWorkaroundCount(s32 count) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1000,1,0); + cmdbuf[1] = (u32)count; + + ret = svcSendSyncRequest(*srvGetSessionHandle()); + if(ret != 0) + return ret; + + return cmdbuf[1]; +} + static Result SOCU_Initialize(Handle memhandle, u32 memsize) { Result ret = 0; @@ -91,7 +104,8 @@ Result miniSocInit(void) svcKernelSetState(0x10000, 2); miniSocEnabled = true; - ROSALINA_PREVENT_DISCONNECT = true; + srvExtAddToNdmuWorkaroundCount(1); + return 0; cleanup: @@ -133,9 +147,9 @@ Result miniSocExitDirect(void) svcControlMemory(&tmp, socContextAddr, socContextAddr, socContextSize, MEMOP_FREE, MEMPERM_DONTCARE); if(ret == 0) { - svcKernelSetState(0x10000, 2); miniSocEnabled = false; - ROSALINA_PREVENT_DISCONNECT = false; + srvExtAddToNdmuWorkaroundCount(-1); + svcKernelSetState(0x10000, 2); } return ret; } diff --git a/sysmodules/sm/source/notifications.c b/sysmodules/sm/source/notifications.c index a9128c6..ce8e015 100644 --- a/sysmodules/sm/source/notifications.c +++ b/sysmodules/sm/source/notifications.c @@ -8,8 +8,9 @@ This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for #include "notifications.h" #include "processes.h" -// 0 by default -#define ROSALINA_PREVENT_DISCONNECT (*(volatile bool*)0x1FF81108) +#include + +static atomic_int ndmuWorkaroundCount; static bool isNotificationInhibited(const ProcessData *processData, u32 notificationId) { @@ -19,7 +20,7 @@ static bool isNotificationInhibited(const ProcessData *processData, u32 notifica // Shell opened, shell closed case 0x213: case 0x214: - return pid == ndmuServicePid && ROSALINA_PREVENT_DISCONNECT; + return pid == ndmuServicePid && atomic_load(&ndmuWorkaroundCount) > 0; default: return false; } @@ -206,3 +207,10 @@ Result PublishToAll(u32 notificationId) return 0; } + +Result AddToNdmuWorkaroundCount(s32 count) +{ + // Note: no check is made to (current value)+count + atomic_fetch_add(&ndmuWorkaroundCount, count); + return 0; +} diff --git a/sysmodules/sm/source/notifications.h b/sysmodules/sm/source/notifications.h index 42b640f..40855e7 100644 --- a/sysmodules/sm/source/notifications.h +++ b/sysmodules/sm/source/notifications.h @@ -17,3 +17,5 @@ Result PublishToSubscriber(u32 notificationId, u32 flags); Result PublishAndGetSubscriber(u32 *pidCount, u32 *pidList, u32 notificationId, u32 flags); Result PublishToProcess(Handle process, u32 notificationId); Result PublishToAll(u32 notificationId); + +Result AddToNdmuWorkaroundCount(s32 count); diff --git a/sysmodules/sm/source/srv.c b/sysmodules/sm/source/srv.c index 5afb505..a27a6fa 100644 --- a/sysmodules/sm/source/srv.c +++ b/sysmodules/sm/source/srv.c @@ -167,6 +167,14 @@ Result srvHandleCommands(SessionData *sessionData) break; } + case 0x1000: // Custom command: AddToNdmuWorkaroundCount + { + res = AddToNdmuWorkaroundCount((s32)cmdbuf[1]); + cmdbuf[0] = IPC_MakeHeader(0x1000, 1, 0);; + cmdbuf[1] = (u32)res; + break; + } + default: goto invalid_command; break;