Vahag Byurat  ·  All Projects
Open Source · macOS · Wine · Apple Silicon

AoE2 HD Crossover

Running Age of Empires II HD Edition on an Apple Silicon Mac: no Windows, no Boot Camp, no paid software. Just open-source tooling, careful debugging, and a working game.

Shell · Bash Wine CrossOver Rosetta 2 wined3d · Metal Goldberg Emulator
AoE2 HD Crossover castle icon
The Problem
A classic game, abandoned on a modern platform

Age of Empires II HD Edition, the 2013 Steam release of the legendary real-time strategy game, never received an official Apple Silicon client. Microsoft moved on to AoE2: Definitive Edition, which has a Mac build, but HD Edition's dedicated community was left behind: the game's multiplayer servers still run, ranked ladders still update, and hundreds of thousands of players still compete, just not on M1 and M2 Macs.

The challenge was threefold. First, the binary is a 32-bit x86 Windows executable; Apple Silicon speaks arm64. Second, the game depends on DirectX 9 and the Steam API; neither exists on macOS. Third, the Steam desktop client itself cannot run under Wine because of a broken authentication chain deep in the Chromium-derived web helper.

Three translation layers. One working game. Zero Windows licenses.
AoE2 HD Crossover decorative header
Medieval architecture meets Apple Silicon engineering
Scope Note

This project predates my copy of AoE2: Definitive Edition and targets the HD Edition specifically. The stack has been tested offline only: single-player skirmish and campaign. Online multiplayer through Steam is outside its scope.


The Solution
Chaining open-source layers into a working stack

Every component in the solution is free and open-source. The key insight was recognising that Wine does not emulate a CPU: it only translates Windows API calls. CPU translation is Rosetta 2's job. The two tools compose perfectly: Wine (compiled as x86_64) is translated by Rosetta while Wine itself translates all the Windows system calls the game makes.

AoK HD.exe x86 Windows binary · DirectX 9 · Steam DRM Game
Wine CrossOver · wined3d Windows API → macOS API · DirectX 9 → OpenGL → Metal API Bridge
Rosetta 2 x86_64 machine code → arm64 machine code · JIT, invisible CPU Bridge
Apple M1 · Metal GPU arm64 native execution · macOS 12+ · no Windows required Hardware
AoE2 HD Crossover translation stack diagram
The four-layer translation chain from Windows binary to Apple Silicon GPU

Key Discoveries
Debugging every layer of the stack

Getting a working game required diagnosing errors across four independent translation boundaries. Most error messages were cryptic, most documentation was fragmented or Windows-specific. Three non-obvious problems stood between "install Wine" and "game running."

Discovery 1 · DXVK vs wined3d

DXVK (the modern DirectX-over-Vulkan bridge) is widely recommended for Wine gaming, but it causes a fatal crash on AoE2 HD. DXVK requests the geometryShader and shaderFloat64 Vulkan features; Metal on Apple Silicon does not expose either. The fix: force wined3d (the older OpenGL bridge) via WINEDLLOVERRIDES="d3d9=b;dxgi=b;d3d10core=b;d3d11=b", which routes rendering through OpenGL → Metal instead. The error message ("Failed to initialize draw system") gives no hint of the real cause.

Discovery 2 · Steam client crash & Goldberg Emulator

The Steam desktop client crashes immediately under Wine because steamwebhelper depends on a bcryptprimitives.dll → chrome_elf.dll initialisation chain that Wine does not support. The solution: use SteamCMD (a headless CLI installer) to download the game files, then replace steam_api.dll with the Goldberg Steam Emulator (gbe_fork), an open-source DLL that satisfies the game's DRM check without any Steam process running.

Discovery 3 · Working directory crash & launch flags

The game crashes with "FATAL: Storage Point #12 does not exist" when launched from the wrong working directory. Its relative paths for resources\_common\drs\ only resolve if Wine is launched with the game folder as the working directory. The fix: use wine start /d "C:\path\to\game" AoKHD.exe rather than a plain wine AoKHD.exe call.

# Launch command: every flag matters WINEPREFIX=~/.wine/aoe2 \ WINEDLLOVERRIDES="d3d9=b;dxgi=b;d3d10core=b;d3d11=b" \ WINED3D_CSMT=1 # multi-threaded GPU commands WINEDEBUG=-all # silence debug log (saves CPU) wine start /d "C:\Program Files (x86)\Steam\steamapps\common\age2hd\" AoKHD.exe

Open Source Components
Built entirely on community tooling

Every tool in this stack is free and open-source. The project contributes back by documenting every error encountered, with root cause analysis and the exact fix, so future Mac players don't have to start from scratch.

Component Role Licence
wine-crossover Windows API translation layer LGPL-2.1
wined3d DirectX 9 → OpenGL → Metal renderer LGPL-2.1
Rosetta 2 x86_64 → arm64 JIT translation (Apple built-in) Apple proprietary · free
gbe_fork (Goldberg) Open-source steam_api.dll (offline DRM bypass) MIT
SteamCMD Headless CLI game installer Valve · free
winetricks Wine prefix configuration helper LGPL-2.1
MoltenVK Vulkan → Metal (for other games in the prefix) Apache 2.0
View on GitHub Troubleshooting Log