2009年10月1日の日記を表示中

2009年10月1日 (木)

セイヴァー2を電池レス化してみる その1

10月になったのでそろそろ原稿モードに移らないとまずい感じなわけですが,その前にこれだけはってことでヴァンパイアセイヴァー2の電池レス化に挑戦してみました.例によって超長い上に,途中で終わってるので最終的な結論だけに興味がある人は後日のを読んでくださいw

CPS2のゲームの電池レス化の手順はCPS-2 Shock に書かれています.ただしアウトラインのみで,具体的な使用ツール類やノウハウについては言及されていません.軽く探した感じだとこれ以上の情報は得られなかったので,これと電池切れになったCPS2のROMボードもエミュレーションできるMAMEのソース,それから実際に電池切れになったボードで動いた実績のある suicidetester のバイナリをヒントに頑張るしかなさそうです.

一応 CPS-2 Shock で公開されている電池レス化の大雑把な手順は以下の通り.

  • 暗号化されたデータをデコードしたROMを用意する
  • プログラム中で 0x400000 からの14Byte にアクセスしている部分を書き換えて,0xFFFFF0 からの 14Byteへのアクセスに置き換える
  • メモリ初期化処理で0xFFFFF0 からの領域に何か書いたりしないようにプログラムを書き換える
  • 元々 0xFFFFF0 を使っている処理は他のところを使うように書き換える

まあ要するにROMをデコードして,さらに0x40000x へのアクセスを 0xFFFFFx へのアクセスに書き換えろという話です.本当にこれだけなのかという感じですが・・・.プログラムに修正を加えなければならない理由は特に見つけられなかったんですが,まあ電池が飛ぶとなんでもかんでもFで埋まるせいかな,と.

というわけで,とりあえずデコードから.MAMEのソースによると,暗号化されているのはプログラムROM (27C4096が8個くらい並んでいるアレ) だけで,さらに実際に暗号化されている範囲はゲームによって異なるようです.ヴァンパイアセイヴァー2の場合,0x000000 〜 0x100000 の範囲が暗号化の対象らしいので,デコードするのは3番と4番のROMの中身だけでよいことになります.

CPS2の暗号化処理のアルゴリズムと各ゲームごとのキーは明らかになっており,全部MAMEで実装されているので,まずはMAMEのcps2crpt.cを使ってデコーダを作成してみました.早速吸い出した3番のROMの中身を突っ込んでみたところ,最初の4Byteがスタックポインタらしき値で,次の4Byteがいかにも実行開始アドレスっぽい値のバイナリが出現.実行開始アドレス (らしき値) から先を逆アセンブルしてみたら 0x400000 などを初期化するコードが出てきたので,デコード自体はうまくいっていそうです.ナイス滑り出し.

