Quantcast
Channel: プログラミング
Viewing all articles
Browse latest Browse all 8607

テリワンレトロ・セーブデータ解析 [1] - Notes

$
0
0

はじめに

レトロゲーム (ゲームボーイポケット) のROM解析をやってみる。ゲームボーイソフトの解析例としては、Pokered (https://github.com/pret/pokered) のようなものがある。ここでは、当時大ハマリしたドラクエテリワンレトロの解析をやってみる。このソフトは日本語版しか出てないはずで、公開されている解析例は見当たらない。なお、ROM全ての解析は途方もない時間がかかるため、暫定的にセーブデータを書き換えて、仲間モンスターの能力値を変えるところを目標とする。

必要とするソフトウェアとして、

チェックサム回避

ゲームボーイの場合、このソフトに限らないが、セーブデータは、0x2000バイトの.sav拡張子のファイルにセーブされる。これは、セーブデータが保管されるSRAMのサイズが0x2000バイトだから。

試しに、ゲームを始めて、セーブが可能な箇所でセーブをする。.savファイルが.gbcファイルの隣に生成されている。このファイルの任意の1バイトを書き換えてみると、ファイル読み込み後、ソフトの処理によって、以下のように、「つづきからあそぶ」が表示されない。

セーブデータの改竄を防止するために、何らかのチェックが実施されている模様。そのため、それを始めに特定する必要がある。 ところで、ゲームボーイのメモリマップは以下のようになっている。

アドレスサイズ説明
0000..3FFF16KB ROM Bank00 バンク0で固定
4000..7FFF 16KB ROM Bank01~NN MBCによってはバンクを1以外に切り替え可能
8000..9FFF 8KB VRAM GBCではバンク0/1で切り替え可能
A000..BFFF 8KB RAM Bank00~NN バンク切り替え可能な場合も存在, SRAM
C000..CFFF 4KB WRAM(Bank00) --
D000..DFFF 4KB WRAM(Bank01~NN) GBCではバンク切り替え可能(バンク数はカートリッジに依存)
E000..FDFF -- Echo RAM C000..DDFF のミラー 任天堂はこのアドレスを使うことを禁止しています
FE00..FE9F 160B OAM --
FEA0..FEFF -- 不使用 任天堂はこのアドレスを使うことを禁止しています
FF00..FF7F 128B IOレジスタ --
FF80..FFFE 127B HRAM(High RAM)| --
FFFF..FFFF 1B IME --

SRAMの位置は、0xA000 - 0xBFFF。ここの領域へのアドレス読み込み時のレジスタの値などを調べて、どのような処理がされているかを調べる。 mGBAにPrintデバッグを入れ、SRAM領域へのアクセス時のレジスタを読み込み、そこから、ROM内の対応関数位置をGhidraでデバッグして進める。なお、ROMの内、先頭0x4000バイトは常にメモリ上にロードされているが、それ以外は、0x4000 - 0x7FFFにバンク切り替えを利用してマッピングされる。

さて、SRAMに最初にアクセスしているコード部分を調べると、どうやら、 先頭2バイト (リトルエンディアンで格納) がチェックサムで、これと0x4638 + 残りの全部のバイトの足し算が一致すればよいらしい。 参考までに、Ghidraのデコンパイル結果が以下だが、あまり適切に表示されないため、アセンブリを同時に参照する必要がある。

試しに任意の1バイトを変更してみる。 オリジナルのセーブデータの先頭部分が以下のようになっていることを確認する。

バイナリエディタでセーブデータを開き、最初の1バイト (チェックサム) を0x8f -> 0x90に、オフセット0xb2の0x78->0x79に変更してみる。

実行したところ、セーブデータを変更したにも関わらず、「つづきからあそぶ」が表示されるようになった。

モンスター能力値の変更

次に、セーブデータのバイナリ列と保存されているべきゲームデータを比較してみる。

このセーブデータには、仲間モンスターとしてスライムがおり、その能力値は以下のようであった。

ここで、ステータス「攻撃力・守備力・すばやさ・かしこさ・やせい」が「8,5,5,0,5」となっている。このバイト列がセーブデータにあるか確認するとオフセット0x252から2バイトずつ、8,5,5,0,5という並びが見つかる。

試しに、先頭の8を9に変更し、ファイルの先頭にあるチェックサムのバイトを0x90->0x91に変更する。

起動して、能力値を確認すると、攻撃力が9になっていることが確認できた。

セーブデータのコピー

次回に向けて、セーブデータのコピーについて簡単に確認する。 チェックサムを確認する処理を実施したあと、2回めにSRAM領域にアクセスする処理を見てみる。この処理が実施される関数は以下のようであった。

0x25c4の関数部分は適切にデコンパイルされていないが、以下のようであった。

0x25c4の関数は、memcpyのような処理をしていて、第1引数が宛先、第2引数がコピーの長さ、第3引数がソースとなっている。つまり、0xa000 - 0xbffff にあるSRAM領域の一部を4回に分けて別の領域にコピーしているということになる。1個目のmemcpyの宛先はhram領域、2、3、4個目はそれぞれWRAM領域にコピーされる。

仲間モンスターの能力値のデータは、オフセット0x252にあったため、2個目のmemcpyでWRAM領域にコピーされることになる。ゲームボーイの場合、便宜上、WRAMの指定したアドレス上で、ゲームに頻繁に必要となるデータをトラッキングし続けるようになっている。そのため、セーブデータからではなく、WRAM領域を書き換えて、能力値を変更することも可能である。


Viewing all articles
Browse latest Browse all 8607

Trending Articles