DQ3 職業別ステータス成長設定とレベルアップ時の処理

レベルアップ時に使用される職業の成長データや性格がどのように影響しているか、という点についてまじめに調べていなかったので調べることにしました。力~運のよさについては仕組みはほとんど同じなので力のみについて解説します。

  • $04179E- 職業
範囲(Byte) 意味
309 男力初期値
310 女力初期値
311 力成長段階1Lv
312 力成長段階1値
313 力成長段階2Lv
314 力成長段階2値
315 力成長段階3Lv
316 力成長段階3値
317 力成長段階4Lv
318 力成長段階4値
319 力成長段階5Lv
320 力成長段階5値

ステータスの成長率は「成長段階Lv」「成長段階値」が1セットになって力については5セットまで設定が可能、というようになっています。体力だけは例外で6セットになっています。これらは「成長段階Lv」までは「成長段階値」の値で成長する、ということを意味しています。成長段階値については実際の値の16倍の値でセットされており、例えば48なら実際は48/16=3成長する、ということを意味します。つまり、DQ3の成長は一定レベル間は基本的に一定値で成長していく、ということになります。16の倍数でない場合は端数は小数点用の計算に回されます。

  • SR: $043C83 レベルアップ処理
043CC1 LDA $01,S A=Stack($01)
043CC3 STA $40C5 $40C5=A
043CC6 JSL $C43021 SR: $043021 レベル変更
043CCA JSL $C42E81 SR: $042E81 装備品によって決定した性格取得
043CCE STA $40C9 $40C9=A
043CD1 JSL $C46980 SR: $046980 職業ID取得
043CD5 STA $40C7 $40C7=A
043CD8 PHA Push A
043CD9 JSL $C42E47 SR: $042E47 性別取得
043CDD STA $4054 $4054=A
043CE0 PHX Push X
043CE1 JSL $C43442 SR: $043442 力取得
043CE5 STA $40CB $40CB=A
043CE8 LDX #$0135 X=#$0135 男初期値へのオフセット
043CEB JSR $3E84 SR: $043E84 ステータス上昇判定(現ステータスが理論値以上c=on)
043CEE BCS #$0C if(c==on) goto $043CFC
043CF0 LDX #$0137 X=#$0137 力成長段階1Lvへのオフセット
043CF3 JSR $3EE8 SR: $043EE8 ステータス増分値計算
043CF6 LDX #$0002 X=#$0002
043CF9 JSR $3F20 SR: $043F20 性格による補正(A=整数値, Y=小数値)
043CFC PLX Pull X
043CFD JSL $C434AC SR: $0434AC レベルアップ時の力ステータスアップ処理
043D01 JSL $C43442 SR: $043442 力取得
043D05 CMP $40CD A>=$40CD? 新ステータスが理論値の加減以下なら補正する
043D08 BCS #$10 if(c==on) goto $043D1A
043D0A LDA $40CD A=$40CD
043D0D JSL $C43450 SR: $043450 力変更
043D11 LDA #$0000 A=#$0000
043D14 JSL $C43460 SR: $043460 力小数点部分変更
043D18 BRA #$E7 goto $043D01

よく使用される情報は下記のRAMにセットされます。

アドレス 意味
$40C5 新レベル
$40C7 職業ID
$40C9 性格ID
$40CB 現ステータス値
$40CD ステータスの下限値
  • SR: $043E84 ステータス上昇判定(現ステータスが理論値以上c=on)
043E84 LDY $40C5 Y=$40C5 新レベル
043E87 LDA $40C7 A=$40C7 職業ID
043E8A JSL $C46B9E SR: $046B9E 指定パラメーターの新レベルでの理論値を取得
043E8E PHA Push A
043E8F STA $4A DP($4A)=A
043E91 CPX #$0135 X==#$0135? 力なら70%
043E94 BEQ #$0D if(z==on) goto $043EA3
043E96 CPX #$0141 X==#$0141? 素早さなら70%
043E99 BEQ #$08 if(z==on) goto $043EA3
043E9B CPX #$014D X==#$014D? 体力さなら60%
043E9E BEQ #$18 if(z==on) goto $043EB8
043EA0 LSR A>>1 賢さ・運の良さなら50%
043EA1 BRA #$28 goto $043ECB
043EA3 LDX #$004A X=#$004A
043EA6 LDA #$0046 A=#$0046
043EA9 JSL $C010D6 SR: $0010D6 $00,X(3B)=A(1B)*$00,X(2B)
043EAD LDA #$0064 A=#$0064
043EB0 JSL $C01243 SR: $001243 $00,X(3B)=$00,X(3B)/A(1B) 剰余=A
043EB4 LDA $4A A=DP($4A)
043EB6 BRA #$13 goto $043ECB
043EB8 LDX #$004A X=#$004A
043EBB LDA #$003C A=#$003C
043EBE JSL $C010D6 SR: $0010D6 $00,X(3B)=A(1B)*$00,X(2B)
043EC2 LDA #$0064 A=#$0064
043EC5 JSL $C01243 SR: $001243 $00,X(3B)=$00,X(3B)/A(1B) 剰余=A
043EC9 LDA $4A A=DP($4A)
043ECB STA $40CD $40CD=A 理論値のX%をセット
043ECE PLA Pull A
043ECF CLC c=off
043ED0 ADC #$000F A+=(#$000F+c) 理論値に15を足す?
043ED3 PHA Push A
043ED4 TYA A=Y
043ED5 ASL A<<1
043ED6 CLC c=off
043ED7 ADC $01,S A+=(Stack($01)+c)
043ED9 STA $01,S Stack($01)=A
043EDB PLA Pull A
043EDC CMP $40CB A>=$40CB?
043EDF BCS #$05 if(c==on) goto $043EE6
043EE1 JSR $3F5F SR: $043F5F 現ステータスが理論値を上回っている場合のステータス上昇分計算(1/2で1成長)
043EE4 SEC c=on
043EE5 RTS return
043EE6 CLC c=off
043EE7 RTS return

