Home > スポンサー広告 > FINAL FANTASY 零式 - ショップアイテム全開コードの作り方 後編

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

コメント: -

Home > スポンサー広告 > FINAL FANTASY 零式 - ショップアイテム全開コードの作り方 後編

Home > PSP memo > FINAL FANTASY 零式 - ショップアイテム全開コードの作り方 後編

FINAL FANTASY 零式 - ショップアイテム全開コードの作り方 後編

前編の続き。
テキストメインなので読みづらさ炸裂(©センチメンタルグラフィティ)。
読みたい人だけ読んでくだちぃ。

psplinkが使えて、MIPSアセンブラが読めるのが大前提。



■手順7

ショップアイテム参照テーブルのアドレスにpsplink改で
ブレークポイントを仕掛ける。
ブレークしたアドレスは5カ所。

bp 0x09D6FD18 r

08AAD4E4:96040000 lhu a0, $0000(s0)
08AAD554:96050000 lhu a1, $0000(s0)
08AAD4F8:92040002 lbu a0, $0002(s0)
08AAD5BC:92070003 lbu a3, $0003(s0)
08AAD63C:92040003 lbu a0, $0003(s0)

exprint(=ep)でレジスタの値を確認する。
s0=0x09D6FD18

これをそれぞれのブレークした箇所で行い、
それぞれにレジスタに何が代入されるかをメモしておく。
メモの代わりに画像でキャプチャーしても良いし、
ep >0x08AAD4E4.txt とリダイレクトでテキストファイルに
保存しておくのも良い方法。


Exception - DEBUG (D)
Thread ID - 0x0504CE53
Th Name - user_main
Module ID - 0x0505581B
Mod Name - YELLOWJP
EPC - 0x08AAD4E4
DRCNTL - 0x0043D004
Status - 0x40088613

zr:0x00000000 at:0xDEADBEEF v0:0x09FFED90 v1:0x08C200D0
a0:0x00000001 a1:0x0000000A a2:0x00000000 a3:0xFFFFFEFF
t0:0xFFFFFFFF t1:0x095E3120 t2:0x0000012C t3:0x00000000
t4:0x00000000 t5:0x0000000D t6:0x00002000 t7:0x00000000
s0:0x09D6FD18 s1:0x095E43FC s2:0x095E0240 s3:0x000000D2
s4:0x09FFE8B0 s5:0x000001A7 s6:0x00000006 s7:0x00000064
t8:0x00000001 t9:0x0000000E k0:0x09FFFB00 k1:0x00000000
gp:0x00000000 sp:0x09FFE8B0 fp:0x08C6E808 ra:0x08AAD3A0




■手順8

ブレークしたアドレスのそれぞれの意味を理解する。




08AAD4E4:96040000	lhu	a0, $0000(s0)	a0=0xD002
08AAD554:96050000 lhu a1, $0000(s0) a1=0xD002
08AAD4F8:92040002 lbu a0, $0002(s0) a0=0x06
08AAD5BC:92070003 lbu a3, $0003(s0) a3=0x00
08AAD63C:92040003 lbu a0, $0003(s0) a0=0x00

レジスタに代入された値を頼りに命令を書き換える。
各アドレスの意味を理解するには、これがてっとり早い。

addiuかoriを使うかは、好みで。
加算処理よりビット演算の方が遙かに高速なので自分はor。
プログラム全体から見れば1カ所程度意味が無いことだが。

同様に分岐を潰すなら速度面ではnopした方がいいのだが
後から読み直すならraで書き換えた方が分かりやすい。

08AAD4E4:3404D002	ori	a0,zero,$D002
08AAD554:3405D002 ori a1,zero,$D002
08AAD4F8:34040006 ori a0,zero,$0006
08AAD5BC:34070000 ori a3,zero,$0000
08AAD63C:34040000 ori a0,zero,$0000




