前回に続き、今度は日本語表示をしていきます。ただ漢字の個数が不明でどれぐらいのデータ量が増加するか検討もつきません。そこでプログラマー的視点に立って、ある程度の概算を出してみます。1ドット1バイト、1文字16x16ドットの場合16 * 16 = 256バイトです。文字数を大雑把に6000字とすると、6000 * 256 = 1,536,000バイト = 1.5MBという予想になります。本職のプログラマーが見たら卒倒しそうな数字ですが、せめて1ドット1ビット単位にしたらどうかと言ってきそうです。ここでは無視します。(ぉ
16進数の数字と文字を対応した表(テーブル)には代表的なものとしてSJIS、EUC、UTF-8などがあります。ここではSJISのみ扱います。たとえば表示したい文字列をSJISで表示してみると、以下のようになります。
猫 - 0x944c ま - 0x82dc ん - 0x82f1 ま - 0x82dc
1文字2バイト表現となっていて、つまり「Mode3DrawSJISStr(0, 0, "猫まんま")」っぽい関数を作り内部で文字コードと文字データを突き合せれば完成するわけです。前のサンプルコードと同じ・・・と行きたいところですが、そうは問屋が下ろしません。SJISコード表をよーくみると微妙な空白地帯が存在しており、空白文字が大量にあるということはそのままデータ量に跳ね返ってきます。ではどうするかというと、空白部分を除去したフォントシートと呼ばれるテキストを用意して、フォントデータのインデックスを求めます。
u8* pDat = pフォントデータ; s32 i; for(i=0; i<フォントシート内の文字数; i++) { if(フォントシート[i] == 表示したい文字) { pDat += i * 横のドット分; break; } } // 描画処理
本職のプログラマーな方がみたら卒倒しそうなループ処理ですね。(爆
今回も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で保存していたら表示されないので注意してください。