サーチの小技


 

ちょっとイレギュラーな小技ばっかを書く予定。
どう利用するかは各人でガンガレ。

 

現在のネタは以下の4つ。
  • タッチした座標の検出
  • 垂直ブランク割り込みの無効化(高速化コードの基礎の基礎)
  • ボタン連打コードのサーチ
  • スローモーションコードの作成方法

 


 

タッチした座標の検出

本来はARM7でXKEYSレジスタ(アドレス04000136)にアクセスしないとダメだが、
そこに格納されてる値から必要なデータを取り出すのは超マンドクセ。
素直に「絶対座標」がほしいならno$gbaで画面をタッチしたまま F1 を押すといい。
これでヘルプ表示でエミュレーションが停止するので、タッチ情報などもそのまんま止まるんだぜ。

 

大抵、ゲーム中では「どこかでタッチ情報を処理」しているので、
それを一時的に保持しているアドレスがヒットするはず。
ちなみにDSのスクリーン解像度は 256×192 なのでこれに近い値のものを探すべし。

 

<タッチ!カービィでそれを検証>

 

下で敵にボコボコにされてるカービィは無視して、適当な場所をクリックしながらF1。
エミュレーションが止まるので、emuhasteからクリック場所を基準に増加 or 減少で絞り込み。
俺の環境だとX座標がアドレス 020D9576 、Y座標が020D9578 にそれっぽい値が入った。
(他にも色々いっぱいヒットしてるけど)。

 

変動アドレスかもしれんけど、そのときはそのときで考える!!
まあ、これらの値は2バイト(WORD)サイズだった。

 


 

垂直ブランク割り込みの無効化(高速化コードの基礎の基礎)

プログラム内に存在するthumbコードから以下の箇所を探す
2200 mov r2,0x00
DF05 swi #0x05
(※ndsdis2ではthumbコードを吐けないので注意)
最も簡単な方法としては、DSエミュレータで起動後にhasteDSもしくはemuhasteで16進数 "002205DF" をパラメータサーチ。
→2箇所以上該当するので、そのアドレスに対して 00002200 を書き込むコードを実行する。

 

(例)直感ヒトフデの場合 "002205DF"がアドレス 02000350 と 0238BD44 に合計2個ヒット。
改造コードはこうなる。
02000350 00002200
0238BD44 00002200

 

なお、ゲームによってはこれで高速化することもあるが、何も起こらない場合もある。

 


 

ボタン連打コードのサーチ

DSのボタン入力情報はアドレス04000130と04000136に格納されている。
んで、連打というのは「ボタン押して離してまた押して…」の繰り返しであり、
必ずプログラム側が「離して」という部分を判断している(はず)。
この「離して」の判断を押しっぱなしでも有効にするのが「ボタン連打コードのサーチ」である。

 

※当然ながらゲームごとにボタン処理のルーチンが異なるため、ここで紹介している方法では連打できない場合もある。

 

とりあえず「ぷよぷよフィーバー」で実験。

 

対戦が始まったら…
Aボタン(に割り当てたキー)を押しながらF1キーを押してヘルプ表示(停止)→値 "01" を検索。
Bボタン(に割り当てたキー)を押しながらF1キーを押してヘルプ表示(停止)→値 "02" を検索。
何も押さずに値 "00" を検索。
↓以下の4つのアドレスに該当
0212C848
0212C84A
021454D8
021454DA

 

これらのアドレスを判定しているルーチンをいじれば連打状態にできると思うが、
ぷよフィだと
2212C848 00000000
2212C84A 00000000
221454D8 00000000
221454DA 00000000
こんな感じで00(何も押さない)を書き込むことで、
1.ユーザがボタンを押す
2.ゲーム中の"ボタンを押した際の処理"を実行
3.改造ツール側が"00"を書き込む
4.ボタンを放したと判断される


という流れが発生し、ボタンを押しっぱなしでもぷよがぐるぐる回るようになる。
ゲームによっては00,01,02ではなくビット反転した値(FF,FE,FD)で処理している可能性もあるので注意。

 


 

スローモーションコードの作成方法


過去ログ7から引用

663 :前スレ346:2007/11/15(木) 01:14:41 ID:Te+tUkrg
とりあえず書いたので投稿します。
高速化とは対照的な「自作ルーチン埋込」の技術を応用したスローモーションコードの作成法です。
スローモーション機能付きのマジコンを持っていない、または持っているけどスローモーションの
ON/OFFをもっと手軽に切り替えたいという場合に有効。

