自分用に改造したDeSmuME

改造箇所:

  • PUSH_LR命令が実行されたときに呼ばれるemu.registerenterfunc
  • 命令アドレスごとの条件付実行ログ機能 (emu.start_log_cond / emu.end_log_cond)
  • ROMファイル全てをメモリに読み込まない変更 (NO_LOAD_ALL_ROM)
  • memory.getregister / memory.setregister の prev_insn_addr / curr_insn_addr / next_insn_addr
  • Luaを実行したときに自動的にカレントディレクトリがスクリプトディレクトリになるように
  • 命令アドレスごとの戻り値のログ機能 (emu.start_log_return / emu.end_log_return)
  • Luaから逆アセンブルをファイル出力できる機能 (emu.output_disasm_arm / emu.output_disasm_thumb)
  • メモリ上にあるバイト列が出来たときにコールバックを呼ぶ機能 (memory.register_bytes_pattern)

いろんな場所でフックを追加しているので当然普通のDeSmuMEより重いです
役に立つようならぜひ使ってみてください

P.S.
僕はまだポケモンBW買ってないです...

いろいろ追記で書いていく

emu.registerenterfunc

これはなんのために作ったかっていうとスタックトレースをとりたかったから

emu.start_log_cond / emu.end_log_cond


実行アドレスごとに条件がtrueかfalseか記録する。これを二つのStateで比べたりしたらある判別をしている処理とか分かるかもしれないと思って作った

NO_LOAD_ALL_ROM

ROMファイルがでっかいと全体をメモリに読み込んでたらきついので
実装するのが面倒なのでこれ有効にすると一部の機能が無効になる

ところでファイル全体に読み込んでいたのをファイルをシークして読み込むようにする変更って、mmapとか使ったら今までのメモリアクセスのままでファイル全体はメモリに乗らないように出来たりするのかなー。

prev_insn_addr, curr_insn_addr, next_insn_addr

  • prev_insn_addrはここの命令ってどっからジャンプしてきてんのってときに使う
  • next_insn_addrはたとえばなにかよくわからない関数呼び出しがあって引数をいろいろたくさん変化させてみて戻り値を確かめたいってときに、関数呼び出しの次の行でmemory.setregister("next_insn_addr", ...)して関数呼び出し前に戻ったりとかして使う

emu.start_log_return, emu.end_log_return

start_log_condの戻り値版。割とこの機能はポテンシャルがあるんじゃないかと予想している

emu.output_disasm_arm / emu.output_disasm_thumb

最近はndsdisじゃなくてこっちを使っている。ndsdisは結果がいくつか間違っている箇所があったりコメントが過剰で見づらいなーと思ったので。

アドレスが小さくなる方へのジャンプとどこかの命令のジャンプ先に設定されているアドレスは先頭の記号をかえているのでそれをエディタのシンタックスハイライトで設定するとプログラムの構造がいくぶんかは見やすくなる

memory.register_bytes_pattern

あるASCIIの文字列があるんだけどメモリサーチしても見つからない、きっとメモリサーチするころにはほかの値で上書きされちゃってるんだろなーってときに使った。

こんなかんじ

memory.register_bytes_pattern(string_to_byte_array("FooBar"), function(addr)
  printf("addr=%.8x, pc=%.8x", addr, PC())
end)

追記 (2010-09-20T18:26:51+09:00)

Luaを実行したときに自動的にカレントディレクトリがスクリプトディレクトリになるように」はgochaさんによって本家にマージしてくれました。(僕がハック的な修正方法をとっていたのとかWindows以外に対応していないのをなおしてくれた上で)
gochaさんありがとう!

筆者: oupo (連絡先: oupo.nejiki@gmail.com)