DQ3 メガザル実装1

およそメガンテと言う呪文はDQをプレイして使ったことがないんですが、敵に使われた記憶もあまりなくて、DQ2でデビルロードに連発されて唖然としたくらいしか実際にお目にかかったことがありません。あの理不尽な死が今となっては懐かしい・・・。というわけで存在意義が怪しいので、DQ4-6でおなじみのメガザルを代わりに僧侶専用呪文として導入することにします(メガンテ自体は残すので爆弾岩は使ってきます)。まずはDQ6でメガザルの動きを確認します。

  1. 死者にはザオリク、生者にはベホマの効果
  2. 使用後術者は死亡
  3. 消費MPは全MP

オリジナルのメガザルはMPを全部使ってしまうと言うデメリットが大きすぎて「メガザルの腕輪」くらいしか使ったことがないんですが、あんまりなので消費MPは60ということにします。DQ4-6では馬車の中の死者も効果の対象なんで全MPを使うでもいいですが、DQ3では最大3人なのでそれだと割りにあわないので全MP消費というイレギュラーな仕様を実装するのが面倒なのでまあこのくらいでいいでしょう。

実装のポイントは2つです

  1. 死者にはザオリク、生者にはベホマの効果を実装する
  2. 使用後術者を死亡させる

・・・上とあんまり変わりませんが。2番目の実装はメガンテでもともと実装されているので新しくプログラムを書く必要はありません。ちょっと設定を追加するだけで実現できます。というわけで前半部分の実装を行います(本当はメガザル実装の説明の前に戦闘の流れの説明をしたかったんですが、まだまとめられていないので若干舌足らずになるかもしれません)。実は戦闘行動の行動プログラムアドレス(6-8バイト)に実装するのは「対象1体に対する処理内容」を実装すればいいようになっています。効果の範囲は対象数(21バイトの0-1ビット)の設定に従ってプログラムが自動でループしてくれます。というわけでここで実装すればいいのは「対象が死者であればザオリク、生者であればベホマ」となります。

  • SR: $02D3E6 メガザル
02D3E6 LDA #$0001 A=#$0001
02D3E9 PEA #$23AE Push #$23AE
02D3EC PEA #$0004 Push #$0004
02D3EF PEA #$7E00 Push #$7E00
02D3F2 JSL $C902E9 SR: $0902E9
02D3F6 LDX $23E8 X=$23E8
02D3F9 JSL $C2BE8A SR: $02BE8A 引数:1#$1C
02D3FE BCS #$42 if(c==on) goto $02D442
02D400 LDA $23E8 A=$23E8
02D403 STA $2428 $2428=A
02D406 JSL $C2BE8A SR: $02BE8A 引数:1#$00
02D40B STA $02 DP($02)=A
02D40D LDA #$FFFF A=#$FFFF
02D410 STA $00 DP($00)=A
02D412 JSL $C2BE8A SR: $02BE8A 引数:1#$04
02D417 JSL $C2BE8A SR: $02BE8A 引数:1#$00
02D41C CMP $02 A==DP($02)?
02D41E BEQ #$4B if(z==on) goto $02D46B
02D420 LDX $23E8 X=$23E8
02D423 JSL $C2CAD9 SR: $02CAD9 引数:1#$203C 引数:2#$00FF
02D42B CMP #$0005 A>=#$0005?
02D42E BCC #$3B if(c==off) goto $02D46B
02D430 JSL $C1E32E SR: $01E32E 引数:1#$00C4
02D436 JSL $C2B977 SR: $02B977
02D43A JSL $C1A867 SR: $01A867 引数:1#$005E
02D440 BRA #$29 goto $02D46B
02D442 LDA $23E8 A=$23E8
02D445 STA $2428 $2428=A
02D448 JSR $9716 SR: $029716
02D44B LDX $23E8 X=$23E8
02D44E JSL $C2CAD9 SR: $02CAD9 引数:1#$203C 引数:2#$00FF
02D456 CMP #$0005 A>=#$0005?
02D459 BCC #$10 if(c==off) goto $02D46B
02D45B JSL $C1E32E SR: $01E32E 引数:1#$00C4
02D461 JSL $C2B977 SR: $02B977
02D465 JSL $C1A867 SR: $01A867 引数:1#$005F
02D46B SEC c=on
02D46C RTL return

それほど長い実装にはなりませんでした。処理自体はいたって簡単です。SR: $02BE8Aで対象者の生死判定をして生きていればベホマの実装をパクったコードを、死んでいればザオリクの実装をパクったコードを実行させるだけです。C言語のイメージでは

[cpp]
if(対象が生きている){
ベホマの実装の一部
}
else{
ザオリクの実装の一部
}
[/cpp]

といった感じです。これ自体はそれほど難しいわけではありません。このSRで注意してもらいたいのは先頭の部分です。

02D3E6 LDA #$0001 A=#$0001
02D3E9 PEA #$23AE Push #$23AE
02D3EC PEA #$0004 Push #$0004
02D3EF PEA #$7E00 Push #$7E00
02D3F2 JSL $C902E9 SR: $0902E9

この部分です。SR: $0902E9はちょっと変わったSRで、フラグのセット、取得を行う場面でたびたび呼ばれるのですが、直前でPushしている6バイトを見れば大体想像がつくのですが、この場合は「$7E23AEの3ビット目(マスクすると04)にAの値(1)をセットする」という意味になっているようです。

—- LDA $23AE A=$7E23AE
—- AND #$FFFB A&=#$FFFB
—- ORA #$0004 A|=#$0004
—- STA $23AE $7E23AE=A

と同じことをしていると思われます。このSRを使う意味は恐らく関係ないビットに影響が出ないようにしたいというものではないかと思います。(逆に情報を取得するのは$09029Eです。こちらは同じようにして直前でPushした6バイトの情報を元に対象ビットのON/OFFをAレジスタに取得します。)さて、なぜこのビットをONにする必要があるかというと「メガンテ実行によって術者が死亡する必要があるか」を意味しているようで、これをONにしないと術者死亡処理で術者が死亡しないからです。メガンテ($0293E0)の先頭の実装も見てみてください。

長くなったので今日はこのへんで。