DQ3 ショートカット機能の一部修正1

以前ろだにうpされていた改造初心者氏のショートカット機能のプログラムですが、基本問題ないんですが一点ルーラを実行すると天井に頭をぶつける場所でルーラをショートカット経由で実行するとハングします。改造初心者氏のプログラムと違うところだけ記載しようと思ったんですが、どこが違うのか調べるのが面倒くさいので、ショートカットの実行部分の実装をまるごと貼ることにします。※現在公開しているDQ3 K.Mixではこの対処は予め組み込んであるので現象は発生しません。

  • SR: $0768C4 移動中パッド入力解釈処理
0768DB JSR $CF00 SR: $07CF00 ショートカット実行処理
0768DE BCC #$03 if(c==off) goto $0768E3
0768E0 RTS return
0768E1 NOP
  • SR: $07CF00 ショートカット実行処理
07CF00 LDA $7F70 A=$7F70 パッド入力内容のチェック
07CF03 BIT #$0010 A & #$0010
07CF06 BNE #$0E if(z==off) goto $07CF16
07CF08 STZ $20C4 $20C4=#$00
07CF0B LDA $18 A=DP($18)
07CF0D STA $7F72 $7F72=A
07CF10 AND $1A A&=DP($1A)
07CF12 STA $18 DP($18)=A
07CF14 CLC c=off
07CF15 RTS return
07CF16 CMP $20C4 A==$20C4?
07CF19 BEQ #$ED if(z==on) goto $07CF08
07CF1B CMP #$0010 A==#$0010?
07CF1E BEQ #$E8 if(z==on) goto $07CF08
07CF20 JSR $CF4C SR: $07CF4C 各キーに割り当てた移動呪文IDから戦闘行動IDを取得(未設定c=off)
07CF23 BCC #$E3 if(c==off) goto $07CF08
07CF25 JSL $C7CFE4 SR: $07CFE4 対象行動が現パーティの状態で実行可能か判定(可能c=on)
07CF29 BCC #$DD if(c==off) goto $07CF08
07CF2B JSL $C7D100 SR: $07D100 ショートカット用呪文実行処理
07CF2F LDA $7F70 A=$7F70
07CF32 STY $20C4 $20C4=Y
07CF35 JSL $C31EE4 SR: $031EE4 フィールド画面復帰?
07CF39 SEC c=on
07CF3A RTS return
  • SR: $07CF4C 各キーに割り当てた移動呪文IDから戦闘行動IDを取得(未設定c=off)(省略)
  • SR: $07CFE4 対象行動が現パーティの状態で実行可能か判定(可能c=on)(省略)
  • SR: $07D100 ショートカット用呪文実行処理
07D100 PHP Push P Flag PUSH 1回目
07D101 REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
07D103 PHA Push A PUSH 2回目
07D104 PHX Push X PUSH 3回目
07D105 PHY Push Y PUSH 4回目
07D106 PHB Push DB PUSH 5回目
07D107 PEA #$7E7E Push #$7E7E
07D10A PLB Pull DB
07D10B PLB Pull DB
07D10C JSL $C32060 SR: $032060 戦闘画面切り替え?
07D110 TSC A=S
07D111 STA $33FC $33FC=A
07D114 LDA #$AD3B A=#$AD3B
07D117 LDX #$00C3 X=#$00C3
07D11A JSL $C316DE SR: $0316DE Y,Rボタン時ジャンプ先アドレスセット?
07D11E LDA $06,S A=Stack($06)
07D120 CMP #$0174 A==#$0174? 処理がまんたん(戦闘行動ID:#$0174として定義)か調べる
07D123 BNE #$11 if(z==off) goto $07D136
07D125 JSL $C32251 SR: $032251 引数:1#$D9 ウィンドウ表示更新(1枚) まんたん専用
07D12A JSL $C91F27 SR: $091F27 まんたん処理メイン
07D12E PLB Pull DB
07D12F REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
07D131 PLY Pull Y
07D132 PLX Pull X
07D133 PLA Pull A
07D134 PLP Pull P Flag
07D135 RTL return
07D136 LDA $06,S A=Stack($06)
07D138 JSR $D14F SR: $07D14F ショートカット用呪文実行処理(コア・移動中通常メニュー処理と階層を合わせるため別関数化した)
07D13B BRA #$F1 goto $07D12E
  • SR: $07D14F ショートカット用呪文実行処理(コア・移動中通常メニュー処理と階層を合わせるため別関数化した)