スローモーションは時間稼ぎをするプログラムを挿入し、故意に処理落ちを発生させることで実現できます。
では実際に「超執刀 カドゥケウス (アトラス ベストコレクション)」でスローモーションコードを作ってみます。
とりあえず逆アセンブルして04000130を検索すると以下の部分でヒット。
:02000F34 E59F10D8 ldr r1,[r15, #+0xd8]    ;r15+0xd8=*(02001014)=#67109168(0x04000130)
:02000F38 E59F00D8 ldr r0,[r15, #+0xd8]    ;r15+0xd8=*(02001018)=#41942952(0x027fffa8)
:02000F3C E1D130B0 ldrh r3,[r1, #+0x0]    ;r1+0x0=*(04000130)=#0(0x00000000)
:02000F40 E1D010B0 ldrh r1,[r0, #+0x0]    ;r0+0x0=*(027fffa8)=#1916546356(0x723c2d34)
:02000F44 E59F20D0 ldr r2,[r15, #+0xd0]    ;r15+0xd0=*(0200101c)=#35515132(0x021deafc)
:02000F48 E59F00D0 ldr r0,[r15, #+0xd0]    ;r15+0xd0=*(02001020)=#12287(0x00002fff)
:02000F4C E1831001 orr r1,r3,r1
:02000F50 E0211000 eor r1,r1,r0
:02000F54 E0010000 and r0,r1,r0
:02000F58 E1A01800 mov r1,r0,lsl #0x10   ;r1=805240832(0x2fff0000)

上記の部分から以下のことが読み取れる。
1. この部分は通常なら毎秒60回実行される。
2. プログラムカウンタが$02000F58に来ている時点ではr3レジスタにキーデータが格納されている。
3. アドレス$02000F58から追加ルーチンへ飛ばしても追加ルーチンの最後で mov r1,r0,lsl #0x10
を実行すれば追加ルーチンではr1レジスタを自由に使用できる。

この3つの条件を頭に入れながら$02000F58の部分に時間稼ぎをするプログラムを挿入する。
$021BD9E0 - $021BD9FCの部分が空き領域として使えるので追加ルーチンはこの部分に埋め込めます。

02000F58 EA06F2A0  b $021BD9E0      ;追加ルーチンへジャンプ

021BD9E0 E3130C01  tsts r3, #$0100    ;Rボタンをチェックして
021BD9E4 0A000003  beq $021BD9F8    ;押されていたら潰した命令を実行して復帰

Rボタンが押されていなければ時間稼ぎをする
021BD9E8 E3A01A40  mov r1, #$00040000 ;r1 = #$00040000
021BD9EC E2411001  sub r1, r1, #$01    ;r1 = r1 - #$01
021BD9F0 E3510000  cmps r1, #$00     ;r1 = #$00 かチェック
021BD9F4 1AFFFFFC  bne $021BD9EC    ;r1 = #$00 ならループ脱出

021BD9F8 E1A01800  mov r1, r0, lsl #$10  ;潰した命令を実行
021BD9FC EAF90D56  b $02000F5C     ;追加ルーチンから復帰

このままでも動くけどARDSの機能を利用して無駄を省いてコード完成。
超執刀 カドゥケウス (アトラス ベストコレクション) AKDJ BA5320CB
スローモーション1/2
52000F58 E1A01800
E21BD9E0 00000020
E3130C01 0A000003
E3A01A40 E2411001
E3510000 1AFFFFFC
E1A01800 EAF90D56
02000F58 EA06F2A0
D0000000 00000000
※ゲームの速度が通常の1/2になります。Rボタンを押している間は通常の速度になります。

過去ログ8から引用

854 :名無しさん@お腹いっぱい。:2008/01/06(日) 04:34:02 ID:1ItsVXNi
前スレのスローモーションコードの作り方を参考に
眼力トレーニングでスローモーションコード作ろうとしているのですが

:0201245C E59F1260 ldr r1,[r15, #+0x260] ;r15+0x260=*(020126c4)=#67109168(0x04000130)
:02012460 E59F0250 ldr r0,[r15, #+0x250] ;r15+0x250=*(020126b8)=#41942952(0x027fffa8)
:02012464 E1D130B0 ldrh r3,[r1, #+0x0] ;r1+0x0=*(04000130)=#0(0x00000000)
:02012468 E1D010B0 ldrh r1,[r0, #+0x0] ;r0+0x0=*(027fffa8)=#1347436608(0x50504040)
:0201246C E59F0254 ldr r0,[r15, #+0x254] ;r15+0x254=*(020126c8)=#12287(0x00002fff)
:02012470 E59F223C ldr r2,[r15, #+0x23c] ;r15+0x23c=*(020126b4)=#34712596(0x0211ac14)
:02012474 E1831001 orr  r1,r3,r1
:02012478 E0211000 eor  r1,r1,r0
:0201247C E0010000 and  r0,r1,r0
:02012480 E1A01800 mov  r1,r0,lsl #0x10 ;r1=805240832(0x2fff0000)

$02106090-&021060ACの部分が空き領域として使えそうなので、ここに追加ルーチン埋め込もうとしているのですが

02012480 ????????  b $02106090   ;追加ルーチンへジャンプ

02106090 E3130C01  tsts r3, #$0100    ;Rボタンをチェックして
02106094 0A000003  beq $021060A8    ;押されていたら潰した命令を実行して復帰

Rボタンが押されていなければ時間稼ぎをする
02106098 E3A01A40  mov r1, #$00040000 ;r1 = #$00040000
0210609C E2411001  sub r1, r1, #$01    ;r1 = r1 - #$01
021060A0 E3510000  cmps r1, #$00     ;r1 = #$00 かチェック
021060A4 1AFFFFFC  bne $0210609C    ;r1 = #$00 ならループ脱出

021060A8 E1A01800  mov r1, r0, lsl #$10  ;潰した命令を実行
021060AC ????????  b $02012484      ;追加ルーチンから復帰

と、????????のとこの、追加ルーチンへジャンプと、復帰の値の算出方法がわからなくて詰まってます。
どなたかご存知でしたら教えて頂きたいです。
857 :名無しさん@お腹いっぱい。:2008/01/06(日) 10:12:02 ID:Q9egwDtY
>>854
b命令のコードはEAxxxxxx。
プラス方向へのジャンプの値は『(飛び先-コード実行位置)/4 - 2』で求められる。
(例):02012480 b $02106090
→EA000000 + (02106090-02012480)/4 - 2
→EA000000 + 3CF02
→EA03CF02

マイナス方向へのジャンプは『(飛び先アドレス-命令実行アドレス-8)/4』で求められる。
(例):021060AC b $02012484
→EA000000 + (02012484-021060AC-8)/4
→EA000000 + 3FFFFFFFFFFC30F4
→EA000000 + FC30F4 ※下6桁のみを切り出す
→EAFC30F4

でも常駐ルーチンはアドレス02000000に配置したほうが良いと思う。
最終更新:2010年01月18日 18:10
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。