今回から実装を行います。実装は大きく分けて以下の3つに分けられます。
- 職業別ステータス最大値構造体の定義とそのアクセスSR実装
- 成長限界パッチとの連動
- その他ステータス変更部分との調整
というわけでまずは1番目から実装していきます。構造体の場所ですが、バンク$04は結構余裕がないのでバンク$05の後ろを使うことにしました。構造体の定義は以下のようにします。
- 職業別ステータス最大値: $05FF45-$5FFDD(9Byte*17rec)
0 | bit0-7 | 力最大値(下位8ビット) |
1 | bit0 | 力最大値(上位1ビット) |
bit1-7 | 素早さ最大値(下位7ビット) | |
2 | bit0-1 | 素早さ最大値(上位2ビット) |
bit2-7 | 体力最大値(下位6ビット) | |
3 | bit0-2 | 体力最大値(上位3ビット) |
bit3-7 | 賢さ最大値(下位5ビット) | |
4 | bit0-3 | 賢さ最大値(上位4ビット) |
bit4-7 | 運のよさ最大値(下位4ビット) | |
5 | bit0-4 | 運のよさ最大値(上位5ビット) |
bit5-7 | 最大HP最大値(下位3ビット) | |
6 | bit0-6 | 最大HP最大値(上位7ビット) |
bit7 | 未使用 | |
7 | bit0-7 | 最大MP最大値(下位8ビット) |
8 | bit0-1 | 最大MP最大値(上位2ビット) |
bit2-7 | 未使用 |
- 職業別ステータス最大値アドレス: $05FFDE-$5FFFF(2Byte*17rec)
省略 |
スペースに余裕があるんだから詰めるのやめればという声も聞こえてきそうですが・・・。全部で17レコードというのはオリジナルの9職業+86氏の拡張パッチで追加されている7職業+システム最大値です。同時に各レコードの開始アドレス(下位2バイト)を$05FFDE-$5FFFF(2Byte*17rec)に定義します。1点注意点ですが、各職業別最大値はシステム最大値以下*1であることを前提とします。また、成長限界を上げた場合に起きる不具合*2についてはタッチしません。従って、職業最大値に500を設定してシステム最大値に300を設定した場合の動作の保証はしません。とりあえずはHPMPは999(#$3E7)、他は全て255(#$FF)をセットしておきます。値を設定する場合はこの点に注意してください。次にこの構造体からデータを取得するSRを定義します。
- SR: $05F800 職業別ステータス最大値構造体アクセス(新SR)
05F800 | PHP | Push P Flag | |
---|---|---|---|
05F801 | PHB | Push DB | |
05F802 | REP #$30 | m=off(A/M:16b) x=off(X/Y:16b) | |
05F804 | TXA | A=X | |
05F805 | PHX | Push X | |
05F806 | PHY | Push Y | |
05F807 | CMP #$0011 | A>=#$0011? | |
05F80A | BCS #$FE | if(c==on) goto $05F80A | |
05F80C | ASL | A<<1 | |
05F80D | TAX | X=A | |
05F80E | LDA $C5FFDE,X | A=$05FFDE+X | |
05F812 | TAX | X=A | |
05F813 | LDA #$00C5 | A=#$00C5 | |
05F816 | STA $62 | DP($62)=A | |
05F818 | LDA $08,S | A=Stack($08) | |
05F81A | PHA | Push A | |
05F81B | PLB | Pull DB | |
05F81C | PLB | Pull DB | |
05F81D | LDY #$0001 | Y=#$0001 | |
05F820 | LDA ($07,S),Y | A=Stack($07+Y) | |
05F822 | STA $60 | DP($60)=A | |
05F824 | INY | Y++ | |
05F825 | INY | Y++ | |
05F826 | LDA ($07,S),Y | A=Stack($07+Y) | |
05F828 | STA $66 | DP($66)=A | |
05F82A | STA $68 | DP($68)=A | |
05F82C | LDA $07,S | A=Stack($07) | |
05F82E | INC | A++ | |
05F82F | INC | A++ | |
05F830 | INC | A++ | |
05F831 | INC | A++ | |
05F832 | STA $07,S | Stack($07)=A | |
05F834 | TXY | Y=X | |
05F835 | LDA $60 | A=$(DP[$60])+Y | |
05F837 | AND $66 | A&=DP($66) | |
05F839 | LSR $68 | DP($68)>>1 | |
05F83B | BCS #$05 | if(c==on) goto $05F842 | |
05F83D | LSR | A>>1 | |
05F83E | LSR $68 | DP($68)>>1 | |
05F840 | BCC #$FB | if(c==off) goto $05F83D | |
05F842 | STA $64 | DP($64)=A | |
05F844 | PLY | Pull Y | |
05F845 | PLX | Pull X | |
05F846 | PLB | Pull DB | |
05F847 | PLP | Pull P Flag | |
05F848 | PHA | Push A | |
05F849 | PLA | Pull A | |
05F84A | RTL | return |
このSRは引数として取得したいインデックス(この場合は職業ID)をXに、開始バイト2バイト、マスクするビットを2バイトで取ります。実装は似たようなことをやっている戦闘中PC情報取得SR: $02CA5Bを丸コピーしたあと、アドレス($05F80E)や要素数($05F807)などをちょっと変えて終わりです。ベースができたので次は各種ステータスを取得するSRをこのSRを使って書いていきます。まずは力の値がちゃんと取得できているかを確認するために力部分だけテストで作ってみます。成長限界上昇パッチでは(力に関して)変更されている部分はSR: $043442の中です。
- SR: $043442 力取得(成長限界上昇パッチ適用後)
043442 | LDA $000C,X | A=$000C+X | |
---|---|---|---|
043445 | JSR $F82F | SR: $04F82F | |
043448 | RTL | return |
$043445の部分で処理を別SRに飛ばしています(オリジナルではたしか#$00FFとANDを取っていた思います)。ここでXとは各キャラクターの構造体の先頭アドレスです。つまり
—— | LDA $0021,X | A=$7E0021+X | |
---|---|---|---|
—— | AND #$00FF | A&=#$00FF |
とかやれば対象キャラクターの職業IDを入手できるので簡単ですね。
- SR: $05FE80 力職業別最大値取得(新SR)
05FE80 | PHX | Push X | |
---|---|---|---|
05FE81 | LDA $0021,X | A=$0021+X | |
05FE84 | AND #$00FF | A&=#$00FF | |
05FE87 | TAX | X=A | |
05FE88 | JSL $C5F800 | SR: $05F800 引数:1#$0000 引数:2#$01FF | |
05FE90 | PLX | Pull X | |
05FE91 | RTL | return |
SR開始時にはXにキャラクターの先頭アドレスが入っているのですが、SR中で職業IDに変える必要があるのでスタックにPUSHして最後でPULLしています。それからもう1つSRを定義します。
- SR: $05FD4B 力を職業最大値でクリップする(新SR)
05FD4B | PHA | Push A | |
---|---|---|---|
05FD4C | JSL $C5FE80 | SR: $05FE80 | |
05FD50 | CMP $01,S | A>=Stack($01)? | |
05FD52 | BCS #$02 | if(c==on) goto $05FD56 | |
05FD54 | STA $01,S | Stack($01)=A | |
05FD56 | PLA | Pull A | |
05FD57 | RTL | return |
Aに調整前の力の値、Xにキャラクターの先頭アドレスが入っていることを前提とし、調整前の力の値(スタック$01)と力の職業別最大値を比較して調整前の値が大きければ職業別最大値に変更してAにセットしなおして終わり、という処理をしています。長くなりすぎたので続きは次回。
コメント
はじめまして。ステータス限界上昇パッチで運のよさの問題が指摘されていますがWikiに 成功率×(1-運のよさ/320)と書かれておりました。
DQ3SFCEditor内で$02C535 A9 40 01 $02C54E A9 40 01
の2つがありどちらかがその計算式になっているようです。(片方はWikiを見る限りザオラルの成功率のようですがどちらなのかは未確認)両方のA9 40 01(320)の部分をA9 F4 01(500)に書き換えてみたところ、運のよさが320を超えても確率系の呪文や特技は100%ではなくなりました。Wikiの計算式が正確ならば約1.56倍オリジナルよりかかりやすくなりますが、はじめからプレイしてみても個人的に大きな問題ではないようでした。まあ、運のよさ自体軽視されがちなステなのでこれでかえって重要度が増してよいかもですがw 長文失礼しました。
コメントありがとうございます。実際にプレイした方の感想は非常に貴重です。成功率判定の解析は5/9にエントリを書きました。成長限界上昇パッチを宛てた状態で両方とも500に変える変更で問題ないと思います。ただ、運のよさが500の場合は確実に成功?なので、オリジナル同様もう少し値を大きくしてもいいかもしれません。