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

| 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。
| 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ターン必要とかならいいかなと思います(もちろんその間別の術者がミナデインは使えない、発動ターンに上記条件を満たしていなかったら不発にするとか)。
コメント