今回から実装に移ります。まず、前提として、オリジナルでも獲得経験値の最大値は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人の場合も同様
コメント