ある日のこと
ある日、いつものように開発を進めているときのこと。……ん??
おわかりになっただろうか……? 画面の下の方に謎のノイズが発生してしまっています。これはスタックサイズが足りないときに起きるフレームバッファの破壊ですね。こういうバグを見かけたときにすぐに原因が思い当たるように、ドキュメントを一通り読んで、あらかじめ幅広く知識を蓄えておくことは大切です。
メモリレイアウトの記事で確認したように、スタックが突き抜けてしまうと、そのさきにあるのはフレームバッファ、つまり画面の表示内容のメモリ領域です。まあこの程度ならゲームのプレイに致命的な支障が生じるわけではないですし、意外にそれ以外は普通に動作したりします。ただし、フレームバッファも突き抜けてしまった場合は、その先はゲームパッドの状態などが格納される領域なので、それが破壊されたらゲームは正しく動かないでしょう。スタックサイズを調節して、フレームバッファの破壊が起きないようにしたいと思います。
スタックサイズの伸長
この記事の執筆時点で、さきほど「ドキュメントを一通り読め」と言ったわりには実は私は、めんどうくさいので Cargo のドキュメントは読んでおらず、Cargo.tomlや.cargo/config.tomlの内容はよくわかっていません。なぜCargo.tomlと.cargo/config.tomlのふたつの設定ファイルがあるのか謎ですが、まあビルドツールの設定ファイルの詳細とかガチで1ミリも興味ないので、勘でなんとかしようと思います。
幸い、.cargo/config.tomlを覗いたら、修正するべき場所はすぐにわかりました。フレームバッファが壊れているならこの値を増やせ、ってちゃんとコメントで書いてくれてありますね。ありがたいです。
# Reserve 2044 bytes of stack space, offset from 6580.
# Bump this value, 16-byte aligned, if the framebuffer gets corrupted.
"-C", "link-arg=-zstack-size=8624",
# Not working? https://github.com/rust-lang/rust/issues/46645#issuecomment-423912553
"-C", "link-arg=--global-base=6560",
筆者はこういう低レベルっぽい環境はほとんどやったことがないので、こんなふうにリンカのオプションで生のスタックサイズをオプションで指定とかもまったく馴染みがありません。いやそんな本質的でないオプションの調整とか自動でやってくれよと思うのですが、まあそうはいかないのがRust/WASMという環境なんでしょう。
現在の設定では、スタックサイズzstack-size
は 16b * 539 = 8624b
となっているようです。どのくらい増やせばいいのかはよくわかりませんが、これを16b * 700 = 11200b
くらいまで増やしてみます。また、global-base
というのもずらさないといけないようで、WASM-4が予約している領域 2044
バイトのぶんだけズレた、11200 - 2044 = 9156
を渡せばいいようです(←よくわかってないので 勘 でやってる)。
"-C", "link-arg=-zstack-size=11200",
"-C", "link-arg=--global-base=9156",
こんな感じで手動でスタック領域を増やして再度実行すると、無事に画面下のノイズが消えました。気になる人は、WASM-4の開発ツールのメモリマップで、どのくらい余裕ができたか確認してみてもいいでしょう。
ある日のこと
ある日、いつものように開発を進めているときのこと。
= note: rust-lld: error: initial memory too small, 65552 bytes needed
!? いきなりリンクエラーとか出るととても心臓に悪いのでやめてほしいのですが、なぜかコードをわずかに足すだけで謎エラーが出ます。「メモリが足りない」というような旨のリンクエラーのようなので、.cargo/config.toml
をいじってみます。よくわからないのですが、適当にlink-arg=-zstack-size
をデフォルトの14752
から14560
に減らすとビルドが通りました。
それでいろいろ調べていたら、上記の--global-base
オプションは機能していない、ということらしいです。
どうも cargo が勝手に --stack-first
というオプションをリンカに渡すのですが、そのオプションをつけると --global-base
オプションは無視されるのだとかなんとか。それで最近テンプレートファイルが修正されており、上記の --global-base
オプションは削除されていました。
詳しいことはよくわからないのですが、私のようにWASM-4&Rustで開発したい人がいたら気をつけたほうがよさそうです。このへん、もうわけがわからなすぎるので、誰かRustに詳しい人がいたらこれでいいのかどうか教えてください。
次回予告
WASM-4はカートリッジを64キロバイトに収めなければなりません。Rustだとそのあたりに意外に工夫が必要です。もしWASM-4をRustで開発したい人がいれば、次回の内容はめちゃくちゃ実践的なテクニックになります。いやさすがに64キロバイトは厳しいやろ!