パスワードを忘れた? アカウント作成
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。

エミュレータ移植のWii版マリオ64、浮動小数点演算の関係でオリジナル版とは挙動が異なることが判明」記事へのコメント

  • 浮動小数点演算の規格IEEE754では複数の丸めモードが定義されているが、同じ丸めモードだったら処理結果は完全に一致するのではないのか?
    それともIEEE754とは無関係に独自実装したのか?

    • by Anonymous Coward on 2018年06月11日 20時29分 (#3423377)

      リンク先でたどれるGoogleドキュメントの [google.com]「Wii VC Rounding / BitFS Platform Drift」という項目によると、

      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は倍精度から単精度への変換方法は未定義です。結果、Wiiでは(SM64で行われる)最近接丸めではなく、切り捨てが行われます。

      とのことで、CPUへの命令の変換の仕方に問題があるとのことです。

      # SM64の意味が解らず、Google先生に聞いたらSuper Mario 64だと教えてもらった

      親コメント
      • by Anonymous Coward

        PowerPCのstfsを使わずに最近接丸めをソフト処理すりゃ直る程度の話かな。

        • by Anonymous Coward

          それよりは、計算誤差でどんどんズレるソフトの設計がマズいんじゃないかと。

          • by Anonymous Coward

            基本短時間のアクションゲームだからOKとするのはあり得るけど、この件はどうなんでしょうね。

            • by Anonymous Coward

              uint32のカウンターを1フレーム、1/60秒毎に++しておいて、キャラの動きやフェードイン、フェードアウトその他、あらゆる演出はそのカウンターの進み具合を基準に動かす、という実装が便利で楽。

              ただこれ、だいたい2年ちょっとでオーバーフローして0に戻るので、その瞬間に表示が乱れる。

              いくつかの場面でデバッガでオーバーフローの瞬間を再現してみて、大した事は起こらなさそう、ぐらいまでは試したけど、ゲーム中のあらゆる場面で大した問題が無いと試すのはテスト工数が多すぎて諦めた。

          • by Anonymous Coward

            設計は最近接丸めを想定していたのにエミュレーションの実装が不完全なのが悪い(まあ普通問題になることではないが)

            • by Anonymous Coward

              この丸めだから、どんなに計算を繰り返しても誤差は想定内に収まる、と証明するのは相当難しそうだと思うけど。

              問題になってる程度のプログラムなら、1周期分計算したら丁度同じ値になった、他の値は取りえない、これで大丈夫、ぐらいで証明できる可能性もあるけど。

              もし、そういう分かりやすい性質がなかったら、かなり大変。
              ちゃんと証明できるとしたら、ガチの数値計算の専門家ぐらい。

              (まともな大学の工学系だと、カリキュラムのどこかで、計算誤差の注意点については習うはず。
              浮動小数点数の計算順序を変えただけで誤差が大きく変わってくるとかそういう。
              プログラマなら誰

          • by Anonymous Coward

            元ゲームプログラマですが、そのとおりですね。
            元のマリオ64の作りが良くないです。
            現在位置に加減算して上下動させると誤差蓄積でずれや歪みが発生するので、
            本来は固定の基準点から相対的に上下動させるようにします。

            • by Anonymous Coward

              実機での誤差が累積して0になることを想定の上でコード書いてたら、
              移植を想定しないゲームのコードとしては問題ないんじゃないかな。

              • by Anonymous Coward

                > 移植を想定しない

                スーファミにもスーパーゲームボーイがあったくらいだから、移植やエミュの想定をしてないとは思えないな。
                OSのバージョンが変わると動かなくなるアプリのように、不用意な作りではあるだろうよ。
                メンテナ泣かせ。

              • by Anonymous Coward

                想定なんてできないってばよ。
                丸め方法の違いも、「誤差が蓄積するやつ」と「蓄積しないやつ」じゃなく、
                「誤差が蓄積するやつ」と「それよりは誤差が蓄積しづらいやつ」ぐらいの差しか無い。

                デバッガで入念にチェックすれば、運良く誤差が蓄積しない動作になってる事を確認できるかもしれないし、
                確認出来ればゲームの実装としてはそれで十分だと思うけど、
                確認に相当な手間が掛かるから、1クロックでも早く動くプログラムにしたい、とかの強い動機でもない限りはお勧めできない。

              • by Anonymous Coward

                一般論と個別論の区別がついとらんね
                「ある」プログラムについて誤差が蓄積しないことを確認するには「それ用」の検証プログラムで十分
                デバッガでやるやつはバカ
                ゲームプログラマにはクロック削りのような目先のことしかできないバカが多い印象があったがまた一つ裏付けられた

              • by Anonymous Coward

                そのスーパーゲームボーイにもゲームボーイ実機より動作速度が2.4%速いというバグがあるとか。
                スーパーゲームボーイ2で修正されたそうですが。

                スーパーゲームボーイと2のゲームスピードを比較してみた。
                http://nico.ms/sm13244115 [nico.ms]

              • by Anonymous Coward

                想定っていうか検証だな。
                記事見ると

                pos.y -= sins(angle) * 0.58;
                angle += 0x100;

                って処理がループするらしいけどangleが一巡した時にpos.yが同一の値になることを検証しておくだけでいい。

                スーパーゲームボーイは画面や入力はエミュだけどCPUはスーパーゲームボーイ内にゲームボーイ互換CPUが入ってたわけで、CPUの互換性が確保されていればCPUの動作に関しての問題は発生しなかった。

        • by Anonymous Coward

          CPUの命令はよくわかりませんが、
          stfsの前にfrspとかいう命令つかって丸める必要があったのかと

          • by Anonymous Coward

            stfsは単純なビットのコピーになってるのか…
            ストアと一緒にしときゃいいのにと思ったが、他の命令 [super-computing.org]を見ると浮動小数レジスタの使い方の問題なのか。
            倍精度のレジスタを持っているけど単精度演算のときも同じレジスタを使ってて使う命令で精度を区別してるぅ……

            倍精度演算の結果をストアせずに単精度演算に持ち込んだりする時に丸め命令単体で普通に使うし、
            単精度計算時の倍精度とのコスト差分やストア時の余計な丸めコストを削るとかそういうことか。

            FPUレジスタ(というか浮動小数レジスタ)に突っ込んだ時点で拡張倍精度に変換してストアまでそのままが基本なx86FPUの感覚で考えちゃ駄目だなコレ。

      • by Anonymous Coward

        エミュレータって、大抵は性能ぎりぎりの状態で開発がスタートするので、挙動が異なるのを承知で速い命令を採用することも少なくないと思います。
        現在のCPUでも丸めやデノーマルの処理方法の変更には大きなペナルティがあったりするので、仕方なく標準ライブラリと合わせていることもあるでしょう。

      • by Anonymous Coward

        縛りプレイなので9じゃなくて4の形になってます

        • by Anonymous Coward

          縛りプレイなので9じゃなくて4の形になってます

          なんだ甲羅の形じゃないのか

          • by Anonymous Coward

            甲羅?縛る?
            マリオにおいて、甲羅は蹴飛ばすものですし、
            SM64については、乗るものでしょう?

「科学者は100%安全だと保証できないものは動かしてはならない」、科学者「えっ」、プログラマ「えっ」

処理中...