羊飼いバグ - 秘密 - ウルティマ 聖者への道


(1) はじめに

本記事は、2ちゃんねるのウルティマスレで話題になった本作品のバグと、その原理・対策について、一部の情報や図解を追加したうえでまとめたものです。
バグの解析をしてくださった有志の皆様に感謝致します。

※当時のスレッド
【Lord】ウルティマ(Ultima) 11(X)【British】 >>971-982
【Lord】ウルティマ(Ultima) Part12【British】 >>21-36


(2) 羊飼いバグとは

以下の条件で戦闘に勝利したとき、羊飼いの経験値がマイナス512されてしまうバグです。
このバグのせいで、3人以下のパーティーで進めていると、羊飼いのレベルが4から上がりません。

  • 3人以下のパーティーで戦闘に勝利する
  • 羊飼いの経験値が512以上ある
    ※正確には、経験値を1024で割ったときの余りが512以上
  • 羊飼いがパーティーメンバーに入っているかは関係しない(旅人の部屋に預けていても発生する)

(3) バグの原理

このバグの原因は、戦闘後にパーティーメンバーのステータスを更新する処理のプログラムミスです。
簡単に説明すると、パーティメンバーに空きがある状態で戦闘終了すると、間違って羊飼いの経験値を更新してしまうのです。

※以下はコンピューター内部の話になるので、興味が無い方は(4)まで読み飛ばしてください。

ゲームの内部では、色々な情報を「バイト(byte)」(0~255の数値)という単位で管理しています。
このうち、キャラクターの経験値は2バイト(バイト2つ分)、ステータスは1バイトで管理されています。
(ちなみに、2バイト使うと0~65,535の数値を管理できます)
この経験値を管理するバイトと、ステータスを管理するバイトのアドレス(内部の位置)は、下図のように連続しています。

さて、問題のステータス更新処理ですが、内部的には「経験値を管理するバイトの最後(アドレス:68C8)から数えて○番目を更新する」という処理になっています。
この68C8が羊飼いの経験値を管理するバイトのアドレスで、○は職業に対応する1~8のID(番号)になります。
例えば、ID=2の吟遊詩人の場合は、68C8 + 2 = 68CA のアドレスを更新します。
ここでパーティーの数が3人以下で空きがある場合、ID=0のメンバーのステータスを更新しようとします。
このID=0が問題で、68C8から0番目、すなわち68C8 + 0 = 68C8 のバイトを書き換えるため、羊飼いの経験値が不正に更新されてしまうのです。


(4) バグを回避する方法

対策1.4人パーティーを組む

バグの原理上、4人パーティーを組んでいる間は、このバグは絶対に発生しません
また、経験値が減ってもレベルが下がることはないので、 4人パーティーで羊飼いのレベルを8まで上げた後なら、3人以下のパーティーにしても問題はありません。
羊飼い一人旅のようなやりこみプレイでもしない限り、この方法で実害なくプレイできます。

対策2.プログラムを書き直す

根本的な解決方法は、プログラムを書き直すことです。
実機(ロム)のプログラム自体を書き換えることはできませんが、 ロムに焼かれたプログラムイメージを特殊なツールを使ってデータ(ロムイメージ)として吸い出し、 その一部をBzなどのバイナリエディタで書き換えることで、プログラムミスを修正することが可能です。
書き換えたロムイメージをVirtuaNESなどのエミュレータを使って読み込めば、バグが修正されたゲームを遊ぶことができます。
以下に、データの修正箇所と修正内容を載せます。

※注意事項
・データの吸出しや変更は、ご自身の責任で実施をお願い致します。
・非合法に配布・コピーされたロムイメージを使って遊ぶのは著作権の侵害であり犯罪です。
 本記事の目的はバグの存在と原理の紹介であり、違法行為を肯定や推奨するものではありません。

データ修正箇所
修正箇所(バイト位置) 修正内容(値の変更)
26C1C BC → A0
26C1D 15 → 08
26C1E 68 → EA
26C27 CA → 88
26C28 10 → D0
26C29 F2 → F5

この修正は、戦闘後のステータス変更処理の対象を、「パーティーメンバー全員」から「主人公+仲間全員」に変更します。
そのため、存在しないメンバー(ID=0)の更新処理がなくなり、バグを完全に回避できるようになります。