九龍妖魔學園紀
キーワード
ベース
レジスタ
論理積、排他的論理和
テーブル
符号拡張
このソフトはシンボル残りのソフトでして普段は出来ないようなコードも作成可能です。
解析者に優しいソフトですので初心者の練習には最適ではないでしょうか?
内容
感情値変動すると指定値へ変更
プリクラなくてもバディ選択可能
アイテム全種x個
感情値表示
感情値変動すると指定値へ変更
ラベルの中で注目して欲しいものは主にこれらのものです。
St_get〜
St_set〜
コードを作り始めて少し経ってから気がつきましたが、getがロード、setがストアの処理のラベルです。
このラベルに続くものでかなりの数のコードが出来ます。例えば
St_SetEtcCharKanjo
これは見た目通りでキャラの感情値をストアしています。
ロードではなくストアを選んだ理由はロードだとその後の処理で変動した数値分加算や減算がされてしまう為。
00137a80 addiu sp, sp, $ffc0 St_SetEtcCharKanjo(ラベル)
00137a84 sd ra, $0030(sp)
00137a88 sq s2, $0020(sp)
00137a8c sq s1, $0010(sp)
00137a90 sq s0, $0000(sp)
00137a94 daddu s1, a1, zero
00137a98 daddu s0, a2, zero
00137a9c andi v1, a0, $ffff
00137aa0 andi s2, v1, $7fff
00137aa4 slti v1, s2, $001e
00137aa8 bne v1, zero, $00137ac4
00137aac nop
00137ab0 lui a0, $0049 a0=$00490000
00137ab4 addiu a0, a0, $69e8 a0=$004969e8
00137ab8 addiu a1, zero, $14ac a1=$000014ac
00137abc jal kwlnAssertFunc_ ▼$001b7310
00137ac0 nop
00137ac4 addiu v1, zero, $001a v1=$0000001a
00137ac8 bne s2, v1, $00137ad4
00137acc nop
00137ad0 daddiu s2, zero, $0002 s2=$00000002
00137ad4 dsll32 v1, s0, 16
00137ad8 dsra32 v1, v1, 16
00137adc slti v1, v1, $270f
00137ae0 bne v1, zero, $00137aec
00137ae4 nop
00137ae8 addiu s0, zero, $270f s0=$0000270f
00137aec andi a0, s2, $ffff
00137af0 sll v1, a0, 1 v1=$00000004
00137af4 addu v1, v1, a0 v1=$00000006
00137af8 sll a0, v1, 2 a0=$00000018
00137afc lui v1, $0077 v1=$00770000
00137b00 addiu v1, v1, $6282 v1=$00776282
00137b04 addu a0, v1, a0
00137b08 dsll32 v1, s1, 16
00137b0c dsra32 v1, v1, 16
00137b10 sll v1, v1, 1
00137b14 addu v1, v1, a0
00137b18 sh s0, $0000(v1)
00137b1c ld ra, $0030(sp)
00137b20 lq s2, $0020(sp)
00137b24 lq s1, $0010(sp)
00137b28 lq s0, $0000(sp)
00137b2c addiu sp, sp, $0040
00137b30 jr ra
目につくものは$270fの比較命令ですこの結果により分岐するかしないかを決めています。
しなければ青いバーの$270fが。分岐した場合は分岐命令を遡ると分かると思いますが
s0レジスタの値が$00137b18でストアされています。この説明は下を見て下さい。
つまり分岐を潰すと最大値である$270fがストアされます。
このサイトに掲載してあるものは最大値固定ですが、
数値を自分で指定できる様なコードを作ります。
分岐を潰し$00137ae8を変える方法もありますがこれだと2行必要になります。
その為今回は違う方法をとりました。
比較しているのは$00137adcのv1レジスタと$270f、
この時点ではv1レジスタに感情値が格納されています。この前の2行を見て下さい。
dsll32 v1,s0,16でs0レジスタを32+16ビット左へシフトし、v1レジスタへ格納
dsra32 v1,v1,16でv1レジスタを32+16ビット右へシフトし、v1レジスタへ格納
という処理をしています。
s0レジスタに感情値が格納されている事が分かりますね。
そうしてs0レジスタがある箇所を上に遡ってみていくと$00137a98で
daddu s0, a2, zero
としている箇所があります。
ここに自分が指定したい数値をs0レジスタへ入れます。
00137a80 addiu sp, sp, $ffc0 St_SetEtcCharKanjo(ラベル)
00137a84 sd ra, $0030(sp)
00137a88 sq s2, $0020(sp)
00137a8c sq s1, $0010(sp)
00137a90 sq s0, $0000(sp)
00137a94 daddu s1, a1, zero
00137a98 addiu s0, zero, $2328 s0=$00002328
00137a9c andi v1, a0, $ffff
00137aa0 andi s2, v1, $7fff
00137aa4 slti v1, s2, $001e
00137aa8 bne v1, zero, $00137ac4
00137aac nop
00137ab0 lui a0, $0049 a0=$00490000
00137ab4 addiu a0, a0, $69e8 a0=$004969e8
00137ab8 addiu a1, zero, $14ac a1=$000014ac
00137abc jal kwlnAssertFunc_ ▼$001b7310
00137ac0 nop
00137ac4 addiu v1, zero, $001a v1=$0000001a
00137ac8 bne s2, v1, $00137ad4
00137acc nop
00137ad0 daddiu s2, zero, $0002 s2=$00000002
00137ad4 dsll32 v1, s0, 16
00137ad8 dsra32 v1, v1, 16
00137adc slti v1, v1, $270f
00137ae0 bne v1, zero, $00137aec
この例だと$2328。10進数で9000ですから比較した結果v1レジスタに1が入り分岐。
$2328がそのままストアされる様になりました。
プリクラ無くてもバディ選択可能
このコードは苦労しましたが、AR誌でバディ全員のコードが掲載された後に出来た為、
かなり意味が無くなってしまいました
きっかけはアイテム移植コードを作った際にもう1度色々探した事。
しかし今後に役立つのではないかと思うコードでした
探し方は3種類ほどあります
1.パッドから探す
2.バディ選択時の処理を遡る
3.ラベルのChkGameFlagから探す
2,3は後から気がついた方法ですが、1は時間が掛かりすぎる。
3は多数のフラグのチェックをしている為あまりおすすめできません
今回は1を詳しく説明します2、3は1と同じ箇所ですので大まかに。
では始めにやった1から説明していきます。
1.パッドから探す
注目する点はパッド情報でして
これはバディを選択する時に○で選択△で外すSELECTでプリクラを拡大、□で詳細表示、STARTで遺跡へ。
という事を参考にします。
これを選んだ理由はもしプリクラがなければボタンを押しても分岐する事が考えられる為です。
これらのパッド情報は
△ |
0010 |
1000 |
○ |
0020 |
2000 |
□ |
0080 |
8000 |
SELECT |
0100 |
0001 |
START |
0800 |
0008 |
この2種類のうちどちらかです。プラス形式である場合は大抵左の数値が使用される為まずはこちらで探します。
16ビットで探しますが、$0010、$0020、$0080これらはプログラムでよく使われていそうな為除外。
残りの$0100、$0800ですが後者の場合もよく使われている様なので$0100で探してみます。
それでも多くヒットしますが$00100000代は今までの経験上あまり無いのでとばします。
探す命令は
andi 〜, 〜, $0100
分岐命令
〜にはそれぞれレジスタが入ります。
動体視力が良ければF4キーを押したままでも見つかると思います。
過ぎてしまってもShift+F4を押せば戻りますので大丈夫です。
見つかったら
andi 〜, 〜, $0100の
$0100(SELECTの値)を$0020(○の値)に変えてみましょう。
こうする事でセレクトを押した場合○の動作をすることが考えられる為です。
念のためその周辺にある
andi 〜, 〜, $0020を$0100(SELECTの値)に変えます。
これでボタンの効果が反対になっていればその処理中にフラグを判定する処理がされているはずです。
正解の箇所を載せますが、本来であれば何カ所もあるところ全てを変えて下さい。
処理1
0015f3c4 andi v0, v1, $0020
0015f3c8 beq v0, zero, $0015fac0
0015f3cc nop
0015f3d0 daddu s2, zero, zero
0015f3d4 lh v1, $00be(s0)
0015f3d8 addiu v0, zero, $0001
0015f3dc bne v1, v0, $00160c30
0015f3e0 nop
0015f3e4 lh v0, $00ba(s0)
0015f3e8 sll a0, v0, 3
0015f3ec dsll32 v1, s5, 16
0015f3f0 dsra32 v1, v1, 16
0015f3f4 addu v0, v1, a0
0015f3f8 sll v0, v0, 2
0015f3fc addu v0, v0, s0
0015f400 lw v0, $00e0(v0)
0015f404 beq v0, zero, $00162168
0015f408 nop
0015f40c addiu v0, a0, $01f5
0015f410 addu v0, v1, v0
0015f414 andi a0, v0, $ffff
0015f418 lui a1, $004b a1=$004b0000
0015f41c addiu a1, a1, $8248 a1="h_buddy.c"
0015f420 addiu a2, zero, $0186 a2=$00000186
0015f424 jal ChkGameFlag ▲$0012bc90
0015f428 nop
0015f42c beq v0, zero, $00162168
処理2
0015f228 lh s5, $00bc(s0)
0015f22c lui at, $0075 at=$00750000
0015f230 lhu v1, $744e(at) v1=$0075744e
0015f234 andi v0, v1, $0100
0015f238 beq v0, zero, $0015f294
0015f23c nop
0015f240 lh v0, $00ba(s0)
0015f244 sll v0, v0, 3
0015f248 addiu v1, v0, $01f5
0015f24c dsll32 v0, s5, 16
0015f250 dsra32 v0, v0, 16
0015f254 addu v0, v0, v1
0015f258 andi a0, v0, $ffff
0015f25c lui a1, $004b a1=$004b0000
0015f260 addiu a1, a1, $8248 a1="h_buddy.c"
0015f264 addiu a2, zero, $016a a2=$0000016a
0015f268 jal ChkGameFlag ▲$0012bc90
0015f26c nop
0015f270 beq v0, zero, $00162168
変更する箇所はそれぞれ青いバーの位置です。これを
andi v0, v1, $0100
andi v0, v1, $0020
へ変えます。結果ボタン操作が入れ替わっています
ここで注目すべき点は○を押した時の処理1の処理です
○を押した場合のパッド情報は$0020。ビットですと
100000
この1の部分がv1レジスタと一致すると後は何が入っても
100000となります
100000 |
$0020 |
111111 |
v1レジスタ |
結果 |
100000 |
v0レジスタ |
ビットの説明ですがうまくできてませんね。
論理積はかけ算、排他的論理和は足し算(同じ場合は0)だと思って下さい
論理和、論理積を調べると何が言いたいのか分かるかと思います
ビットの説明はここで終えて、続きに入ります。
簡単に言うと○を押した時にv0レジスタに$0020が入るという事です。
そうすると○ボタンを押している時は分岐しません。この後を見ていくと
$0015f424にChkGameFlagへジャンプする命令がありますので→キーを押しジャンプしてみましょう
0012bc90 andi v0, a0, $ffff ChkGameFlag(ラベル)
0012bc94 andi v1, v0, $001f
0012bc98 bgez v0, $0012bcac
0012bc9c nop
0012bca0 beq v1, zero, $0012bcac
0012bca4 nop
0012bca8 addiu v1, v1, $ffe0
0012bcac addiu v0, zero, $0001 v0=$00000001
0012bcb0 sllv a1, v0, v1
0012bcb4 andi v0, a0, $ffff
0012bcb8 srl v0, v0, 5
0012bcbc sll v1, v0, 2
0012bcc0 lui v0, $0077 v0=$00770000
0012bcc4 addiu v0, v0, $6900 v0=_GameFlag
0012bcc8 addu v0, v0, v1
0012bccc lw v0, $0000(v0)
0012bcd0 and v0, a1, v0
0012bcd4 sltu v0, zero, v0
0012bcd8 jr ra
その名の通りフラグをチェックしているようです。
青いバーを見ると、jr raで戻る前に比較命令でv0レジスタに0もしくは1が入ります。
戻ると$0015f42cでv0が0の場合分岐。1の場合分岐しない様になっていますね。
という事は上の方で書いた通り「プリクラがなければボタンを押しても分岐する事が考えられる」が
あっているようで、フラグが立っている。1であれば分岐しない筈なのでこの分岐命令を潰して
プラグが立っていなくても分岐させなければ良い訳です。
2.バディ選択時の処理を遡る
バディ選択はSt_GetBuddyでデータをロードしSt_SetBuddyでストアしています。
ではまず最初にSt_GetBuddyの処理の先頭の$0012f900をスペースキーでマークし
F3キーで参照箇所へ
0012f900 andi v1, a0, $ffff St_GetBuddy(ラベル)
0012f904 ori v0, zero, $8000 v0=$00008000
0012f908 bne v1, v0, $0012f934
0012f90c nop
0012f910 dsll32 v0, a1, 16
0012f914 dsra32 v0, v0, 16
0012f918 sll v1, v0, 1 v1=$00010000
0012f91c lui v0, $0078 v0=$00780000
0012f920 addiu v0, v0, $99c4 v0=$007799c4
0012f924 addu v0, v0, v1
0012f928 lhu v0, $0000(v0)
0012f92c beq zero, zero, $0012f938
0012f930 nop
0012f934 ori v0, zero, $ffff v0=$0000ffff
0012f938 jr ra
するといくつかの参照箇所の中の$0015f490の上を見るとandiと分岐命令があります。
これは前にもあげた様にパッド判定をしている可能性があります。
ここから下へ行くと先ほどと同じ箇所でしてフラグをチェックした後分岐するかしないかになっています。
後は同じように分岐を潰す事でフラグが立っている様に出来ます。
0015f3c4 andi v0, v1, $0020
0015f3c8 beq v0, zero, $0015fac0
0015f3cc nop
0015f3d0 daddu s2, zero, zero
0015f3d4 lh v1, $00be(s0)
0015f3d8 addiu v0, zero, $0001 v0=$00000001
0015f3dc bne v1, v0, $00160c30
0015f3e0 nop
0015f3e4 lh v0, $00ba(s0)
0015f3e8 sll a0, v0, 3
0015f3ec dsll32 v1, s5, 16
0015f3f0 dsra32 v1, v1, 16
0015f3f4 addu v0, v1, a0
0015f3f8 sll v0, v0, 2
0015f3fc addu v0, v0, s0
0015f400 lw v0, $00e0(v0)
0015f404 beq v0, zero, $00162168
0015f408 nop
0015f40c addiu v0, a0, $01f5
0015f410 addu v0, v1, v0
0015f414 andi a0, v0, $ffff
0015f418 lui a1, $004b a1=$004b0000
0015f41c addiu a1, a1, $8248 a1="h_buddy.c"
0015f420 addiu a2, zero, $0186 a2=$00000186
0015f424 jal ChkGameFlag ▲$0012bc90
0015f428 nop
0015f42c beq v0, zero, $00162168
0015f430 nop
0015f434 addiu a0, zero, $0001 a0=$00000001
0015f438 jal ReqSe ▼$001667e0
0015f43c nop
0015f440 lh v1, $00bc(s0)
0015f444 lh v0, $00ba(s0)
0015f448 sll v0, v0, 3
0015f44c addu v0, v1, v0
0015f450 addiu v0, v0, $0001
0015f454 andi s3, v0, $ffff
0015f458 addiu v0, zero, $0002 v0=$00000002
0015f45c bne s3, v0, $0015f488
0015f460 nop
0015f464 addiu a0, zero, $034c a0=$0000034c
0015f468 lui a1, $004b a1=$004b0000
0015f46c addiu a1, a1, $8248 a1="h_buddy.c"
0015f470 addiu a2, zero, $018a a2=$0000018a
0015f474 jal ChkGameFlag ▲$0012bc90
0015f478 nop
0015f47c beq v0, zero, $0015f488
0015f480 nop
0015f484 daddiu s3, zero, $001a s3=$0000001a
0015f488 ori a0, zero, $8000 a0=$00008000
0015f48c daddu a1, zero, zero
0015f490 jal St_GetBuddy ▲$0012f900
3.ラベルのChkGameFlagから探す
これはChkGameFlag処理の先頭から参照箇所探し上の場所を探す。です
しかしこれはあまりにも参照箇所がある為、止めた方がいいです。
ただ多数のフラグをChkGameFlagで処理している為自由行動時会話済みにならない等の
コードを探す場合は役に立ちました。
具体的なフラグは「フラグ色々『副作用あり』(セーブ未反映)」コードの効果を見て下さい。
しかしこれだけではなくほかにも効果があるようですが、どういった物があるのかは未確認です。
2ページ目へ 雑記へ戻る