diff --git a/sysmodules/loader/source/loader.c b/sysmodules/loader/source/loader.c index 3455dc22..3e9f3cbb 100644 --- a/sysmodules/loader/source/loader.c +++ b/sysmodules/loader/source/loader.c @@ -272,7 +272,7 @@ Result PLGLDR__IsPluginLoaderEnabled(bool *isEnabled) } // Try to load a plugin for the game -static Result PLGLDR_LoadPlugin(u32 processID) +static Result PLGLDR_LoadPlugin(u32 processID, bool isHomebrew) { // Special case handling: games rebooting the 3DS on old models if (!isN3DS && g_exheaderInfo.aci.local_caps.core_info.o3ds_system_mode > 0) @@ -288,8 +288,9 @@ static Result PLGLDR_LoadPlugin(u32 processID) u32* cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(1, 1, 0); + cmdbuf[0] = IPC_MakeHeader(1, 2, 0); cmdbuf[1] = processID; + cmdbuf[2] = isHomebrew; return svcSendSyncRequest(plgldrHandle); } @@ -452,12 +453,12 @@ static Result LoadProcessImpl(Handle *outProcessHandle, const ExHeader_Info *exh res = R_SUCCEEDED(res) ? 0 : res; // check for plugin - if (!res && !isHomebrew && ((u32)((titleId >> 0x20) & 0xFFFFFFEDULL) == 0x00040000)) + if (!res && ((u32)((titleId >> 0x20) & 0xFFFFFFEDULL) == 0x00040000)) { u32 processID; assertSuccess(svcGetProcessId(&processID, *outProcessHandle)); assertSuccess(plgldrInit()); - assertSuccess(PLGLDR_LoadPlugin(processID)); + assertSuccess(PLGLDR_LoadPlugin(processID, isHomebrew)); plgldrExit(); } } diff --git a/sysmodules/rosalina/include/plugin/3gx.h b/sysmodules/rosalina/include/plugin/3gx.h index d1403095..068610c5 100644 --- a/sysmodules/rosalina/include/plugin/3gx.h +++ b/sysmodules/rosalina/include/plugin/3gx.h @@ -24,7 +24,8 @@ typedef struct CTR_PACKED u32 eventsSelfManaged : 1; u32 swapNotNeeded : 1; u32 usePrivateMemory : 1; - u32 unused : 23; + u32 allowHomebrewLoad : 1; + u32 unused : 22; }; }; u32 exeLoadChecksum; diff --git a/sysmodules/rosalina/include/plugin/plgloader.h b/sysmodules/rosalina/include/plugin/plgloader.h index 7178bf13..4b2941a8 100644 --- a/sysmodules/rosalina/include/plugin/plgloader.h +++ b/sysmodules/rosalina/include/plugin/plgloader.h @@ -34,7 +34,7 @@ u32 saveSwapFunc(void* startAddr, void* endAddr, void* args); u32 loadSwapFunc(void* startAddr, void* endAddr, void* args); u32 loadExeFunc(void* startAddr, void* endAddr, void* args); -bool TryToLoadPlugin(Handle process); +bool TryToLoadPlugin(Handle process, bool isHomebrew); void PLG__NotifyEvent(PLG_Event event, bool signal); void PLG__SetConfigMemoryStatus(u32 status); u32 PLG__GetConfigMemoryStatus(void); diff --git a/sysmodules/rosalina/source/plugin/file_loader.c b/sysmodules/rosalina/source/plugin/file_loader.c index 6bea9bda..0e2a3499 100644 --- a/sysmodules/rosalina/source/plugin/file_loader.c +++ b/sysmodules/rosalina/source/plugin/file_loader.c @@ -142,7 +142,7 @@ static Result CheckPluginCompatibility(_3gx_Header *header, u32 processTitle) return -1; } -bool TryToLoadPlugin(Handle process) +bool TryToLoadPlugin(Handle process, bool isHomebrew) { u64 tid; u64 fileSize; @@ -208,7 +208,14 @@ bool TryToLoadPlugin(Handle process) // Check compatibility if (!res && fileHeader.infos.compatibility == PLG_COMPAT_EMULATOR) { ctx->error.message = "Plugin is only compatible with emulators"; - return false; + res = -1; + } + + // Check if plugin can load on homebrew + if (!res && (isHomebrew && !fileHeader.infos.allowHomebrewLoad)) { + // Do not display message as this is a common case + ctx->error.message = NULL; + res = -1; } // Flags diff --git a/sysmodules/rosalina/source/plugin/plgloader.c b/sysmodules/rosalina/source/plugin/plgloader.c index f3aea991..c1b3be1b 100644 --- a/sysmodules/rosalina/source/plugin/plgloader.c +++ b/sysmodules/rosalina/source/plugin/plgloader.c @@ -151,7 +151,7 @@ void PluginLoader__HandleCommands(void *_ctx) { case 1: // Load plugin { - if (cmdbuf[0] != IPC_MakeHeader(1, 1, 0)) + if (cmdbuf[0] != IPC_MakeHeader(1, 2, 0)) { error(cmdbuf, 0xD9001830); break; @@ -164,7 +164,7 @@ void PluginLoader__HandleCommands(void *_ctx) TaskRunner_RunTask(j_PluginLoader__SetMode3AppMode, NULL, 0); bool flash = !(ctx->useUserLoadParameters && ctx->userLoadParameters.noFlash); - if (ctx->isEnabled && TryToLoadPlugin(ctx->target)) + if (ctx->isEnabled && TryToLoadPlugin(ctx->target, cmdbuf[2])) { if (flash) {