目次: RISC-V
DOOMのクローン実装prboom2を組み込み環境に移植する話です。前回はUARTしかないショボい組み込み環境でも動作できるようにprboom2を改造しました。
Linuxの仮想端末は超速いので描画速度はあまり気になりませんが、組み込み機器に移植すると描画がめちゃくちゃ遅いことに気づくと思います。理由は簡単でUARTが遅いからです。UARTは9600bps〜115.2kbpsがよく使われる速度で、速いものでもせいぜい1.5Mbps程度です。
前回の実装では24bit色モードを使ったので、1つのピクセルを表現するために、エスケープシーケンス16バイト+スペース2バイト = 18バイト必要です。128x120の画面を1枚表示するのに276kB必要、9600bpsだと230秒(0.0043fps)、1.5Mbpsでも1.47秒(0.67fps)です。
端末の背景色設定は24bit色モードと256色モードがあります。256色モードの場合、エスケープシーケンス10バイト+スペース2バイト = 12バイトなので、24bit色より多少は軽量です。128x120の画面を1枚表示するのに184kB必要です。1.5Mbpsで0.98秒(1.01fps)ですね。
24bit色モードはエスケープシーケンスでR, G, Bの各値を指定できるのでどんな色でも指定できました。256色モードの場合はパレットの各色に番号が振られていて、エスケープシーケンスで番号を指定する仕組みです。カラーパレットは上記の配置で固定されていてパレットにない色は使えません。
DOOMの画面の各ピクセルの色を見て、256色モードパレットの色を指す番号を探す減色処理を追加します。256色モードのカラーパレット番号と色の関係は規則的です(※)から、それほど難しくないでしょう。
256色モードだとこんな感じです。24bit色版と比較するとややディティールが潰れていて黒っぽいですけど、まあまあ良さそうです。
(※)16-231番(216色)はR, G, Bそれぞれ6段階の組み合わせです。パレット番号を表す式は、16 + 36r + 6g + b (0 <= r, g, b <= 5) となっています。
もう少し軽くできないか考えてみましょう。今は毎回「背景色変更のエスケープシーケンス + スペース2つ」を出力していますが、左隣のピクセルと色が同じピクセルであれば、背景色変更をする必要はないです。
つまり左隣と同じ色のピクセルが連続する限りエスケープシーケンスの出力を省略できます。非常に単純なRLE(Run-Length Encoding)の一種とも言えましょう。
デモ開始直後のところがわかりやすいですが、256色モードで描画すると真っ黒になってしまう画面が散見されます。
DOOMの画面は比較的暗い色が多いですが、256色モードのパレットは暗い色から明るい色まで均等に割り振られているため、暗い色の表現力が低いです。単純に近似すると画面の色がほぼ真っ黒になります。
この問題を回避するために暗い色をグレースケールに置き換えます。グレースケールと暗い赤、緑、青は違う色ですが、暗い色の色味は区別しづらいのでグレースケールに置き換えてもさほど不自然にはなりません。
こんな感じです。良く見ると壁の暗い緑がグレーになっていたり若干変ですが、総じて悪くない仕上がりです。これで256色モードが活用でき、24bit色モードに比べて描画速度が1.5倍以上になりました。
今まではずっとLinuxの上で作業してきましたが、次回でようやく組み込み機器に移植します。
目次: RISC-V
目次: 独自OS
DOOMのクローン実装prboom2を組み込み環境に移植する話です。前回は画面描画を1.5倍ほど高速化しました。
今まで「組み込み環境」とひとまとめにして呼んでいましたが、OSだけでもLinux、RTOS、もっとシンプルなものも含めると無数にあります。既存のOSの上で動かすのも大変興味深いですが、今回は自作OS(2022年12月14日の日記参照)の上で動かしてみたいと思います(リポジトリへのリンク)。
今まで下記の機能を削除したり、代替機能で置き換えてきたのはこのためです。動作させるボードやSoCにHW機能がない場合もあれば、自作OSにドライバを実装しておらずHW機能があっても自作OSから使う方法がないのです。
自作OSの特徴は下記のようにLinuxと同じlibcを採用して、Linuxのアプリケーションを移植しやすい仕組みになっていることです。速度の遅い組み込み環境で何度も動作確認するのは大変ですから、なるべくLinux上で検証できるようにした構成です。
今回のprboom2の移植の際もC言語のコードを弄る必要はありませんでした。ビルドシステムというかMakefileを別途作っていますが、なんでだったか忘れました……。
自作OSのランタイム側のビルドのための準備については、ドキュメント(リンク)を見ていただくとして。QEMU RISC-V 32bit向けに自作OSをビルドします。
$ cd baremetal_crt $ cmake ./ -G Ninja -B build \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_INSTALL_PREFIX=./test/sysroot/ \ -DARCH=riscv \ -DCROSS_COMPILE=riscv64-unknown-elf- \ -DCC=gcc \ -DDEFCONF=riscv_qemu_virt_32_xip $ ninja -C build install
次に改造prboom2をビルドします。前回まで説明してきた改造を全て適用したprboom2をGitHubに置いた(リンク)ので、このコードを使うと簡単です。実装が適当かつ書きかけのコードとかが残っていて美しくありませんが、細かいことは気にしないでください……。
$ cd prboom2 $ ./configure --disable-gl $ cd src/riscv $ make USE_NEWLIB=y USE_SYSROOT=(baremetal_crtのパス)/test/sysroot all
最初のconfigureはconfig.hを作成するために実行しています。特にconfig.hを変更する予定はないので固定で置いてしまえば良かったんじゃないか?と思いましたけど、まあいいでしょう。
$ qemu-system-riscv32 \ -machine virt \ -bios none \ -net none \ -nographic \ -chardev stdio,id=con,mux=on \ -serial chardev:con \ -mon chardev=con,mode=readline \ -smp 4 \ -s -kernel prboom2/src/riscv/prboom
こんな感じで動作確認できます。
描画速度を稼ぐため解像度を半分にしている以外、見た目が前回まで(つまりLinuxで動作させたとき)と同じなのであまり面白くないですね……。
< | 2024 | > | ||||
<< | < | 06 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | - | - | - | - | 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | - | - | - | - | - | - |
合計:
本日:
管理者: Katsuhiro Suzuki(katsuhiro( a t )katsuster.net)
This is Simple Diary 1.0
Copyright(C) Katsuhiro Suzuki 2006-2023.
Powered by PHP 8.2.20.
using GD 2.3.3(png support.)