diff --git a/sysmodules/rosalina/include/plugin/3gx.h b/sysmodules/rosalina/include/plugin/3gx.h index 570bc227..738fa8a6 100644 --- a/sysmodules/rosalina/include/plugin/3gx.h +++ b/sysmodules/rosalina/include/plugin/3gx.h @@ -20,7 +20,10 @@ typedef struct CTR_PACKED u32 embeddedExeLoadFunc : 1; u32 embeddedSwapSaveLoadFunc : 1; u32 memoryRegionSize : 2; - u32 unused : 28; + u32 compatibility : 2; + u32 eventsSelfManaged : 1; + u32 swapNotNeeded : 1; + u32 unused : 24; }; }; u32 exeLoadChecksum; @@ -67,6 +70,12 @@ typedef struct CTR_PACKED } _3gx_Header; +enum _3gx_Compatibility { + PLG_COMPAT_CONSOLE = 0, + PLG_COMPAT_EMULATOR = 1, + PLG_COMPAT_CONSOLE_EMULATOR = 2, +}; + Result Check_3gx_Magic(IFile *file); Result Read_3gx_Header(IFile *file, _3gx_Header *header); Result Read_3gx_ParseHeader(IFile *file, _3gx_Header *header); diff --git a/sysmodules/rosalina/include/plugin/plgloader.h b/sysmodules/rosalina/include/plugin/plgloader.h index ff5a2c8f..2f0b95fd 100644 --- a/sysmodules/rosalina/include/plugin/plgloader.h +++ b/sysmodules/rosalina/include/plugin/plgloader.h @@ -91,6 +91,8 @@ typedef struct u8 pluginMemoryStrategy; u32 exeLoadChecksum; u32 swapLoadChecksum; + + bool eventsSelfManaged; } PluginLoaderContext; extern PluginLoaderContext PluginLoaderCtx; diff --git a/sysmodules/rosalina/source/plugin/file_loader.c b/sysmodules/rosalina/source/plugin/file_loader.c index 6d38dcfe..a96dd54c 100644 --- a/sysmodules/rosalina/source/plugin/file_loader.c +++ b/sysmodules/rosalina/source/plugin/file_loader.c @@ -205,6 +205,19 @@ bool TryToLoadPlugin(Handle process) if (!res && R_FAILED((res = Read_3gx_Header(&plugin, &fileHeader)))) ctx->error.message = "Couldn't read file"; + // Check compatibility + if (!res && fileHeader.infos.compatibility == PLG_COMPAT_EMULATOR) { + ctx->error.message = "Plugin is only compatible with emulators"; + return false; + } + + // Flags + if (!res) { + ctx->eventsSelfManaged = fileHeader.infos.eventsSelfManaged; + if (ctx->pluginMemoryStrategy == PLG_STRATEGY_SWAP && fileHeader.infos.swapNotNeeded) + ctx->pluginMemoryStrategy = PLG_STRATEGY_NONE; + } + // Set memory region size according to header if (!res && R_FAILED((res = MemoryBlock__SetSize(memRegionSizes[fileHeader.infos.memoryRegionSize])))) { ctx->error.message = "Couldn't set memblock size."; diff --git a/sysmodules/rosalina/source/plugin/plgloader.c b/sysmodules/rosalina/source/plugin/plgloader.c index 52751f79..9056ec6b 100644 --- a/sysmodules/rosalina/source/plugin/plgloader.c +++ b/sysmodules/rosalina/source/plugin/plgloader.c @@ -449,7 +449,7 @@ static void __strex__(s32 *addr, s32 val) void PLG__NotifyEvent(PLG_Event event, bool signal) { - if (!PluginLoaderCtx.plgEventPA) return; + if (PluginLoaderCtx.eventsSelfManaged || !PluginLoaderCtx.plgEventPA) return; __strex__(PluginLoaderCtx.plgEventPA, event); if (signal) @@ -458,6 +458,7 @@ void PLG__NotifyEvent(PLG_Event event, bool signal) void PLG__WaitForReply(void) { + if (PluginLoaderCtx.eventsSelfManaged) return; __strex__(PluginLoaderCtx.plgReplyPA, PLG_WAIT); svcArbitrateAddress(PluginLoaderCtx.arbiter, (u32)PluginLoaderCtx.plgReplyPA, ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT, PLG_OK, 10000000000ULL); } @@ -482,8 +483,8 @@ static void WaitForProcessTerminated(void *arg) (void)arg; PluginLoaderContext *ctx = &PluginLoaderCtx; - // Wait until all threads of the process have finished (svcWaitSynchronization == 0) or 5 seconds have passed. - for (u32 i = 0; svcWaitSynchronization(ctx->target, 0) != 0 && i < 100; i++) svcSleepThread(50000000); // 50ms + // Wait until all threads of the process have finished (svcWaitSynchronization == 0) or 2.5 seconds have passed. + for (u32 i = 0; svcWaitSynchronization(ctx->target, 0) != 0 && i < 50; i++) svcSleepThread(50000000); // 50ms // Unmap plugin's memory before closing the process if (!ctx->pluginIsSwapped) { @@ -500,6 +501,7 @@ static void WaitForProcessTerminated(void *arg) ctx->isExeLoadFunctionset = false; ctx->isSwapFunctionset = false; ctx->pluginMemoryStrategy = PLG_STRATEGY_SWAP; + ctx->eventsSelfManaged = false; g_blockMenuOpen = 0; MemoryBlock__ResetSwapSettings(); //if (!ctx->userLoadParameters.noIRPatch)