ゲームボーイを作るその6。CPUを作るためにcpu_instrsを解析していたが、最初に動かすテストとして使うのは厳しそうということで、まずは自前のテストコードをそれを動かす環境を用意する。
簡単なテストコードを作る
CPUを作るためにcpu_instrsを解析していたが、テスト部分にたどり着くまでに、CPUがだいたい動く状態になってそうな気配を感じた。 そのためcpu_instrsを通すのは、CPUの基本的な動作がある程度動いた状態で、細かい(&把握できてない)部分の仕様を確認する段階で使うのが良いと判断した。 今回は自分で簡単なテストコードを作り、それを動かすためのテスト環境を実装してみることにする。
命令については、次のサイトとかが見やすくまとまっていて非常にありがたかった。
最初はレジスタのロード命令あたりから、ということでただ単にレジスタへのロード命令を並べたコードを用意した。ちなみにcpu_instrsとかのアセンブラ眺めながら、適当に雰囲気で書いてます。せっかくなので、ビルドに失敗したやつとかも含めて載せてます。
- 最初に書いたコード(ビルド失敗)
.org $100 ld a, hl
上記はリセット開始直後のアドレスにただ単にld
命令を書いただけのもの。これをwla-gb
に渡すと、次のような表示が出てビルドに失敗した。(なんかエラーメッセージっぽくないんだけど、オブジェクトファイルが生成されない)
$ wla-gb -o test.o ./01_ld.s INCLUDE_DIRECTIVES: ROMBANKS/ROMBANKMAP wasn't defined.
どうやらROMバンクとバンクのマップというものを定義しないとダメらしい。ということで、それらしき部分をbuild_rom.s
から持ってきて再トライ。
- ROMBANKS/ROMBANKMAP追加したつもり版(これも失敗)
.romBankSize $4000 .romBanks 2 .org $100 ld a, (hl)
$ wla-gb -o test.o ./01_ld.s MEM_INSERT: The current address ($0100) overflows from SLOT 0. ^ ./01_ld.s:7: Writing a byte
今度は先頭のアドレスが、SLOT 0の領域からはみ出ていると言われた。というか、ROMBANKMAP
追加版のつもりだったけど、MAP的な要素が確かに入っていなかった。
- ROMBANKS/ROMBANKMAP追加したつもり版2(成功)
.memoryMap defaultSlot 0 slot 0 $0000 size $4000 slot 1 $C000 size $4000 .endMe .romBankSize $4000 .romBanks 2 .org $100 ld a, (hl)
上記のコードを再度ビルドしてみた所、ちゃんとオブジェクトファイルが生成され、wlalink
コマンドによりバイナリが生成できた。
ここで使用しているlinkfile
はcpu_instrs/common
にあるものをそのまま流用している。
$ wla-gb -o test.o ./01_ld.s $ wlalink linkfile test.gb $ ls -l 合計 44 -rw-rw-r-- 1 diningyo diningyo 213 7月 17 23:44 01_ld.s -rw-rw-r-- 1 diningyo diningyo 17 7月 17 23:42 linkfile -rw-rw-r-- 1 diningyo diningyo 32768 7月 17 23:44 test.gb -rw-rw-r-- 1 diningyo diningyo 102 7月 17 23:44 test.o
出来上がったバイナリをエミュレータで実行してみると、チェックサムが一致しないとの警告が出ていた。テスト用のバイナリなので、あんまり気にしなくもよいが、一応確認しておく。
cpu_instrsのデータはちゃんとチェックサムが一致しているのになんで??と思って探してみた所wla-dx
のドキュメントがあるのに気づいた。
ちゃんとチェックサム計算のディレクティブ(.computeChecksum
/.computeComplementCheck
)が準備されてますね。build_rom.s
にもしっかり含まれていました。
なんか今のドキュメントによると古い名前のようで、今は.COMPUTEGBCHECKSUM
/.COMPUTEGBCOMPLEMENTCHECK
になっている模様。
ひとまず、この2つのディレクティブを追加したところ、チェックサムに関する警告はでなくなった。その代わりロゴに関するデータのチェックに失敗するというメッセージが出ているけど。
このメッセージは、build_rom.s
に含まれている、次のデータを$104
から配置すれば消すことができる。今回のCPUテスト用バイナリデータとしては、必要ではないので、この辺のデータは省く方向で。
.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
という事で、最終的に作った最初のテストコードは次のような感じ。ただ単に即値ロード命令でa
レジスタに0xa5
をロードして、それを他のレジスタに伝搬させていくだけ。
.memoryMap defaultSlot 0 slot 0 $0000 size $4000 slot 1 $C000 size $4000 .endMe .romBankSize $4000 ; generates $8000 byte ROM .romBanks 2 .org $100 ld a, $a5 ; a = $a5 ld b, a ld c, b ld d, c ld e, d ld l, e ld e, l
次はテストベンチ側の実装をしていく。