今回から実装に移ります。まず、前提として、オリジナルでも獲得経験値の最大値は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を超えないことがわかったのでその処理はスキップします。御託が長くなりましたが作業を開始します。まず、傾斜配分した経験値の保存先として、$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 |
|
思いのほか長くなってしまったのでこのへんで。次回は実際の経験値配分計算(平均・傾斜)を実装します。
コメント