以前ろだにう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:作業進度は極めて遅い
コメント