ビットマップモード2

先ほどのサンプルコードを変更して移動処理を加えてみます。

int main(void)
{
	SetMode(MODE_3 | BG2_ENABLE);

	s32 x=0, y=0;

	for(;;)
	{
		if(y > 0 && x > 0)
		{
			Mode3PutPixel(x-1, y-1, RGB5(0, 0, 0));
		}

		Mode3PutPixel(x, y, RGB5(31, 31, 31));

		x++;
		y++;

		if(y > 160)
		{	
			x = 0;
			y = 0;
		}
	}
}

変数xとyの座標には白色ドット、1つ前に描画したドットには黒色(背景色)で上書きしています。x, y共にインクリメントしているので、どのように表示されていくかは想像できると思います。ただし、残念ながらこの書き方では想像どおりの結果になりません。失敗した状態をぜひ自分の目で確かめてください。ダウンロードはこちらです。

垂直同期待ちの処理を加える

失敗からわかることは、点が滑らかに表示されておらずブツ切りにされています。結論から言ってしまうと垂直同期待ちの処理をしていないからです。GBAは高速で画面を書き換えています。具体的には左上0,0座標から右へ順番にドット単位で行い、その行が終わったら次の行へ、という具合です。

1.png

もう少し詳しく言い直しましょう。液晶画面は240x160ドットです。最初のラインは240ドット描画後、描画しない68ドット分が存在します。この非描画期間をH-Blankといいます。この横ラインが完了したら次の横ラインへ、(0,1)ドット目からとなります。縦160ライン分終わった後にも縦68ライン分存在します。この非描画期間をV-Blankといいます。

描画処理を行う場合、基本的にはV-Blankの間に行います。先ほどのサンプルコードはV-Blankを無視して描画した為、チラついて見えたりしました。V-Blankを調べるには以下のレジスタを参照します。

4000006h - VCOUNT - Vertical Counter (Read only)
Indicates the currently drawn scanline, values in range from 160..227 indicate 'hidden' scanlines within VBlank area.

  Bit   Expl.
  0-7   Current Scanline (LY)      (0..227)                              (R)
  8     Not used (0) / NDS: MSB of Current Scanline (LY.Bit8) (0..262)   (R)
  9-15  Not Used (0) 
void WaitForVsync(void)
{
	while(*(vu16*)0x4000006 >= 160) {};
	while(*(vu16*)0x4000006 <  160) {};
}

WaitForVsync関数は、VCOUNT(描画中のライン)が160になるまで待つことを意味しています。先ほどのコードに加えた違いを確認してください。結果が良好になることがわかると思います。

流れ星っぽいドット表示

#include "lib/gba.h"

//---------------------------------------------------------------------------
void WaitForVsync(void)
{
	while(*(vu16*)0x4000006 >= 160) {};
	while(*(vu16*)0x4000006 <  160) {};
}
//---------------------------------------------------------------------------
void Mode3PutPixel(u32 x, u32 y, u16 color)
{
	u16* ScreenBuffer     = (u16*)0x6000000;
	ScreenBuffer[y*240+x] = color;
}
//---------------------------------------------------------------------------
int main(void)
{
	SetMode(MODE_3 | BG2_ENABLE);

	s32 x=0, y=0;

	for(;;)
	{
		WaitForVsync();

		if(y != 0 || x != 0)
		{
			Mode3PutPixel(x-1, y-1, RGB5(0, 0, 0));
		}

		Mode3PutPixel(x++, y++, RGB5(31, 31, 31));

		if(y > 160)
		{	
			x = 0;
			y = 0;
		}
	}
}

動作画面

2.png

履歴


添付ファイル: filetut03 bitmap2_test_nowait.gba 77件 [詳細] file2.png 22件 [詳細] file1.png 28件 [詳細]

トップ   差分 履歴 リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2023-05-30 (火) 10:35:12