今回から実装に移ります。まず、前提として、オリジナルでも獲得経験値の最大値は3バイトMaxの#$FFFFFFです(平均前)。それ以上獲得しても#$FFFFFFでクリップされます。これを各自のレベルに応じて配分していくわけですが、分子の取り得る最大値は99、分母の取り得る最大値は298(レベル99が1人にレベル1が3人)となります。
誤差を極力抑えるため、分子*経験値をしてから分母で割るようにします(当たり前ですが)。獲得経験値が#$FFFFFFだった場合でも分子をかけた値の最大値は4バイトを超えません。従って分子*経験値の計算はSR: $001107 $00,X(4B)=A(1)*$00,X(3B)が使用できます。次にこれを分母(2バイト)で割るのですが、この除算を行うSRが存在しないので自作します。SR: $001295 $00,x(3B)=$00,X(3B)/A(2B?) 剰余=A,$30というSRが存在するので、基本このSRをパクって割られる数が4バイトに対応したものを作ればいい、ということになります。
というわけで、後は使用するRAM領域を決めて、条件に該当していれば傾斜配分計算を行い、各自への経験値の加算部分をいじれば終わり、ということになります。また、除算した余りを合計し、分母で割った数を余りの経験値として生存人数で割って加算する、ということも考えたのですが、理論的にこの値が各自に加算する際に1を超えないことがわかったのでその処理はスキップします*1。御託が長くなりましたが作業を開始します。まず、傾斜配分した経験値の保存先として、$7E2640-5Fを使用します。戦闘終了時のみ使用となるので、他の使用領域とかぶっていても問題ありません。
| $7E2640-3 | 1人目の獲得経験値 | |
| $7E2644-7 | 2人目の獲得経験値 | |
| $7E2648-B | 3人目の獲得経験値 | |
| $7E264C-F | 4人目の獲得経験値 | |
| $7E2650-1 | 最大レベル+1-1人目のレベル(2Byte),0の場合は経験値はもらえない | |
| $7E2652-3 | 最大レベル+1-2人目のレベル(2Byte),0の場合は経験値はもらえない | |
| $7E2654-5 | 最大レベル+1-3人目のレベル(2Byte),0の場合は経験値はもらえない | |
| $7E2656-7 | 最大レベル+1-4人目のレベル(2Byte),0の場合は経験値はもらえない | |
| 7E2658-9 | 生存者の中の最大レベル+1 | |
| 7E265A-B | 傾斜配分の分母 | |
| 7E265C-D | 傾斜によって発生した余りの合計値(分母は7E265A) | |
| 7E265E | 0bit | 経験値傾斜配分が発生した |
| 1bit | 獲得経験値ウィンドウを表示している |
- SR: $02A6AF 戦闘終了時処理SR_SR_0001(勝利時)
| 略 | |||
|---|---|---|---|
| 02A6ED | JSR $EC75 | SR: $02EC75 | 戦闘終了後経験値計算用RAM初期化 |
| 02A6F0 | JSR $EE5C | SR: $02EE5C | 一人当たりの経験値計算 |
| 略 | |||
| 02A6F6 | JSR $EE7C | SR: $02EE7C | 各自獲得経験値ウィンドウオープン |
| 略 |
SR: $02EE7C 各自獲得経験値ウィンドウオープンについては次回にまわします。
- SR: $02A7B3 経験値加算+レベルアップ処理
| 略 | |||
|---|---|---|---|
| 02A7CA | JSR $EC83 | SR: $02EC83 | 各自の経験値を$00-03にセット(インデックス:Y) |
| 02A7CD-D3 | NOP | ||
| 略 |
- SR: $02EC75 戦闘終了後経験値計算用RAM初期化(新SR)
| 02EC75 | LDX #$001E | X=#$001E | |
|---|---|---|---|
| 02EC78 | LDA #$0000 | A=#$0000 | |
| 02EC7B | STA $2640,X | $7E2640+X=A | |
| 02EC7E | DEX | X– | |
| 02EC7F | DEX | X– | |
| 02EC80 | BPL #$F9 | if(n==off) goto $02EC7B | |
| 02EC82 | RTS | return |
- SR: $02EC83 各自の経験値を$00-03にセット(インデックス:Y)(新SR)
| 02EC83 | PHX | Push X | |
|---|---|---|---|
| 02EC84 | TYA | A=Y | |
| 02EC85 | ASL | A<<1 | |
| 02EC86 | ASL | A<<1 | |
| 02EC87 | TAX | X=A | |
| 02EC88 | LDA $2640,X | A=$7E2640+X | 下位2バイト |
| 02EC8B | STA $00 | $000000=A | |
| 02EC8D | LDA $2642,X | A=$7E2642+X | 上位2バイト |
| 02EC90 | STA $02 | $000002=A | |
| 02EC92 | PLX | Pull X | |
| 02EC93 | RTS | return |
- SR: $02EE5C 一人当たりの経験値計算(新SR)
| 02EE5C | PHA | Push A | |
|---|---|---|---|
| 02EE5D | PHX | Push X | |
| 02EE5E | PHY | Push Y | |
| 02EE5F | JSR $ECC1 | SR: $02ECC1 | 生存者の最大レベル+1を返す |
| 02EE62 | STA $2658 | $7E2658=A | |
| 02EE65 | JSR $ECC6 | SR: $02ECC6 | 生存者中の最大レベル+1-レベル値をセット |
| 02EE68 | JSR $ED50 | SR: $02ED50 | 経験値の傾斜配分をするか(該当c=on) |
| 02EE6B | BCS #$05 | if(c==on) goto $02EE72 | |
| 02EE6D | JSR $ECF4 | SR: $02ECF4 | 一人当たりの経験値計算(平等) |
| 02EE70 | BRA #$03 | goto $02EE75 | |
| 02EE72 | JSR $ED8F | SR: $02ED8F | 一人当たりの経験値計算(傾斜) |
| 02EE75 | JSR $A746 | SR: $02A746 | 一人当たりの獲得経験値計算処理 |
| 02EE78 | PLY | Pull Y | |
| 02EE79 | PLX | Pull X | |
| 02EE7A | PLA | Pull A | |
| 02EE7B | RTS | return |
- SR: $02ECC1 生存者の最大レベル+1を返す
| 02ECC1 | JSR $EC94 | SR: $02EC94 | |
|---|---|---|---|
| 02ECC4 | INC | A++ | |
| 02ECC5 | RTS | return |
- SR: $02EC94 生存者中の最大レベル取得(新SR)
| 02EC94 | JSL $02B9A6 | SR: $02B9A6 | パーティ人数取得 |
|---|---|---|---|
| 02EC98 | STA $02 | $000002=A | パーティ人数を$02にセット |
| 02EC9A | LDY #$0000 | Y=#$0000 | |
| 02EC9D | LDA #$0001 | A=#$0001 | 初期値としてレベル1をセット |
| 02ECA0 | PHA | Push A | |
| 02ECA1 | CPY $02 | Y==$000002? | |
| 02ECA3 | BEQ #$18 | if(z==on) goto $02ECBD | |
| 02ECA5 | JSL $043F87 | SR: $043F87 引数:1#$01 引数:2#$FD 引数:3#$FF | 生死判定(死亡c=on?) |
| 02ECAC | AND #$0010 | A&=#$0010 | |
| 02ECAF | BNE #$09 | if(z==off) goto $02ECBA | 死人は飛ばす |
| 02ECB1 | JSR $ED35 | SR: $02ED35 | 指定キャラクターのレベルを返す(ひとりじめベルト装備時は1) |
| 02ECB4 | CMP $01,S | A>=Stack($01)? | スタック中のレベル値と比較 |
| 02ECB6 | BCC #$02 | if(c==off) goto $02ECBA | |
| 02ECB8 | STA $01,S | Stack($01)=A | 大きければ入れ替え |
| 02ECBA | INY | Y++ | |
| 02ECBB | BRA #$E4 | goto $02ECA1 | |
| 02ECBD | NOP | ||
| 02ECBE | NOP | ||
| 02ECBF | PLA | Pull A | |
| 02ECC0 | RTS | return |
- SR: $02ED35 指定キャラクターのレベルを返す(ひとりじめベルト装備時は1)(新SR)
| 02ED35 | STY $2428 | $7E2428=Y | |
|---|---|---|---|
| 02ED38 | LDA #$00F2 | A=#$00F2 | ひとりじめベルトのアイテムID |
| 02ED3B | STA $242C | $7E242C=A | |
| 02ED3E | JSL $02B87A | SR: $02B87A | アイテム装備チェック |
| 02ED42 | BVC #$04 | if(v==off) goto $02ED48 | |
| 02ED44 | LDA #$0001 | A=#$0001 | レベル1 |
| 02ED47 | RTS | return | |
| 02ED48 | JSL $042FEB | SR: $042FEB 引数:1#$01 引数:2#$FD 引数:3#$FF | レベル取得 |
| 02ED4F | RTS | return |
- SR: $02ECC6 生存者中の最大レベル+1-レベル値をセット(新SR)
| 02ECC6 | JSL $02B9A6 | SR: $02B9A6 | パーティ人数取得 |
|---|---|---|---|
| 02ECCA | STA $02 | $000002=A | |
| 02ECCC | LDY #$0000 | Y=#$0000 | |
| 02ECCF | CPY $02 | Y==$000002? | |
| 02ECD1 | BEQ #$20 | if(z==on) goto $02ECF3 | |
| 02ECD3 | JSL $043F87 | SR: $043F87 引数:1#$01 引数:2#$FD 引数:3#$FF | 生死判定(死亡c=on?) |
| 02ECDA | AND #$0010 | A&=#$0010 | |
| 02ECDD | BNE #$11 | if(z==off) goto $02ECF0 | 死人は飛ばす |
| 02ECDF | JSR $ED35 | SR: $02ED35 | 指定キャラクターのレベルを返す(ひとりじめベルト装備時は1) |
| 02ECE2 | STA $00 | $000000=A | |
| 02ECE4 | TYA | A=Y | |
| 02ECE5 | ASL | A<<1 | |
| 02ECE6 | TAX | X=A | |
| 02ECE7 | LDA $2658 | A=$7E2658 | |
| 02ECEA | SEC | c=on | |
| 02ECEB | SBC $00 | A-=$000000 | 差分を計算 |
| 02ECED | STA $2650,X | $7E2650+X=A | |
| 02ECF0 | INY | Y++ | |
| 02ECF1 | BRA #$DC | goto $02ECCF | |
| 02ECF3 | RTS | return |
- SR: $02ED50 経験値の傾斜配分をするか(該当c=on)
| 02ED50 | LDA #$FFFF | A=#$FFFF | |
|---|---|---|---|
| 02ED53 | CMP $06FFE2 | A==$06FFE2? | ROM中の傾斜配分フラグを調べる#$FFFF以外は傾斜配分しない |
| 02ED57 | BEQ #$02 | if(z==on) goto $02ED5B | |
| 02ED59 | CLC | c=off | |
| 02ED5A | RTS | return | |
| 02ED5B | JSR $A7A1 | SR: $02A7A1 | 生存人数取得 |
| 02ED5E | CMP #$0001 | A==#$0001? | 生存人数が1人なら傾斜配分しない |
| 02ED61 | BEQ #$F6 | if(z==on) goto $02ED59 | |
| 02ED63 | JSR $EE03 | SR: $02EE03 | 経験値を傾斜配分するレベル差数取得 |
| 02ED66 | STA $00 | $000000=A | |
| 02ED68 | LDX #$0000 | X=#$0000 | |
| 02ED6B | LDA $2650,X | A=$7E2650+X | |
| 02ED6E | CMP $00 | A>=$000000? | |
| 02ED70 | BCS #$09 | if(c==on) goto $02ED7B | |
| 02ED72 | INX | X++ | |
| 02ED73 | INX | X++ | |
| 02ED74 | CPX #$0008 | X>=#$0008 ? | |
| 02ED77 | BCC #$F2 | if(c==off) goto $02ED6B | |
| 02ED79 | CLC | c=off | |
| 02ED7A | RTS | return | |
| 02ED7B | SEC | c=on | |
| 02ED7C | RTS | return |
- SR: $2EE03 経験値を傾斜配分するレベル差数取得(新SR)
| 02EE03 | LDA $2658 | A=$7E2658 | |
|---|---|---|---|
| 02EE06 | STA $00 | $000000=A | |
| 02EE08 | LDA #$000A | A=#$000A | |
| 02EE0B | LDX #$0000 | X=#$0000 | |
| 02EE0E | JSL $00121C | SR: $00121C | $00,X(2B)=$00,X(2B)/A(1B) 剰余=A |
| 02EE12 | LDA $00 | A=$000000 | |
| 02EE14 | CLC | c=off | |
| 02EE15 | ADC #$0002 | A+=#$0002 | |
| 02EE18 | PHA | Push A | |
| 02EE19 | LDA #$0006 | A=#$0006 | |
| 02EE1C | CMP $01,S | A>=Stack($01)? | |
| 02EE1E | BCS #$02 | if(c==on) goto $02EE22 | |
| 02EE20 | BRA #$02 | goto $02EE24 | |
| 02EE22 | STA $01,S | Stack($01)=A | |
| 02EE24 | PLA | Pull A | |
| 02EE25 | RTS | return |
思いのほか長くなってしまったのでこのへんで。次回は実際の経験値配分計算(平均・傾斜)を実装します。
*1:例:分母が100で、生存人数が4人の場合、余りの合計値の最大は396、分母の100で割ると整数部分は3となり、これを生存人数の4で割っても各自に加算する経験値は1を超えない。生存人数が2人、3人の場合も同様


コメント