Tutorial | Fixing Character Voices in STEINS;GATE RE:BOOT on Mac with CrossOver
AIAI-assisted translation·Read the source version
Some time ago, while running the Steam edition of STEINS;GATE RE:BOOT through CrossOver 26.3.0 on an Apple Silicon Mac, I ran into a rather peculiar problem. The game started normally, and both the background music and interface sound effects worked, but the character voices were completely silent.
I eventually confirmed that the game files were not at fault. The problem lay in CrossOver’s audio-decoding chain: the character voices use Windows Media Audio 2 (WMA v2), while the current environment lacked a usable GStreamer libav decoder plugin.
This article records the solution that ultimately worked for me.
This article describes an Apple Silicon Mac running CrossOver 26.3.0 and the Steam edition of STEINS;GATE RE:BOOT. A CrossOver update may change its bundled GStreamer version, so the dynamic libraries described here should not be copied unchanged into another version.
For the voices to play through CrossOver, the data has to travel through roughly the following chain:
1 | WMA v2 voice data in the game |
CrossOver already includes Wine, the GStreamer core and macOS audio output. That is why the BGM and ordinary sound effects can still play. Their working correctly, however, does not mean every audio format can be decoded. In this case, the voice data reached the media chain, but there was no usable libgstlibav component to decode it. The failure therefore appeared only when a character began to speak.
CodeWeavers also documents the broader Missing GStreamer 1.0 libav problem. It is not unique to STEINS;GATE RE:BOOT; this game simply exposes it as missing voices while other audio remains intact.
Before testing any media components, the most important step is not downloading a library but copying the working Steam bottle. In CrossOver, right-click the bottle in which Steam currently starts normally and select Duplicate Bottle. Name the copy Steam-SGRE-Voice-Test, leave the main bottle untouched, and perform every later experiment in the copy.
I kept the known stable graphics settings—Graphics Backend set to Auto and MSync enabled. As long as the main bottle is not altered, a failed experiment will not affect the Steam installation used every day.
Do not copy files directly into:
1 | /Applications/CrossOver.app/Contents/SharedSupport/CrossOver/ |
This environment is shared by every bottle. One incompatible dynamic library can affect Steam and other bottles, and a CrossOver update may overwrite the files anyway.
I tested the native Windows 7 wmadmod.dll. It called CrossOver’s bundled mfplat.dll and crashed with a null-pointer write as soon as a character spoke. Replacing that file with the Windows 7 mfplat.dll did not help: the game then failed to start because that version lacks the newer MFLockSharedWorkQueue interface.
Media DLLs taken from different Windows versions, Wine and CrossOver are not interchangeable building blocks.
On Apple Silicon, GStreamer installed through Homebrew is normally ARM64, while the media process used by CrossOver for this Windows game is x86_64. Those architectures cannot be mixed directly.
If variables such as GST_PLUGIN_PATH are applied to Steam itself, Steam and its web components will also scan the private libav bundle. Steam may then remain stuck during startup. The decoder environment should be passed only to sgre_steam.exe.
Instead of replacing any Windows system DLL, I placed a private GStreamer libav bundle inside the test bottle and made it available only to SGRE:
1 | ~/Library/Application Support/CrossOver/Bottles/ |
The components came from the official GStreamer macOS Universal 1.24.13 runtime. I chose the 1.24 series because this CrossOver version bundles GStreamer 1.24.4, and staying within one stable series makes binary compatibility more likely. The corresponding upstream information is available in the GStreamer 1.24 release notes.
There is an important limitation. The official 1.24.13 plugin declares a minimum compatible library version at the 1.24.14 level, while CrossOver supplies 1.24.4. Simply copying the files is therefore insufficient. I adapted the plugin’s minimum compatibility version and dependency paths, then applied ad-hoc signatures to the modified dynamic libraries.
The SHA-256 values of the two critical files that worked in this environment are:
1 | libgstlibav.dylib |
I do not recommend that inexperienced users modify
.dylibfiles with a hex editor. Use components that match the CrossOver version, come from a known source and can be verified by checksum. Compatibility should be checked again after any CrossOver or GStreamer update.
Even after the files are placed inside the bottle, launching from Steam’s Play button still lets SGRE see only CrossOver’s default plugin directory. I therefore made a dedicated launcher that sets the decoder environment only when sgre_steam.exe starts:
1 | #!/bin/zsh |
If the bottle has a different name, both bottle_name and bottle_root need to be changed. To avoid opening Terminal every time, I packaged and signed the script as a normal macOS application:
1 | STEINS;GATE REBOOT Voice Fix.app |
For ordinary use, I first start Steam in the Steam-SGRE-Voice-Test bottle without clicking Play, then open the dedicated launcher. This keeps the variables limited to SGRE instead of placing all of Steam inside the private plugin environment.
The fact that the game no longer crashes is not enough. I checked that the game window opened normally, that BGM, interface sounds and ambient effects still worked, and that several consecutive spoken lines contained voices. The voices remained after loading a save or changing scenes, and the game could be closed and started again through the launcher.
The diagnostic log explicitly contained:
1 | avdec_wmav2 |
The running game process also loaded libgstlibav.dylib, libavcodec.60.dylib and the other components from the test bottle’s cx_gstreamer_libav directory. The voices had not returned by accident: the WMA v2 decoding chain was actually connected.
If the voices are still missing, check that the game was started through the dedicated launcher rather than Steam’s Play button. The bottle name in the script must exactly match the name shown in CrossOver, cx_gstreamer_libav must still be inside the test bottle, and libgstlibav.dylib must be x86_64 or Universal rather than ARM64 only.
Check whether native wmadmod.dll, mfplat.dll or other media DLLs were copied into drive_c/windows/system32. If so, stop mixing components and restore the bottle backup made before testing.
This usually means GST_PLUGIN_PATH and related variables were passed to Steam itself. Exit the test bottle, restore the normal Steam launch method, and keep those variables only in the dedicated SGRE launcher.
A CrossOver update may change its bundled GStreamer version. Do not copy the old plugin into the new shared directory. Duplicate the bottle first, then inspect the new GStreamer version and architecture before adapting the bundle again.
Because all changes are confined to the test bottle and the separate launcher, rollback is simple: stop using STEINS;GATE REBOOT Voice Fix.app, move the cx_gstreamer_libav directory out of the bottle, or restore the clean duplicated bottle. There is no need to delete the working main Steam bottle or reinstall CrossOver.
The missing voices were caused by WMA v2 character audio meeting a CrossOver media chain without a usable GStreamer libav decoder. The final method can be reduced to the following sequence:
1 | Duplicate the test bottle |
This takes more work than dropping a few DLLs into the bottle, but it keeps the entire change inside a disposable copy. The main Steam environment and CrossOver’s shared directory remain untouched.