魔法の忘却処理 その2

前回のプログラムでは全然正常に動いてくれませんでした。
アキュームレータの値を保持しつつ、一旦アドレスに値を書き込んでおかねば
ORの後のEORがまともに動いてくれないですね、はい。
というわけで第2弾はこんな感じ。


045810 22 71 F9 C4 JSL $04F971
045814 59 24 00 EOR $0024 "Y"


04F971 BF AC 56 C4 LDA $0456AC "X" ; "A" = $0456AC+"X"
04F975 48 PHA
04F976 19 24 00 ORA $0024 "Y"
04F979 99 24 00 STA $0024 "Y"
04F97C 68 PLA
04F97D 6B RTL


動作確認をしたところ、ちゃんと魔法を忘れ、かつ思い出さないことは確認。
ただし、レベルアップ後のメッセージには毎回「おもいだすを覚えた」と表示されてしまう。
でもまあ、ステータスがらみの部分は一段落つけたかな、と。
あとはメッセージ絡みの問題に着手していく。

魔法の忘却処理

レベルアップ時に魔法を覚える処理について少し調査してみた。


045814 19 24 00 ORA $0024 "Y"
この処理で魔法を覚えさせているみたい。
ORだとビットが立ってしまうので、とりあえずビットを削るという意味でEORとしてみた。
結果、最初のレベルアップ時に魔法を忘れることができたが、
次のレベルアップの時に魔法を思い出してしまうという現象が発生。
どうやら、レベルアップの際に毎回「覚えていない魔法」を走査して
足りてない魔法をすべて覚えさせようとしているみたいだ。


よって、以下のマトリクスによって値を書き込む/書き込まないという処理を記述してやらないといけない。
いろいろ考えたのですが、とりあえずORした後にEORするという方法を考案してみました。
EOR処理を追記する場所はないので、直前の


045810 BF AC 56 C4 LDA $0456AC "X" ; "A" = $0456AC+"X"
となっているところにJSLを差し込んでフックさせてみる。
とりあえずこんな感じでしょうか。



045810 22 71 F9 C4 JSL $04F971
045814 59 24 00 EOR $0024 "Y"


04F971 BF AC 56 C4 LDA $0456AC "X" ; "A" = $0456AC+"X"
04F975 19 24 00 ORA $0024 "Y"
04F978 6B RTL

レベルアップ処理

キャラメイキングの方はとりあえず一段落して、
次の行程はレベルアップ時の処理です。


ステータス変更はプラスしてる処理をマイナスにするだけなのでそんなに手間にはならないと思うんだけど、
問題は呪文を「忘れる」処理だと思っている。
実際のプログラムがどうなっているのか確認していないので、
もしかしたら案外簡単なのかもしれないけど、っていうか簡単であってほしい。

仲間の作成 その2

魔法の取得については完全オリジナルの関数を作ってやる必要があると思い始めた。
ちょうど関数$046980で職業IDを取得しているので、取得してから次の処理で分岐させてやり、パラメータを固定で書き込む方がいいのではないだろうか。
まあ、そうなると転職したときとかどうすんだっていう問題がつきまとってくるわけですけど。
それはまた後で考えよう。


上記の通りやろうと思うと、「呪文の取得 その2」で書いたプログラムに手を加えていかないといけないことに。
紆余曲折の末書き上げたプログラムはちょっと長くなってしまったのでここでの掲載は省略。
ひとまず酒場で作ったキャラクタの初期状態は一段落しました。

仲間の作成

勇者のキャラメイキングはほどほどに、ルイーダの酒場にやってきた。
まずは初期メンバーの確認。
ステータスは普通(改造されてない的な意味で)だけど、対応するのが面倒くさいのでひとまず放置。
2階に上がり、キャラメイキングを開始。
以下の問題点が浮上。
・女性キャラ作成時のパラメータが変
・戦士系の魔法が使えないキャラでも最初から魔法が全部使える
前者はともかく、後者はやっかいだなあ。
キャラメイク時限定で職業を判別して取得する魔法を上書きしてやるしかないのか?


ひとまず、性別によってパラメータがおかしい件について。
関数$04425Dを見ていると、