このSRを呼ぶ前にXレジスタには各ステータスの開始位置(男初期値)がセットされています。SR: $046B9Eの詳細の説明は省略しますが、上記初期値、成長設定に従って現レベルにおける理論値を作成しています。ランダム要素は絡まないので同じ設定値なら何度実行しても同じ値が返ってきます。理論値の70%,60%,50%を$40CDにセットしています。このSRでは、現ステータスが理論値(+15+レベル*2)以上かどうかを判定し、理論値以上であれば1/2の確率で上昇値を1にしています。それ以外の場合は成長段階に応じた成長値をベースにステータスの増分を計算します。

  • SR: $043EE8 ステータス増分値計算
043EE8 LDY $40C5 Y=$40C5 新レベル
043EEB LDA $40C7 A=$40C7 職業ID
043EEE JSL $C46B78 SR: $046B78 成長段階に応じた成長値を取得
043EF2 PEA #$0000 Push #$0000
043EF5 AND #$00FF A&=#$00FF
043EF8 TAX X=A
043EF9 JSL $C01457 SR: $001457 $00-FFの乱数発生
043EFD JSL $C010B4 SR: $0010B4 X(1B)=A(1B)*X(1B)
043F01 LSR A>>1
043F02 LSR A>>1
043F03 LSR A>>1
043F04 LSR A>>1
043F05 LSR A>>1
043F06 LSR A>>1
043F07 LSR A>>1
043F08 TAY Y=A
043F09 AND #$000F A&=#$000F
043F0C ASL A<<1
043F0D ASL A<<1
043F0E ASL A<<1
043F0F ASL A<<1
043F10 STA $01,S Stack($01)=A
043F12 TYA A=Y
043F13 AND #$00F0 A&=#$00F0
043F16 LSR A>>1
043F17 LSR A>>1
043F18 LSR A>>1
043F19 LSR A>>1
043F1A PLY Pull Y
043F1B RTS return

後半部分がわかりにくいですが、ざっくり言うと、「レベルに応じた成長値を取得し、$00-FFのランダム値をかけ、成長値を計算する」ということをしています。成長を一定にしたい場合、$043EF9-のあたりをLDA #$00FF#$0100(桁あふれするので#$0100は多分ダメ)にすれば常に最大値で成長することになります。

  • SR: $043F20 性格による補正(A=整数値, Y=小数値)
043F20 XBA Exchange A(HighByte) and A(LowByte)
043F21 AND #$FF00 A&=#$FF00
043F24 PHA Push A
043F25 TYA A=Y
043F26 ORA $01,S Aor=Stack($01)
043F28 STA $01,S Stack($01)=A
043F2A LDA $40C9 A=$40C9
043F2D JSL $C46C63 SR: $046C63 性格に対応するステータス補正値(ベース:128)を取得
043F31 PLX Pull X
043F32 STX $4A DP($4A)=X
043F34 LDX #$004A X=#$004A
043F37 JSL $C010D6 SR: $0010D6
043F3B LDA $4C A=DP($4C)
043F3D LSR A>>1
043F3E ROR $4A DP($4A)>>1
043F40 LSR A>>1
043F41 ROR $4A DP($4A)>>1
043F43 LSR A>>1
043F44 ROR $4A DP($4A)>>1
043F46 LSR A>>1
043F47 ROR $4A DP($4A)>>1
043F49 LSR A>>1
043F4A ROR $4A DP($4A)>>1
043F4C LSR A>>1
043F4D ROR $4A DP($4A)>>1
043F4F LSR A>>1
043F50 ROR $4A DP($4A)>>1
043F52 LDA $4A A=DP($4A)
043F54 AND #$00FF A&=#$00FF
043F57 TAY Y=A
043F58 LDA $4A A=DP($4A)
043F5A XBA Exchange A(HighByte) and A(LowByte)
043F5B AND #$00FF A&=#$00FF
043F5E RTS return

ここも後半部分はわかりにくいですが、結論から言うとこのSRから戻ってくるとAレジスタに性格補正後のステータス増分値(整数部分)、Yレジスタに性格補正後のステータス増分値(小数点部分)がセットされます。

  • SR: $0434AC レベルアップ時の力ステータスアップ処理
0434AC PHA Push A
0434AD PHY Push Y
0434AE JSL $C43449 SR: $043449 力小数点部分取得
0434B2 CLC c=off
0434B3 ADC $01,S A+=(Stack($01)+c)
0434B5 JSL $C43460 SR: $043460 力小数点部分変更
0434B9 CMP #$0100 A==or>=#$0100? 小数点部分がオーバーフローしていれば整数部分に加算
0434BC LDA $03,S A=Stack($03)
0434BE BCC #$01 if(c==off) goto $0434C1
0434C0 INC A++
0434C1 JSL $C43497 SR: $043497 力加算+加算後のステータスを返す
0434C5 PLY Pull Y
0434C6 PLA Pull A
0434C7 RTL return