08AAD554をori a1,zero,$D002と命令変更すると、
なんということでしょう、表示されたアイテムが全てシルバーバングル
になったではありませんか(棒)。(©ビフォーアフター)
どうやらこれが本体。

08AAD4E4も同じ値を取るが、これはいったい何か。

08AAD4E4の場合

08AAD4E4:96040000 lhu a0, $0000(s0) a0=0xD002
08AAD4E8:8E850000 lw a1, $0000(s4) s4=0x09FFE8B0 a1=0x0000000A
08AAD4EC:00042303 sra a0, a0, 12 a0=a0右シフト12回 a0=0D
08AAD4F0:14850096 bne a0, a1, $08aad74c a1=0A 消費アイテムじゃなかったら08AAD74Cへ
08AAD4F4:00000000 nop

08AAD4E4はアイテムのカテゴリ判別関数のようだ。

08AAD4F8は何だろうか。ヒントはこれ↓




表示可能かどうかを識別する番号のように見える。





後続に07があるので試しに07に変更してみる。


08AAD4F8:34040007	ori	a0,zero,$0007




「買える物がありません。」と表示された。
店番号か、進行フラグのどちらかだろう。

08AAD5BCと08AAD63Cには0しか見当たらず、
テーブルにも0としか書かれていない。
0x09D6FF3Cあたりから0x10が入っているが
現段階では役割が分からない。
コード書き換えは必要なところだけ分かれば良く
全部を理解する必要ないのでとりあえず置いておく。

ある程度ゲームを進めてしまったセーブデータの場合は
このようなフラグが既にONになっていて気がつかない場合が
あるので、解析時は序盤のセーブデータを利用した方が良い(重要)。

もちろん、ゲームが進んだセーブデータがあればフラグの比較が出来て
フラグの意味も理解出来るので両方あれば解析が楽になるのは言うまでも無い。




■手順9

出来る範囲でアイテム全開にしてみる。
ヒントは08AAD4F8での「買える物がありません。」
つまりこの逆が、「買える物がある」ということ。

08AAD4F8:92040002	lbu	a0, $0002(s0)		a0=6
08AAD4FC:14960093 bne a0, s6, $08aad74c s6=6

08AAD4FCでa0とs6が違っていたら、表示されないということなので
分岐しないようにすれば良い。

08AAD4FC:13E00093	beq	ra, zero,$08aad74c
08AAD4FC:00000000 nop






全開っぽくなったが、アイテムの種類が限定されているようだ。
消費アイテム、武器、アクセサリーしか表示されていない。

ここでスクロールバーに注目。
このように限定解除すると、本来用意されているアイテム欄を
全て埋める形でアイテムが表示される。
アイテム欄の数を数えることで、繰り返し回数が分かる。(重要)

アイテム欄1画面11個表示*27ページ+最終ページ4個=301=0x012D

おそらく、ショップ関数の最後の方にslt(u)かslti(u)の比較式と
bne zeroのループがあるはず。

sltiu	v0,a0,$012C	a0はループカウンタ
sltu v0,a0,t0 t0=$012C

FF零式では、存在しないアイテム番号を表示すると
バスエラーでフリーズすることが分かっているので、
アイテム全開コードを作る際には繰り返し回数を
自分で設定してやる必要がある。




■手順10

ショップ関数は08AAD34Cから始まり08AAD4E4から
アイテムテーブルを読み出しに行く。
08AAD4E4の前後の分岐にブレークポイントを仕掛けてレジスタの
値を見ながら役割を特定して、必要な命令を集める。

今回は手順8と9のおさらいなので、詳細は割愛する。

08AAD4F0:14850096	bne	a0, a1, $08aad74c
08AAD4FC:14960093 bne a0, s6, $08aad74c
08AAD508:1080000C beq a0, zero, $08aad53c

この3つを書き換えれば全開表示(もどき)。
分岐命令だけを書き換えた場合は、これらの分岐はそれらしく見える。

