DQ6戦闘部分解説12

長らくサボっていましたが、とりあえず再開します。改造作業も完全にサボってますwww。モチベ回復にはもうしばらく掛かりそうです。

  • SR:$023A0A 特技呪文対象選択処理
023A0A LDA $3874 A=$3874
023A0D STA $258D $258D=A
023A10 CMP #$0012 A==#$0012? 戦闘行動がミナデインか
023A13 BEQ #$34 if(z==on) goto $023A49
023A15 JSL $C2C1EC SR: $02C1EC 現MPが消費MP以上か(該当c=on)
023A19 BCS #$0D if(c==on) goto $023A28
023A1B LDA #$0060 A=#$0060 戦闘メッセージ「MPが たりない!」
023A1E STA $303E $303E=A
023A21 JSL $C5F58B SR: $05F58B 戦闘メッセージ表示
023A25 SEP #$40 v=on
023A27 RTS return
023A28 JSR $3AA5 SR: $023AA5 対象行動情報セット
023A2B BCC #$07 if(c==off) goto $023A34
023A2D JSL $C3B0B9 SR: $03B0B9 ウィンドウ消去(フェードなし)
023A31 SEP #$40 v=on
023A33 RTS return
023A34 LDA $258D A=$258D
023A37 CMP #$0012 A==#$0012?
023A3A BNE #$03 if(z==off) goto $023A3F
023A3C JSR $3A54 SR: $023A54 ミナデインフラグON
023A3F LDA $38B0 A=$38B0
023A42 DEC A–
023A43 JSL $C3B4F9 SR: $03B4F9 指定ページ以上の深さのバッファクリア
023A47 CLV v=off
023A48 RTS return
023A49 JSL $C26590 SR: $026590 ミナデインが実行可能か(該当c=on)
023A4D BCC #$D9 if(c==off) goto $023A28
023A4F LDA #$0089 A=#$0089 戦闘メッセージ「いまは となえられない!」
023A52 BRA #$CA goto $023A1E
  • SR:$02C1EC 現MPが消費MP以上か(該当c=on)
02C1EC PHP Push P Flag
02C1ED REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
02C1EF PHA Push A
02C1F0 PHX Push X
02C1F1 PHY Push Y
02C1F2 PHB Push DB
02C1F3 PEA #$7E7E Push #$7E7E
02C1F6 PLB Pull DB
02C1F7 PLB Pull DB
02C1F8 STZ $00 DP($00)=#$00
02C1FA LDA $2516 A=$2516
02C1FD AND #$0008 A&=#$0008 やまびこ発動中なら現MPは無視
02C200 BNE #$40 if(z==off) goto $02C242
02C202 LDA $2515 A=$2515
02C205 AND #$0080 A&=#$0080 まねまねによる反撃なら現MPは無視
02C208 BNE #$38 if(z==off) goto $02C242
02C20A LDA $258B A=$258B
02C20D ASL A< <1
02C20E TAX X=A
02C20F LDA $C2F092,X A=$02F092+X
02C213 TAX X=A
02C214 LDA $204F,X A=$204F+X
02C217 AND #$01FF A&=#$01FF
02C21A CMP #$0100 A>=#$0100? 発動者がPC側か
02C21D BCS #$08 if(c==on) goto $02C227
02C21F LDY #$FFFF Y=#$FFFF
02C222 LDA $2032,X A=$2032+X モンスター側現MPを取得
02C225 BRA #$0B goto $02C232
02C227 LDA $2061,X A=$2061+X
02C22A AND #$001F A&=#$001F 仲間になった順を取得
02C22D TAY Y=A
02C22E JSL $C46F13 SR: $046F13 現MPを取得
02C232 PHA Push A
02C233 LDX $258D X=$258D
02C236 JSR $C254 SR: $02C254 消費MP計算
02C239 STA $00 DP($00)=A
02C23B PLA Pull A
02C23C BCS #$0D if(c==on) goto $02C24B
02C23E CMP $00 A>=DP($00)?
02C240 BCC #$09 if(c==off) goto $02C24B
02C242 PLB Pull DB
02C243 REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
02C245 PLY Pull Y
02C246 PLX Pull X
02C247 PLA Pull A
02C248 PLP Pull P Flag
02C249 SEC c=on
02C24A RTL return
02C24B PLB Pull DB
02C24C REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
02C24E PLY Pull Y
02C24F PLX Pull X
02C250 PLA Pull A
02C251 PLP Pull P Flag
02C252 CLC c=off
02C253 RTL return

ここで重大なことを発見してしまいました。戦闘中アドレスの$2061の下位5ビットは「仲間になった順番」を意味しています。RAM中ではこの順番で移動中のPC情報を保存しているので、5ビットの最大値31体までしかこの情報を正しくこの領域に保持できません。DQ6 Extendedでは36体まで仲間を持てるようにしてしまったので32体目以降この部分の判定が正しくできないことになります(まだ確認していませんが)。恐らく32体目以降は1-5番目の仲間の現MP情報が使用されてしまうことになります。他に同様の箇所がどれくらいあるのかわかりませんが、全部別の方法で対象PCの開始アドレスを取得する方法に差し替える必要がありそうです。解決策としては$204F-50に保持しているキャラクターID(同じ種族の仲間モンスターでもIDが別になっているので特定可能)から開始アドレスを取得するという変換SRを使う(なければ新規作成)ことで対応することはできそうです。こういう発見があるので記事にするべく真面目に解析をするのは意味があると再認識しましたwww。

  • SR:$02C254 消費MP計算
