TECHNICAL OVERVIEW Apple Silicon Mac · Windowsゲーム互換 · 多層変換 Orrery Case Notes

なぜMacでWindowsゲームは動かないのか

答えは「翻訳が一段ずつ積み上がるから」

Apple Silicon 以降、MacでWindowsのゲームを動かすのは「翻訳を一枚かませば済む」話ではなくなった。CPUの命令、Windowsのシステムコール、描画、動画、音声 ― それぞれ別々の翻訳層を通り、しかも層が縦に積み上がる。層が増えるほど、絵や音が「継ぎ目」で落ちる。この Case Notes がなぜ何本も存在するのか、その地図を先に描いておく。

x86 → arm64 · DirectX → Vulkan → Metal · GDI · DirectDraw · DirectShow → GStreamer · wined3d · DXVK · MoltenVK
§1

退路が、二つ同時に消えた

Apple が Mac のチップを Intel から自社設計(Apple Silicon)へ切り替えたとき、Windowsゲームを動かす素直な道が二本とも塞がった。

ひとつは CPUの命令セットが変わったこと。Windowsの exe は x86 という命令で書かれているが、Apple Silicon は ARM という別系統で、そのままでは 一命令も実行できない。もうひとつは 退路の消滅だ。Intel Mac 時代には二つの逃げ道があった ― Windows向けの命令を変換する Rosetta と、Mac に Windows を直接入れる Boot Camp。だが Rosetta は Intel *Mac* アプリを動かすための仕組みで Windows の exe は対象外。Boot Camp は Apple Silicon で廃止された。

Rosetta で変換する

x86 Windows exe → ✕

Rosetta 2 が変換するのは Intel 版の *Mac* アプリだけ。Windows の実行ファイルは形式そのものが違い、対象外。

Windows を入れて動かす

Boot Camp → ✕ 廃止

MacにWindowsを直接インストールして切り替える Boot Camp は、Apple Silicon 世代では提供されなくなった。

「そのまま動かす」も「Windowsを入れる」も塞がった。残るのは 翻訳して動かす道だけ ― そしてその翻訳は、一枚では終わらない。

§2

一段目 ── 命令とAPIを訳す

ゲームを動かす土台になるのが Wine だ。ただし、これは「一枚の翻訳」ではなく、すでに二重になっている。

Wine は、WindowsをインストールせずにWindowsアプリを動かす互換レイヤーで、ゲームが呼ぶWindowsのシステムコール(API)を macOS の API へ翻訳する。エミュレーターではなく「翻訳者」なので、ここまでは一段。だがゲームの中身は依然 x86 の命令のまま。ARM の Mac で走らせるには、その命令自体を ARM へ変換する層がもう一枚要る。APIの翻訳(Wine)命令の変換、この時点で翻訳は二枚重なっている。

§3

二段目 ── 絵はもっと長い鎖を通る

画面に一枚の絵が出るまでが、いちばん長い。Windowsゲームは DirectX で描くが、macOSにDirectXは無い。だから絵は何度も別のAPIに載せ替えられる。

1
DirectX
ゲームが描く
2
DXVK / wined3d
Direct3D を受ける
3
Vulkan
中間API
4
MoltenVK
Vulkan→Metal
5
Metal
GPUが描く
DirectXの命令は DXVK で Vulkan に、Vulkan は MoltenVK で Apple の Metal に、と順に載せ替わってようやくGPUに届く(古いゲームでは DXVK を使わず wined3d が同じ役割を担う別ルートもある)。一枚の絵のために、翻訳が三段以上重なる。
§4

三段目 ── 20年前のAPIが追い討ちをかける

やっかいなのは、ビジュアルノベルが今も現役なのに、中身は2000年代のAPIを引きずっている点だ。新しい翻訳鎖の 外側を通る古い経路が、タイトルごとに混ざる。

2000年代の2D描画

GDI / DirectDraw

DirectXより古い描画の仕組み。今の Direct3D→Metal の鎖とは別経路で処理され、Mac上では別の壊れ方をする。

古い動画再生

DirectShow / VMR

OPやロゴのムービーを再生する旧世代フレームワーク。Wineでは GStreamer などを経由し、映像・音声・同期がそれぞれ別々に翻訳される。

層が読めない

エンジン名では決まらない

同じ「動画が黒い」でも、通っている層はタイトルごとに違う。だから エンジンの名前だけでは、どの翻訳が壊れたのか特定できない

§5

積み上がった翻訳の、全体像

一枚の絵、一つの音、一枚のサムネイル ― それが画面に届くまでに、これだけの層を通り抜ける。

01
Windowsゲーム x86 の命令 / DirectX / 古い描画・動画API
02
Wine(swingby-wine) Windows API → macOS API の翻訳層
03
命令変換 + 描画変換 x86→ARM / DirectX→(DXVK / wined3d)→Vulkan
04
MoltenVK Vulkan → Metal の翻訳
05
Metal / macOS ようやく画面に絵が出る

↑ どの層も単体では正しい。壊れるのは、いつも層と層の「継ぎ目」

§6

だから、継ぎ目で壊れる

各層は単体では動く。だが翻訳が積み上がると、継ぎ目でフレームが画面に出なくなる ― 絵が黒くなる、映像は流れるのに音だけ消える、描いているのに真っ黒、メニューが真っ白になる。この Case Notes は、その一つひとつの継ぎ目を解体した記録だ。

継ぎ目 · D3D9 / wined3d

CMVS:セーブサムネイルが黒くなる

Present後に失われるフレームを、GetBackBuffer + LockRectへ供給した記録。

CASE を読む →
継ぎ目 · 動画と音声

winegstreamer:高ビットレート動画で音声だけが途切れる

映像が続く一方で音声だけ約1秒途切れる現象を、multiqueueの上限とA/Vインターリーブまで切り分けた記録。

CASE を読む →
継ぎ目 · DirectX→Metal

DXVK:未bindの頂点ストリームで画面が黒くなる

DXVKの固定機能シェーダでbinding 16が未bindになる条件を、DrawPrimitiveUPの入力まで追って修正した記録。

CASE を読む →
継ぎ目 · 副作用

CatSystem2:動画OFFで設定メニューが白くなる

CatSystem2で動画再生経路のON/OFF差分を比較し、採用運用と残課題を分けた記録。

CASE を読む →
継ぎ目 · OSの実行許可

Wine更新後、一部の旧作が起動しない

Wine更新後に旧作が起動しなくなった現象を、file-backed mmapのEXEC付与順序まで切り分けた記録。

CASE を読む →
継ぎ目 · Metal と OpenGL の同居

Artemis Engine:動画だけが白くなる

DirectDrawの前面描画ビューがMetal表示の背後に隠れる原因を切り分け、Metal上へ表示した記録。

CASE を読む →
継ぎ目 · D3D11 / DXVK

D3D11/DXVK:セーブサムネイルが黒くなる

非ゼロのswapchain buffer要求が拒否される原因を、DXVKのGetImageまで追った記録。

CASE を読む →