実際には08AAD4F0は、アイテムショップで装備可能キャラ表示に
使用する判定なので書き換えると装備可能キャラ表示が出なくなる。
元の数値(08AAD4E4か08AAD4ECのこと)を書き換えた方が良い。




■手順11

手順9で書いたループ回数の比較式を探す。
この関数の下の方にあるのは確実なのでps2disで
スクロールして見ていくか、逆参照解析で
08AAD4E4かこれより前に戻ってくる分岐を探す。




ps2disでは命令の横にアドレス数値が書かれていれば分岐で
::(コロン2つ)が書かれている時は、ジャンプで飛んできている。
08AAD4E4の行でスペースバーを押して反転表示させて、
F3を押して逆参照解析を実行。

なお、jalr rdやjr rsなどで飛んでくる場合には表示されない。
その場合はブレークポイントを仕掛けて、exprintでレジスタを表示
どのレジスタに行き先が書かれているか確認する。

jalr rdならraにリターンアドレスが書かれているのですぐに分かる。
jr rsの場合、近距離から飛ぶ場合が多い。
jr atなら、jr atをマシン語に変換し(00200008)、この数値で付近を
ps2disでサーチして、ヒットした場所にブレークポイントを仕掛ける。





F3で飛んだらずいぶん分かりやすいところに出た。

08AAD738:2884012C	slti a0, a0, $012c	a0 < 0x012C a0=1

sltiで比較する前に加算しているので、ループカウンタの初期値は1。
sltiの即値に手順9で求めた数値-1が入っている。
試しに数値を書き換えてみる。

08AAD738:28840002	slti a0, a0, $0002





アイテム種類表示数が2個になった。

アイテム全開コードを作成する際には
この命令をアイテムのカテゴリごとに設定する。




■手順12

残りはアイテム番号を読み出す方法だがパターンは2つ。

1つめは、自作関数でループカウンタを作りアイテム番号に1を加算していく。
2つめは、プログラム側で用意されているループカウンタを拝借する。

08AAD4E4:96040000	lhu	a0, $0000(s0)		a0=D002	アイテムID s0=0x09D6FD18

08AAD72C:8E240000 lw a0, $0000(s1) a0=ループカウンタ
08AAD730:24840001 addiu a0, a0, $0001 a0=a0+1
08AAD734:AE240000 sw a0, $0000(s1) a0を書き込む
08AAD738:2884012C slti a0, a0, $012c a0<0x012Cなら a0=1
08AAD73C:14800003 bne a0, zero, $08aad74c a0<>0なら08aad74cへ。
08AAD740:00000000 nop
08AAD744:10000005 beq zero, zero, $08aad75c
08AAD748:00000000 nop
08AAD74C:26730001 addiu s3, s3, $0001
08AAD750:0275202A slt a0, s3, s5
08AAD754:1480FF63 bne a0, zero, $08aad4e4
08AAD758:26100004 addiu s0, s0, $0004

ループカウンタ本体は08AAD72Cで読み出されるa0。
08AAD74Cで+1加算するs3も08AAD73Cと連動しているので使えそうだ。

a0を使う場合は、すぐに書き換えれられてしまうので、
空きメモリにジャンプしてどこかにループカウンタを書き込んでおく。
初期化も必要になるので、ショップ関数の入り口で0にしておく。
もしくは、この関数内で空きレジスタがあれば適当なレジスタ(atなど)に
a0の値をコピーしても良い。

どうするかは08AAD4E4にブレークポイントを設置して決める。
何回かループさせてレジスタを確認してみる。

bpset(bp) 0x08AAD4E4

breakしたら

exprint(ep) >>reg.txt
bpdis(bd) 0
skip(s)
bpena(be) 0
exresume(c)

breakしたらに戻る

ep >>reg.txtでリダイレクトしてreg.txtに追記する形になる。


■1周目

