coreinit: Fix initialization order

Threads were initialized before SDA values were available from RPL loader. Fixes crash in Skylanders Swap Force and some other games
This commit is contained in:
Exzap 2026-02-09 07:08:01 +01:00
parent 8cd5ce102f
commit 9f58f3a118
10 changed files with 65 additions and 32 deletions

View File

@ -427,10 +427,8 @@ void cemu_initForGame()
cemuLog_log(LogType::Force, "------- Run title -------");
// wait till GPU thread is initialized
while (g_isGPUInitFinished == false) std::this_thread::sleep_for(std::chrono::milliseconds(50));
// init initial thread
OSThread_t* initialThread = coreinit::OSGetDefaultThread(1);
coreinit::OSSetThreadPriority(initialThread, 16);
coreinit::OSRunThread(initialThread, PPCInterpreter_makeCallableExportDepr(coreinit_start), 0, nullptr);
// run coreinit rpl_entry
RPLLoader_CallCoreinitEntrypoint();
// init AX and start AX I/O thread
snd_core::AXOut_init();
}

View File

@ -2305,6 +2305,25 @@ void RPLLoader_CallEntrypoints()
}
}
// calls the entrypoint of coreinit and marks it as called so that RPLLoader_CallEntrypoints() wont call it again later
void RPLLoader_CallCoreinitEntrypoint()
{
// for HLE modules we need to check the dependency list
for (auto& dependency : rplDependencyList)
{
if (strcmp(dependency->modulename, "coreinit") != 0)
continue;
if (!dependency->rplHLEModule)
continue;
if (dependency->hleEntrypointCalled)
continue;
dependency->rplHLEModule->rpl_entry(dependency->coreinitHandle, coreinit::RplEntryReason::Loaded);
dependency->hleEntrypointCalled = true;
return;
}
cemu_assert_unimplemented(); // coreinit.rpl present in cafelibs? We currently do not support native coreinit and no thread context exists yet to do a PPC call
}
void RPLLoader_NotifyControlPassedToApplication()
{
rplLoader_applicationHasMemoryControl = true;
@ -2350,11 +2369,13 @@ uint32 RPLLoader_FindModuleOrHLEExport(uint32 moduleHandle, bool isData, const c
uint32 RPLLoader_GetSDA1Base()
{
cemu_assert_debug(rplModuleCount > 0); // this should not be called before the main executable was loaded
return rplLoader_sdataAddr;
}
uint32 RPLLoader_GetSDA2Base()
{
cemu_assert_debug(rplModuleCount > 0);
return rplLoader_sdata2Addr;
}

View File

@ -25,6 +25,7 @@ void RPLLoader_SetMainModule(RPLModule* rplLoaderContext);
uint32 RPLLoader_GetMainModuleHandle();
void RPLLoader_CallEntrypoints();
void RPLLoader_CallCoreinitEntrypoint();
void RPLLoader_NotifyControlPassedToApplication();
void RPLLoader_AddDependency(std::string_view name);

View File

@ -331,7 +331,7 @@ namespace coreinit
// init GHS and threads
coreinit::PrepareGHSRuntime();
coreinit::InitializeThread();
coreinit::MapThreadExports();
// reset threads
activeThreadCount = 0;
@ -353,13 +353,13 @@ namespace coreinit
coreinit::InitializeLC();
coreinit::InitializeMP();
coreinit::InitializeTimeAndCalendar();
coreinit::InitializeAlarm();
coreinit::MapAlarmExports();
coreinit::InitializeFS();
coreinit::InitializeSystemInfo();
coreinit::InitializeConcurrency();
coreinit::InitializeSpinlock();
coreinit::InitializeMessageQueue();
coreinit::InitializeIPC();
coreinit::MapIPCExports();
coreinit::InitializeIPCBuf();
coreinit::InitializeMemoryMapping();
coreinit::InitializeCodeGen();
@ -373,16 +373,20 @@ namespace coreinit
coreinit::miscInit();
osLib_addFunction("coreinit", "OSGetSharedData", coreinitExport_OSGetSharedData);
osLib_addFunction("coreinit", "UCReadSysConfig", coreinitExport_UCReadSysConfig);
// async callbacks
InitializeAsyncCallback();
};
void rpl_entry(uint32 moduleHandle, coreinit::RplEntryReason reason) override
{
if (reason == coreinit::RplEntryReason::Loaded)
{
// todo
coreinit::InitializeThread();
coreinit::InitializeAlarm();
coreinit::InitializeIPC();
InitializeAsyncCallback();
// remaining coreinit initialization happens in coreinit_start and requires a valid PPC context
OSThread_t* initialThread = coreinit::OSGetDefaultThread(1);
coreinit::OSSetThreadPriority(initialThread, 16);
coreinit::OSRunThread(initialThread, PPCInterpreter_makeCallableExportDepr(coreinit_start), 0, nullptr);
}
else if (reason == coreinit::RplEntryReason::Unloaded)
{

View File

@ -349,7 +349,7 @@ namespace coreinit
}
}
void InitializeAlarm()
void MapAlarmExports()
{
cafeExportRegister("coreinit", OSCreateAlarm, LogType::CoreinitAlarm);
cafeExportRegister("coreinit", OSCreateAlarmEx, LogType::CoreinitAlarm);
@ -358,7 +358,10 @@ namespace coreinit
cafeExportRegister("coreinit", OSSetPeriodicAlarm, LogType::CoreinitAlarm);
cafeExportRegister("coreinit", OSSetAlarmUserData, LogType::CoreinitAlarm);
cafeExportRegister("coreinit", OSGetAlarmUserData, LogType::CoreinitAlarm);
}
void InitializeAlarm()
{
// init event
OSInitEvent(g_alarmEvent.GetPtr(), OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, OSEvent::EVENT_MODE::MODE_AUTO);

View File

@ -49,5 +49,6 @@ namespace coreinit
void alarm_update();
void MapAlarmExports();
void InitializeAlarm();
}

View File

@ -445,15 +445,8 @@ namespace coreinit
return r;
}
void InitializeIPC()
void MapIPCExports()
{
for (uint32 i = 0; i < Espresso::CORE_COUNT; i++)
{
IPCDriver_InitForCore(i);
IPCDriver_InitIPCThread(i);
}
// register API
cafeExportRegister("coreinit", IOS_Open, LogType::PPC_IPC);
cafeExportRegister("coreinit", IOS_Close, LogType::PPC_IPC);
cafeExportRegister("coreinit", IOS_Ioctl, LogType::PPC_IPC);
@ -462,4 +455,13 @@ namespace coreinit
cafeExportRegister("coreinit", IOS_IoctlvAsync, LogType::PPC_IPC);
}
void InitializeIPC()
{
for (uint32 i = 0; i < Espresso::CORE_COUNT; i++)
{
IPCDriver_InitForCore(i);
IPCDriver_InitIPCThread(i);
}
}
};

