ハードウェアの気になるあれこれ

技術的に興味のあることを調べて書いてくブログ。主にハードウェアがネタ。

ゲームボーイを作る(3) - テストROMの解析2

スポンサーリンク

ゲームボーイを作るその3。今日は実装に使用するテストROMを解析してメモった内容の続き。今の段階では解析して、こう見える、、、程度の状態で書いているので、何か誤認識があるかもです。(後で気づいたことは、適宜修正入れていきます。)

テストROMの解析2

今回はblargg-gb-testsに同梱されているテストバイナリが、shell.incのどのdefineでビルドされたものかを確認して、このインクルードファイルを含んだ全体像を確認していく。(defineの指定自体はどっかに書いてはありそうだけど。。)

shell.incのdefineの調査

前回も記載したshell.incを再度ペタリ。ここでインクルードされている4つのファイルのうち、真ん中の2つについてはそもそもダウンロードしたzipファイルに含まれていないので除外でいいはず。

  • shell.inc
.incdir "common"

; GBS music file
.ifdef BUILD_GBS
     .include "build_gbs.s"
.endif

; Devcart
.ifdef BUILD_DEVCART
     .include "build_devcart.s"
.endif

; Sub-test in a multi-test ROM
.ifdef BUILD_MULTI
     .include "build_multi.s"
.endif

; GB ROM (default)
.ifndef RUNTIME_INCLUDED
     .include "build_rom.s"
.endif

とすると、build_gbs.sbuild_rom.sのいずれか、、、なんだけど、まあデフォルト設定のbuild_rom.sだろうなとは思っている。gbsの方はmusic fileとか書いてあるし。

build_gbs.sかbuild_rom.sの比較

この2つのファイルを見比べると、build_rom.sの方には.byteで指定されるセクションに固有の情報が埋め込まれてそうな気配がある。

  • build_rom.s
; Build as GB ROM

.memoryMap
     defaultSlot 0
     slot 0 $0000 size $4000
     slot 1 $C000 size $4000
.endMe

.romBankSize   $4000 ; generates $8000 byte ROM
.romBanks      2

.cartridgeType 1 ; MBC1
.computeChecksum
.computeComplementCheck


;;;; GB ROM header

; GB header read by bootrom
.org $100
     nop
     jp   reset

; ここ。任天堂のロゴ情報??
; Nintendo logo required for proper boot
.byte $CE,$ED,$66,$66,$CC,$0D,$00,$0B
.byte $03,$73,$00,$83,$00,$0C,$00,$0D
.byte $00,$08,$11,$1F,$88,$89,$00,$0E
.byte $DC,$CC,$6E,$E6,$DD,$DD,$D9,$99
.byte $BB,$BB,$67,$63,$6E,$0E,$EC,$CC
.byte $DD,$DC,$99,$9F,$BB,$B9,$33,$3E

このHEXデータはbuild_gbs.sには存在しないので、ビルド済みのバイナリにこのデータが含まれていれば、build_rom.sの方がビルドされたと判断できる。01-special.gbをHEXLモードで開いて確認すると、0x102から、これらのデータが書き込まれている事を確認できた。

                    |->ここから。
00000100: 00c3 1302 ceed 6666 cc0d 000b 0373 0083  ......ff.....s..
00000110: 000c 000d 0008 111f 8889 000e dccc 6ee6  ..............n.
00000120: dddd d999 bbbb 6763 6e0e eccc dddc 999f  ......gcn.......
00000130: bbb9 333e 0000 0000 0000 0000 0000 0000  ..3>............

Pan Docsによると、アドレス$0100から$014Fまでは「カートリッジ・ヘッダー」で$0100はエントリーポイントになるらしい。確かにテストROMをエミュで動かすと、スタートのアドレスが$0100からになっていた。

reset

カートリッジ・ヘッダーの2番めの命令(jp reset)でresetラベルにジャンプするが、この宛先のアドレスが含まれているのがruntime.sになる。

  • runtime.s
; Copies $1000 bytes from HL to $C000, then jumps to it.
; A is preserved for jumped-to code.
copy_to_wram_then_run:
     ld   b,a

     ld   de,$C000
     ld   c,$10
-    ldi  a,(hl)
     ld   (de),a
     inc  e
     jr   nz,-
     inc  d
     dec  c
     jr   nz,-

     ld   a,b
     jp   $C000

.ifndef CUSTOM_RESET
     reset:
          ; Run code from $C000, as is done on devcart. This
          ; ensures minimal difference in how it behaves.
          ld   hl,$4000
          jp   copy_to_wram_then_run

     .bank 1 slot 1
     .org $0 ; otherwise wla pads with lots of zeroes
          jp   std_reset
.endif

resetでのメインの処理はcopy_to_wram_then_runで、ここでは$4000から$1000 byte分のデータを$C000にコピーした後、$C000へジャンプする。

上記の.bank 1 slot 1からは、build_rom.sで宣言したバンクサイズに従い、余った部分にパディングが挿入されている様に見える。 このためjp std_resetはアドレスとしては$4000に配置される。 またstd_resetというラベルの持つ、ジャンプ先アドレスはデバッガーでみるとjp C220とデコードされており、slot 1の宣言から計算されているみたい。

  • build_rom.s
.memoryMap
     defaultSlot 0
     slot 0 $0000 size $4000
     slot 1 $C000 size $4000 ; slot 1は$C000から$4000 bytes
.endMe

.romBankSize   $4000 ; generates $8000 byte ROM
.romBanks      2 ; ROMはサイズが$4000で2面分。

このjp命令以降、つまりアドレス$4000以降に、テストに必要な共通処理と各テストが配置されており、これをリセットからの一連の処理で$C000にコピーして実行する形になっているようだ。

これ、ちゃんとビルド環境作って確かめてみたほうが良さそうだな。