2025/05/10 01:46 Building a bare-metal bootable game for Raspberry Pi in C#

ロボ子、今日はすごいニュースがあるのじゃ!なんと、C#が仮想マシンなしでネイティブコードにコンパイルできるようになったらしいぞ!

それはすごいですね、博士! 仮想マシンなしで、ですか? どういう仕組みなのでしょう?

.NET 7の追加で、それが可能になったらしいのじゃ。これまではプログラムの実行を管理する「ランタイム」が必要だったけど、代わりにC++みたいな「ランタイムライブラリ」を使うらしいぞ。

ランタイムライブラリ、ですか。ランタイムとどう違うんですか?

ネイティブAOT(Ahead-of-Time)コンパイルっていうのを使うらしいのじゃ。これによって、.NET SDK付属のランタイムライブラリを、C#の最小限のサブセットを実行するために必要なものに置き換える実験ができるようになったみたい。

なるほど。最小限のライブラリで済むようにするんですね。zerosharpリポジトリには、ベアメタルブートアプリケーションでHello Worldを表示するデモがあるそうですね。

そうそう!しかも、bflatプロジェクトっていうのがあって、これは.NET SDKの一部から構築されたC#のAOTコンパイラなのじゃ。dotnet/runtimeリポジトリのフォークをベースにしてるらしいぞ。

bflatコンパイラですか。ランタイムライブラリは何が選べるんですか?

.NETのフルランタイムライブラリ、bflat独自の最小実装であるzerolib、または標準ライブラリなしのいずれかを選択できるらしいのじゃ。

すごい! 色々試せますね。UEFI(Unified Extensible Firmware Interface)もターゲットにできるんですか?

さすがロボ子、よく知ってるのじゃ! その通り! `--os:uefi`引数を指定してUEFIをターゲットにできるらしいぞ。生成されたbootx64.efiファイルをFAT32形式のUSBフラッシュドライブに置けば、UEFI互換のコンピュータから起動できるのじゃ。

へえー! UEFIブート環境は、efi/bootディレクトリにあるbootx64.efi(またはARM64の場合はbootaa64.efi)というファイルを検索して実行するんですね。

そう!そして、bflatのzerolibには、UEFI APIを使ってファームウェアと通信するSystem.Consoleの実装が含まれているらしいぞ。C#のp/invoke(プラットフォーム呼び出し)を使えば、アンマネージドコードとの相互運用も簡単なのじゃ。

p/invoke便利ですよね。UEFIでは、ほとんどの通信はインターフェースを通じて行われるんですね。プログラムの開始時に、エントリポイントはUEFIファームウェアから「EFIシステムテーブル」へのポインタを受け取る、と。

.NET 8以降では、unsafe accessorsを使って`object.s_efiSystemTable`フィールドからシステムテーブルにアクセスできるらしいぞ。システムテーブルのメンバーの1つはBootServicesへのポインタで、LocateProtocolを使ってグラフィックス出力用のプロトコルなどのデータ構造を検索できるのじゃ。

zerolibは、入力チェック用のAPIも提供しているんですね。迷路の描画ロジックは、Lode's Computer Graphics TutorialとかThe Game Engine Black Book – Wolfenstein 3Dを参照、と。

System.Mathクラスがzerolibに実装されていないから、テイラー展開でSin/Cos関数を実装したらしいぞ!

すごい! そこまでやるんですね! 作成されたゲームはGitHubで公開されているんですね。今度見てみます。

これでC#でベアメタルな世界でも戦えるようになったのじゃ!

本当ですね! 博士、今日はためになるお話ありがとうございました!

どういたしましてなのじゃ! しかし、C#でベアメタルって、まるでスッポンポンで戦場に行くようなものじゃな。風邪ひかないように気をつけないと!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。