#author("2023-05-25T13:49:11+09:00","","")
#author("2023-05-30T00:23:15+09:00","","")
* ビットマップモードの文字表示2 [#ddd6c703]
前回に続き、今度は日本語表示をしていきます。ただ漢字の個数が不明でどれぐらいのデータ量が増加するか検討もつきません。そこでプログラマー的視点に立って、ある程度の概算を出してみます。1ドット1バイト、1文字16x16ドットの場合16 * 16 = 256バイトです。文字数を大雑把に6000字とすると、6000 * 256 = 1,536,000バイト = 1.5MBという予想になります。本職のプログラマーが見たら卒倒しそうな数字ですが、せめて1ドット1ビット単位にしたらどうかと言ってきそうです。ここでは無視します。(ぉ

*** 日本語を表示しよう [#wac1d7f2]
16進数の数字と文字を対応した表(テーブル)には代表的なものとしてSJIS、EUC、UTF-8などがあります。ここではSJISのみ扱います。たとえば表示したい文字列をSJISで表示してみると、以下のようになります。
16進数の数字と文字を対応した表(テーブル)には、代表的なものとしてSJIS、EUC、UTF-8などがあります。ここではSJISのみ扱います。たとえば表示したい文字列をSJISで表示してみると、以下のようになります。

 猫 - 0x944c
 ま - 0x82dc
 ん - 0x82f1
 ま - 0x82dc

#ref(1.png,nolink)

1文字2バイト表現となっていて、つまり「Mode3DrawSJISStr(0, 0, "猫まんま")」っぽい関数を作り内部で文字コードと文字データを突き合せれば完成するわけです。前のサンプルコードと同じ・・・と行きたいところですが、そうは問屋が下ろしません。[[SJISコード表:https://www.tohoho-web.com/ex/draft/code.htm]]をよーくみると微妙な空白地帯が存在しており、空白文字が大量にあるということはそのままデータ量に跳ね返ってきます。ではどうするかというと、空白部分を除去したフォントシートと呼ばれるテキストを用意して、フォントデータのインデックスを求めます。

- Mode3DrawSJISStr関数のラフスケッチ

 u8* pDat = pフォントデータ;
 s32 i;
 
 for(i=0; i<フォントシート内の文字数; i++)
 {
 	if(フォントシート[i] == 表示したい文字)
 	{
 		pDat += i * 横のドット分;
 		break;
 	}
 }
 
 // 描画処理

本職のプログラマーな方がみたら卒倒しそうなループ処理ですね。(爆

*** Mode3で日本語表示 [#d7aa4409]

今回もmain関数から見てみましょう。

 int main(void)
 {
 	SetMode(MODE_3 | BG2_ENABLE);
 
 	ST_FONT f;
 
 	f.pDat   = (u8*)&mplus_j10rBitmap;
 	f.imgCx  = 69630 + 2;		// +2は、gritのサイズ調整分
 	f.cx     = 10;
 	f.cy     = 11;
 
 	f.pSheet = (u16*)&mplus_jfnt_txt;
 	f.cnt    = 6963;
 
 	Mode3DrawSJISStr(&f, 0, 0, "猫まんま", RGB5(31,31,31));
 
 	(中略)
 
 	for(;;)
 	{
 	    WaitForVsync();
 	}
 }

サンプルでは10x11ドットのmplusフォントを使用しました。6963文字入っています。

 void Mode3DrawSJISStr(ST_FONT* p, s32 sx, s32 sy, char* str, u16 col)
 {
 	u16 chr;
 	s32 i=0, x=0, y=0;
 
 	for(;;)
 	{
 		chr = str[i] | (str[i+1] << 8);
 		i += 2;
 
 		if(chr == '\0')
 		{
 			return;
 		}
 
 		// 改行処理
 		if(sx + x >= 240)
 		{
 			x  = 0;
 			y += p->cy;
 
 			if(sy + y + p->cy >= 160)
 			{
 				return;
 			}
 		}
 
 		Mode3DrawSJISChr(p, sx + x, sy + y, chr, col);
 		x += p->cx;
 	}
 }

2バイト文字を扱うため、chr変数に2バイト入れるようにしています。

 void Mode3DrawSJISChr(ST_FONT* p, s32 sx, s32 sy, u16 chr, u16 col)
 {
 	u8* pDat = p->pDat;
 	s32 i;
 
 	for(i=0; i<p->cnt; i++)
 	{
 		if(chr == p->pSheet[i])
 		{
 			pDat += i * p->cx;
 			break;
 		}
 	}
 
 	u16* pScreen = (u16*)VRAM + (sy * 240) + sx;
 	s32  x, y;
 
 	for(y=0; y<p->cy; y++)
 	{
 		for(x=0; x<p->cx; x++)
 		{
 			if(pDat[y*p->imgCx + x] == 0x00)
 			{
 				continue;
 			}
 
 			pScreen[y*240 + x] = col;
 		}
 	}
 }

フォントシートのインデックスを求めるだけで前回のコードとそれほど変わりありません。なお、main関数の「猫まんま」はソースコードの''テキスト保存形式''に依存しています。EUCで保存していたら表示されないので注意してください。

*** 動作画面 [#p581ee87]
#ref(2.png,nolink)


** 履歴 [#f4f1f935]
- 2022/04/16
- 2014/11/16

トップ   差分 履歴 リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS