GUC コードステーション情報
ソフト名 4-4.技術コード作成技法(アイテム全所持コード編)
ソフト品番情報
ソフト対応機種 PS(PlayStaition)
改造対応ツール
投稿者(敬称略) D-RAM【GUC】
投稿者連絡先 mopro@jade.dti.ne.jp
登録日 1999/07/26
更新日 1999/07/26
サーチ環境
コメント 「何か動作がおかしい」とか、「こういうことができるコードが欲しい」
また、「ここはこうするべきでは」等のご意見がありましたら、お手数ですが
D-RAM【GUC】
e-mail mopro@jade.dti.ne.jp
までメールをいただけると大変ありがたいです。


4-4.技術コード作成技法(アイテム全所持コード編) いよいよ最難関の「アイテム全所持コード」です。 もっともPAR2以降では反復コードが利用できるので そちらを使用したほうが便利なのですが、 PAR1では数十行、またはそれ以上のコードを入力しなければならないので、 プログラム操作によって数行のコードで済ます、という趣旨です。 これは対応できるゲームタイトルも限られるので、 実現するにはかなり困難がつきまといます。 方法としては、アイテムせいとんをした場合に 所持していないアイテムも含め全種類を出現させ、かつ個数を最大数に 変更させるのが最善でしょう。 まずはアイテム全所持コードの必須条件 1.全種類のアイテムを一度に所持できなくてはならない アイテムの所持個数に制限があり、全アイテムを 同時に持ち歩くことができないものはダメ。 2.アイテムのせいとんコマンドがある せいとんコマンドがない代わりに自動的に整列されるものは この方法は使用できない。 この2つの条件を満たしたゲームタイトルのみ対象になります。 特に、条件1を満たさないものはPAR2以降の反復コードも 通用しないので注意が必要です。 ここでは、例としてまたまた「ファイナルファンタジー8」を取り上げます アイテム全所持には2つのステップがあります。 全種類のアイテムを出現させることと、 アイテムの所持個数を最大にすることです。 まずは比較的簡単な後者から解説します。 最初に1個目のアイテムのアドレスを探し出します。 個数は数値サーチで80076DBDと割り出せます。 ここでHBPを使用する前に、1個目のアイテムを空白にしましょう。 というのも、アイテムのせいとんといっても単に空白を詰めるだけの 場合があるからです。 HBPの設定 Breakpoint Address:$80076DBD Address Mask :$0FFFFFFF Event :Write Break Count :$0001 としてアイテムのせいとんをしたところ、 $801e8934 sb zero,$0000(v1) ;ゼロをアドレスv1+$0に1バイト分書き込み $801e8938 addiu v1,v1,#$0001 ;v1=v1+1 >$801e893c sb zero,$0000(v1) ;ゼロをアドレスv1+$0に1バイト分書き込み $801e8940 addiu a0,a0,#$0001 ;a0=a0+1 $801e8944 slti v0,a0,#$00c6 ;a0の値と$c6(198)を比較し結果をv0に代入 $801e8948 bne v0,zero,$801e8934 ;v0がゼロ以外(a0が$c7未満)ならば$801e8934へ分岐 $801e894c addiu v1,v1,#$0001 ;v1=v1+1 という部分で引っかかりました。 ここではzeroを書き込んでいるので、目的の場所ではないようです。 HBPの設定でBreak Countを$0002にして再度やり直します。 $801e8960 lbu v0,$0000(a1) ;アドレスa1+$0から1バイトの値をv0に読み込み $801e8964 nop ;ロード待ち $801e8968 beq v0,zero,$801e8984 ;v0がゼロと等しければ$801e8968へ分岐 $801e896c nop ;遅延スロット、何もしない $801e8970 sb a0,$0000(v1) ;a0の値をアドレスv1+$0に1バイト分書き込み $801e8974 lbu v0,$0000(a1) ;アドレスa1+$0から1バイトの値をv0に読み込み $801e8978 addiu v1,v1,#$0001 ;v1=v1+1 >$801e897c sb v0,$0000(v1) ;v0の値をアドレスv1+$0に1バイト分書き込み $801e8980 addiu v1,v1,#$0001 ;v1=v1+1 $801e8984 addiu a0,a0,#$0001 ;a0=a0+1 $801e8988 sltiu v0,a0,#$00c7 ;v0の値と$c7(199)を比較し結果をv0に代入 $801e898c bne v0,zero,$801e8960 ;v0がゼロ以外(a0が$c7未満)ならば ;$801e8960へ分岐 $801e8990 addu a1,a2,a0 ;a1=a2+a0 今度はここでブレークしました。 念のためBreak Countを$0003にして再度やり直たところ、 1回のせいとんでカウントが2減ったことから、 目的の場所であるといえそうです。 HBPの引っかかったアドレス801e897cで v0レジスタの値を書き込んでいるので、 v0レジスタを追っていくと、2つ上の $801e8974 lbu v0,$0000(a1) があります。ここでv0レジスタに値をロードしているので、 その命令を変更して、v0レジスタに任意の値を入れます。 とりあえず最大数の100を入れることにしますが、 レジスタに即値を代入する命令に、li命令があります。 li v0,$0064 というように使います。 データ変換は、 li xx,$yyyy 上位2バイト=2400+xxのレジスタ番号 下位2バイト=$yyyyに代入する値です。 レジスタ番号については、 zero(0),at(1),v0(2),v1(3),a0(4),a1(5),a2(6),a3(7), t0(8),t1(9),t2(10),t3(11),t4(12),t5(13),t6(14),t7(15), s0(16),s1(17),s2(18),s3(19),s4(20),s5(21),s6(22),s7(23), t8(24),t9(25),k0(26),k1(27),gp(28),sp(29),fp(30),s8(30),ra(31) 以上の通りです。fpとs8は同一のレジスタですが、 逆アセンブラによって呼び名が異なるので、両方載せておきました。 li v0,$0064は、24020064と変換できます。 PARコードに直すと 801E8974 0064 801E8976 2402 になります。 まだ途中ですが、この状態でアイテムのせいとんをすると 所持アイテムの個数が100個に固定されるようになります。 次は全種類のアイテムを出現させる部分です。 アイテムのせいとんではループ処理を行っています。 このループ処理に使用されているループカウンタの値を うまく利用することで、アイテムの種類を変更します。 具体的には、1個目のアイテムにアイテム番号1を、 2個目にアイテム番号2・・・と入れていけば 重複なしに全てのアイテムが揃ってしまいます。 そこで、何度かHBPをかけてレジスタの値の変化を見て ループカウンタの格納レジスタを特定します。 今度はアイテムの種類のアドレスにHBPをかけます。 アイテムのいれかえを行って比較サーチをした結果、 アイテムの種類のアドレスは80076DBCと判明しました。 HBPの設定 Breakpoint Address:$80076DBC Address Mask :$0FFFFFFF Event :Write Break Count :$0001 では、個数と同様zeroを書き込む命令で引っかかったので Break Countを$0002にしてやり直したところ、 >$801e8970 sb a0,$0000(v1) と、個数を書き込む命令のすぐそばでブレークしました。 この時点での全てのレジスタの値をメモしてから、 次は2個目のアイテムにHBPをかけ、 レジスタの値の変化を追っていきます。 その結果、1個目のアイテムのときに値がゼロか1で、 2個目、3個目では値が1ずつ増加しているのが ループカウンタの格納レジスタです。 そうしたらHBPの引っかかった命令で書き込んでいる a0レジスタの値を追っていき、該当した命令を a0レジスタにループカウンタの格納レジスタを代入する命令に変更します。 これにはmove命令が相応しいですが、ここではaddiu命令を使用します。 仮にループカウンタの格納レジスタをs0とすると、 addiu a0,s0,$0000 というようにします。a0=s0+ゼロなので、 a0にs0の値を代入するという意味になります。 データ変換は、 addiu xx,yy,$zzzz 上位2バイト=2400+yyのレジスタ番号*20+xxのレジスタ番号 下位2バイト=$zzzzに代入する値です。 これは計算に多少手間取りますが、 addiu a0,s0,$0000は、26040000と変換できます。 実は先ほどのli命令はaddiu命令のyy部分を zeroレジスタにしただけのものなのです。 さて、ファイナルファンタジー8の例では ループカウンタの値はa0レジスタです。 つまり、ループカウンタの格納レジスタと、 HBPの引っかかった命令で書き込むレジスタが同じです。 こういう場合は、1つ手前の条件分岐命令を潰すだけで済みます。 801e8968のbeq v0,zero,$801e8984 がそうですが、これをbne zero,zero,$801e8984に変更します。 命令の上位2バイトを1400にすればよいので、 PARコードに直すと 801E896A 1400 です。 これで完成しました。最後の仕上げに誤動作防止のDコードの挿入です。 データ部分が0000の場合、別のプログラムがロードされても 偶然0000と重なることがあるので、なるべく他の値を使用しましょう。 一例ですが、ファイナルファンタジー8の アイテムのせいとんをすると全てのアイテムを100個所持は、 D01E8968 0006 801E896A 1400 D01E8968 0006 801E8974 0064 D01E8968 0006 801E8976 2402 やっと終わりました。 しかしこれは相当難しいです。ある程度アセンブラに慣れていないと かなり辛いかもしれません。 反対に、これをマスターできれば、プログラムコードは ほぼ完璧と言えるかもしれません。 ------------------------------- まとめ アイテム全所持コードの作成法 ステップ1:個数の最大化 HBPがヒットした命令で値を書き込むレジスタを追いかけていき、 該当した命令を li xx,$yyyy(yyyyには個数の最大値が入る)に変更 =命令の上位2バイトを2400+xxのレジスタ番号 命令の下位2バイトをyyyyの値に変更する ステップ2:全種類のアイテムを出現させる HBPがヒットした命令で値を書き込むレジスタを追いかけていき、 該当した命令を addiu xx,yy,$0000に変更(yyはループカウンタの格納レジスタ) =命令の上位2バイトを2400+yyのレジスタ番号*20+xxのレジスタ番号 命令の上位2バイトを0000に変更する HBPがヒットした命令で値を書き込むレジスタ= ループカウンタの格納レジスタの場合は HBPがヒットした命令の1つ手前の条件分岐命令を bne zero,zero,$80xxxxxxに変更 =条件分岐命令の上位2バイトを1400にする または、分岐先を1つ先の命令に変更 =条件分岐命令の下位2バイトを0001にする レジスタ番号一覧 zero: 0 at: 1 v0: 2 v1: 3 a0: 4 a1: 5 a2: 6 a3: 7 t0 : 8 t1: 9 t2:10 t3:11 t4:12 t5:13 t6:14 t7:15 s0 :16 s1:17 s2:18 s3:19 s4:20 s5:21 s6:22 s7:23 t8 :24 t9:25 k0:26 k1:27 gp:28 sp:29 fp:30 s8:30 ra:31



無断転載・無断商用利用・無断直接リンク禁止
ホームページサイト登録はこちらゲーム個別検索登録はこちら