プログラミング
ホビーOSでWineを使ってWindowsゲームを動かす
Running Windows Games on a Hobby OS with Wine (astral-os.org)
要約
著者は、自身が長年開発しているホビーOS「Astral」にWineを移植し、Windowsゲームを動作させることに成功しました。特に32ビット専用ゲーム「Cogmind」を動作させるため、32ビットコードのサポートやOpenGL(EGL)の統合といった多くの技術的課題を解決しています。この取り組みは、ホビーOSが予想以上に多くのゲームをプレイ可能であり、将来的に日常的なOSとして機能する可能性を示すものです。
全文翻訳
メインページ | について | 投稿
AstralにWineを移植する
数ヶ月前、私は長年取り組んできたホビーOSであるAstralでMinecraftを動かしたことについて投稿しました。それ以来、他の人々もMinecraftの最新バージョンやFactorio(glibc互換のlibcを使用)を動かしてきました。しかし、これらのゲームは新しいOSで動かしやすいように作られたりパッケージ化されたりしていますが、ほとんどのゲームはそうではありません。多くのゲームはクローズドソースでWindows用にコンパイルされており、それらをプレイするにはWineのようなものが必要不可欠です。私のお気に入りのゲームの一つであるCogmindもその範疇に入ります。これは32ビットWindows専用のローグライクゲームであり、それをAstralで動かすことが私の目標となりました。既存のWineポートはすでにありましたが、notepad.exeさえも適切に動作しないほど非常に不完全でした。Cogmindを動かすには、Wineポートを完成させる必要があり、それはまた、元々64ビット専用のOSで32ビットコードを実行する機能を追加することも意味しました。
基本的なWineの機能
Wineを立ち上げて実行するための最初のステップは、MinGWをダウンロードし、Wineビルドで有効にすることでした。これはPE DLLをコンパイルするために必要です。これを有効にすると、notepad.exeが動作し、「名前を付けて保存」を選択してもクラッシュしなくなりました!
libEGL.soのコンパイル
まだ一つの大きな問題が残っています。WineはOpenGLサポートなしでコンパイルされています。AstralにはOpenGLがありましたが、WineはEGLが明示的に必要であり、AstralのMesaポートはそれを提供していませんでした。EGLはOpenGLのようなレンダリングAPIとウィンドウシステムを接続し、Wineがグラフィックスを適切に初期化するために必要です。最初は簡単な修正だと思われ、Mesaで有効にするだけだと考えました。しかし、MesaはxlibバックエンドでEGLをサポートしていないため、代わりにDRIバックエンドに切り替えることを余儀なくされました。DRI (Direct Rendering Infrastructure) は、アプリケーションがXサーバーを介さずにGPUとより直接的に通信することを可能にします。これにより、/dev/driなしでX.orgサーバーを起動できるようにMesaをパッチするという、泥沼にはまってしまいました。最終的には成功し、Deltaruneという実際のゲームを起動させることができました。
WoW64と32ビットWindowsプログラム
Cogmindは32ビットでAstralは64ビットであるため、さらに多くのインフラが必要です。これはWineのWoW64モードを使用して実現されました。これは32ビットのUnixライブラリを必要としません。これは、32ビットWindowsバイナリを64ビットプロセスで実行し、必要に応じて32ビットと64ビットのシステムコールとデータ構造の間で変換することで機能し、完全な32ビットユーザー空間の必要性を回避します。これを機能させるには、主にカーネルにLDT (Local Descriptor Table) サポートを実装する必要がありました。x86-64では、32ビットセグメントディスクリプタを使用してロングモードで32ビットコードを実行できるためです。これらはメモリがどのようにアクセスされるべきか、またコードセグメントの場合、プロセッサがそれらの命令をどのように実行するかを記述します。LDTはこれらのセグメントディスクリプタを定義するために使用されるメカニズムの一つであり、プロセスごとに設定することを可能にします。また、Wineのシグナルおよびシステムコール処理コードに、いくつかのデリケートな接着剤も必要でした。
Cogmind!
AstralポートにWoW64サポートを実装し、カーネルのいくつかの他のバグを修正した後、Cogmindが動作しました!ゲームはプレイ可能で、ゲームニュースとスコアシートのアップロードが動作しない以外に目立った問題はありませんでした。
壊れたスコアシートのアップロード
このバグは、CogmindサーバーへのTCP接続が開かれ、データが一切転送されずに瞬時に閉じられるという形で現れました。最初はネットワークスタックの問題かと思いましたが、そうではありませんでした。他に何かあると疑わせたのは、Wineのデバッグログ関数__wine_dbg_writeがWoW64で全く動作していなかったことです。Wineのコードを深く掘り下げた結果、最終的に__wine_unix_call_dispatcher関数でレジスタの保存を忘れていたことに気づきました。これがPEからUnixへの移行を壊し、UBを引き起こしていました。これを修正すると、スコアシートのアップロードが動作するようになりました!
他のゲームやプログラム
Wineでいくつかの他のアプリケーションも実行しようとしました。
プログラム ステータス 備考
FTL 動作 完全にプレイ可能。
Steam 一部動作 インストールとアップデートはできるが、壊れたGetInterfaceAddresses()のためにChromiumの起動時にクラッシュ。
iexplore.exe 一部動作 簡単なサイトはレンダリングされる。複雑なページはSteamと同じ根本原因でクラッシュ。
Factorio 一部動作 ウィンドウは開くが、読み込みから先に進まない。
Spooky's Jumpscare Mansion 一部動作 起動するが、遅すぎてプレイできない。
Noita 一部動作 起動するが、遅すぎてプレイできない。
Plants vs. Zombies 動作しない メインメニューに到達する前にSteam DRMにブロックされる。
Half-Life 動作しない WineのC++ランタイムでアサート失敗。ポートに実装が不足している可能性が高い。
Firefox / Chromium 動作しない インストーラーが失敗。実行可能な状態にならない。
SCP: Containment Breach 動作しない 起動しない。原因はまだ診断されていない。
Unity games全般 動作しない Astralではwine-monoに問題があるようで、UnityゲームはMonoManager ReloadAssemblyで停止する。
最終的な考え
Wineの移植は楽しい挑戦であり、ホビーOSが元々考えられていたよりもはるかに多くのゲームをプレイするために使用できることを証明する方法でした。これは、ホビーOSが実行可能な日常的なOSになる方向への一歩です。まだいくつかの粗削りな部分、パフォーマンスの問題、奇妙なクラッシュがありますが、中核は機能しています。この作業は、Wineの内部動作、特にPEからUnixへの移行を修正するために掘り下げていく中で、多くのことを教えてくれました。Wineポートに関する私の大きな目標の一つは、Steamを動作させることであり、それはChromiumも動作することを意味します。Astralについては、近い将来、最適化、新しいドライバー、バグ修正にもっと焦点を当てる予定です。カーネル側にはまだ多くの改善の余地があります。読んでいただきありがとうございます!