View File

@ -12,5 +12,6 @@ namespace coreinit
IOS_ERROR IOS_Ioctlv(IOSDevHandle devHandle, uint32 requestId, uint32 numIn, uint32 numOut, IPCIoctlVector* vec);
IOS_ERROR IOS_IoctlvAsync(IOSDevHandle devHandle, uint32 requestId, uint32 numIn, uint32 numOut, IPCIoctlVector* vec, MEMPTR<void> asyncResultFunc, MEMPTR<void> asyncResultUserParam);
void MapIPCExports();
void InitializeIPC();
};

View File

@ -1588,7 +1588,7 @@ namespace coreinit
}
}
void InitializeThread()
void MapThreadExports()
{
cafeExportRegister("coreinit", OSCreateThreadType, LogType::CoreinitThread);
cafeExportRegister("coreinit", OSCreateThread, LogType::CoreinitThread);
@ -1632,16 +1632,16 @@ namespace coreinit
// OSThreadQueue
cafeExportRegister("coreinit", OSInitThreadQueue, LogType::CoreinitThread);
cafeExportRegister("coreinit", OSInitThreadQueueEx, LogType::CoreinitThread);
OSInitThreadQueue(g_activeThreadQueue.GetPtr());
for (sint32 i = 0; i < PPC_CORE_COUNT; i++)
OSInitThreadQueue(g_coreRunQueue.GetPtr() + i);
for (sint32 i = 0; i < PPC_CORE_COUNT; i++)
__currentCoreThread[i] = nullptr;
__OSInitDefaultThreads();
__OSInitTerminatorThreads();
}
void InitializeThread()
{
OSInitThreadQueue(g_activeThreadQueue.GetPtr());
for (sint32 i = 0; i < Espresso::CORE_COUNT; i++)
OSInitThreadQueue(g_coreRunQueue.GetPtr() + i);
for (sint32 i = 0; i < Espresso::CORE_COUNT; i++)
__currentCoreThread[i] = nullptr;
__OSInitDefaultThreads();
__OSInitTerminatorThreads();
}
}

View File

@ -503,7 +503,9 @@ static_assert(sizeof(OSThread_t) == 0x6A0);
namespace coreinit
{
void MapThreadExports();
void InitializeThread();
void InitializeConcurrency();
bool __CemuIsMulticoreMode();