Exception - Breakpoint
Thread ID - 0x0504CE55
Th Name - user_main
Module ID - 0x0505581D
Mod Name - YELLOWJP
EPC - 0x08AAD4E4
Cause - 0x10000024
BadVAddr - 0x0ED3F708
Status - 0x60088613

zr:0x00000000 at:0xDEADBEEF v0:0x09FFED90 v1:0x08C200D0
a0:0x00000001 a1:0x09FFE8C4 a2:0x00000000 a3:0xFFFFFEFF
t0:0xFFFFFFFF t1:0x095E3160 t2:0x0000012C t3:0x00000000
t4:0x00000000 t5:0x0000000D t6:0x00002000 t7:0x00000000
s0:0x09D6F9D0 s1:0x095E443C s2:0x095E0280 s3:0x00000000
s4:0x09FFE8B0 s5:0x000001A7 s6:0x00000006 s7:0x00000064
t8:0x00000001 t9:0x0000000E k0:0x09FFFB00 k1:0x00000000
gp:0x00000000 sp:0x09FFE8B0 fp:0x08C6E808 ra:0x08AAD3A0
■2周目

Exception - Breakpoint
Thread ID - 0x0504CE55
Th Name - user_main
Module ID - 0x0505581D
Mod Name - YELLOWJP
EPC - 0x08AAD4E4
Cause - 0x10000024
BadVAddr - 0x0ED3F708
Status - 0x60088613

zr:0x00000000 at:0xDEADBEEF v0:0x09FFED90 v1:0x08C200D0
a0:0x00000001 a1:0x0000000A a2:0x00000000 a3:0xFFFFFEFF
t0:0xFFFFFFFF t1:0x095E3160 t2:0x0000012C t3:0x00000000
t4:0x00000000 t5:0x0000000D t6:0x00002000 t7:0x00000000
s0:0x09D6F9D4 s1:0x095E443C s2:0x095E0280 s3:0x00000001
s4:0x09FFE8B0 s5:0x000001A7 s6:0x00000006 s7:0x00000064
t8:0x00000001 t9:0x0000000E k0:0x09FFFB00 k1:0x00000000
gp:0x00000000 sp:0x09FFE8B0 fp:0x08C6E808 ra:0x08AAD3A0
■3周目

Exception - Breakpoint
Thread ID - 0x0504CE55
Th Name - user_main
Module ID - 0x0505581D
Mod Name - YELLOWJP
EPC - 0x08AAD4E4
Cause - 0x10000024
BadVAddr - 0x0ED3F708
Status - 0x60088613

zr:0x00000000 at:0xDEADBEEF v0:0x09FFED90 v1:0x08C200D0
a0:0x00000001 a1:0x0000000A a2:0x00000000 a3:0xFFFFFEFF
t0:0xFFFFFFFF t1:0x095E3160 t2:0x0000012C t3:0x00000000
t4:0x00000000 t5:0x0000000D t6:0x00002000 t7:0x00000000
s0:0x09D6F9D8 s1:0x095E443C s2:0x095E0280 s3:0x00000002
s4:0x09FFE8B0 s5:0x000001A7 s6:0x00000006 s7:0x00000064
t8:0x00000001 t9:0x0000000E k0:0x09FFFB00 k1:0x00000000
gp:0x00000000 sp:0x09FFE8B0 fp:0x08C6E808 ra:0x08AAD3A0
■4周目

