#25 【懐ゲーム】ドラクエⅣのバグについてプログラマー視点で解説する
本日仕事中に盛り上がった話について書いていこうと思います。
新人にchar型変数1バイトのビットの管理を教えている最中、シフトし続けてオーバーフローしたらどうなるか?という話をしていたのですが、
そこで突如、ドラクエⅣで8回逃げたら会心の一撃連発になるバグ、あれってオーバーフローが原因だったらしいよ、という同僚の言葉。
ああ確かにそんなバグあった!!!って盛り上がるおじさん連中にキョトンとする新人くん。
まさかビット計算の話から、ドラクエ4に話が飛ぶとは思いませんでした(笑)
ドラクエⅣ
今までロト3部作のシリーズから一転。
のちに、天空シリーズと呼ばれる第一作目。
そのバグについて今更ながら解説。
ファミコン版のドラクエ4は、今考えると信じられませんが、512キロバイトのROM容量だったようです。
スマホで撮った写真1枚より小さいね。
そんなROMであったため、少しでも容量を抑えるための努力として、フラグをビットで管理していたようなのです。
高々数回のカウンターとしか使わない変数に、1バイトすら使うのがもったいないと。
ドラクエⅣの場合、通常の戦闘であれば4回目の逃げるを行うと確実に逃げられるようになるのですが、その際のフラグカウントとして、以下。
初期値 :0000 0000(2進数8ビットです)
逃げ1回:0000 0001
逃げ2回:0000 0010
逃げ3回:0000 0011
という管理になっていたようで、要は2ビットあれば0~3を表現できるため、3桁目~8桁目は別の情報として使っていたのですね。
ところが、ボス戦では当然何回逃げようが逃げられるわけがないので、逃げるカウンターがどんどん加算されていきます。
(これがバグですね)
逃げ4回:0000 0100
逃げ5回:0000 0101
逃げ6回:0000 0110
逃げ7回:0000 0111
逃げ8回:0000 1000
この逃げ8回の状態までカウントアップして書き込まれた領域。
これが、会心の一撃連発状態、になるフラグだったようです。
(通常であれば、パルプンテを使って「力がみなぎってきた」が発動したときに書かれる領域らしいです)
ここに「1」が設定されていると常に会心の一撃モード。
当時エスタークが倒せなかった小学生は、大変お世話になったバグですねw
また、ついでにもう一つ同じようなバグが。
838861
この数字に聞き覚えはありますでしょうか。
そう。
カジノコイン激安で買える裏ワザです。
ドラクエのカジノでは、1枚20ゴールドで買えるコインを使って、スロットマシンやらポーカーやらでコインを増やし、はぐれメタルシリーズの防具を手に入れることができました。
838,860枚のコインを買うために必要なお金は、約1,700万ゴールド。
ですが、この数字に1を足した、838,861枚に設定することで、なんと4ゴールドで買えてしまうというバグがありました。
これはいわゆるオーバーフローが原因だったようです。
逃げるフラグとは違い、カジノコイン変数は24ビットで表現していたみたいです。
4バイト変数の下位24ビットを使っていたのでしょうね。
1が24個分のビットで
1111 1111 1111 1111 1111 1111(2進数)
10進数表記で16,777,215。
これを20ゴールドで割ると838,860.75枚になり、一度に買うことのできる最大枚数は838,860枚のハズでした。
が、これに1枚足して買うことによって、
838,861枚×20ゴールド=16,777,220
2進数で表記すると
1 0000 0000 0000 0000 0000 0100
25桁になってしまい、オーバーフローした25桁目の1が有効値ではなくなり、(100)が残ります。
この(100)は10進数で4になるため、4ゴールドで838,861枚のコインが買えてしまう、というバグなのですね。
いやー懐かしすぎて涙出るほど笑いましたw
noteまとめ『文書遊戯』に参加しています
面白いnote沢山更新されるので、覗いてみてはいかがでしょうか♪
この記事が気に入ったらサポートをしてみませんか?