ロケットゲームコーナーの隠しコインのバグ

ロケットゲームコーナーには、見えないコインがいくつか落ちています。これらの隠しコインのうち、いくつかはバグによって異常な挙動を示します。

40枚落ちているはずのコイン(赤緑青ピカチュウ)

(x = 11, y = 7、スイッチがあるポスターから右に2マス・下に3マスのところ)に落ちているコインは、データ上40枚落ちていることになっています。ところが、隠しコインを拾ったときのコイン取得処理にバグがあり、実際には20枚しか手に入れることができません。

隠しコインを拾ったときの処理で、以下のように落ちている枚数に応じてコインを増やす処理があります。

  1. 落ちているコインの枚数を調べる
  2. 落ちているコインが10枚なら、6へ進む
  3. 落ちているコインが20枚なら、7へ進む
  4. 落ちているコインが40枚なら、7へ進む
  5. 落ちているコインが上記以外の枚数なら、9へ進む
  6. 手持ちのコインを10枚増やす
  7. 手持ちのコインを20枚増やす
  8. 手持ちのコインを40枚増やす
  9. 手持ちのコインを100枚増やす

4の処理は本来「落ちているコインが40枚なら、8へ進む」ですが、誤って20枚のときと同じ7へ進むようになっています。

拾えないコイン(赤緑青ピカチュウ)

(x = 12, y = 15、右から3列目・一番下のスロット台)にはコイン10枚が落ちています。ここはスロットと同じ場所であり、このマスを調べるとスロットで遊ぼうとするため、このコインを拾うことはできません。これは、調べているマスに隠しオブジェクトが存在するかどうかをチェックする処理と、隠しオブジェクトのリストでの定義順によるものです。

隠しオブジェクトが存在するマップでAボタンを押したとき、マップごとに定義されている隠しオブジェクトのリストを先頭から順に調べます。調べているマスと同じ場所に存在する隠しオブジェクトを見つけたとき、リストの探索を終了し、見つけた隠しオブジェクトに対応した処理を行います。

ロケットゲームコーナーの隠しオブジェクトは、36台のスロットと12個の隠しコインがこの順で定義されています。そのため、スロットと隠しコインが同じ場所に存在するマスではスロットの処理が行われ、隠しコインの処理は行われません。したがって、冒頭の場所にある隠しコインを拾うことはできません。

片方ずつしか取れないコイン(赤緑)

赤緑版には、片方の隠しコインを取得すると、もう片方の隠しコインが取れなくなるというバグがあります[1]。これは、隠しコインを調べたときに誤った場所のフラグを参照することがあるためです。詳細を以下で述べます。

まず、フラグとリストの定義をします。

隠しコイン取得フラグ
各隠しコインごとにbit単位で与えられる。1なら取得済み、0なら未取得。
リストC
隠しコインのあるマップと座標を定義しているリストで、フラグ立て・フラグ参照に使用される。リストCの各エントリはマップ番号(すべて87h)・y座標・x座標(各1バイト)の順で構成される。最後のエントリの直後には、終端を表すFFhの1バイトがある。各エントリの座標を以下の表に示す。
リストCのエントリごとの座標
No. 座標 落ちているコインの枚数(参考)
0 x = 0, y = 8 10枚
1 x = 1, y = 16 10枚
2 x = 3, y = 11 20枚
3 x = 3, y = 14 10枚
4 x = 4, y = 12 10枚
5 x = 9, y = 12 20枚
6 x = 9, y = 15 10枚
7 x = 16, y = 14 10枚
8 x = 10, y = 16 10枚
9 x = 11, y = 7 20枚*1
10 x = 15, y = 8 100枚
11 x = 12, y = 15 10枚*2

隠しコインが置いてあるマスを調べたとき、以下の処理が行われます。

  1. コインケースを持っているかどうかを調べる。持っていない場合は以降の処理を行わない。
  2. 調べている隠しコインが、リストCの何番目にあるかを探し、その位置を返す(この値をaとする)。なお、リストCの先頭は0番目とする。
  3. a番目の隠しコイン取得フラグを参照し、調べている隠しコインが取得済みかどうかを調べる。取得済みの場合は何もせず、未取得の場合はa番目の隠しコイン取得フラグを立ててコインを入手する。

2の処理にはバグがあり、正しくないaの値が返ってくることがあります。以下に、上記2の処理の内容を示します。

※以下の「○○ += n」は、「○○にnを加算する」という意味である。また、以下の処理が終了したときのaの値が、上記2の処理におけるaの値となる。

  1. a = 00h、hl = 「リストCの先頭アドレス」とする。
  2. アドレスhlの値を調べ、hl += 1とする。その値がFFhならa = FFhとして終了する。その値と現在のマップ番号が異なっている場合、hl += 2、a += 1として2に戻る。
  3. アドレスhlの値を調べ、hl += 1とする。その値と調べているマスのy座標が異なっている場合、hl += 1、a += 1として2に戻る。
  4. アドレスhlの値を調べ、hl += 1とする。その値と調べているマスのx座標が異なっている場合、2に戻る。
  5. リストCのa番目のエントリは調べている隠しコインに対応しているエントリなので、終了する。

バグがあるのは4の部分で、2に戻る前に「a += 1」の処理が抜けています。このバグが発生するのはリストCの5・7・8・10・11番目に対応する隠しコインを調べたときで、実際に参照されるフラグ(=aの値)はそれぞれ4・6・7・9・10番目となります。したがって、4と5、6と7、9と10の隠しコインはそれぞれ片方しか取ることができません。

参考文献

[1] おとしもの(隠しアイテム) - ポケモン 赤 緑 青 ピカチュウ 攻略 wiki

http://pokemon1gb2rgbp.wiki.fc2.com/wiki/%E3%81%8A%E3%81%A8%E3%81%97%E3%82%82%E3%81%AE%28%E9%9A%A0%E3%81%97%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0%29、2022年5月16日閲覧。

*1:上記の通り、データ上は40枚

*2:上記の通り、取得不可