Repository navigation
Platform shim: stop hanging games in Meta's uninitialized implementation - #20
Merged
Villagers654 merged 3 commits intoOct 24, 2026
Conversation
The shim answers initialization locally, so Meta's real implementation never gets a context. Its context-bound calls throw "Context::Get: Called before context was initialized." without one, yet the shim still forwarded every empty ovr_PopMessage poll (and the user check in ovr_AssetFile_GetList) to it. The Lone Echo II trailer crashed there right after sign-in, and its crash reporter then hung, which looked like a stall before the first frame. Ask Meta's own ovr_IsPlatformInitialized, which only reads the context, before forwarding those calls. The trailer also unlocks an achievement at startup and waits for the reply before rendering. Answer ovr_Achievements_Unlock locally in offline mode, like the achievement definitions and progress already are.
Older Unity Platform SDKs, such as the one in Blocks, initialize through ovr_UnityInitWrapperWindows, which the shim forwarded to Meta's implementation. That waits for an Oculus service that never answers under Wine, so the game hung on its main thread before its first frame, with a black window and nothing in the headset. The shim now answers ovr_UnityInitWrapperWindows and the Unity initializer it calls, ovr_PlatformInitializeUnityWindows, like the Windows, Unreal and asynchronous Unity ones. Meta's wrapper always reports true, and so does the shim's.
In offline mode ovr_Achievements_Unlock is answered with a local message. A game that reads the result through ovr_Message_GetAchievementUpdate and the ovr_AchievementUpdate getters handed that message to Meta's implementation, which treats it as one of its own: an access violation in a harness against Meta's DLL. The shim now answers those getters for its own messages, with the update just unlocked under the requested name.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
The platform shim answers initialization, login and entitlement itself, so Meta's real implementation
(
LibOVRPlatformImpl64_1_real.dll) is never started. Everything the shim doesn't answer is forwarded to it. Three gapslet games run into that unstarted implementation, which then either throws or waits for an Oculus service that never
answers under Wine.
Empty message polls crashed the game. When the shim had no message of its own,
ovr_PopMessageforwarded the pollto Meta's implementation. Without its context that throws
Context::Get: Called before context was initialized.onevery poll (101 C++ exceptions in 100 empty polls, measured against Meta's DLL). The Lone Echo II Trailer Experience
crashed there right after sign-in, and its crash reporter then hung, which looked like a stall before the first frame.
The user check in
ovr_AssetFile_GetListraised the same exception. Both now ask Meta's ownovr_IsPlatformInitialized, which only reads the context, before forwarding.An achievement unlock nobody answered. The trailer unlocks an achievement at startup and waits for the reply before
rendering. Forwarded, Meta's implementation returns request 0 and never replies. In offline mode
ovr_Achievements_Unlockis now answered locally, like the achievement definitions and progress already are. Itsupdate getters (
ovr_Message_GetAchievementUpdate,ovr_AchievementUpdate_GetJustUnlocked,ovr_AchievementUpdate_GetName) answer for that local reply too; handed to Meta's DLL, it caused an access violation.Older Unity games hung on a black screen under Proton. Older Unity Platform SDKs, such as the one in Blocks,
initialize through
ovr_UnityInitWrapperWindows. The shim forwarded it, so Meta's implementation started its onlineservices (OAF, MQTT), and under Proton Blocks' main thread then waited inside it forever. On Windows, Meta's
implementation returns there, and Blocks renders with main's shim too. The shim now answers it and the Unity initializer
it calls,
ovr_PlatformInitializeUnityWindows, like the Windows, Unreal and asynchronous Unity ones (upstream answersovr_UnityInitWrapperWindowsAsynchronoussince 10855ee). Meta's wrapper always reports true, and so does the shim's.How it was found
Backtraces of the stalled games (
winedbg bt allin the game's prefix):ovr_PopMessageof Meta's implementation, raising the C++ exception; after that fix, themain thread looped on
ovr_PopMessagewaiting for the reply toovr_Achievements_Unlock(message type0x593CCBDD).ovr_UnityInitWrapperWindows.Testing
On 0.11.1.2
The synchronous Unity initializers sit beside upstream's asynchronous ones; the build script's export list and its
initializer check cover all six.
compat/tests(built with MinGW, run under Wine) pass on the ported branch. Upstream's shim and its own test,with only the stub's
ovr_PopMessagethrowing without a context as Meta's DLL does, die with the unhandled C++exception (0xE06D7363) on the first empty poll.
ovr_UnityInitWrapperWindows,ovr_PlatformInitializeUnityWindows,ovr_Achievements_Unlockand the achievement update getters) alongsideupstream's asynchronous ones.
stays black.
ovr_UnityInitWrapperWindowson Windows, and Blocks goes onto the entitlement check.
success", "initialize unity windows: success" in its log). The headset view changes between captures 10 s apart
with both builds.
headset; Quest 3 on WiVRn and through Steam Link into SteamVR):
renders too (WiVRn 7,468 frames, SteamVR 7,677).
through SteamVR.
Wine's exception log on, main's shim causes 2,414 C++ exceptions (
0xE06D7363) in 60 s; Lone Echo catchesthem and carries on, where the trailer hangs.
the same on both. Login, entitlement and the org-scoped ID are answered locally. On the Quest 3 through SteamVR
it was played by hand with the controllers.
Earlier, on 7289ef6
compat/tests: new cases for polling before Meta's implementation is started, the asset list check, achievementunlocks in both modes, and all four initializers. Main's shim fails the polling test with the same unhandled C++
exception the game hit.
-Werror; its export list is identical to the release shim's (1266 names).ovr_AssetFile_GetList: one exception from the user check, against none.name after.
ovr_UnityInitWrapperWindows: Meta's online services start, against a local answer.WiVRn and SteamVR (Steam Link). Controls were checked by hand on an earlier run with the same code.