A compatibility shim that lets an older Goldberg Steam Emulator libsteam_api.dylib work with games built against a newer Steamworks SDK (1.58 or later) on macOS.
Goldberg isn't bundled. Grab a macOS build yourself (for example from the inflation/goldberg_emulator releases) and drop its libsteam_api.dylib into place. The shim wraps that dylib: it keeps every symbol Goldberg already provides and only fills in the newer entry points that recent games look for.
Why you'd want Goldberg at all: if the game isn't on your Steam account (e.g. a pirated copy) and you launch it without an emulator, Steam refuses to start it with a license error. Goldberg stands in for the Steam client so the game starts; this shim just keeps an old Goldberg build working with newer games.
Games using a recent steam_api / Steamworks.NET fail on an old Goldberg build, first with:
System.EntryPointNotFoundException: Unable to find an entry point named
'SteamInternal_SteamAPI_Init' in shared library 'steam_api'.
and then, once that's resolved, a silent init failure (Everest/Celeste logs Steam not found! and quits).
Two SDK changes that old Goldberg builds predate cause this:
SteamInternal_SteamAPI_Init, the flat init entry point added in SDK 1.58. Old Goldberg never exported it.ISteamTimeline(STEAMTIMELINE_INTERFACE_V001, added in 2024). Wrappers like Steamworks.NET'sCSteamAPIContext.Init()fetch every interface and abort if any returnsNULL. Old Goldberg doesn't implement Timeline, so init failed even though the game never touches it.
- Adds
SteamInternal_SteamAPI_Initand forwards it to Goldberg's legacySteamAPI_Init(). - Returns a no-op object from
SteamInternal_FindOrCreateUserInterfacefor any interface Goldberg returnsNULLfor, so all-or-nothing init succeeds. - Reads the AppID from the sibling
steam_appid.txton load, which fixes launches from Finder (working directory is/). - Re-exports everything else from your Goldberg dylib unchanged.
- macOS with the Xcode command line tools (
clang,nm,codesign,install_name_tool). - An existing Goldberg
libsteam_api.dylibalready placed where the game loads it. This tool does not provide one.
# point it at the folder containing your Goldberg libsteam_api.dylib
./install.sh /path/to/game/libdirThe installer backs up your original to libsteam_api.goldberg-orig.dylib, builds a universal (x86_64 + arm64) shim, installs it as libsteam_api.dylib, ad-hoc signs it, and clears the quarantine flag. Re-running is safe.
Goldberg needs the game's Steam AppID. The shim reads it from a steam_appid.txt file (one line, just the number) next to libsteam_api.dylib, and sets the SteamAppId/SteamGameId environment variables from it so launches from Finder work. The AppID is in the game's Steam store URL, e.g. store.steampowered.com/app/504230/ means 504230. You can also set SteamAppId in the environment yourself instead.
steam_appid.txt for Celeste is just:
504230
- The shim only re-exports the architectures your Goldberg dylib actually contains. If the game runs as x86_64 under Rosetta, the dylib needs an x86_64 slice; check with
lipo -archs libsteam_api.dylib. - Goldberg's own configuration (save location, achievements, DLC, unlocks) lives in a
steam_settingsfolder next to the dylib. The shim leaves all of that alone; see the Goldberg docs to set it up. - If a game uses a hardened runtime with library validation it may reject an ad-hoc signed dylib. The games this was tested with load it fine, but that's a possible failure mode elsewhere.
To revert:
cd /path/to/game/libdir
cp libsteam_api.goldberg-orig.dylib libsteam_api.dylib
codesign -s - -f libsteam_api.dylibThe shim is one C file linked with -reexport_library against your renamed Goldberg dylib, so the final libsteam_api.dylib exports the shim's overrides plus every original Goldberg symbol. See src/shim.c and install.sh.
- Verified with Celeste + Everest. Other games may request additional newer entry points; the same approach extends to them.
- The Timeline stub is a no-op, which is fine for games that don't use Steam Timeline. A game that actually calls into an unimplemented interface would need a real implementation.
- This is an interoperability and game-preservation tool, meant for things like LAN/offline play and testing without the Steam client. Only use it with software you're entitled to run, and follow the rules that apply to you.
Builds on the Goldberg Steam Emulator (LGPL-3.0) and its forks. Goldberg is not included here; supply your own dylib.
The shim source is MIT licensed (see LICENSE). It dynamically links and re-exports Goldberg at install time rather than bundling it, so it's a separate work; redistributing a Goldberg binary is still subject to Goldberg's own license.