A script that rebuilds a legacy Adobe AIR game you already own so it runs on modern macOS (Apple Silicon and Intel).
This ships no game content and no Adobe/Wipro code. It only transforms files already on your machine. You supply your own legally purchased copy.
Tested with Detective Grimoire (SFB Games, 2014). It may work with other Adobe AIR apps, but that is untested. Nothing is hardcoded, since the script reads the app's own descriptor for its identity and content, so other AIR desktop titles of the same era have a reasonable chance of working. Reports welcome.
You do not need to know anything about programming. This is copy and paste, and takes about five minutes. Nothing here modifies your Mac's system files, and your original game download is never changed.
Buy and download Detective Grimoire from the
Humble Store,
choosing the Mac download. You will get a file ending in .dmg, which
normally lands in your Downloads folder.
The Steam version will not work for this, because Steam only offers the Windows build.
Download and install it from airsdk.dev, then drag it to your Applications folder like any other app. You do not need to open it or create an account. The script only borrows one file from it.
Press Command + Space, type Terminal, and press Return. A window with a
text prompt appears. That is normal.
Copy this whole block, paste it into Terminal, and press Return:
cd ~/Downloads
curl -O https://raw.githubusercontent.com/jmealo/air-game-apple-silicon/main/build.sh
chmod +x build.shNow run the build. If your download has a different filename, replace the part
after --source with the correct one:
./build.sh --source ~/Downloads/DetectiveGrimoire.dmg --download-runtimeTip: instead of typing the filename, you can type ./build.sh --source
(with a space at the end), then drag your .dmg file from Finder into the
Terminal window. It will fill in the path for you. Then type
--download-runtime and press Return.
It may ask whether you want crisper Retina graphics. Either answer is fine, and
off uses noticeably less battery.
When it finishes, it prints Done: and a path. Your game is now in your
Applications folder. Open it like any other app.
If macOS says the app "cannot be opened" or is from an unidentified developer: right-click (or Control-click) the app and choose Open, then click Open in the dialog. You only need to do this once.
If you hear choppy or stuttering audio: check whether your Mac is playing sound through AirPlay to a TV or speaker. AirPlay breaks this game's audio. Option-click the volume icon in your menu bar and pick MacBook Pro Speakers (or any directly connected output).
Read the error message, since the script tries to explain what to do. The most common causes are a mistyped filename in Step 4, or skipping Step 2. If you are stuck, open an issue and paste what Terminal printed.
# 1. Install the free AIR SDK Manager (supplies the universal launcher stub)
# https://airsdk.dev/download/airsdkmanager/?platform=macos
# 2. Build
./build.sh --source ~/Downloads/YourGame.dmg --download-runtimeTwo things must both be right, or you get a black window with no error:
| Component | Requirement | Why |
|---|---|---|
| Launcher stub | Universal (arm64 + x86_64), from AIR SDK Manager | The stub inside the AIR framework is x86_64-only and black-screens |
| AIR runtime | 51.1.2.2 or older | 51.3.3.1 black-screens legacy titles |
That is the whole fix. Everything else in this README is diagnosis.
This script requires a copy you own. Please buy it. It is an excellent game by a small studio, and none of this works without their files.
Detective Grimoire (SFB Games):
- Humble Store:
DRM-free, cross-platform. This is the one you want, because it provides
the macOS
.dmgthis script needs. - Official site, which links to all storefronts
- Steam. Note the Steam build is Windows-only, so it will not give you a macOS installer.
- iOS App Store
- Google Play
Also worth your money: Tangle Tower, the studio's modern sequel. It is natively supported and needs none of this.
Open a 2014-era AIR game on a current Mac and nothing happens:
$ file "Install Detective Grimoire.app/Contents/MacOS/Install Detective Grimoire"
Mach-O executable i386
Both the installer and the game launcher are 32-bit i386. macOS dropped 32-bit execution in Catalina (10.15), so these cannot launch on any modern Mac. This is not Apple-Silicon-specific: an Intel Mac on a current OS fails identically, and installing Rosetta does not help, because Rosetta translates 64-bit x86_64 only.
Only the tiny native launcher is architecture-specific. The game itself is a SWF plus assets, which is portable bytecode. Replace the launcher, pair it with a working runtime, and it runs.
The most important finding here, and the one that cost the most time.
AIR runtime 51.3.3.1 renders legacy titles as a black window. The game launches, allocates memory, creates its save directory, runs ActionScript, and never draws. No error, no crash, no log entry.
Verified by swapping only the runtime inside an otherwise identical bundle:
| Runtime | Result | CPU | RSS |
|---|---|---|---|
| 51.1.1.4 | works | ~93% | 172 MB |
| 51.1.2.2 | works | ~90% | 98 MB |
| 51.3.3.1 | black screen | ~0.8% | 60 MB |
All three are universal binaries (x86_64 arm64), so this is a genuine version
regression and not an architecture mismatch.
(51.2.1.7 is referenced in places but is not actually published. That download returns a ~1 KB stub, so the regression lands somewhere in 51.2.x to 51.3.x.)
The CPU and memory figures are the practical tell: a working build sits near 100% of a core and 100 MB or more, while a black one idles near zero.
--download-runtime fetches a known-good runtime automatically. The script also
checks the version you selected and warns before building something that will
not render.
Worth noting that the AIR SDK Manager happens to bundle 51.1.1.4. That was luck, not design, and may change in future releases.
- Finds the payload, by locating
META-INF/AIR/application.xmlinside the installer. That directory is a complete, unpacked AIR application. - Reads the original identity, parsing
<id>,<name>,<versionNumber>and the content SWF from the original descriptor. Reusing the original<id>matters, because AIR derives the save path (~/Library/Application Support/<id>) from it, so changing it orphans saves. - Clones a donor shell for its universal launcher stub.
- Installs a known-good runtime into
Contents/Frameworks/. - Writes a modern descriptor (namespace 51.0) with explicit dimensions. This is a convenience, not a fix. See below.
- Rebrands
Info.plist, resolves Retina, and ad-hoc code-signs.
- macOS 10.13+
- AIR SDK Manager:
download.
Required for its universal launcher stub. Any AIR app with a universal stub
and
Contents/Frameworks/Adobe AIR.frameworkworks via--runtime-donor. - Your own copy of the game.
chmod +x build.sh
./build.sh --source ~/Downloads/YourGame.dmg --download-runtime--source <path> .dmg, installer .app, or a directory (required)
--runtime-donor <app> default: /Applications/AIRSDKManager.app
--runtime <path> an Adobe AIR.framework, an .app containing one,
or an AdobeAIR.dmg (mounted and extracted)
--download-runtime [v] fetch a known-good runtime (default 51.1.2.2)
--output <path> default: /Applications/<Game Name>.app
--width / --height initial window size (default 1280x720)
--fullscreen launch fullscreen
--render <mode> direct | gpu | auto (default: direct)
--hidpi <mode> on | off | auto (default: auto)
--force overwrite an existing bundle
Fullscreen, windowed mode, and save games were all verified working.
Legacy AIR titles were authored for 1x. Enabling HiDPI makes AIR rasterize at 2x, roughly 4x the pixels. Measured on an M2 Max, same build, only this flag changed:
| HiDPI | CPU |
|---|---|
| off | ~95% |
| on | ~240% |
Roughly 2.5x. Crisper, but it can starve audio on a busy machine, which is
why the original developers shipped NSHighResolutionCapable=false. auto
detects a Retina display and asks, recommending on for Macs with 8 or more
performance cores. Non-interactive runs default to off.
Documented because each one cost real debugging time, and because guides elsewhere get some of these wrong.
A 2014 descriptor looks alarming:
<application xmlns="http://ns.adobe.com/air/application/14.0">
<initialWindow>
<fullScreen>true</fullScreen>
<renderMode>direct</renderMode>
<!-- no <width> / <height> -->It is tempting to blame namespace 14.0, or fullScreen with no dimensions. It
is not the cause. Tested directly: the untouched 2014 descriptor paired with a
known-good runtime runs fine (~145% CPU, 99 MB). Namespace 14.0 is still
accepted by current runtimes.
The script still writes a modern descriptor, but only so it can offer windowed mode and explicit window sizing. If you keep the original, it will work.
direct, gpu, and auto all measured within noise of each other (~80 to 95%
CPU). If you have a black window, changing render mode will not save you.
The launcher is i386. Rosetta 2 translates x86_64 only. There is no path that runs a 32-bit binary on modern macOS.
The AIR framework ships Resources/Template.app/Contents/MacOS/Template, which
looks like exactly the launcher you want. It is x86_64-only, and produces a
black window even paired with a known-good runtime. The AIR SDK Manager's stub
is universal and works. That is the entire reason a donor app is required.
If you pick a stub with no runtime to load, you get an honest dialog:
This application requires a version of Adobe AIR which cannot be found.
That message is a gift. A missing runtime is far easier to debug than a silent black window.
This does work. The payload directory is a complete unpacked .air, and its
self-signed certificate is typically valid for decades, so the signature still
verifies. But the archive ordering is strict and absent from the error messages:
1. mimetype (STORED, not deflated)
2. META-INF/AIR/application.xml
3. META-INF/AIR/hash
4. META-INF/signatures.xml
5. ...content...
Also: no directory entries (zip -D) and no .DS_Store, or you get
Found N files that were not listed in signatures.xml. And exclude
Icon.icns, because the original Mac installer generates it at install
time, so it is not in signatures.xml.
Every failure surfaces to the user as the same unhelpful dialog: "The
application could not be installed because the installer file is damaged." The
real error is in ~/Library/Application Support/Adobe/AIR/install.log.
Even after a clean install this route has a fatal flaw: an AIR-installed app
ignores edits to its application.xml, because it uses a registered copy. You
cannot iterate. A standalone bundle reads its descriptor directly, which is why
the script builds one. The official installer also runs lipo -thin x86_64,
stripping arm64 and forcing the game through Rosetta.
If you also own the iOS build (Apple Silicon Macs can run iPhone apps), it shares the game's bundle identifier. The AIR installer finds it, assumes a previous installation to upgrade, looks for AIR metadata inside an iOS bundle, and fails:
Info: No app located in directory /Applications/<Game>.app
Error: Missing necessary file META-INF/AIR/application.xml
Remove or relocate the iOS build first.
- Check the runtime version. See the regression table above. This is the
most likely cause, and
--download-runtimefixes it. - Check the stub is universal, with
lipo -info "YourGame.app/Contents/MacOS/"*. It should listarm64. - Verify AIR works at all by launching your donor app. If it renders, the runtime is fine and the problem is your bundle. Worth doing early, since it splits the problem cleanly in half.
A black window looks identical to a hung process. Memory and CPU tell them apart:
ps -o pid,rss,%cpu -p $(pgrep -f "YourGame.app/Contents/MacOS" | head -1)A game genuinely loading assets climbs to 100 MB or more and burns most of a core. One flat at ~30 to 60 MB and ~0% CPU never started.
Check whether it created its save directory, which proves ActionScript is running:
ls ~/Library/Application\ Support/<app.id>/Local\ Store/Check your audio output device before blaming the game.
system_profiler SPAudioDataType | grep -A6 "Default Output Device: Yes"If Transport: AirPlay appears, that is almost certainly the cause. AirPlay is
network-streamed and buffered, so it stutters under CPU or network load.
Streaming video tolerates that buffering; real-time game audio does not. Switch
to built-in speakers by Option-clicking the volume icon.
The tell: if the game also stutters on your phone, it is not the game. A software bug cannot follow you across devices, but a shared speaker can.
Then check contention and memory pressure:
uptime # load average vs. core count
sysctl vm.swapusage # near-full swap starves audio buffers
ps -Ao pid,%cpu,comm -r | headAlso try --hidpi off, which cuts CPU roughly 2.5x.
The bundle is ad-hoc signed, so moving it may trigger quarantine. Right-click and choose Open, or:
xattr -cr "/Applications/YourGame.app"
codesign --force --deep --sign - "/Applications/YourGame.app"Contains no game assets, no Adobe code, and no Wipro/HARMAN code. It rebuilds
software you already own to run on hardware you already own, and circumvents no
copy protection, since legacy AIR packages are self-signed rather than
encrypted. The optional --download-runtime flag fetches the AIR runtime from
Wipro's own servers.
Adobe AIR is a trademark of Adobe. AIR is now maintained by Wipro Engineering Connected Services (formerly HARMAN DTS), which took over support after Adobe discontinued it in 2020. The SDK is commercially licensed per developer seat (free tier under $50k/yr revenue, which injects a splash screen; paid tiers $199 to $1,199/yr). Runtimes are free for end users. Check airsdk.harman.com and respect the licensing of whatever runtime you bundle before redistributing a built app.