逆汗でGBAプログラム改造

GBA全般に通用すると言えば通用しますが、取り上げているのはファイアーエムブレム封印の剣です。ご了承下さい。

準備編

・no$gba for debugger

・Stirling

・goldroad ARM assembler

・DISARM
(customized to GBA版は逆に使いにくいです。本家を使いましょう)

逆アセンブル

まず使用するのは「DISARM」です。このソフトは、GBAROMを逆アセンブルしてくれます。逆アセンブル自体はVBAやno$gbaでも可能ですが、これを使うと一括でテキストデータにダンプしてくれます。

ただし、そのままだと武器データや画像データなど、プログラム以外も逆アセンブルしてしまいます。それは無駄なので、まずはROMの後半(プログラム以外)を削除します。

まずはStirlingでお手元のROMを読み込みます。そして、封印なら「0xA0000~」烈火と聖魔は「0xE0000~」を削除しましょう。Stirlingには「データ末尾まで選択」という機能があるので、それを使えば一気に選択、削除が可能です。
sr5yfdrt

「DISARM」はコマンドプロンプトから使います。[-t]オプションをつけて、FE6.srcとでも出力しましょう。では実行してください。
使い方が分からない? そういう人がプログラム改造に手を出すのは止めましょう。

出力したらそのファイルをテキストエディタで開いてみましょう。
これがFEの全容なのです。この大量の文字列の中にお目当てのプログラムが潜んでいるのは確実なのですが、もちろん目で見て発見なんてできるわけがありません。

ではどうするのかというと、「解析」をするのです。これは何が何のプログラムなのかを突き止める作業のことです。
次からは解析を行っていきます。

ちなみにいわゆる逆汗というものは、「逆アセンブル」「解析」「ASMコーディング」をひっくるめた総称という紛らわしい名称であることに注意しましょう。なお海外では「ASM Hack」と呼ばれており、そういう改造を「ASM Trick」と呼んでいるようです。

no$gbaの使い方

それではGBAの解析を行います。その為に使うツールがno$gbaです。GBAのエミュレータの中でも有名中の有名ソフトのデバッグ機能版です。解析をする前に、まずはこのツールの紹介から始めましょう。

解析をするなら、右クリックの「送る」メニューに追加しておくことを勧めます。
まずは最初の設定を済ましておきましょう。ちなみにGBAのBIOSファイルを持っている人は「ROM.BIN」と名前を付けて、no$gba本体と同じ階層に置きましょう。

dtybjfghvgg
まずは起動して、オプションを変更しましょう。

[Option] > [Files Setup] > [SAV/SNA File Format] = [Raw]

と変更して下さい。
あとはお好みでコントローラーのセッティングや・音量・明るさを変えるといいでしょう。
なお、no$gbaはセーブファイルをno$gbaのフォルダ内SAVフォルダに生成します。VBAと違いますので注意しましょう。

さて解析作業は例えばコードサーチなんかでもよく行いますね。GBAにはシンボルとか無いので、もっぱらブレイクポイントを使っての解析となります。no$gbaは非常にHelpが充実しているので、そこを確認するのが一番だと思いますが、一番利用するものをご紹介します。それが[Break on Read]と[Break on Write]です。[Break on Thumb/ARM]と3つでほぼ事足ります。

まずはブレイクポイントの解説をします。ブレイクポイントのブレイクとは「中断」という意味で使っています。つまりプログラムを中断するポイントですね。先ほど挙げた3つはそれぞれの異なったブレイクポイントを仕掛ける命令です。
[Break on Read]は指定のメモリを読み込んだときに中断。[Break on Write]は指定のメモリが変化した時に中断。[Break on Thumb/ARM]は指定のプログラムを通過した時に中断するポイントを仕掛けます。

no$gbaの左下のWindowをクリックしてTabキーを押下して下さい。すると、Break Point Windowに切り替わります。

dt7ifg

現在は何も入力されていませんね。では使い方はおいおい説明するとして、まずは入力法の説明をします。

まずは[Break on Thumb/ARM]です。ARMにブレイクポイントを仕掛けることはまずないと思うので、実質は[Break on Thumb]です。
仕掛け方は様々です。一番直接シンプルなのが、左上のWindowにある目的の命令をクリックすれば、それだけで仕掛けられます。

・BRKとありますね
seygdv
Break Point Windowにもしっかり反映されています。また、ブレイクポイントとは少し違いますが、右クリックで[Run to Cursor]があります。これは「選択したところまでプログラムを実行する」というものなので、これでも似たような事ができます。ブレイクポイントと違う所は、中断させるのは一回限りという点ですね。ブレイクポイントを仕掛けた場合は、同じ処理を行う度に毎回中断します。

また、もうひとつの仕掛け方もあります。Break Point Window内で右クリックをして、[Define Breakpoint]を選びましょう。
5s7idgfuhyg
ここで、仕掛けたいアドレスを入力する事でも可能です。
例えばこんな感じですね。
tdyfbhb
ekberjg

次は[Break on Read]と[Break on Write]です。これを仕掛けるために、また下のWindowを出して下さい。
5s7idgfuhyg
そして、[Break on Read]なら例えば以下のように入力します。
etybjf
[Break on Write]なら、以下のように入力します。
et5jybfh
小さすぎて見えにくいですが、アドレスを[括弧]でとじ、末尾に「!」か「?」をつける事で仕掛けています。なお「!!」だと変化が無くても書き込まれたらブレイクします。そういう細かい話はともかく、ブレイクポイントの仕掛け方は理解できましたね。
他にも、今は理解できなくてもいい機能に、以下のようなものがあります。

「F9」で「Run」
「F8」で「サブルーチン終了までRun」
「Alt+X」で終了

ゲーム画面下にある

「Trace」で「次の処理」
「Run Next」で「サブルーチンを無視して次の処理」
「Reload」で「再読込」

このあたりを私はよく使います。今は分からなくとも、解析を進めるととても便利な機能ばかりです。慣れてきたときに思い出してください。私もすべてを使いこなしているわけでは無いので、他の機能は「Help」で確認して下さい。(英語です)

解析の仕方

さて解析作業はハッキリ言って難易度がピンキリです。簡単にみつかる物もあれば、難しいものは経験が物を言う世界です。ここではやるのは基本なので、簡単な作業です。
それではとno$gbaを使って解析を行います。ここからはゲームを実行させての作業となるので、ROMを読み込ませて下さい。

さて、解析の基本は[Break on Read]です。と私が思ってるだけで基本というのは嘘ですが、簡単なのは確かです。例をあげると、成長に関する処理を見つけたい場合はユニットの成長率を読み込んだときにブレイクさせれば良いです。命中率の計算処理を見つけたければ、武器の命中率にブレイクポイントを仕掛ければ良いです。
それでは、攻速に関する処理を見つけるためにはどうすれば良いと思いますか?

答えのひとつが武器の「重さ」です。攻速に使う要素のひとつですからね。ここにブレイクポイントを仕掛けるのが一番楽だと思うので、仕掛けましょう。

武器の重さのアドレスがぱっと分かれば良いのですが、意外に手間がかかったりします。まずはProjects_FE_GBAで武器のデータを見て、それを元にバイナリエディタで確認しましょう。
書込先頭アドレスをもとにしてそのアドレスを確認。Projects_FE_GBAと照らし合わせてどれが重さなのかを探して下さい。

seyvgdfyh
drtbujfgyh
順番的に、ここの「05」が重さでしょうね。

つまり、0x60B67Fがてつの剣の重さのアドレスとなります。ではここにブレイクポイントを仕掛けましょう。覚えていますか?
srhbvc
この状態でてつの剣を装備しているユニットの能力を確認すればブレイクします。

u8niouikh
なにこれ?
ざっくりと解説すると、「ldrb r0, [r1, 17h]」という処理でてつの剣の重さを読み込んだから止まったという事です。

ここはいいので、まずは右の方の「Trace」をクリックして処理を進めて下さい。
t7inuykg
さて、「080248F4」というアドレスにやってきました。
ここが攻速の計算プログラムだと考えられます。このままno$gbaで解析を進めることも可能ですが、少し前に逆アセンブルしたファイルを開いた方が楽なので、そちらを開いて下さい。

「000248F4」とか「080248F4」で検索すればno$gbaと同じ所を開くことができるはずです。

さて、ではこれで攻速の計算プログラムが見つかりましたね。あとはこのプログラムを読んで、予想したり想像し、当たってたら解析は完了です。

これで解析は終わりなんですが、それはそれとして、「読めますか?」
問題無くニーモニックが読める人は別にいいんですが、読めない人もいますよね。なのでここはニーモニックの解説を少し行います。

プログラムを読み解く

さてでは読んでいきましょう。先ほどの続き、つまり000248f4から見ていきます。自分のソースファイルと比較して見てくださいね。

mov r1, r0 (add r1, r0, #0)

()の中身はどちらにせよ同じ処理ということです。
これの意味は「r1 <- r0」です。移動元が消えないのでムーブというよりコピーです。

r0には「てつの剣」の重さが入ってますので、
つまりはr1にも鉄の剣の重さを入れるという事です。

mov r0, #24

さっきと同じですね。R0に24をmoveします。

ldsb r0, [r4, r0]

“Load Sign-Extended Byte” ldrb…?いえいえldsbです。(とはいえldrbと基本的に同じと思えば差し支えないです。読み込む数字がマイナスの可能性があるときはldsbを使います。例を挙げると0xFFを255と判断するか、-1と判断するかで使い分けます)
これはロード命令です。意味は、「r4からr0番目にあるデータをr0にロードする」となっています。

今の状況では24番目の何かを読み込んでいるな、としか分かりません。
さて、これはなんでしょうね?

sub r1, r1, r0

引き算”subtract”です。英語の勉強になりますね。
意味は「r1 <- (r1-r0)」です。計算結果は一番左のレジスタに入ります。

変化するレジスタは一番左のだけというのは他の命令でも共通のルールなので
それだけ気をつければ混乱はしません。

さて、R1ってなんでしたっけ?

cmp r1, #0

“compare”比較する、です。比較をするだけです。
他のものとセットになって効果を発揮します(重要)。

レジスタの変更が無い引き算命令と言われています。
意味としては「(R1-0)の結果がプラスか?等しいか?マイナスか?」となります。

bge $00024902

“Branch on Greater than or Equal to”
意味は、大きい、もしくは等しい場合にBranch(分岐)するです。

さっきのcmpはこの命令の為にあったという事ですね。

となると、「r1がゼロ以上だったら$00024902へ分岐・ゼロ未満なら分岐しない」という意味です。

mov r1, #0

さっき出ましたね。r1をゼロにします。
上の処理とさらに組み合わせると、「r1がマイナスの場合はゼロにする」という事ですね。


さてニーモニックは理解できましたね。じゃあこれで分かったはずです。さっきの

「ldsb r0, [r4, r0]」

で読み込んだデータとはなんでしょうか?

答えは「体格」です。GBAの攻速式を知っていればなんとなく分かるでしょう。

その他のニーモニックの意味はsinzan氏が作ったリファレンスの日本語訳を参考にしましょう。
https://ngmansion.github.io/hokanko/ARM7TDMI/
もっと詳しいものならいくらでもありますが、ハックロム程度の小さなプログラムに使う命令なんてこれで十分です。

これでプログラムが理解できましたね。それでは本当に理解したかテストです。

このプログラムのどれかひとつの命令を削除することで、速さ=攻速という式に変えることが可能です。それはどこでしょうか?
そもそもどれが攻速を書き込んでいる命令か? 速さはどこで読み込んでいるのか? まずそれが分かるかという話ですね。

さて…正解はこちらです。

00024906 1a40 sub r0, r0, r1

この命令を消します。そうすれば速さがストレートに攻速として書き込まれるのがわかるでしょうか? 処理を潰すときはバイナリエディタで00024906を”C0 46″と書き換えます(”00 00″でも一応可能です。正確ではありません)。

どれが攻速を書き込んでいる命令か? 速さはどこで読み込んでいるのか? それが分かれば今は良しとしてもいいと思います。
これでGBAの解析は大丈夫ですね。

ASMコーディング

さて、先ほどプログラムの書き換え方を教えましたね。あれがもっともシンプルなASMコーディングだと言えるでしょう。“C0 46”と書き換えましたが、あれは「nop」という命令に書き換えたのです(何もしないという意味です)。分かっていればそれでもいいんですけどね。でも、addは? movは? ldrbは? と、ある程度ならともかく、普通は覚えてられません。

それを解決するのが[goldroad gba assembler]です。
goldroadはnopと打てばC0 46に変換してくれますし、addも”00 30″movも”00 20″と、変換してくれます。つまりは最初にやったDisarmと逆の事をします。

実際に使ってみましょう。新しいテキストファイルを開いて適当に記述してみます。

@thumb
mov r0, #77
mov r1, #66
add r0, r0, r1 ;コメントもはさめます
sub r0, #10
cmp r0, #150

意味の欠片もない処理ですが、とりあえずコピペして保存。ファイル名を「aaa.asm」のように2バイト文字を避けるように変えて下さい。
それを「goldroad.exe」にドラッグアンドドロップ。基本の使い方はこれだけです。成功すれば「aaa.gba」というファイルが出てきます。

失敗するようなら、ファイルパスが日本語なのかもしれません。分からないならDフォルダ直下にでも「goldroad」を置きましょう。「送る」メニューに追加しておけば楽です。

さて上手く変換できていたらこんなファイルの筈です。
srubhfjgvb

まあ意味なんてないので、何の役にも立たないんですけれどね。

では折角なのでちょっとは意味がある処理を作りましょう。
今回は攻速の計算を、体格ではなく、技/2で減算する処理にします。つまり、技をロードし、それを2分の1にする命令を作って下さい。

@thumb
??   ;技を読み込む
??   ;値を1/2にする

こんな感じになるはずですね。1/2にする命令は探せば良いとして、技を読み込むにはどうすれば良いでしょうか?速さを読み込む命令をヒントにして考えてみて下さい。
ぼやいてしまうと「体格は#24・速さは#20」という風に読み込んでいましたねぇ…

@thumb
ldrb r0, [r4, #19]
asr r0, r0, #1

これでできました!

mov r0, #19
ldsb r0, [r4, r0]
asr r0, r0, #1

これでもいいんですが、これでなくてもいいので短い方を利用します。使い分けの判断は慎重に

では体格を読み込む処理をこいつで書き換えてしまいましょう。

000248f6 2018 mov r0, #24
000248f8 5620 ldsb r0, [r4, r0]

これが体格を読み込む処理ですね。これを書き換えましょうか。
さっきの処理をgoldroadで変換しましたか?それでは書き換えましょう。

zdybg6dftbyc

ufkyngyu

あとはゲーム内で確認してみましょう! 戦闘情報を詳細にすれば確認が楽です。
うまくいっていたら終わりですが、変になっていたらバグ取り作業です。この単純さでバグがあるとは思えませんが、長い処理になればなるほどバグ確認、バグ取りが大変です。

今後もプログラム改造をしたいという人は、goldroadのマニュアルは確実に読みましょう。もしくはわたしの作ったASMコードを参考にすると良いと思います(なるべく新しい奴を)。
例えばわたしはスキル追加をやったりしてますが、使っている命令なんて一部だけだし、全部の命令なんて覚えてません。
あとはFE知識を総動員しながらソースコードを眺めて慣れるだけです。それでは頑張って下さい。

「逆汗でGBAプログラム改造」への5件のフィードバック

  1. どうやって、スキルを作られてるのか工程と解説がぜひ
    みてみたいです。
    気分が向いて、時間があって、やってもいいなって思われたらぜひ
    お願いしたいです!

    1. スキルですか。いぜん考えた事はあるのですが、何を取り上げればちょうどいい難しさなのか悩んだきりでしたねぇ
      やってみたいとは思っているのでぼちぼち考えてみます

  2. 前回の逆アセ解説が見たいのですがみれなくなっていました。
    見れるようにしてもらえないですかね

    1. あれですか。まあ今さら見る価値が有るかは分かりませんがね…

      それはさておき、アドレスが分からないということでしょうか、分かっていても見れないということでしょうか。
      わたしが試した所、何故かchromeだと見れずにFirefoxだと見れました。なんでかは分からないんですが…
      なお旧サイトのアドレスはこちらです。
      https://dl.dropboxusercontent.com/u/65840711/HomePage/index.html

コメントを残す

メールアドレスが公開されることはありません。