02C254 PHA Push A
02C255 TXA A=X
02C256 ASL A< <1
02C257 TAX X=A
02C258 LDA $C8EE67,X A=$08EE67+X
02C25C TAX X=A
02C25D LDA $C8C660,X A=$08C660+X
02C261 AND #$003F A&=#$003F 対象の戦闘行動の消費MPを取得
02C264 CMP #$003F A==#$003F? #$3FならMP全消費
02C267 BEQ #$0F if(z==on) goto $02C278
02C269 STA $01,S Stack($01)=A
02C26B PLA Pull A
02C26C BEQ #$08 if(z==on) goto $02C276
02C26E CPY #$FFFF Y==#$FFFF?
02C271 BEQ #$03 if(z==on) goto $02C276
02C273 JSR $C27D SR: $02C27D 職業が賢者の場合の消費MP調整
02C276 CLC c=off
02C277 RTS return
02C278 PLA Pull A
02C279 BNE #$FB if(z==off) goto $02C276
02C27B SEC c=on
02C27C RTS return
  • SR:$02C27D 職業が賢者の場合の消費MP調整
02C27D PHA Push A
02C27E JSL $C476C8 SR: $0476C8 職業ID取得
02C282 CMP #$000E A==#$000E? 職業IDが賢者か?
02C285 BNE #$0E if(z==off) goto $02C295
02C287 TYA A=Y
02C288 ASL A< <1
02C289 TAX X=A
02C28A PLA Pull A
02C28B JSR $C297 SR: $($02C297+X)
02C28E CMP #$0000 A==#$0000?
02C291 BNE #$01 if(z==off) goto $02C294
02C293 INC A++ 消費MPが0なら1にする
02C294 PHA Push A
02C295 PLA Pull A
02C296 RTS return

ここでは行動主体者が賢者の場合に熟練度に応じてMPを調整する処理を行っています。処理の解析は省略しますが、以下のようになっています。さらに、計算の結果消費MPが0になる戦闘行動は消費MP1に強制的に変更しています。

熟練度 消費MP
1 100%
2 100%
3 87.5%
4 87.5%
5 75%
6 75%
7 62.5%
8 50%
  • SR:$026590 ミナデインが実行可能か(該当c=on)
026590 CLC c=off
026591 PHP Push P Flag
026592 REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
026594 LDA $2516 A=$2516
026597 AND #$0008 A&=#$0008 やまびこ中なら可能だから判定スキップ?
02659A BNE #$36 if(z==off) goto $0265D2
02659C LDA #$0006 A=#$0006 グループ番号6を指定してマスク情報作成
02659F JSL $C2E939 SR: $02E939 引数:1#$02 指定グループのキャラクターのみ残す
0265A4 JSL $C2E966 SR: $02E966 引数:1#$04 馬車内のキャラクターを外す
0265A9 JSL $C2E966 SR: $02E966 引数:1#$00 死人を外す
0265AE JSL $C2E9C6 SR: $02E9C6 引数:1#$28 麻痺中を外す
0265B3 JSL $C2E9C6 SR: $02E9C6 引数:1#$14 混乱中を外す
0265B8 JSL $C2E9C6 SR: $02E9C6 引数:1#$0C マホトーン中を外す
0265BD JSL $C2E966 SR: $02E966 引数:1#$3A 現MPが10未満を外す
0265C2 JSL $C252DF SR: $0252DF マスク情報から行動可能キャラクター数を取得
0265C6 CMP #$0004 A>=#$0004? 4人全員行動可能でないとミナデインは実行できない
0265C9 BCS #$07 if(c==on) goto $0265D2
0265CB LDA $01,S A=Stack($01)
0265CD ORA #$0001 Aor=#$0001
0265D0 STA $01,S Stack($01)=A
0265D2 PLP Pull P Flag
0265D3 RTL return

ミナデインという呪文は自分はDQ6で使った記憶がないのでよく知らなかったのですが、発動させるには条件があることがわかりました。

  • 4人全員生存
  • 麻痺中のPCがいない
  • マホトーン中のPCがいない
  • 混乱中のPCがいない
  • 全員のMPが10以上

1番目と5番目はともかくとして、マホトーン中や混乱中の仲間がいると発動できないとは知りませんでした。逆に睡眠中の仲間はいてもいいようですwww。ミナデインは実行ターンでは仲間全員の行動もできなくなるので、回復が必要なボス戦では危なっかしくて使う気にならないのですが(イメージ的にはそれで正しいとは思うけど)、これまたなんとかしたいところではあります。術者以外は動けるけど発動まで3ターン必要とかならいいかなと思います(もちろんその間別の術者がミナデインは使えない、発動ターンに上記条件を満たしていなかったら不発にするとか)。