07D14F STA $33DA $33DA=A
07D152 JSR $D04B SR: $07D04B ショートカット呪文実行者決定処理
07D155 STA $33D6 $33D6=A
07D158 STA $BE7D $BE7D=A
07D15B LDX $33DA X=$33DA
07D15E JSL $C2CC03 SR: $02CC03 引数:1#$0060 戦闘行動構造体アクセスSR インデックス:X
07D164 STA $BE77 $BE77=A
07D167 JSL $C32251 SR: $032251 引数:1#$DA ウィンドウ表示更新(1枚)ショートカット汎用
07D16C JSL $C90D2F SR: $090D2F 移動中呪文使用処理
07D170 RTS return

ポイントは$07D100、$07D14Fです。ここの出だしを移動中メインメニュー処理($03AC8A)と同じにすることでルーラで頭をぶつけた時のハングを回避できます。ルーラで頭をぶつけた後の処理は以下のようになっています。

  • SR: $090E80 キメラの翼使用(移動中)
090EAF JSL $C3416A SR: $03416A 頭をぶつける場所でルーラを実行するとここに飛ぶ
090EB3 JSL $C31EE4 SR: $031EE4
090EB7 JSL $C1D22A SR: $01D22A ルーラでPCが頭をぶつける描画
090EBB JSL $C1A8D4 SR: $01A8D4 引数:1#$0021 メッセージ表示:「頭をぶつけた」
090EC1 JSL $C340F7 SR: $0340F7 ウィンドウでのキー入力結果取得(キャンセルc=on)
090EC5 PLA Pull A $091188でPUSHした分をPULL
090EC6 JMP $090EDA goto $090EDA
090EDA SEP #$20 m=on(A/M:8b)
090EDC PLA Pull A PULL 1バイト
090EDD REP #$20 m=off(A/M:16b)
090EDF PLA Pull A PULL 合計3バイト
090EE0 PLA Pull A PULL 合計5バイト
090EE1 JSL $C31EE4 SR: $031EE4
090EE5 PLB Pull DB PULL 1回目
090EE6 REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
090EE8 PLY Pull Y PULL 2回目
090EE9 PLX Pull X PULL 3回目
090EEA PLA Pull A PULL 4回目
090EEB PLP Pull P Flag PULL 5回目
090EEC RTL return

移動中メインメニュー処理($03AC8A)から各呪文を実行するまで、プログラムカウンタは各種メニューSR(SR: $($03AD2F+X))をコールして(2バイト1回)、移動中呪文使用処理(SR: $090D2F)をコールして(3バイト1回)の合計5バイトスタックに積まれます。この分のプログラムカウンタをPULLして帳尻を合わせているのが$090EDA~EE0です。下流でこういう処理がされている以上、上流で同じようにプログラムをコールしてやらないとスタックの対応関係がおかしくなってハングすることになります。従って、$07D14Fを2バイトコールにして2バイト分、$090D2Fをコールして3バイト分にすると辻褄が合うことになります。回復呪文などの処理は$07D12Eに戻ってくるので関係ありません。

さて、最近は例のDQ6のAIの解析+DQ3 K.MixへのAI移植をつらつらとやっています*1。AI部分の解析率は40%~50%くらいといったところで、大枠に関しては大体把握したのでいつまで眺めてばかりいても話が進まないので、見よう見まねで一部を移植しています。とりあえずはUI+枠組みとモンスターの情報が関係ない回復・蘇生系に関しては大体終わり、実装の終わっている範囲でテストを繰り返してベースに関してはまあそこそこできているかなというところです。バイナリwikiにRAMの意味が詳細に書いてあるのでDQ6の解析はやる気になれば割と捗ります。基本的にはDQ3はDQ6より情報量が少ないので移植は楽なはずですが、DQ3にはモシャスというバグの温床のような仕組みがあるのでこの点には十分注意が必要になります(あとは呪術師の思考パターンが結構面倒そう)。また、気になるのはAIの思考速度です。呪文・特技の量が多いDQ6と違ってDQ3の呪文数はそれほど多くないのでDQ6と同じレベルで実装できれば問題無いと思うのですが、まだ解析が進んでいない攻撃・補助系の実装如何では体感できる遅さが現れるかもしれません。ちなみに、DQ6では実行コード量を極力少なくするため、各種情報へのアクセスはSRを使わずメモリへのダイレクトアクセスを多用しているようです。依然として公開できるレベルの満足の行くものができるかの見通しは不透明のままです。作業してて面白いことは確かですが。

*1:作業進度は極めて遅い