2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

前回は、画面を使用しなかったのですが、これでは全く面白くないので、絵を出してみました。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

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?