BUSIN 0 Atlus Best Collection
キーワード
相対アドレス
ベース
ワークアドレス
内容
味方HP最大値維持
宿屋に泊まると魔術師魔法最大・残り使用回数9+α
全AA使用回数xに変更
味方HP最大値維持
このソフトは戦闘中と非戦闘中で共通のプログラムを使用している様で、1つ探すと共に効果があるというソフトでした。
それに加えワークアドレスがそのまま参照箇所になっているところが他のソフトより多く、コードを作りやすかったです。
この事を踏まえまずはワークアドレスを探します。
通常版のコードが多くでており、最大値がわかっているので最大値検索で探していきますが
999だと多数のステータスの最大値ですのでHPの9999を最大値で探します。
以下がLVUPの際の最大値修正処理です。
001c88d8 dsll32 v0, a1, 16
001c88dc dsra32 v0, v0, 16
001c88e0 slti at, v0, $2710
001c88e4 bne at, zero, $001c88f0
001c88e8 nop
001c88ec addiu a1, zero, $270f a1=$0000270f
001c88f0 sll v0, a2, 5
001c88f4 subu v1, v0, a2
001c88f8 lui v0, $0056 v0=$00560000
001c88fc sll s0, v1, 4
001c8900 addiu v0, v0, $ddda v0=$0055ddda
001c8904 addu v0, v0, s0
001c8908 jal $001c8ef0
灰色の箇所を潰すと最大になり、ストアのベースである$0055dddaが最大HPのワークアドレス
後は通常版のワークアドレスとの差分を出し、ベスト版のワークアドレスを調べます。
最大HPに+2hしたものが現在HPであるので$0055dddcが現在HPです。
最大HPのワークアドレスの参照箇所を探して、頻繁に動作しているものを探します。
例えばメニューや画面下に表示させるためにHPの値をロードしている筈なので、ロード命令の場所を探し、
その箇所を適当な数値に変えます。
例えば、lh v0,$0000(v1)とあった場合addiu v0,zero,$0063と変えてみます。多数ある怪しい箇所を全て変えてみて、
$0063,$0064,$0065等といれ画面に反映されているものが、実際にロードされている箇所になると思います。
(実際には例外もあります)
001c8e78 lui v0, $0056 v0=$00560000
001c8e7c sll v1, v1, 4
001c8e80 addiu v0, v0, $ddda v0=$0055ddda
001c8e84 addu v0, v0, v1
001c8e88 lh v0, $0000(v0)
001c8e8c nop
001c8e90 jr ra
上がその箇所です。後はこの様に書き換えます。
001c8e78 lui v0, $0056 v0=$00560000
001c8e7c sll v1, v1, 4
001c8e80 addiu v0, v0, $ddda v0=$0055ddda
001c8e84 addu t0, v0, v1
001c8e88 lh v0, $0000(t0)
001c8e8c sh v0, $0002(t0)
001c8e90 jr ra
ベースが$0055dddaですのでp$0000が最大HP、p$0002が現在HPです。
v0からt0に変更したのはベースと格納レジスタが同じだとストアさせる際に格納した数値がベースとなってしまう為です。
これでHP維持のコードが出来ました。
しかし今回はワークアドレスが参照箇所になっているため見つけられましたが、
他のソフトでは最大値をストアしている相対アドレスと同じものを探していく。という形になるかと思います。
但しこれも相対アドレスの数値が良くあるもので実際やってみると見つからないです。
もっと違うやり方でなければ見つからないのかもしれませんが、今の私では技術不足なためわかりません。
宿屋に泊まると魔術師魔法最大・残り使用回数9+α
これも上と同じで、ワークアドレスの参照箇所から探していきます。
ワークアドレスは差分から$0055dd67が残り回数で$0055dd66が最大の回数だとわかっています。
ですので残り使用回数のアドレス$0055dd67から参照箇所移動してそれらしいものを探していきます。
これも多数ある参照箇所で怪しいところを↑のようにストアさせたり、ロードする値を適当な数値に変え、
魔法を使用したり残り使用回数を回復するなどをし、変動させて反映された数値に変えた箇所が
変動した際に通る処理です。そうして宿屋に泊まるとLV1の魔法の残り回数が変わりました。
その処理がこちらです。
001c6d08 slt at, a0, v1
001c6d0c beq at, zero, $001c6d18
001c6d10 nop
001c6d14 daddu s2, a0, zero
001c6d18 sll v1, s1, 5
001c6d1c subu v1, v1, s1
001c6d20 lui a0, $0056 a0=$00560000
001c6d24 sll a1, v1, 4
001c6d28 addiu a0, a0, $dd67 a0=$0055dd67
001c6d2c sll v1, s0, 1
001c6d30 addu a0, a0, a1
001c6d34 addu v1, v1, s0
001c6d38 sll v1, v1, 1
001c6d3c addu v1, v1, a0
001c6d40 sb s2, $0000(v1)
001c6d44 nop
001c6d48 ld ra, $0030(sp)
$0055dd67にストアしているs2レジスタを変えると残り使用回数を変えられます。
その際に注目したいことが残り回数-1hが最大の回数であること。
つまり、ベースのv1レジスタから1h引いたアドレスにストアさせれば最大の回数も変わります。
-1ですからsb s2, $ffff(v1)といれることでv1レジスタから-1hのアドレスにs2の値をストアさせる事が出来ます
これがその書き換えた処理です。
001c6d08 slt at, a0, v1
001c6d0c addiu a0, zero, $0009 a0=$00000009
001c6d10 nop
001c6d14 daddu s2, a0, zero s2=$00000009
001c6d18 sll v1, s1, 5
001c6d1c subu v1, v1, s1
001c6d20 lui a0, $0056 a0=$00560000
001c6d24 sll a1, v1, 4
001c6d28 addiu a0, a0, $dd67 a0=$0055dd67
001c6d2c sll v1, s0, 1
001c6d30 addu a0, a0, a1
001c6d34 addu v1, v1, s0
001c6d38 sll v1, v1, 1
001c6d3c addu v1, v1, a0
001c6d40 sb s2, $0000(v1)
001c6d44 sb s2, $ffff(v1)
001c6d48 ld ra, $0030(sp)
a0に$0009をいれているのは分岐を潰した上でa0に$0009を入れておき、その$0009をaddu s2,a0,zeroで
s2に移させそのまま残り回数のsb s2, $0000(v1)と最大の回数のsb s2, $ffff(v1)でストアさせて双方の回数を変更する為
これで終わりです。僧侶魔法もアドレスが違うだけで同じ処理をします。
全AA使用回数xに変更
これは最大値がわからなかったので技LVがUPする回数でデータテーブルを探してみましたが見つかりませんでした。
データテーブルはキーワードのテーブルを参照下さい。つまりHPの様に最大値が1つしかないものではなく、
LVUPに必要な経験値の様にLV毎に変わる数値等をデータ部に並べてあるものです。
今回はこれで技のLVUPに必要な回数を設定していないのか、もしくはどこか別にあるのものを見つけられなかったのか
わかりませんが300等のLVUPに必要な回数が見つかりませんでした。その為まずはワークコードを探していきます。
ところが通常版では技の使用回数のコードがありませんでしたので、自分で探します。
まず今の回数をセーブデータから探します。
そうするとpsu形式のセーブデータでは$43f2cがAAの使用回数のアドレスのようです。
それから他のアドレスとの差分をだし、ワークコードにするのが一般的です。
しかし他のデータとのアドレスがかなり離れている為、そのまま差分をだしても実際とは違う場合があります。
ですのでその近くでワークコードが出来そうなもののデータが無いか探していきます。そうするとすぐ上の$43eceに
合成素材のウジのわいた肉の個数のデータがありました。
この時戦闘後獲得した素材99個というコードが出来ていましたのでその処理を見てストアしているアドレスを探します。
まずはこの処理を見て下さい。
001b80a4 jal $001b6260
001b80a8 daddu s0, a1, zero
001b80ac beq v0, zero, $001b8158
001b80b0 dsll32 a0, s1, 16
001b80b4 dsra32 a0, a0, 16
001b80b8 bltz a0, $001b80c8
001b80bc slti v1, a0, $0029
001b80c0 bne v1, zero, $001b80d0
001b80c4 nop
001b80c8 beq zero, zero, $001b8158
001b80cc nop
001b80d0 dsll32 v1, s0, 16
001b80d4 dsra32 v1, v1, 16
001b80d8 bgez v1, $001b80e8
001b80dc nop
001b80e0 daddu s0, zero, zero
001b80e4 nop
001b80e8 dsll32 v1, s0, 16
001b80ec dsra32 v1, v1, 16
001b80f0 slti at, v1, $0064
001b80f4 bne at, zero, $001b8100
001b80f8 nop
001b80fc addiu s0, zero, $0063 s0=$00000063
001b8100 sll v1, a0, 1
001b8104 lui at, $0001 at=$00010000
001b8108 addu v1, v1, v0
001b810c ori at, at, $91ec at=$000191ec
001b8110 dsll32 v0, s0, 16
001b8114 addu a0, v1, at
001b8118 dsra32 v0, v0, 16
001b811c lh v1, $0000(a0)
001b8120 addu v0, v1, v0
001b8124 slti at, v0, $0064
001b8128 bne at, zero, $001b8140
001b812c nop
001b8130 addiu v0, zero, $0063 v0=$00000063
001b8134 beq zero, zero, $001b8148
001b8138 sh v0, $0000(a0)
↑が戦闘後獲得した時に通る処理です。一番下が獲得した個数のストアで、このベースの値a0の値が
わかればワークアドレスもわかります。
a0を所持金のワークアドレスにストアさせてアドレスを調べる方法もありますが、それだと手間がかかるのでやめます。
$001b8114でaddu a0, v1, atとatの$000191ecが加算されています。しかしこの値がアドレスとは思えないので更に遡ると
$001b8108でaddu v1, v1, v0となっていますv1はすぐ上で1ビット左シフトですからa0×2つまりは2hずつアドレスを
ずらしているということです。残ったv0を調べていきますがこの部分を見るだけでは見つかりません。
そこで1番上のjalへ飛んでみるとこの様になっていました。
001b6260 lui v0, $0054 v0=$00540000
001b6264 jr ra
001b6268 addiu v0, v0, $2660 v0=$00542660
v0=$00542660+at=$000191ecがアドレスとなります。1ビットシフトを足さないのは通常初期値が0(この場合はa0)から
増えてアドレスに+〜hしていくため。
実際に$0055b84cを暗号化しコードとして使用してみます。
するとアイテム画面で素材の1番上に空欄が出来、指定した個数になっていました。
それに+2hしたアドレスがウジのわいた肉でしたのでセーブデータの差分とワークアドレスの差分をだし、
$0055b8acというAAのワークアドレスが出来ます。
後はこれをそれぞれの技のワークコードにしていけばいいのですが。30種類あるので30行になってしまい
入力が面倒です。ですから自作の処理を作り、それぞれのアドレスに格納させていきます。
まず頻繁に通る処理を探します。HP最大維持の復帰でもいいのですが、今回は別の場所を使用しました。
001c1be0 dsll32 v1, a0, 16
001c1be4 dsra32 v1, v1, 16
001c1be8 bltz v1, $001c1bf8
001c1bec slti v0, v1, $001e
001c1bf0 bne v0, zero, $001c1c00
001c1bf4 nop
001c1bf8 beq zero, zero, $001c1c20
001c1bfc addiu v0, zero, $03e7 v0=$000003e7
001c1c00 sll v0, v1, 5
001c1c04 subu v1, v0, v1
001c1c08 lui v0, $0056 v0=$00560000
001c1c0c sll v1, v1, 4
001c1c10 addiu v0, v0, $dd38 v0=$0055dd38
001c1c14 addu v0, v0, v1
001c1c18 lw v0, $0000(v0)
001c1c1c nop
001c1c20 j $000f7000
これはステータス異常があるか無いかのロードをしている箇所で、$0055dd38がステータス異常のワークアドレスです。
この復帰箇所であったものjr raをjに変えて空きメモリへ飛ばします。そうして作った処理がこちらになります。
000f7000 addu t1, zero, zero
000f7004 addiu t2, zero, $0003 t2=$00000003
000f7008 addiu t3, zero, $0514 t3=$00000514
000f700c lui t4, $0056 t4=$00560000
000f7010 slti t5, t1, $001d
000f7014 sll t7, t1, 3
000f7018 addu t6, t4, t7 t6=$00560000
000f701c sb t2, $b8a8(t6) [0055b8a8]
000f7020 sh t3, $b8ac(t6) [0055b8ac]
000f7024 addiu t1, t1, $0001 t1=$00000001
000f7028 bne t5, zero, $000f7010
000f702c sb t2, $b9a8(t4) [0055b9a8]
000f7030 jr ra
000f7034 sh t3, $b9ac(t4) [0055b9ac]
$0055b8a8は習得しているか、装備しているかのフラグ。$0055b8acが使用回数。
t2はフラグt3は使用回数で1300回$0514がLVUPする為に必要な使用回数の一番多かった数値。
最後の方の2つのストア命令は最後の技だけアドレスが離れていたので別に加えたものです。
その為ループ回数は29回$001dにしています。
本当は$000f7014のsll、$000f7024のaddiuは短縮して1行にも出来るのですが、気まぐれでsllを使用し1行多く
なっています。
戻る