ゲームボーイを作るその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.s
かbuild_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
にコピーして実行する形になっているようだ。
これ、ちゃんとビルド環境作って確かめてみたほうが良さそうだな。