Skip to content

Instantly share code, notes, and snippets.

@akatsuki105
Created January 28, 2020 01:51
Show Gist options
  • Select an option

  • Save akatsuki105/5074fca62dd2d5eb513f1a3a06a01550 to your computer and use it in GitHub Desktop.

Select an option

Save akatsuki105/5074fca62dd2d5eb513f1a3a06a01550 to your computer and use it in GitHub Desktop.
GameBoyのHello worldROMを丁寧に解説したもの
; hello world DMG example by tmk @ https://github.com/gitendo/
INCLUDE "hardware.inc" ; system defines
SECTION "Start",ROM0[$100] ; start vector, followed by header data applied by rgbfix.exe
nop
jp start
SECTION "Example",ROM0[$150] ; code starts here
; 初期化(割り込みの無効化とスタックの初期位置設定)
start:
di ; 割り込みを禁止する
ld sp,$E000 ; スタックの初期位置
.wait_vbl ; startでdiにより割り込みを禁じているため、vblankのタイミングを自分でポーリングして入手する
ld a,[rLY] ; LYレジスタの値から現在描画中のy座標(px)を得る
cp $90 ; 0x90 = 144 つまりV-blankか判定
jr nz,.wait_vbl ; vblankが来るまでループする
; これより下はvblank時に行う処理
; 主要なレジスタを0クリア
xor a
ld [rIF],a
ld [rLCDC],a
ld [rSTAT],a
ld [rSCX],a
ld [rSCY],a
ld [rLYC],a
ld [rIE],a
; WRAM(0xc000-0xdfff)を0クリア
ld hl,_RAM ; _RAM == 0xc000
ld bc,$2000-2
call fill ; aレジスタのデータをhlにbc分転送する bcは0になる
; HRAM(0xff80-0xfffe)を0クリア
ld hl,_HRAM ; _HRAM == 0xff80
ld c,$80
call fill ; aレジスタのデータをhlにbc分転送する bcは0になる
; VRAMの0x8000-0x97ff部分を0クリア
; 0x8000-0x97ff => タイルデータを格納しておくところ
ld hl,_VRAM
ld b,$18 ; b=$18 ということは bc = $1800ということになる
call fill ; aレジスタのデータをhlにbc分転送する bcは0になる
; VRAMの0x9800-0x9fff部分をスペースで埋める
; 0x9800-0x9fff => 上のタイルデータ番号を指定すると、アドレスに対応する画面の場所にそのタイルデータが描画される
; この操作で画面がまっさらになる
ld a,$20 ; スペースのタイル番号を選択
ld b,8 ; b=$8 ということは bc = $800ということになる
call fill ; 上の0x8000-0x97ffのfillでhlが0x9800にセットされている
; パレットデータを各レジスタにロード
ld a,%10010011 ; bits: 7-6 = 1st color, 5-4 = 2nd, 3-2 = 3rd and 1-0 = 4th color
; color values: 00 - light, 01 - gray, 10 - dark gray, 11 - dark
; パレット番号を割り当てている 00=>白 01=>白グレー 10=>黒グレー 11=>黒
; 今回の例では
; 色番号1 => bit[6-7] = 10 つまり黒グレー
; 色番号2 => bit[4-5] = 01 つまり白グレー
; 色番号3 => bit[3-2] = 00 つまり白
; 色番号4 => bit[0-1] = 11 つまり黒
; という割り当てになる
ld [rBGP],a
ld [rOBP0],a
ld [rOBP1],a
; VRAMにフォントデータ(あらかじめ用意したデータ)を転送
; フォントデータ = フォントを表す画像のタイルデータ
ld hl,font ; フォントデータのベースアドレス
ld de,_VRAM+$200 ; ここ(0x8200)からフォントデータを配置していく 0x200を加えることでasciiコードとタイル番号が一致するようになる
ld bc,1776 ; フォントデータのサイズ 1776バイト
call copy ; hlからdeにbc分コピーする
; Hello worldを表示する
; 具体的には0x9800-0x9fffのRAMを書き換えて"Hello 8-bit world!"のフォントデータを指すようにする
ld hl,text ; "Hello 8-bit world!"のasciiコードを格納した配列のベースアドレス
ld de,_SCRN0+$100 ; 0x9800+0x100から"Hello 8-bit world!"を敷き詰めるとちょうど真ん中に表示される
ld c,text_end-text ; "Hello 8-bit world!"のデータ長さ
call copy ; hlからdeにbc分コピーする
; LCDCレジスタを設定していく
; 設定するデータ 画面表示を有効化、タイルデータに0x8000-0x8800を使う 背景マップに0x9800-0x9bffを使う その他もろもろの画面設定...
ld a,LCDCF_ON | LCDCF_BG8000 | LCDCF_BG9800 | LCDCF_OBJ8 | LCDCF_OBJOFF | LCDCF_WINOFF | LCDCF_BGON
ld [rLCDC],a ; 設定をLCDCレジスタに書き込んで設定を適用する
.the_end
halt ; これらの作業が終わったらCPUを稼働させる必要はないので次の割り込みが来るまでここでCPUを止めておく(diで割り込みが来ないようになっているのでここから先に進むことはない)
jr .the_end ; 無限ループ
;-------------------------------------------------------------------------------
copy:
;-------------------------------------------------------------------------------
; hlからdeにbc分コピーする
; hl - コピーするデータのベースアドレス
; de - コピー先のベースアドレス
; bc - コピーするデータのサイズ
inc b
inc c
jr .skip
.copy
ld a,[hl+]
ld [de],a
inc de
.skip
dec c
jr nz,.copy
dec b
jr nz,.copy
ret
;-------------------------------------------------------------------------------
fill:
;-------------------------------------------------------------------------------
; aレジスタのデータをhlにbc分転送する bcは0になる
; a - 転送するデータ
; hl - 対象のアドレス
; bc - 転送するデータサイズ
inc b
inc c
jr .skip
.fill
ld [hl+],a
.skip
dec c
jr nz,.fill
dec b
jr nz,.fill
ret
;-------------------------------------------------------------------------------
font:
INCBIN "font_8x8.chr" ; converted with https://github.com/gitendo/bmp2cgb
text:
DB " Hello 8-bit world! "
text_end:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment