ゲームボーイの boot ROM ダンプ
背景
初代 Game Boy の boot ROM はパッケージをバラして顕微鏡で読むことにより吸い出された。初代より後のさまざまな機種ではまだダンプが得られていなかったので、初代の情報を元に電気的に吸い出すことになった。
性質
外部バスとして VRAM と external WRAM/ROM(カートリッジの ROM)のバスが露出している
ほぼすべてのメモリマップに対するアクセスは external bus にも現れる
External WRAM/ROM に対してではないアクセスではデータ線がすべて FF に固定される
つまり、boot ROM の読み出しをそのまま見ることはできないが、どのアドレスにアクセスしているかは少なくともわかる
Boot ROM 領域 0x0000 - 0x0100 のアクセス禁止フラグとして、レジスタ 0xFF50 への書き込みがユーザーコードへのジャンプ直前に行われる
一度 0xFF50 に何かが書かれると以降 CPU からは読めなくなる
作戦
クロックとバスを全部 FPGA に繋ぎ、その命令の直前までゆっくり 2MHz で進めて、0xFF50 への書き込みが発生する手前で 24MHz という明らかに速すぎるクロックを入れる。すると、PC (program counter) は進むが書き込み命令が実行されない。これにより、boot ROM 領域の読み込みが無効化されていない状態でユーザーコードに到達する。
ユーザーコード領域には以下のアセンブリが置かれる。
code:dump.s
ld hl, 0
ld de, $4000
ld b, 0
copy_loop:
ld a, hl # アドレス 0x0000 ~ の命令を a に入れる ld de, a # a にある命令を 0x4000 に書く inc hl # 命令ポインタを incr
inc de # 書き出し先ポインタを incr
dec b # b を decr
jr nz, copy_loop # b がゼロでないなら copy_loop へ飛ぶ
# b は 8bit 幅なので decr でアンダーフロー後はちょうど256回回る
end_loop: jr end_loop
上記のコードは、0x0000 から 256 Bytes を 0x4000(外からでも読める適当な ROM 領域)へ書く。これを FPGA ですべて読み出す事により boot ROM がダンプできる。