Help us understand the problem. What is going on with this article?

アセンブリ言語でのゲームボーイ開発(背景表示)

More than 1 year has passed since last update.

前回は、画面を使用しなかったのですが、これでは全く面白くないので、絵を出してみました。GBは背景画面の上にスプライトと呼ばれる動く画像を重ねて表示する(多分。まだちゃんと調べてない)。今回は、背景画面の方を試してみました。

ソースコードはこちら

GBの画面表示の仕組み

タイル

  • ゲームボーイの背景画像は、タイルと呼ばれる8X8ピクセルの画像を並べることで構成されている。
  • タイルの画像は、VRAMに書き込む。(ROMから必要に応じてコピーする)

背景画面の構成

  • サイズは、32タイル×32タイルである。VRAM上では、タイルの番号が1バイトごとに書き込まれている。
  • 背景画面は、実際の画面より大きい。SCRXレジスタとSCRYレジスタに、「背景画面のどこを、画面表示の起点(左上)にするか」を指定する。なお、このレジスタを変化させることで、スクロールが実現できる。

初期化の流れ

パレットとスクロールレジスタを設定する。

bg.asm
    ld  a, %11100100    ; パレット(パレットごとに2bitで白さを指定。MSBがパット番号0番)
    ld  [rBGP], a       ; BGPレジスタにパレットを設定

    ld  a,0             ; スクロールレジスタを設定し、画面を左上に固定
    ld  [rSCX], a       ; SCXレジスタ
    ld  [rSCY], a       ; SCYレジスタ

画面の描画中はVRAMへの書き込みが行えないので、一旦画面の表示をオフにする。

bg.asm
.waitVBlank:                ; 画面描画を止めるため、まず現在の描画が終るのを待つ
    ld  a, [rLY]
    cp  145                 ; 画面描画が終った=描画位置がY=145であるか?
    jr  nz, .waitVBlank     ; 違ったらまだ待つ(jrは相対ジャンプで、命令長が短くなる)

    ld  a, [rLCDC]
    res 7, a             
    ld  [rLCDC], a          ; VRAMに書き込むため、画面描画を止める

タイルをVRAMにロードする。

bg.asm
    ld  hl, Tile            ; vramcpy コピー元 (ハードコードしたタイルの画像のアドレス)
    ld  bc, _VRAM           ; vramcpy コピー先 ($8000)
    ld  de, TileEnd-Tile    ; vramcpy コピー長さ
    call  vramcpy           ; VRAMに値をコピーするするサブルーチン

VRAMにタイル番号を設定する。

bg.asm
    ld  b, $0               ; vramset 設定値
    ld  hl, _SCRN0          ; vramset コピー先
    ld  de, 32*32           ; vramset コピー長さ
    call  vramset           ; サブルーチン。画面全域にタイル番号0番を設定

画面の描画を再開する。GBには背景画面が2つあり、今回は「BG8000」を使用しているため、LCDCレジスタに「LCDCF_BG8000」をセットしている。また、タイルも2セットVRAMに持つことができ、今回は「BG9800」を使用している。スプライトを使用しないため、「LCDCF_OBJOFF」で表示をオフにしている。

bg.asm
    ld  a, LCDCF_ON|LCDCF_BG8000|LCDCF_BG9800|LCDCF_BGON|LCDCF_OBJ16|LCDCF_OBJOFF
    ld  [rLCDC], a          ; 画面ON

メインループ開始

bg.asm
mainloop:
    halt
    nop
    jr mainloop

スクリーンショット

bg_test.png

タイルのフォーマット

タイルのデータフォーマットは、なかなかにトリッキーである。今回使ったこのタイル(パレット番号0が白、1が明るい灰、2が暗い灰、3が黒)の場合、
tile.png

下のような形でピクセルごとにパレットの番号を指定する。

bg.asm
;タイル用画像
;2バイトで1ラインを表し、各バイトの各ビットが1ピクセルに対応する。
;偶数バイトが、パレット番号の下位ビットを表し、奇数バイトが上位ビットを表す
Tile:  
    ;1行目8ピクセルのパレット番号は, 0,3,3,3, 3,3,3,3
    db  %01111111   ;1行目, パレット番号下位ビット 
    db  %01111111   ;1行目, パレット番号上位ビット

    ;2行目8ピクセルのパレット番号は, 2,2,2,2, 2,2,2,2
    db  %00000000   ;2行目, パレット番号下位ビット
    db  %11111111   ;2行目, パレット番号上位ビット

    db  %11111111   ;3行目
    db  %00000000
    db  %00000000   ;4
    db  %00000000
    db  %11111111   ;5
    db  %00000000
    db  %00000000   ;6
    db  %11111111   
    db  %11111111   ;7
    db  %11111111   
    db  %00000000   ;8
    db  %00000000
TileEnd:

手で書くのはとても辛いので、下のようなツールがある。アセンブラのソースにそのままインクルードできるコードを出力してくれる優れものだ。
http://www.devrs.com/gb/hmgd/gbtd.html

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away