- 追加された行はこの色です。
- 削除された行はこの色です。
- doc.13 へ行く。
#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