DQ6ルイーダ熟練度表示バグの解析(完全版)

以前下記のエントリで不完全に直したつもりになっていましたが、改めて調査をして原因がわかりました。

DQ6 ルイーダ熟練度表示バグの解析(不完全版)
相変わらずrcで止まっているDQ6インターフェース改良パッチですが、ルイーダの酒場での熟練度表示バグについて説明して欲しいというコメントがあったので回答します。まずはどういう現象かというと、以下の動画を見て下さい。 どうやらルイーダの酒場に...

結論から言うと前回の修正は直した「気」になっていただけで正しい変更法ではありませんでした。改めて不具合の内容については下記の動画を見てください。

問題としては軽微で「ルイーダに預けている仲間の職業熟練度の表示(熟練度の☆の部分)が別のキャラクターのもので表示される」というものです。データが破壊されているわけでもなく、仲間にして表示すると正しい内容で表示されます。

まずルイーダに預けている仲間の職業熟練度表示は以下のSRで処理されています。

  • SR:$0328D0 ウィンドウ_描画SR_001F
0328D0 JSL $C3736C SR: $03736C
0328D4 LDX $386E X=$386E
0328D7 JSL $C43674 SR: $043674 引数:1#$03 引数:2#$FE
0328DD LDA #$0070 A=#$0070
0328E0 JSL $C383FE SR: $0383FE
0328E4 LDA #$0070 A=#$0070
0328E7 JSL $C37C95 SR: $037C95
0328EB LDA #$0092 A=#$0092 ルイーダ待機中の仲間の職業熟練度表示(職業名)
0328EE JSL $C37C95 SR: $037C95
0328F2 LDA #$0093 A=#$0093 ルイーダ待機中の仲間の職業熟練度表示(熟練度)
0328F5 JSL $C37C95 SR: $037C95
0328F9 LDA #$008A A=#$008A
0328FC JSL $C37C95 SR: $037C95
032900 LDA #$0003 A=#$0003
032903 JSL $C37C95 SR: $037C95
032907 LDX #$0001 X=#$0001
03290A JSL $C37854 SR: $037854
03290E PLB Pull DB
03290F REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
032911 PLY Pull Y
032912 PLX Pull X
032913 PLA Pull A
032914 PLP Pull P Flag
032915 RTL return

大体は移動中のつよさ表示処理中で呼び出される職業熟練度表示処理SR: $0337DCと同じなのですが、$0328EC、$0328F3でセットしている値が、#$0092、#$0093と異なります。まだ完全には把握できていませんがDQ6のウィンドウ描画処理は「ウィンドウに描画したい項目のIDをセット→後でセットされたIDに対応する項目を一括描画」という手順らしく、実際の描画はSR: $037854がコールされるまでは行われません。この点逐次描画処理をやっているDQ3とは実装が異なります。当たり前ですが、後発のDQ3のほうがベースはDQ6を使っているものの、各所の実装もかなり洗練されている感があります。散々DQ3の実装に慣れてからDQ6を見るといろいろ不便に感じるところは多いです。

さて、動画を見てもらうとわかりますが、正しくない情報を表示しているのは「職業熟練度」のほうだけです。「職業名」自体は問題ないことがわかります。次に#$0092、#$0093コールされるSRを見てみます。

  • SR:$03A4D3 ウィンドウ描画処理アドレスリスト_SR_0092
03A4D3 LDX $3868 X=$3868
03A4D6 JSL $C42C26 SR: $042C26 引数:1#$03 引数:2#$FE 引数:3#$FD 指定位置のキャラクターID取得
03A4DD JSL $C42DB2 SR: $042DB2 引数:1#$FD 引数:2#$00 引数:3#$FE 指定キャラクターIDの並び順取得
03A4E4 STX $3868 $3868=X
03A4E7 BRL #$FE7B goto $03A365

このSRがコールされた時点で$7E3868には選択したキャラクターのウィンドウ中のインデックス(待機中の一番最初の仲間が0)がセットされています。これを元に最終的にはパーティメンバーも含めた何番目に相当するのかを調べて$7E3868にセットしなおしてやるという処理をしています。SR: $042C26のようなSRはDQ3にもありますが、「1番目の引数のモードで」「2番目の引数の値のインデックスを」「キャラクターIDに変換して3番目の場所にセットして返す」という意味です。キャラクターIDというのは$08BD12-に定義されている主人公が1、ハッサンが2…のIDのことです。#$FFならAレジスタ、#$FEならXレジスタ、#$FDならYレジスタ、それ以外ならDP($??)にセットされて返ってきます。この辺の解釈はDQ3、DQ6で共通なので知っておくとSRの理解がかなり進みます。自分も最初は何のことやらさっぱりわかりませんでしたが、今となってはそこそこ自在に操れます(他に使いどころがないのが笑えますが)。SR: $042DB2は「1番目の引数のキャラクターIDを」「2番目の引数のモードで」「3番目の引数に(モードに応じた)並び順等を返す」という意味のようです。モードについてはバリエーションが8つあるようです。なお、このSRの後は通常の職業熟練度表示処理(職業名のみ)に飛ばし表示処理をしているようです。これ自体は何も問題はありませんが、問題は次のSRです。

  • SR:$03A4EA ウィンドウ描画処理アドレスリスト_SR_0093
03A4EA LDX $3868 X=$3868
03A4ED JSL $C42C26 SR: $042C26 引数:1#$03 引数:2#$FE 引数:3#$FD
03A4F4 JSL $C42DB2 SR: $042DB2 引数:1#$FD 引数:2#$00 引数:3#$FE
03A4FB STX $3868 $3868=X
03A4FE BRL #$FF74 goto $03A475

この後のジャンプ先は今度は職業熟練度の表示(☆マークの方)に飛ばしています。同じことやってるだけなんだから別にいいじゃん、とぱっと見思ってしまうのですが、実はこのSRが呼ばれた時点で$7E3868にはSR: $03A4D3ですでに変換された値がセットされたままなのです。これをウィンドウ中のIDとして再度変換しているので、実質1ページ後ろのキャラクターを指してしまう(正確にはパーティメンバーの数によって変わると思いますが)ということになります。結論として、どう直すのが正しいかというと

  1. SR: $03A4EAの先頭で間の変換処理を挟まずにすぐに$03A4FEにジャンプしてしまう
  2. 変換自体が不要なので、通常のキャラクターの職業熟練度描画用のID(#$0090)を$0328F3でセットしてしまう

のどっちかということになります。キャラクターの情報の管理の仕方についても触れようと思ったのですが、非常に重要な部分なのでまた別途(投稿予定は未定)とします。

コメント

  1. マジックソース より:

    さっそく完全版の修正法を試してみました。ばっちり表示されました。
    実害はないバグとはいえ、育成キャラを眺めてニヤニヤしたいプレイヤーにはありがたいですよ!

    管理者より返信:

    この変更はDQ6 Extended対応のインターフェース改良パッチにも含める予定です。