Exception - Breakpoint
Thread ID - 0x0504CE55
Th Name - user_main
Module ID - 0x0505581D
Mod Name - YELLOWJP
EPC - 0x08AAD4E4
Cause - 0x10000024
BadVAddr - 0x0ED3F708
Status - 0x60088613
zr:0x00000000 at:0xDEADBEEF v0:0x09FFED90 v1:0x08C200D0
a0:0x00000001 a1:0x0000000A a2:0x00000000 a3:0xFFFFFEFF
t0:0xFFFFFFFF t1:0x095E3160 t2:0x0000012C t3:0x00000000
t4:0x00000000 t5:0x0000000D t6:0x00002000 t7:0x00000000
s0:0x09D6F9DC s1:0x095E443C s2:0x095E0280 s3:0x00000003
s4:0x09FFE8B0 s5:0x000001A7 s6:0x00000006 s7:0x00000064
t8:0x00000001 t9:0x0000000E k0:0x09FFFB00 k1:0x00000000
gp:0x00000000 sp:0x09FFE8B0 fp:0x08C6E808 ra:0x08AAD3A0

s3がループカウンタとして使えるようなのでこれを使用する。
あとはアイテム番号にループカウンタを足すだけ。

ここでは普通のアイテム屋さんをチョコボ屋にしてみる。


08AAD554:96050000	lhu	a1, $0000(s0)

08AAD554:2665C000 addiu a1,s3,$C000 $C000~$C020がチョコボ

このままだとフリーズしてしまうので表示数ループを
こちらで設定する。

08AAD738:2884012C	slti a0, a0, $012c

08AAD738:28840021 slti a0, a0, $0021

表示フラグも全開にしておく

08AAD4FC:14960093	bne	a0, s6, $08aad74c

08AAD4FC:13E00093 beq ra, zero, $08aad74c





従卒ちゃんがチョコボ屋へ転身。

あとはこれをCWCやTempARなどで使えるようにコード化するだけ。



ついでに販売価格を0ギルにしちゃう。

08AAD088:14E9000B	bne a3, t1, $08aad0b8

08AAD088:10000050 beq zero,zero, $08AAD164




FFXIの弓レリックが0ギル…
従卒ちゃん、価格設定間違ってるよ。

価格0ギルにするとアイテムを買うときの個数設定で文字表示がおかしくなるので
価格1ギルにしておいた方が無難。

08AAD088:14E9000B	bne a3, t1, $08aad0b8

08AAD088:1000004F beq zero,zero, $08AAD160



実際にはこれだけでは足りず、従卒とそれ以外などでアイテム表示が食い違う。

従卒で武器とアクセサリーを表示させようとすると、「買える物はありません」と言われる。
他にも、どの店でもチョコボとファントマを表示させようとすると
「買える物はありません」と言われる。

08AAD4F0をnopすれば表示されるが、装備可能キャラ表示が出なくなる上に、
リスト最後にアイテム番号00が2個か3個表示される。

これを解消しなくてはならないが、アイテム全開には直接関係無いので触れない。

下のコードでは解消してるので興味があれば参考にしてください。


