読者です 読者をやめる 読者になる 読者になる

納涼?「すぐにけせ」を再現するUEFIバイナリを作ってみた

「すぐにけせ」?

f:id:sosoru_m:20150819024045j:plain
オカルト都市伝説の一つ,SFCで発売された「真・女神転生(II?)」を起動すると1/65536の確率で表示されるメッセージのことです.
これは広く「ガセネタ」として認識されています.私自身も,SFCは疑似的に乱数を発生させて(る気がし)ますので,起動時にランダムで表示するのは厳しいと思ってます.(セーブデータが消えたら,とか,別のトリガーで出てきたら面白いですけどね)

UEFIとは?

マザーボードに乗っかってるファームウェアのインタフェースです.最近のマザーボードUEFIを実装していて,UEFISDKも公開されているので,OS起動前の処理を比較的簡単に書けたりします.
今回はこれを使って,起動前にメッセージを表示させています.

ポイント

とりあえず,周知の事実から「すぐにけせ」は「起動時」に「1/65536で再現」することが出来れば良さそうです.

「起動時」

起動時に再現するためには,UEFIに関わらず,MBRブートした小さなLinuxに表示させれば良いんじゃないかなぁとも思いました.表示する判定の場合は表示して,表示しない判定の場合には,次回ブートするデバイスをBIOSに伝えればいいわけです.ただ,メッセージを表示しない確率が非常に高いはずなので,毎回起動時に2回ブートさせるのはちょっと微妙だなぁと思いました.
僕のマザーのブートマネージャだけかもしれませんが,UEFIブートであれば,起動に失敗した場合,すぐに次の起動プログラムを試してくれるようです.これを悪用しない手はありません.最初に「すぐにけせ」バイナリを起動させて,2段目に使用するOSを起動するように設定すれば,違和感なく起動時に「すぐにけせ」判定をさせることが出来ます.

「1/65536」

起動時に確率で発生させることはSFCでは出来ないはずです.しかし,我々の使っているモダンなコンピュータはRTCが内蔵されているので,起動時でも問題なく乱数を発生できそうです.
UEFIで日付を手に入れようとするには,RuntimeServicesのGetTime()を使えば良いのですが,渡されるのはEFI_TIME構造体で,○○年元旦からの積算秒で表しているわけではなく,年月日等々が直感的に分かる仕様*1でした.
時分秒とミリ秒が分かるようなので,ミリ秒ベースに変換して65536で割っています.お手軽実装です.ミリ秒だけは電源投入時から計測しているような気がして不安ですが.

画像について

複雑なファイルシステムを扱えるのがUEFIの売りな気がしますが,表示させる画像はリテラルconst unsigned char [] に直してソースコードに埋め込んでいます.
GraphicsOutputで表示させるために,BMP画像を変換してくれる関数がEDK2内のBdsConsole.cで定義されているので利用します.
変換した画像で画面を埋め尽くします.横端・縦端を描画する場合にはスクリーンをはみ出すので,書き込む範囲を予め計算しておきますが,横端を描画するために,描画するwidthを元画像より小さくしようとすると,何というか,水平同期の周期がズレる感じになって,うまく描画されません.1ピクセルずつ書けば良さそうですが,今回は諦めています.

ビルド

VS2012でビルドしました.下の記事を見てやってましたが,IntelliSense効かないっぽいのが悲しいです.
http://uefi.blogspot.jp/2012/06/how-to-set-up-edk2s-windows-hosted-uefi.html
実機で動かすバイナリをビルドするには,Conf/target.txtのACTIVE_PLATFORMをAppPkg/AppPkg.dscのように適切に変更しておきます.Nt32Pkg.dscでは動かなかったです.
また,実機がX64アーキテクチャしかサポートしていない場合には,VS2012の「VS2012 x64 Cross Tools コマンド プロンプト」からedk2setup.bat→buildでクロスコンパイルします.

動作

f:id:sosoru_m:20150819023004j:plain
実機動作.(ASRock Z87 Extreme 3)
1/2で出てくる高確率版を作って動作を確認しました.失敗した場合には,Windowsのブートに移ってくれるようです.
今日から1/65536版を入れてブートしますので,運悪く出てきたら追記します.

コード

EDK2のAppPkg/Mainを改変して作りました.
https://github.com/sosoru/sugunikese-on-uefi

その他

元ネタの記事には音もしたとあるので,ビープ音あたりで作れたら面白いのかなぁ.
むかし,SFCの「真・女神転生」やったときは,イケブクロあたりでやめてしまった気がします.RPGツクールの非公式リメイクでようやくエンディングを見ました.3Dダンジョン系はあんまり得意じゃないんだよなぁ.
この界隈のSFCのROM解析は進んでいて,バグを直すパッチが有志でリリースされてるの見たときはとても驚きました.