前回の実装で新規に作成した職業別ステータス最大値構造体から力を取得するSRの定義は終わりました。次にこのSRを45氏が拡張した部分に埋め込みます。
- SR: $04F82F 力取得
04F82F | XBA | Exchange A(HighByte) and A(LowByte) | |
---|---|---|---|
04F830 | SEP #$20 | m=on(A/M:8b) | |
04F832 | LDA $0011,X | A=$0011+X | |
04F835 | AND #$01 | A&=#$01 | |
04F837 | REP #$20 | m=off(A/M:16b) | |
04F839 | XBA | Exchange A(HighByte) and A(LowByte) | |
04F83A | JSL $C5FCF0 | SR: $05FCF0 | |
04F83E | NOP | ||
04F83F | NOP | ||
04F840 | NOP | ||
04F841 | NOP | ||
04F842 | RTS | return |
変更している部分は後半部分です。変更前は$04F839で作成した力の値(9ビット)が500以上かを調べて500以上だったら500を返すという処理をしていました。というわけでこの部分を変更してSR: $05FD4Bを呼ぶように変えます。これで職業別ステータス最大値構造体の力の値でクリップされるようになるはずです。というわけで早速試してみました。
大丈夫そうですね。というわけで、変更を続けることにします。
- SR: 0$43450 力変更
043450 | JSL $C5FCF0 | SR: $05FCF0 | |
---|---|---|---|
043454 | NOP | ||
043455 | NOP | ||
043456 | NOP | ||
043457 | NOP | ||
043458 | SEP #$20 | m=on(A/M:8b) | |
04345A | JSR $F843 | SR: $04F843 | |
04345D | REP #$20 | m=off(A/M:16b) | |
04345F | RTL | return |
- SR: $043497 力加算
043497 | PHA | Push A | |
---|---|---|---|
043498 | JSL $C43442 | SR: $043442 | |
04349C | CLC | c=off | |
04349D | ADC $01,S | A+=(Stack($01)+c) | |
04349F | JSL $C5FD4B | SR: $05FD4B | |
0434A3 | NOP | ||
0434A4 | STA $01,S | Stack($01)=A | |
0434A6 | PLA | Pull A | |
0434A7 | JSL $C43450 | SR: $043450 | |
0434AB | RTL | return |
多分これで問題はないと思います。次は力の種使用時の処理を変更します。
- SR: $90F6E 力の種使用(移動中)
略 | |||
---|---|---|---|
090F7B | JSR $E4AD | SR: $09E4AD | |
略 |
力の種はステータスがMAXのときは「しかし なにもおこらなかった」と表示され消費されません。オリジナルではC9 FF 00(255と比較)、成長限界上昇パッチでもC9 F4 01(500と比較)となっていますが、今回は職業別最大値と比較する必要があります。しかし職業別最大値と比較するSRはバンク$05にあるため、呼ぶためには4バイト(#$22 + アドレス3バイト)が必要です。90F6Eの中身全部を別の場所に飛ばしてもいいのですが、容量節約のため「Aの値を職業最大値と比較して最大値未満ならOFF、最大値以上ならONを変えす」というSRを同じバンク$09に定義することにします。
- SR: $09E4AD 力が職業最大値以上か調べる(以上c=on)(新SR)
09E4AD | PHA | Push A | |
---|---|---|---|
09E4AE | JSL $C5F84B | SR: $05F84B 引数:1#$01 引数:2#$FE 引数:3#$FF | |
09E4B5 | CMP $01,S | A==Stack($01)? | |
09E4B7 | BEQ #$05 | if(z==on) goto $09E4BE | |
09E4B9 | BCC #$03 | if(c==off) goto $09E4BE | |
09E4BB | CLC | c=off | |
09E4BC | BRA #$01 | goto $09E4BF | |
09E4BE | SEC | c=on | |
09E4BF | PLA | Pull A | |
09E4C0 | RTS | return |
ここで1つ問題があることがわかりました。今までのSRではXに「対象キャラクターの先頭アドレス」がセットされていることが前提条件だったために職業アドレスを取得することが容易でした。しかし今回のケースではXにセットされているのは「キャラクターのインデックス」です。従ってこのままでは職業最大値を取得できません。というわけで「キャラクターのインデックスを元にそのキャラクターのデータの先頭アドレスを取得してちからの職業最大値を取得する」SRを実装する必要があります。とはいえ、同様の処理がすでに存在するのでそれをパクれば問題ありません。ここではSR: $05F84Bが期待通りの値を返すとして話を続けます。期待した値がAにセットされて返ってくるので、あらかじめキャラクターの力の値をスタックにPUSHしておきます。そして値を比較するのですが、
A=職業最大値、Stack($01)=ステータス値
となっているのでちょっと処理が厄介です。A>Stack($01)のときにc=onでリターンするようにコードを書く必要があります。
c=off | z=関係なし | A<Stack($01) | c=offをリターン |
c=on | z=on | A=Stack($01) | c=offをリターン |
c=on | z=off | A>Stack($01) | c=onをリターン |
というわけでこの部分は終わりです。続けて力の職業最大値を取得するSRの実装を行います。
- SR: $05F84B 力の職業最大値を取得(新SR)
05F84B | PHP | Push P Flag | |
---|---|---|---|
05F84C | PHB | Push DB | |
05F84D | REP #$30 | m=off(A/M:16b) x=off(X/Y:16b) | |
05F84F | PHA | Push A | |
05F850 | PHX | Push X | |
05F851 | PHY | Push Y | |
05F852 | JSL $C42777 | SR: $042777 | |
05F856 | PEA #$7E7E | Push #$7E7E | |
05F859 | PLB | Pull DB | |
05F85A | PLB | Pull DB | |
05F85B | LDX #$40B5 | X=#$40B5 | |
05F85E | JSL $C4289E | SR: $04289E | |
05F862 | BCC #$03 | if(c==off) goto $05F867 | |
05F864 | LDA #$3925 | A=#$3925 | |
05F867 | TAX | X=A | |
05F868 | JSL $C5FE80 | SR: $05FE80 | |
05F86C | LDX #$40B7 | X=#$40B7 | |
05F86F | JSL $C428FD | SR: $0428FD | |
05F873 | PLY | Pull Y | |
05F874 | PLX | Pull X | |
05F875 | PLA | Pull A | |
05F876 | PLB | Pull DB | |
05F877 | PLP | Pull P Flag | |
05F878 | RTL | return |
基本はSR: $043414 力取得と変わらないです。同じようなSRがその周辺に存在します。この手のSRは1バイトずつ3つの引数を取ります(バイナリスレで86氏に教えてもらいました)。1番目の引数はDPのアドレス($01)、FF=Aレジスタ、FE=Xレジスタ、FD=Yレジスタを意味するようで、この場合(SR: $09E4AD中の$09E4AE)では、2番目の引数(Xレジスタ)をもとに結果を3番目の引数(Aレジスタ)にセットして返せという意味のようです。というわけで力の種を投与、すごろくでステータスアップをさせてみて期待通りに動作すればOKです。思わぬところで長くなったので続きは次回。
コメント