逆アセンブルした結果を眺めてみたところ,0x40000xへの書き込み部分を4ヶ所ほど発見.さっそくバイナリエディタ (というかEmacs) で0xFFFFFxに書き換えてみました.ひょっとしてこれで動いちゃったりして? といきなり焼き込んでみたけどピクリともしませんでした (´・ω・`) .画面はいつだってグレー.まあ,そんなに簡単にいくわけないですね.にしてもサンハヤトのROM抜き (GX-7) は便利だなぁ.みんなも買った方がいいよw

というわけでここからはMAME上でデバッグします.SDLMAME の電池切れCPS2 (dead_cps2) のゲームとしてヴァンパイアセイヴァー2を追加して (以下vsav2d),デバッグオプションつきでビルドし直してパッチを当てたROMイメージを動かしてみたところ,ばっちり暴走することが確認できました(笑) (もちろんデコードとかしてない素のROMイメージの方 (vsav2) は普通に動く)

vsav2とvsav2dとで挙動を比較してみると,ROMから読み出した飛び先のアドレスがvsav2dとvsav2とで違うために暴走していることが判明.・・・vsav2dの方が正しい値 (デコードされた値) を読み出しているように見えますが・・・.あれ? vsav2の方で読めてる値はデコード前の値だじゃん? あれ? デコードしちゃいけないってこと?

そこで,吸い出したROMをちゃんとバイナリエディタで眺めてみたところ衝撃の事実が発覚しましたw.普通に「WORK」とか「OKAMOTO」とかの文字列がバリバリでてきます.もしかして,命令メモリとしてアクセスする際はデコードした結果を使い,データメモリとしてアクセスする際は生の値を使うとかそういう感じ? そういえば,前にどこかでCPS2は命令部分のみデコードが必要とか読んだような (出典見つけられず).命令メモリのことだと思ってたわ・・・.MAMEだとデコードした後にあらためて m68k_set_encrypted_opcode_rangeとか呼んでいるのはそういうことか.

もしそうだとすると,全体をデコードするのではなく,実行時に命令としてアクセスされる部分だけをデコードする必要がありそうです.これを静的にやろうと思うと,どこが命令でどこがデータとしてアクセスされるのかを見極めなければならないわけですが・・・,うーん.無理やり全体をデコードしても命令だけは出揃うはずなので,これを逆アセンブルした結果を元に解析できるかもしれませんが,GNUのアセンブラだと厳しそう・・・.MAMEでvsav2の方を動かしてトレースを取って調べるという手も考えられますが,これはカバレッジ面で現実的じゃないし・・・どうしたものか.

プログラムを静的に解析して,データとそれ以外とで分離して結果を出してくれる逆アセンブラとかがあればいいんだけど・・・とググってみたところ発見.dis.xというツール.・・・あるんだ.X68000やっぱすげぇ.

これ,X68000用らしいんですが,落として説明を読んだところFreeBSDでも動くっぽい.じゃあLinuxでも動くんじゃない? というわけで make してみたら,make時にいっぱい警告が出るものの普通に動くバイナリができちゃいました (main.cでcurses.hを常にincludeするように変更する必要あり).なんかいい流れじゃない?

さっそくこんな感じでエンディアンを入れ替えたバイナリをdis.xにかけてみたところ,見事にコードとデータが分かれたアセンブリが出てきました.そしてさっきデコードしてしまって問題になった部分は,きちんとデータとして認識されているっぽいです.すごい!素敵!どんなコードかはここに出せないので,まあ想像してくださいw

dis.xの出力を信じて,逆アセンブルの結果をからデータのアドレス範囲を抜き出し,その範囲に入っているデータのみデコードせずに元の値を使うようにしてROMイメージを作り直してやったところ・・・メモリチェックキタ━━━━(゜∀゜)━━━━ッ!!

なんとMAME上でメモリチェックが始まりました.やったね! ってメモリRAMがNGだし.あー,例の 0xFFFFFx アクセス問題か.該当箇所を見つけてそこを修正したら突破・・・したけどメモリチェックから先でやっぱり暴走するw.

というわけで今日はこの辺でおしまい.後日に続くー.

今日のプロギア

2回だけプレー.1回目は4面の下方向に弾をばらまきまくるヘリ2機が同時に出てくるところのちょっと先で終了.2回目は4ボスで終了.地味に進んでいるけど3ボスがまだよくわからん.2ボスもあんまり安定しないなぁ.まあ,あまりにもいつも通りですがw

4ボスで撃沈

いい加減画面デジカメで撮るのもアレだし,綺麗に静止画撮れる環境考えるべきか?でもゲームの度に裏でそれ動かすのもなんか面倒で結局使わなくなりそう・・・

[コメントを書く]

通りすがり 2010/03/11(木) 11:50:07
デジカメの画像の方が、味があって自分は好みです。
結構綺麗ですし、臨場感もあるので。

nosuke 2010/03/13(土) 05:35:15
おお,ありがとうございます.
確かにキャプチャだと実機で動いている感がなくなっちゃうんですよね.
ベストは
プレー中の動画を高画質でキャプチャ
→後で再生して一時停止してデジカメで撮影
かなぁ(笑)

2009年10月1日の日記を表示中

中の人情報

名前:
nosuke (のすけ)
メール:
sasugaanijaのgmail.com
「の」は「@」みたいな
関連リンク:

カレンダー

2009年10月
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

<<先月分

翌月分>>

最新の10件のエントリ

最近の10件のコメント

過去ログ