2006.02.11
No.006 条件分岐コードの活用

条件分岐コードとは?
「任意アドレスの値が条件を満たした場合のみ、次の行のコードが実行される」
というわけで、コード書式は以下のような感じです。
ワード(4バイト)判定コード
D2001500 11FF5522
0215000C 000000FF

アドレス02001500が11FF5522の場合、
アドレス0215000CにFFを書き込む。
ハーフワード(2バイト)判定コード
E2001500 10005522
0215000C 000000FF

アドレス02001500が5522の場合、
アドレス0215000CにFFを書き込む。
バイト(1バイト)判定コード
E2001500 00000022
0215000C 000000FF

アドレス02001500が22の場合、
アドレス0215000CにFFを書き込む。
これだけを知っても「どこに使うねん?」と思うかもしれませんねぇ。
それでは、実例で説明しましょう。

ぷよぷよフィーバー
DSエミュレータDeSmuME v0.3以降で「ぷよぷよフィーバー」が実用レベルで動作するようになりました。
(キャラ絵が出てなかったりセーブエラーが出たり常にマイクに息を吹きっぱなしになってますが)。
ぷよフィ
相殺を1回行うごとに「フィーバーゲージ」が溜まり、7個でフィーバーに突入するのですが、
フィーバーゲージそのものはサーチツールhasteDS(No.004参照)で簡単にサーチ可能で、
あっさりとアドレス02146766に絞り込めます。

マスターコードサーチも前回と同じように "04000130" をサーチして…
---
:020014C8 E59F1170 ldr r1,[r15, #+0x170] ;r15+0x170=*(02001640)=#67109168(0x04000130)
(中略)
:0200163C E12FFF1E bx r14 (Jump to addr_0212C648?)
---
マスターコードは F200163C E12FFF1E ですね。

フィーバーゲージ7個でフィーバーに突入するのですから、
F200163C E12FFF1E
02146766 00000007

これで常にフィーバーゲージが7の状態が維持されるようになります。

が…
確かにフィーバーゲージは最大まで溜まっているものの、一向にフィーバーが始まりません。
その上、相殺するごとに相手にフィーバー時間が加算されて、ますますシビアになっただけです。
かといって02146766 00000006では常に6個のままなので結局フィーバーが始まりません。
フィーバーが発生するためには「6→7に変化する瞬間が必要」なのです。

そう、フィーバーゲージを増加させても固定にはしない……その条件を満たせば良いわけですね。

どうすれば良いか?を考える
〜書き込む値〜
・フィーバーゲージに7を書き込むとフィーバーが発生しない→書き込む値は6
(相殺するとフィーバーゲージが+1されるので結果的に7になるはず)
〜書き込むタイミング〜
・フィーバーゲージが0個のとき
・フィーバーゲージが1個のとき(甘口)
・フィーバーゲージが3個のとき(激甘)
→上記条件のときに6が書き込まれ、6→7の時は書き込まれないのでフィーバー発生。

これをそのままコードにすると…
F200163C E12FFF1E
E2146766 00000000
02146766 00000006
E2146766 00000001
02146766 00000006
E2146766 00000003
02146766 00000006

非常に非合理的なコードですが、これ以外にはプログラムコードくらいしか方法が無いため、
事実上「最も手軽に効果を得られる」コードは上のものになります。
このコードを実行して、相殺1回でフィーバーが発生すれば成功です。
(こんな改造コードを実行した状態で「激甘」「甘口」を選ぶ必要が無いので、実際は上3行だけで十分なのですが)。

別の分岐方法〜ボタン入力判定〜
先ほどのコードは「パラメータの状況」により書き込みの可否を判断していましたが、
他にも「ボタン入力」で条件を切り替えることが可能です。
別に、専用コードが存在しているわけでは無く、アドレス04000130の値を判定に使うだけで実現できます。
(厳密には04000130〜04000131のハーフワード)。
ただ、X/Yボタンやタッチスクリーンの情報はアドレス04000136に格納されているものの、
ARM7以外で制御できないので、今回は省略します。
15-109876543210
000000LRSTARTSELECTBA
各ビットには上記リストのようにボタンが割り当てられており、平常時は1、押下時は0が入ります。
(例)
Aボタンを押す=0000001111111110=0x03FE … E4000130 100003FE
LとR同時押し =0000000011111111=0x00FF … E4000130 100000FF
何も押さない =0000001111111111=0x03FF … E4000130 100003FF

ボタン情報の格納されているアドレスは全てのゲームに共通(というかハード仕様)ですので、
全てのゲームで利用することができます。

さいごに
今回で、基本的なサーチに関するネタは一旦終了です。
次回より、少しだけARM命令に触れていってみましょう。
>>次の講座へ進む