ガンパレード・オーケストラ 白の章 〜青森ペンギン伝説〜

キーワード
相対アドレス
レジスタ
ワークアドレス


内容
最大・最低値チェック


最大・最低値チェック

このソフトは最大値を指定、比較、修正という処理が固まって並んではいません。
他のソフトとやっていることはあまり変わらないのですが、16ビット検索をして最大値を見つけても
その付近に修正のチェックが入っていないのでわかりづらいという印象を受けました。

ではどの様な流れになっているのか。まずは最大値の指定部を16ビット検索で特定します。

00142008 addiu  a1, a1, $1708      a1="所持金"
0014200c lui   v0, $05f5        v0=$05f50000
00142010 addiu  a0, sp, $13f0
00142014 addiu  a1, zero, $0012     a1=$00000012
00142018 daddu  a2, zero, zero
0014201c daddu  a3, zero, zero           
00142020 jal   $001cc830
00142024 ori   t0, v0, $e0ff      t0=$05f5e0ff

ラベルへの参照がある為、この辺りはすぐに見付かります。
t0レジスタへ最大値を格納し、$001cc830へのジャンプ先でp$0010へストア。

001cc830 sh   a1, $0000(a0)
001cc834 daddu  v0, a0, zero
001cc838 sw   a2, $0004(a0)
001cc83c sh   zero, $0008(a0)
001cc840 sh   zero, $0014(a0)
001cc844 sw   a3, $000c(a0)            
001cc848 sw   t0, $0010(a0)            
001cc84c sw   zero, $0018(a0)
001cc850 sw   zero, $001c(a0)
001cc854 jr   ra
001cc858 sw   zero, $0020(a0)

最大値の指定はこれで終了しています。
変動時のチェックが付近でされていない為にここが最大値の指定部分ではないのかと思うかもしれませんが、
ジャンプ先の下の処理を見てみるとp$0010とp$0014のロードした値の加算(以下y)が比較されています。
$001cc830ではp$0014に0がストアされている為実質p$0010との比較としても恐らく問題はないと思います。

001cc910 lh   a2, $0014(a0)            パラメータ変動(ラベル)
001cc914 lw   v1, $0010(a0)
001cc918 addu  t0, v1, a2             
001cc91c bgtz  t0, $001cc928
001cc920 lw   a3, $0004(a0)
001cc924 addiu  t0, zero, $0001     t0=$00000001
001cc928 lw   v1, $0004(a0)
001cc92c addu  v1, v1, a1             
001cc930 sw   v1, $0004(a0)
001cc934 lw   a2, $000c(a0)
001cc938 lw   a1, $0004(a0)
001cc93c slt   v1, a1, a2
001cc940 bnel  v1, zero, $001cc958
001cc944 sw   a2, $0004(a0)
001cc948 slt   v1, a1, t0
001cc94c bne   v1, zero, $001cc958
001cc950 nop
001cc954 sw   t0, $0004(a0)
001cc958 lw   a1, $0004(a0)
001cc95c lw   v1, $0018(a0)
001cc960 subu  a1, a1, a3
001cc964 addu  v1, v1, a1
001cc968 sw   v1, $0018(a0)
001cc96c lw   v1, $001c(a0)
001cc970 addu  v1, v1, a1
001cc974 sw   v1, $001c(a0)
001cc978 jr   ra

この処理を見るとyが0以下であるとt0=1となり、p$0004が1以下であると1がp$0004へストアされています。
その他p$000Cのロード値との比較もされています。
$001cc830ではp$000Cにa3の値がストアされている為、最大値が記述されていた付近を見るとa3は0。
比較処理と0がストアされている点を見るとp$000Cは最低値が格納されているとみて間違いありません。
ここまで見るとp$0004がパラメータの現在値であり、$001cc92cのa1が変動値であるとわかります。

この付近は$001cc830のすぐ下の$001cc860が戦闘後のパラメータのチェック処理、その下の$001cc910が通常時の
変動とパラメータの最低・最大値の修正処理となっています。

最初はこれまでの流れで見つけたわけではなく、所持金減少処理を探して$001cc980へだどり着いたのですが
どうやってたどり着いたかはとり頭なので覚えていません
しかし$001cc980の付近の処理を流し読みしてp$0004が所持金の現在値であると見当をつけ、
$001cc92cで適当な値にし、ゲームをしてみるとパラメータ関係ほぼ全てに効果が出ていたので、
変動値が0以下である場合は0にした上で、x倍にしてみました。体力等が減らない効果は一応狙って作っています。

その後に上の流れで最大値を格納していると気付いたので$001cc830の参照箇所を検索していくと
以下の様になっていました。ここで処理している他のパラメータは「特定パラメータのみ数値変更」のリストを参照
p$0000=a1=パラメータのナンバー
p$0004=a2=発言力は$00c8それ以外は0。パラメータの初期化?
p$000C=a3=最低値
p$0010=t0=最大値
またゲーム中に最低値の記述部分へ最大値を入れる様にパッドコードで命令の書き換えを行っても
うまくいかなかった点から最大・最低値のストアはセーブデータのロード時点までで行っており、
その後はストアされた値のみ読み込む様です。


ごちゃごちゃと書きましたが、まとめると
セーブデータをロードするまで(?)に最低・最大値をステータスのワークアドレス付近に記録し、変動時はそれと比較する

p$0000=パラメータのナンバー
p$0004=パラメータの現在値
p$000C=パラメータの最低値
p$0010=パラメータの最大値
となっていて

例えば運動力のワークアドレスが$00400004であると仮定した場合
$00400000=$0002
$00400004=運動力
$0040000C=$0000
$00400010=$00ff
最大値をチェックする場合は$00400010を。最低値は$0040000Cを読み込み比較。という特殊なものとなっています

なお、最大値等の他p$0000〜p$0020まで何らかのデータを格納しています。
ワークアドレスが異様に離れているのはこういった理由からの様です。
これは各キャラ毎に適用されている上に、キャラによる最大値の違いがない模様。
何故こんな面倒なことを・・・
ところでワークコードを使うとフリーズする場合があるのはコレのせいですか?
                            ↓
               p$0004=a2=発言力は$00c8それ以外は0。パラメータの初期化?

戻る