_C0 @ Shop Item Change
_M 0x9A000000 0xFF7F0080
_M 0x08AAD554 0x2665A000
_M 0x08AAD738 0x2884002A
_M 0x08AAD020 0x1000004F
_M 0x08AAD4FC 0x13E00093
_M 0x08AAD508 0x1000000C
_M 0x08AAD4EC 0x3404000A
_M 0x08AAD55C 0x1488000B
_M 0x08AAD590 0x14880008
_M 0x08AAD3BC 0x10000024
_M 0xD2000000 0x00000000
_M 0x9A000000 0xFFDF0020
_M 0x08AAD554 0x2665B000
_M 0x08AAD738 0x288400A8
_M 0x08AAD020 0x1000004F
_M 0x08AAD4FC 0x13E00093
_M 0x08AAD508 0x1000000C
_M 0x08AAD4EC 0x3404000B
_M 0x08AAD55C 0x1488000B
_M 0x08AAD590 0x14880008
_M 0x08AAD3BC 0x10000024
_M 0xD2000000 0x00000000
_M 0x9A000000 0xEFFF1000
_M 0x08AAD554 0x2665C000
_M 0x08AAD738 0x28840021
_M 0x08AAD020 0x1000004F
_M 0x08AAD4FC 0x13E00093
_M 0x08AAD508 0x1000000C
_M 0x08AAD4EC 0x3404000A
_M 0x08AAD55C 0x1488000B
_M 0x08AAD590 0x14880008
_M 0x08AAD3BC 0x10000024
_M 0xD2000000 0x00000000
_M 0x9A000000 0xFEFF0100
_M 0x08AAD554 0x2665D000
_M 0x08AAD738 0x288400FF
_M 0x08AAD020 0x1000004F
_M 0x08AAD4FC 0x13E00093
_M 0x08AAD508 0x1000000C
_M 0x08AAD4EC 0x3404000D
_M 0x08AAD55C 0x13E0000B
_M 0x08AAD590 0x14880008
_M 0x08AAD3BC 0x10000024
_M 0xD2000000 0x00000000
_M 0x9A000000 0x7FFF8000
_M 0x08AAD554 0x2665E000 # ファントマ
_M 0x08AAD738 0x2884001D
_M 0x08AAD020 0x1000004F
_M 0x08AAD4FC 0x13E00093
_M 0x08AAD508 0x1000000C
_M 0x08AAD4EC 0x3404000A # ファントマ(E)だと申請すると「買える物はありません」と言われるので
_M 0x08AAD55C 0x1488000B # ↑消費アイテム(A)のフリをする
_M 0x08AAD590 0x14880008
_M 0x08AAD3BC 0x10000024
_M 0xD2000000 0x00000000
_M 0x9A000000 0xFDFF0200 # パッドコード
_M 0x08AAD554 0x2665F000 # addiu a1,s3,$F000 アイテム番号 武器1番目
_M 0x08AAD738 0x288400E3 # slti a0,a0,$00E3 ループ回数
_M 0x08AAD020 0x1000004F # beq zero,zero,$08AAD160 アイテム全カテゴリ全種類1ギル
_M 0x08AAD4FC 0x13E00093 # beq ra,zero,$08AAD74C フラグ照合 アイテム全開1
_M 0x08AAD508 0x1000000C # beq zero,zero,$08AAD53C フラグ照合 アイテム全開2
_M 0x08AAD4EC 0x3404000F # ori a0,zero,$000F アイテムカテゴリ武器
_M 0x08AAD55C 0x1488000B # bne a0,t0,$08AAD58C 装備可能表示アクセサリー 操作しない
_M 0x08AAD590 0x13E00008 # beq ra,zero,$08AAD5B4 装備可能表示武器 表示可能
_M 0x08AAD3BC 0x10000024 # beq zero,zero,$08AAD450 従卒などで武器アクセサリー表示可能
_M 0xD2000000 0x00000000
_M 0x68C05F20 0x00000016 # お店(0x16)の外だったら復元
_M 0x08AAD554 0x96050000 # lhu a1,$0000(s0)
_M 0x08AAD738 0x2884012C # slti a0,a0,$012c
_M 0x08AAD020 0x14E4000B # bne a3,a0,$08AAD050
_M 0x08AAD4FC 0x14960093 # bne a0,s6,$08AAD74C
_M 0x08AAD508 0x1080000C # beq a0,zero,$08AAD53C
_M 0x08AAD4EC 0x00042303 # sra a0,a0,12
_M 0x08AAD55C 0x1488000B # bne a0,t0,$08AAD58C
_M 0x08AAD590 0x14880008 # bne a0,t0,$08AAD5B4
_M 0x08AAD3BC 0x16C00009 # bne s6,zero,$08AAD3E4
_M 0xD2000000 0x00000000
← 消費アイテム
→ キーアイテム
R 武器
L アクセサリー
□ ファントマ
△ チョコボ

全カテゴリ全種類1ギル
お店から出ると自動復元







関連記事
スポンサーサイト

コメント: -

Home > PSP memo > FINAL FANTASY 零式 - ショップアイテム全開コードの作り方 後編

Return to page top

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。