This is caused by the Wii VC incorrectly converting the MIPS cvt.s.d instruction to the PowerPC stfs instruction. With the latter, double to single precision floating point conversion is undefined. The Wii uses round-to-zero for this conversion, while SM64 uses round-to-nearest. 【適当な訳】 このバグは、WiiVCが内部的にMIPS(64のCPU)の命令「cvt.s.d」をPowerPC(WiiのCPU)の命令「stfs」に変換することによって発生します。stfsは倍精度から単精度
設計がおかしいのか? (スコア:1)
浮動小数点演算の規格IEEE754では複数の丸めモードが定義されているが、同じ丸めモードだったら処理結果は完全に一致するのではないのか?
それともIEEE754とは無関係に独自実装したのか?
Re: (スコア:5, 参考になる)
リンク先でたどれるGoogleドキュメントの [google.com]「Wii VC Rounding / BitFS Platform Drift」という項目によると、
Re:設計がおかしいのか? (スコア:0)
PowerPCのstfsを使わずに最近接丸めをソフト処理すりゃ直る程度の話かな。
Re: (スコア:0)
それよりは、計算誤差でどんどんズレるソフトの設計がマズいんじゃないかと。
Re: (スコア:0)
基本短時間のアクションゲームだからOKとするのはあり得るけど、この件はどうなんでしょうね。
Re: (スコア:0)
uint32のカウンターを1フレーム、1/60秒毎に++しておいて、キャラの動きやフェードイン、フェードアウトその他、あらゆる演出はそのカウンターの進み具合を基準に動かす、という実装が便利で楽。
ただこれ、だいたい2年ちょっとでオーバーフローして0に戻るので、その瞬間に表示が乱れる。
いくつかの場面でデバッガでオーバーフローの瞬間を再現してみて、大した事は起こらなさそう、ぐらいまでは試したけど、ゲーム中のあらゆる場面で大した問題が無いと試すのはテスト工数が多すぎて諦めた。
Re: (スコア:0)
設計は最近接丸めを想定していたのにエミュレーションの実装が不完全なのが悪い(まあ普通問題になることではないが)
Re: (スコア:0)
この丸めだから、どんなに計算を繰り返しても誤差は想定内に収まる、と証明するのは相当難しそうだと思うけど。
問題になってる程度のプログラムなら、1周期分計算したら丁度同じ値になった、他の値は取りえない、これで大丈夫、ぐらいで証明できる可能性もあるけど。
もし、そういう分かりやすい性質がなかったら、かなり大変。
ちゃんと証明できるとしたら、ガチの数値計算の専門家ぐらい。
(まともな大学の工学系だと、カリキュラムのどこかで、計算誤差の注意点については習うはず。
浮動小数点数の計算順序を変えただけで誤差が大きく変わってくるとかそういう。
プログラマなら誰
Re: (スコア:0)
元ゲームプログラマですが、そのとおりですね。
元のマリオ64の作りが良くないです。
現在位置に加減算して上下動させると誤差蓄積でずれや歪みが発生するので、
本来は固定の基準点から相対的に上下動させるようにします。
Re: (スコア:0)
実機での誤差が累積して0になることを想定の上でコード書いてたら、
移植を想定しないゲームのコードとしては問題ないんじゃないかな。
Re: (スコア:0)
> 移植を想定しない
スーファミにもスーパーゲームボーイがあったくらいだから、移植やエミュの想定をしてないとは思えないな。
OSのバージョンが変わると動かなくなるアプリのように、不用意な作りではあるだろうよ。
メンテナ泣かせ。
Re: (スコア:0)
想定なんてできないってばよ。
丸め方法の違いも、「誤差が蓄積するやつ」と「蓄積しないやつ」じゃなく、
「誤差が蓄積するやつ」と「それよりは誤差が蓄積しづらいやつ」ぐらいの差しか無い。
デバッガで入念にチェックすれば、運良く誤差が蓄積しない動作になってる事を確認できるかもしれないし、
確認出来ればゲームの実装としてはそれで十分だと思うけど、
確認に相当な手間が掛かるから、1クロックでも早く動くプログラムにしたい、とかの強い動機でもない限りはお勧めできない。
Re: (スコア:0)
一般論と個別論の区別がついとらんね
「ある」プログラムについて誤差が蓄積しないことを確認するには「それ用」の検証プログラムで十分
デバッガでやるやつはバカ
ゲームプログラマにはクロック削りのような目先のことしかできないバカが多い印象があったがまた一つ裏付けられた
Re: (スコア:0)
そのスーパーゲームボーイにもゲームボーイ実機より動作速度が2.4%速いというバグがあるとか。
スーパーゲームボーイ2で修正されたそうですが。
スーパーゲームボーイと2のゲームスピードを比較してみた。
http://nico.ms/sm13244115 [nico.ms]
Re: (スコア:0)
想定っていうか検証だな。
記事見ると
って処理がループするらしいけどangleが一巡した時にpos.yが同一の値になることを検証しておくだけでいい。
スーパーゲームボーイは画面や入力はエミュだけどCPUはスーパーゲームボーイ内にゲームボーイ互換CPUが入ってたわけで、CPUの互換性が確保されていればCPUの動作に関しての問題は発生しなかった。
Re: (スコア:0)
CPUの命令はよくわかりませんが、
stfsの前にfrspとかいう命令つかって丸める必要があったのかと
Re: (スコア:0)
stfsは単純なビットのコピーになってるのか…
ストアと一緒にしときゃいいのにと思ったが、他の命令 [super-computing.org]を見ると浮動小数レジスタの使い方の問題なのか。
倍精度のレジスタを持っているけど単精度演算のときも同じレジスタを使ってて使う命令で精度を区別してるぅ……
倍精度演算の結果をストアせずに単精度演算に持ち込んだりする時に丸め命令単体で普通に使うし、
単精度計算時の倍精度とのコスト差分やストア時の余計な丸めコストを削るとかそういうことか。
FPUレジスタ(というか浮動小数レジスタ)に突っ込んだ時点で拡張倍精度に変換してストアまでそのままが基本なx86FPUの感覚で考えちゃ駄目だなコレ。