Zigで書いたゲームボーイアドバンスのゲーム
(jonot.me)なぜZigでゲームボーイアドバンスのゲームを書いたのか
-
ゲームボーイアドバンスの魅力
ゲームボーイアドバンスは現代的なCPU(32ビットARM、多数のレジスタ)を搭載している一方で、古いタイルベースのレンダラーを使っている。これはNESが80年代に使っていた方式に近い。任天堂における最後期のタイルベースシステムの1つであり、アフィン変換、透明度、スプライト効果など、さまざまな機能を備えている。 -
Zig言語を選んだ理由
当初はC++でゲームボーイアドバンスのプロジェクトを始めたが、最初の完全なゲームはZigで書いた。Zigはまだベータ版で、ゲームボーイアドバンスの発売から15年後に作られた言語であるにもかかわらず、組み込みプログラミングに適した機能を備えている。
ツールチェーン
-
LinuxとdevKitPro
Linuxを使う中でパッケージ管理の難しさを感じており、Nintendo DS向けの3Dシーンを作る際にはdevKitProを使う必要があった。これにはGCCツールチェーン、ライブラリ、開発ツールが含まれている。ArchLinuxのパッケージマネージャー経由でインストールしなければならない煩雑さがある。 -
Zigの利点
Zigはクロスコンパイルを容易にし、複雑なパッケージマネージャーを設定する必要がない。Zigのビルドシステムは、build.zigファイルのbuild関数を実行してビルドを進める。これにより、ビルドプロセスが簡素化され、エラーも減る。
Packed Structs
- Packed Structsの重要性
ゲームボーイアドバンスは高級API呼び出しなしに、レジスタを通じてハードウェアを制御する。Zigのpacked structはメモリレイアウトを最適化し、ハードウェア制御を容易にしてくれる。これはゲームボーイアドバンスのプログラミングで非常に有用な機能である。
Comptime
- コンパイル時のコード実行
Zigはコンパイル時にコードを実行できる機能を提供している。これにより、実行時にデータを圧縮するのではなく、コンパイル時に圧縮できる。Zigのこの機能によって、データを簡単に圧縮できるようになる。
標準ライブラリ
- Zigの柔軟な標準ライブラリ
Zigの標準ライブラリはジェネリクスをサポートしており、メモリ確保関数にアロケータを引数として渡せる。これにより、独自のメモリ確保方式を利用できる。Zigの標準ライブラリは、ハードウェア制約のある環境でも柔軟に使える。
問題点
-
インラインアセンブリ
Zigはインラインアセンブリをサポートしているが、出力は1つしかできない。これはGBAのBIOS関数で複数の値を出力する必要がある場合に問題となる。 -
Thumbコード/ARMコード
ゲームボーイアドバンスのCPUはARMモードとThumbモードをサポートしている。ZigではARMモードとThumbモードを明示的に指定できない。 -
奇妙なメモリ
ゲームボーイアドバンスのビデオメモリは8ビット単位で書き込めず、そのためグラフィックが壊れる問題を引き起こす。Zigはメモリコピー時にmemcpyを使って最適化するが、これはGBAの「奇妙なメモリ」と衝突する可能性がある。
1件のコメント
Hacker Newsの意見
volatileを使っても解決しないなら、コンパイラにバグ報告することを勧めるmemcpyに置き換える最適化を行うことがある。この最適化はユーザー空間でのみ行われるものだと予想しており、-nostdlibオプションで自動的に防げることを期待していたpacked structを使う方法としてビットフィールドを提案。有効なCコードの例も示している