diff --git a/src/engine/host_cmd.cpp b/src/engine/host_cmd.cpp index a166f652..a299aca5 100644 --- a/src/engine/host_cmd.cpp +++ b/src/engine/host_cmd.cpp @@ -8,9 +8,22 @@ #include "windows/id3dx.h" #endif // !DEDICATED -#ifndef DEDICATED static void DoNothing(){}; +static const char* const s_paksToLoad[] = +{ + // Used to store assets that must be loaded after common_early.rpak, but + // before common.rpak is being loaded. One use case is to preserve the + // fixed linked list structure for the player settings layouts, we must + // load SDK layouts before common.rpak as the Game DLL expects the linked + // list to be ordered in a specific manner that is determined by bakery. + "common_roots.rpak", +#ifndef DEDICATED + // Used to load UI assets associated with the main menu. + "ui_mainmenu.rpak" +#endif // !DEDICATED +}; + /* ================== Host_SetupUIMaterials @@ -26,19 +39,28 @@ static void Host_SetupUIMaterials() void* const oldSyncFn = g_pakGlobals->threadSyncFunc; g_pakGlobals->threadSyncFunc = DoNothing; - static const char* const pakFileName = "ui_mainmenu.rpak"; - const PakHandle_t pak = g_pakLoadApi->LoadAsync(pakFileName, AlignedMemAlloc(), 3, false); + for (size_t i = 0; i < V_ARRAYSIZE(s_paksToLoad); i++) + { + const char* const pakFileName = s_paksToLoad[i]; - // NOTE: make sure to wait for the async load, as the pak must be loaded - // before we continue processing UI materials. - if (pak == PAK_INVALID_HANDLE || !g_pakLoadApi->WaitForAsyncLoad(pak, DoNothing)) - Error(eDLL_T::ENGINE, EXIT_FAILURE, "Failed to load pak file '%s'\n", pakFileName); + // NOTE: make sure to wait for the async load request, as these paks + // must be loaded before we continue processing anything else. + const PakHandle_t pakHandle = g_pakLoadApi->LoadAsyncAndWait(pakFileName, AlignedMemAlloc(), 3, DoNothing); + + if (pakHandle == PAK_INVALID_HANDLE) + Error(eDLL_T::ENGINE, EXIT_FAILURE, "Failed to load pak file '%s'\n", pakFileName); + } g_pakGlobals->threadSyncFunc = oldSyncFn; + // For dedicated, we shouldn't continue with setting up ui materials. + // Return out here. This is the only place we can reliably load core + // paks directly after common_early.rpak and ui.rpak without having + // the engine do anything in between. +#ifndef DEDICATED v_Host_SetupUIMaterials(); -} #endif // !DEDICATED +} /* ================== @@ -114,9 +136,7 @@ static bool DFS_InitializeFeatureFlagDefinitions(const char* pszFeatureFlags) /////////////////////////////////////////////////////////////////////////////// void VHostCmd::Detour(const bool bAttach) const { -#ifndef DEDICATED DetourSetup(&v_Host_SetupUIMaterials, &Host_SetupUIMaterials, bAttach); -#endif // !DEDICATED DetourSetup(&v_Host_Shutdown, &Host_Shutdown, bAttach); DetourSetup(&v_Host_Status_PrintClient, &Host_Status_PrintClient, bAttach); DetourSetup(&v_DFS_InitializeFeatureFlagDefinitions, &DFS_InitializeFeatureFlagDefinitions, bAttach); diff --git a/src/engine/host_cmd.h b/src/engine/host_cmd.h index 011d87c5..efef3a27 100644 --- a/src/engine/host_cmd.h +++ b/src/engine/host_cmd.h @@ -22,8 +22,8 @@ inline void(*v_Host_Init)(); #ifndef DEDICATED inline void(*v_Host_Init_DuringVideo)(bool* bDedicated); inline void(*v_Host_Init_PostVideo)(bool* bDedicated); -inline void(*v_Host_SetupUIMaterials)(); #endif // !DEDICATED +inline void(*v_Host_SetupUIMaterials)(); inline void(*v_Host_Shutdown)(); inline bool(*v_Host_NewGame)(char* pszMapName, char* pszMapGroup, bool bLoadGame, char bBackground, LARGE_INTEGER PerformanceCount); inline void(*v_Host_Disconnect)(bool bShowMainMenu); @@ -44,8 +44,8 @@ class VHostCmd : public IDetour #ifndef DEDICATED LogFunAdr("Host_Init_DuringVideo", v_Host_Init_DuringVideo); LogFunAdr("Host_Init_PostVideo", v_Host_Init_PostVideo); - LogFunAdr("Host_SetupUIMaterials", v_Host_SetupUIMaterials); #endif // !DEDICATED + LogFunAdr("Host_SetupUIMaterials", v_Host_SetupUIMaterials); LogFunAdr("Host_Shutdown", v_Host_Shutdown); LogFunAdr("Host_Disconnect", v_Host_Disconnect); LogFunAdr("Host_NewGame", v_Host_NewGame); @@ -62,8 +62,8 @@ class VHostCmd : public IDetour #ifndef DEDICATED g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9").GetPtr(v_Host_Init_DuringVideo); g_GameDll.FindPatternSIMD("48 8B C4 41 56 48 81 EC ?? ?? ?? ?? 45 33 F6").GetPtr(v_Host_Init_PostVideo); - g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC ?? 48 8B 05 ?? ?? ?? ?? 48 8D 3D").GetPtr(v_Host_SetupUIMaterials); #endif // !DEDICATED + g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC ?? 48 8B 05 ?? ?? ?? ?? 48 8D 3D").GetPtr(v_Host_SetupUIMaterials); g_GameDll.FindPatternSIMD("48 8B C4 ?? 41 54 41 55 48 81 EC 70 04 ?? ?? F2 0F 10 05 ?? ?? ?? 0B").GetPtr(v_Host_NewGame); g_GameDll.FindPatternSIMD("40 53 48 83 EC 30 0F B6 D9").GetPtr(v_Host_Disconnect); g_GameDll.FindPatternSIMD("40 56 57 41 56 48 81 EC ?? ?? ?? ??").GetPtr(v_Host_ChangeLevel);