YouTubeを見ていたらファミコン(FC)版のDQ3プログラマーの方が、格闘場でズルして大量ゴールドGETしようとしてた。
...けどオーバーフローのせいで失敗していて、その結果が気になったのでちょっと計算してみました。
[DQ3 王様誘惑激八百長祭り開催!]
王様はついに城を出て、アッサラームへ!
そこに待っていた誘惑に耐える王様!
そしてかつてない八百長が始まる・・最後までお見逃しなく!
格闘場の仕様
- 賭けるゴールドは主人公Lvの2倍となる。Lv99の時の198ゴールドが上限
(198=99*2)
- 闘技場のバトル・モンスターごとに倍率は決まっている。
- 通常は9.9倍が上限。
だが、FC内のメモリ値を改ざんすることで最大99.9倍まで設定できる?!
Youtubeの動画で行われたこと
準備
- モンスターの倍率が格納されているアドレスを確認する
0x6AD5
: モンスター1の闘技場での倍率(整数)0x6AD9
: モンスター1の闘技場での倍率(小数)
- 主人公のレベルを99に改ざんして、198ゴールド賭けれるようにする。
0x0700
: 主人公のレベル (0x63にすると10進数で99なので、Lv99になる)
-
モンスター1の倍率を99.9に改ざんし、モンスター1に賭ける
-
バトルが始まったら、モンスター1のHPを255・モンスター2以降のHPを1に改ざんし、モンスター1を強制的に勝利させる
0x5000,5001
: モンスター1のHP0x5002,5003
: モンスター2のHP0x5004,5005
: モンスター3のHP0x5006,5007
: モンスター4のHP
結果
- 19899.9なので19820ゴールドもらえる想定。(19820.2 = 19899.9)
- ...だが、120ゴールドしかもらえなかった。
- なぜ? (動画中ではオーバーフローのためとの説明)
- 動画中では、なぜ120ゴールドかについての説明は省略...
なぜ120ゴールドになったのか?
FCのハードウェア仕様や結果のゴールド数を見る感じでは以下の処理になっていそう。
獲得ゴールドの計算ロジック(予想)
FCのCPUは小数点の計算をする機能がない。
なので、内部的には下記の2ステップで獲得ゴールド(198*99.9)を求めている。
- Step1: まず198/999を計算する
- Step2: 上記Step1の結果を10で割る
処理結果
この流れで実際に計算すると、以下の処理となる。
- 198*999を計算すると197802になる
- だが、197802は16ビット整数の上限である65535に収まらない...
(2の16乗=655336)
- なのでオーバーフローして、この計算は1197になる
(19780を65536で割ると、3あまり1197)
- オーバーフローした1197を10で割って119.7、端数処理して120ゴールドと判定された。
その他メモ
上記のロジックであっているなら、オーバーフローしないギリギリは下記の倍率にすれば良さそう
- Lv99の場合、66.1倍の6544ゴールドになる
(65439=99*661)
- Lv90だと、72.8倍にすれば6552ゴールドまで獲得できる
(65520=90*728)
こちらもおススメ