044262 22 47 2E C4 JSL $042E47
この処理で性別を取得して、

044266 C9 01 00 CMP #$0001
044269 F0 61 BEQ #$61 -> $0442CC
この処理で男性女性と分岐していくわけだ。
前回までの対応では男性時の分岐側しか対応できていなかったのが原因っぽいので、女性時の分岐も対応していく。
パラメータ変更時の処理は共通なので、前回フックさせた関数に同様に変更していく。
対応箇所は以下の通り。

0442DB 22 50 34 C4 JSL $043450
0442EE 22 8A 35 C4 JSL $04358A
044301 22 07 37 C4 JSL $043707
044314 22 41 38 C4 JSL $043841
044327 22 88 39 C4 JSL $043988

呪文の取得 その2

前回のプログラムが何で動かなかったかというと、EORの実行結果はAに格納されるだけだから。
対象アドレスに書き込む処理を追加してやらなくてはいけない。
というわけでSTA命令を追加すれば何とかなるかな、と思った。
ついでに、ただ単純にEORとSTAを羅列するだけだと冗長になるので、forループっぽい処理も追加してみたのが以下のプログラム。
これを、関数$04425Dの最初の処理にフックさせる。


04425D 22 41 F8 C4 JSL $04F841

04F841 48 PHA
04F842 DA PHX
04F843 E2 20 SEP #$20
04F845 A9 00 LDA #$00
04F847 22 5D F8 C4 JSL #04F85D
04F84B 1A INC
04F84C E8 INX
04F84D C9 0A CMP #$0A
04F84F F0 03 BEQ #$03
04F851 4C 47 F8 JMP #04F847
04F854 C2 20 REP #$20
04F856 FA PLX
04F857 68 PLA
04F858 22 80 69 C4 JSL $046980
04F85C 6B RTL

04F85D 48 PHA
04F85E A9 FF LDA #$FF
04F860 5F 24 00 7E EOR #7E0024,x
04F864 9F 24 00 7E STA #7E0024,x
04F868 68 PLA
04F869 6B RTL

このプログラムを実装したところ、「おもいだす」だけ覚えていない勇者が誕生しました。


残件
レベルアップ時のステータスダウンと呪文の忘却処理
ルイーダの酒場でのキャラメイキング処理

呪文の取得

次の問題は、呪文の取得処理である。
初期パラメータでキャラクタは当然すべての呪文を使える状態でなくてはいけないが、「取得するはずの呪文は忘れる」という仕様から、勇者が最初から使える「おもいだす」はリストから外されていなくてはいけない。
単純にすべての呪文を取得させるだけなら7E3949-7E3952までを0xFFを埋めてやるだけでよいのだが・・・


まずはキャラメイキングで取得している呪文の設定をしている場所を探す。
「おもいだす」の場合、7E3950が0x20で覚えられるので7E3950にブレークポイントを設置。
冒険の書を作成」を実行すると早速ブレークが発生。
場所は以下の通り。


$C4/5817 99 24 00 STA $0024,y[$7E:3950] A:0020 X:000A Y:392C P:envmxdIzc


ここは関数$0457F7の中だが、この関数がいったい何をしているのかがよくわからない。
DQ3SFC ROM Editorにも記述がない。
なので、開き直って別のところで手を加えていこうと思う。
その場所とは、関数$04425D「職業・男女別のステータス初期値を取得」内だ。


一番最後にジャンプを行っている処理である以下をフックしてみる。


04433B 22 3E 13 C0 JSL $00133E

04433B 22 41 F8 C4 JSL $04F841
で、$04F841以降に、7E3949-7E3952までのアドレスに対してEOR 0xFFを行っていく。
その際、Xが0x3925にセットされているので、これを基準にしていきたい。


実際のコードとしてはこんな感じか。


PHA
SEP #$30
LDA #$FF
EOR $24,x
EOR $25,x
EOR $26,x
EOR $27,x
EOR $28,x
EOR $29,x
EOR $2A,x
EOR $2B,x
EOR $2C,x
EOR $2D,x
REP #$30
PLA
JSL $00133E
まあ、実際にこれを入力したら全然動かなかったんですけどね。