#概要
8x8のドットマトリクスLEDに日本語を表示させる為、マイコンで扱える形にする必要があったので、FONTX2の仕様を調べてハマったのでメモとして残す。
#使ったフォント
8x8ドットの日本語フォント、美咲フォントを使わせていただきました。
8×8 ドット日本語フォント「美咲フォント」
#参考にしたサイト
FONTXの使いかた
Arduino Unoで漢字を扱う(2) FONTX形式のフォントを扱う
#解析する簡単なスクリプト
美咲フォントのウェブサイトよりFONTX2形式のzipファイルをダウンロードします。
zipファイルの中のMISAKIMN.FNTを下記の簡単なPerlスクリプトで中身を見てみました。
#!/usr/bin/perl
use strict;
my $filename = "MISAKIMN.FNT";
binmode FH;
open FH,'<',$filename;
my $ct=0;
while(read(FH, my $val, 1)){
my $int = unpack("C",$val);
my $str = sprintf("%08b",$int);
$str =~s/0/ /g;
$str =~s/1/@@/g;
printf("%05d - %02x - %03d - %08b %s\n",$ct,$int,$int,$int,$str);
$ct++;
}
取得したいフォントの形状を取得するには、文字コードからFONTX2ファイルの中のどこに該当の文字が存在するのかを調べる必要があります。
#出力結果(ヘッダ部)
00000 - 46 - 070 - 01000110 @@ @@@@
00001 - 4f - 079 - 01001111 @@ @@@@@@@@
00002 - 4e - 078 - 01001110 @@ @@@@@@
00003 - 54 - 084 - 01010100 @@ @@ @@
00004 - 58 - 088 - 01011000 @@ @@@@
00005 - 32 - 050 - 00110010 @@@@ @@
00006 - 4d - 077 - 01001101 @@ @@@@ @@
00007 - 49 - 073 - 01001001 @@ @@ @@
00008 - 53 - 083 - 01010011 @@ @@ @@@@
00009 - 41 - 065 - 01000001 @@ @@
00010 - 4b - 075 - 01001011 @@ @@ @@@@
00011 - 49 - 073 - 01001001 @@ @@ @@
00012 - 20 - 032 - 00100000 @@
00013 - 20 - 032 - 00100000 @@
00014 - 08 - 008 - 00001000 @@
00015 - 08 - 008 - 00001000 @@
00016 - 01 - 001 - 00000001 @@
00017 - 5c - 092 - 01011100 @@ @@@@@@
ヘッダの仕様はこちらに詳しく記載があります。
http://elm-chan.org/docs/dosv/fontx.html
重要なのは
14バイト目 フォント形状の幅ドット数
15バイト目 フォント形状の高ドット数
17バイト目 ブロックテーブル数
です。
#出力結果(ブロックテーブル部)
00018 - 40 - 064 - 01000000 @@
00019 - 81 - 129 - 10000001 @@ @@
00020 - 7e - 126 - 01111110 @@@@@@@@@@@@
00021 - 81 - 129 - 10000001 @@ @@
18バイト目,19バイト目が1番目のブロックテーブルの開始アドレスを示します。
20バイト目,21バイト目が1番目のブロックテーブルの終了アドレスを示します。
注意しなければならないのは2バイトのこの値のバイトオーダーがリトルエンディアンである事。
よって
1番目のブロックテーブルの開始アドレスは0x8140
1番目のブロックテーブルの終了アドレスは0x817e
となります。
このブロックテーブルはヘッダの17バイト目(0x5c=92)の値分の数があります。
美咲フォントの場合、92個存在します。
#出力結果(データボディー部)
00386 - 00 - 000 - 00000000
00387 - 00 - 000 - 00000000
00388 - 00 - 000 - 00000000
00389 - 00 - 000 - 00000000
00390 - 00 - 000 - 00000000
00391 - 00 - 000 - 00000000
00392 - 00 - 000 - 00000000
00393 - 00 - 000 - 00000000
00394 - 00 - 000 - 00000000
00395 - 00 - 000 - 00000000
00396 - 00 - 000 - 00000000
00397 - 00 - 000 - 00000000
00398 - 00 - 000 - 00000000
00399 - 80 - 128 - 10000000 @@
00400 - 40 - 064 - 01000000 @@
00401 - 00 - 000 - 00000000
00402 - 00 - 000 - 00000000
00403 - 00 - 000 - 00000000
00404 - 00 - 000 - 00000000
00405 - 00 - 000 - 00000000
00406 - 40 - 064 - 01000000 @@
00407 - a0 - 160 - 10100000 @@ @@
00408 - 40 - 064 - 01000000 @@
00409 - 00 - 000 - 00000000
分かりにくいので、もうちょっと後も添付。
02066 - 20 - 032 - 00100000 @@
02067 - 7c - 124 - 01111100 @@@@@@@@@@
02068 - 20 - 032 - 00100000 @@
02069 - 3c - 060 - 00111100 @@@@@@@@
02070 - 6a - 106 - 01101010 @@@@ @@ @@
02071 - b2 - 178 - 10110010 @@ @@@@ @@
02072 - 64 - 100 - 01100100 @@@@ @@
02073 - 00 - 000 - 00000000
02074 - 00 - 000 - 00000000
02075 - 00 - 000 - 00000000
02076 - 48 - 072 - 01001000 @@ @@
02077 - 44 - 068 - 01000100 @@ @@
02078 - 44 - 068 - 01000100 @@ @@
02079 - 50 - 080 - 01010000 @@ @@
02080 - 20 - 032 - 00100000 @@
02081 - 00 - 000 - 00000000
02082 - 00 - 000 - 00000000
02083 - 88 - 136 - 10001000 @@ @@
02084 - 84 - 132 - 10000100 @@ @@
02085 - 82 - 130 - 10000010 @@ @@
02086 - 82 - 130 - 10000010 @@ @@
02087 - 50 - 080 - 01010000 @@ @@
02088 - 20 - 032 - 00100000 @@
02089 - 00 - 000 - 00000000
02090 - 00 - 000 - 00000000
02091 - 38 - 056 - 00111000 @@@@@@
02092 - 00 - 000 - 00000000
02093 - 38 - 056 - 00111000 @@@@@@
02094 - 44 - 068 - 01000100 @@ @@
02095 - 08 - 008 - 00001000 @@
02096 - 30 - 048 - 00110000 @@@@
02097 - 00 - 000 - 00000000
02098 - 3c - 060 - 00111100 @@@@@@@@
02099 - 00 - 000 - 00000000
02100 - 3c - 060 - 00111100 @@@@@@@@
02101 - 42 - 066 - 01000010 @@ @@
02102 - 02 - 002 - 00000010 @@
02103 - 04 - 004 - 00000100 @@
02104 - 38 - 056 - 00111000 @@@@@@
02105 - 00 - 000 - 00000000
02106 - 00 - 000 - 00000000
02107 - 38 - 056 - 00111000 @@@@@@
02108 - 00 - 000 - 00000000
02109 - 78 - 120 - 01111000 @@@@@@@@
02110 - 10 - 016 - 00010000 @@
02111 - 30 - 048 - 00110000 @@@@
02112 - 4c - 076 - 01001100 @@ @@@@
02113 - 00 - 000 - 00000000
02114 - 3c - 060 - 00111100 @@@@@@@@
02115 - 00 - 000 - 00000000
02116 - 7c - 124 - 01111100 @@@@@@@@@@
02117 - 08 - 008 - 00001000 @@
02118 - 18 - 024 - 00011000 @@@@
02119 - 28 - 040 - 00101000 @@ @@
02120 - 46 - 070 - 01000110 @@ @@@@
02121 - 00 - 000 - 00000000
02122 - 00 - 000 - 00000000
02123 - 20 - 032 - 00100000 @@
02124 - 74 - 116 - 01110100 @@@@@@ @@
02125 - 20 - 032 - 00100000 @@
02126 - 38 - 056 - 00111000 @@@@@@
02127 - 64 - 100 - 01100100 @@@@ @@
02128 - 28 - 040 - 00101000 @@ @@
02129 - 00 - 000 - 00000000
02130 - 20 - 032 - 00100000 @@
02131 - f4 - 244 - 11110100 @@@@@@@@ @@
02132 - 22 - 034 - 00100010 @@ @@
02133 - 3c - 060 - 00111100 @@@@@@@@
02134 - 62 - 098 - 01100010 @@@@ @@
02135 - a2 - 162 - 10100010 @@ @@ @@
02136 - 6c - 108 - 01101100 @@@@ @@@@
02137 - 00 - 000 - 00000000
データボディー部は8バイトづつ区切られてフォントの形状が格納されています。
例えば"宝"という字を調べてみます、文字コードは0x95f3です。
http://charset.7jp.net/sjis.html
しかし、このままではどの場所に欲しい文字のフォント形状があるかが分かりません。
フォント形状の場所(アドレス)の調べ方はリンク先サイトから引用させて頂きます。
ヘッダサイズ+4×Cb*+該当コードまでの文字数×フォントサイズ
*Cb=コードブロック=ブロックテーブル
フォントサイズはヘッダの14バイト目(フォント形状の幅ドット数:8ドット)と15バイト目(フォント形状の高ドット数:8ドット)を下記式から求められます。
int((フォント形状の幅ドット数+7)/8)*フォント形状の高ドット数です。
つまり、8x8の美咲フォントの場合、フォントサイズは8バイトになります。
##当該コードまでの文字数の調べ方
当該コードまでの文字数の調べ方は、まずブロックテーブル部から該当の文字コードがどのブロックテーブルに存在するか、を調べます。
アドレスブロック | A | B | C(B+A) | D | E | F(E+D) | G(F-C) |
---|---|---|---|---|---|---|---|
0 | 40 | 81 | 8140 | 7e | 81 | 817e | 63 |
1 | 80 | 81 | 8180 | ac | 81 | 81ac | 45 |
2 | b8 | 81 | 81b8 | bf | 81 | 81bf | 8 |
3 | c8 | 81 | 81c8 | ce | 81 | 81ce | 7 |
4 | da | 81 | 81da | e8 | 81 | 81e8 | 15 |
5 | f0 | 81 | 81f0 | f7 | 81 | 81f7 | 8 |
6 | fc | 81 | 81fc | fc | 81 | 81fc | 1 |
7 | 4f | 82 | 824f | 58 | 82 | 8258 | 10 |
8 | 60 | 82 | 8260 | 79 | 82 | 8279 | 26 |
9 | 81 | 82 | 8281 | 9a | 82 | 829a | 26 |
10 | 9f | 82 | 829f | f1 | 82 | 82f1 | 83 |
11 | 40 | 83 | 8340 | 7e | 83 | 837e | 63 |
12 | 80 | 83 | 8380 | 96 | 83 | 8396 | 23 |
13 | 9f | 83 | 839f | b6 | 83 | 83b6 | 24 |
14 | bf | 83 | 83bf | d6 | 83 | 83d6 | 24 |
15 | 40 | 84 | 8440 | 60 | 84 | 8460 | 33 |
16 | 70 | 84 | 8470 | 7e | 84 | 847e | 15 |
17 | 80 | 84 | 8480 | 91 | 84 | 8491 | 18 |
18 | 9f | 84 | 849f | be | 84 | 84be | 32 |
19 | 40 | 87 | 8740 | 5d | 87 | 875d | 30 |
20 | 5f | 87 | 875f | 75 | 87 | 8775 | 23 |
21 | 7e | 87 | 877e | 7e | 87 | 877e | 1 |
22 | 80 | 87 | 8780 | 9c | 87 | 879c | 29 |
23 | 9f | 88 | 889f | fc | 88 | 88fc | 94 |
24 | 40 | 89 | 8940 | 7e | 89 | 897e | 63 |
25 | 80 | 89 | 8980 | fc | 89 | 89fc | 125 |
26 | 40 | 8a | 8a40 | 7e | 8a | 8a7e | 63 |
27 | 80 | 8a | 8a80 | fc | 8a | 8afc | 125 |
28 | 40 | 8b | 8b40 | 7e | 8b | 8b7e | 63 |
29 | 80 | 8b | 8b80 | fc | 8b | 8bfc | 125 |
30 | 40 | 8c | 8c40 | 7e | 8c | 8c7e | 63 |
31 | 80 | 8c | 8c80 | fc | 8c | 8cfc | 125 |
32 | 40 | 8d | 8d40 | 7e | 8d | 8d7e | 63 |
33 | 80 | 8d | 8d80 | fc | 8d | 8dfc | 125 |
34 | 40 | 8e | 8e40 | 7e | 8e | 8e7e | 63 |
35 | 80 | 8e | 8e80 | fc | 8e | 8efc | 125 |
36 | 40 | 8f | 8f40 | 7e | 8f | 8f7e | 63 |
37 | 80 | 8f | 8f80 | fc | 8f | 8ffc | 125 |
38 | 40 | 90 | 9040 | 7e | 90 | 907e | 63 |
39 | 80 | 90 | 9080 | fc | 90 | 90fc | 125 |
40 | 40 | 91 | 9140 | 7e | 91 | 917e | 63 |
41 | 80 | 91 | 9180 | fc | 91 | 91fc | 125 |
42 | 40 | 92 | 9240 | 7e | 92 | 927e | 63 |
43 | 80 | 92 | 9280 | fc | 92 | 92fc | 125 |
44 | 40 | 93 | 9340 | 7e | 93 | 937e | 63 |
45 | 80 | 93 | 9380 | fc | 93 | 93fc | 125 |
46 | 40 | 94 | 9440 | 7e | 94 | 947e | 63 |
47 | 80 | 94 | 9480 | fc | 94 | 94fc | 125 |
48 | 40 | 95 | 9540 | 7e | 95 | 957e | 63 |
49 | 80 | 95 | 9580 | fc | 95 | 95fc | 125 |
調べたい文字コード 0x95f3 は 49番目のアドレスブロック、開始アドレス(C列) 0x9580 ~ 終了アドレス(F列) 0x95fc の間に該当します。
出力結果で言う所の下記の部分です。
00214 - 80 - 128 - 10000000 @@
00215 - 95 - 149 - 10010101 @@ @@ @@ @@
00216 - fc - 252 - 11111100 @@@@@@@@@@@@
00217 - 95 - 149 - 10010101 @@ @@ @@ @@
G列は該当アドレスブロックの文字数を表します。
G列=F列(終了アドレス(リトルエンディアン))-C列(開始アドレス(リトルエンディアン))です。
##該当コードまでの文字数
直前のアドレスブロックまでに存在する文字数+該当のアドレスブロックの開始アドレスからの文字数です。
直前のアドレスブロックまでに存在する文字数は48番目のアドレスまでの文字数(G列)の合計です。
0番目のアドレスブロックの文字数63+
1番目のアドレスブロックの文字数45+
2番目のアドレスブロックの文字数8+
...
48番目のアドレスブロックの文字数63
=3020文字
という事で、直前のアドレスブロックまでに存在する文字数は3020文字になりました。
##該当のアドレスブロックの開始アドレスからの文字数
該当のアドレスブロックの開始アドレスからの文字数は、調べたい文字コード-該当のアドレスブロックの開始アドレスです。
調べたい文字コード 0x95f3 から 開始アドレス 0x9580 を引くと,0x73(115)です。
という事で、該当のアドレスブロックの開始アドレスからの文字数は115文字になりました。
##該当文字のアドレスを求める。
再度引用しますが、該当文字のアドレスは
ヘッダサイズ+4×Cb*+該当コードまでの文字数×フォントサイズ
なので、
ヘッダサイズ18+(4バイト*アドレスブロック数92)+((該当コードまでの文字数3020+該当のアドレスブロックの開始アドレスからの文字数115)×フォントサイズ8)=
18+(4*92)+((3020+115)8)=
18+368+(31358)=25466
25466バイト目が調べたい文字(宝)の文字コード(0x95f3)のフォント形状が格納されているアドレスとなりました。
実際に見てみると…
25466 - 10 - 016 - 00010000 @@
25467 - fe - 254 - 11111110 @@@@@@@@@@@@@@
25468 - ba - 186 - 10111010 @@ @@@@@@ @@
25469 - 10 - 016 - 00010000 @@
25470 - 38 - 056 - 00111000 @@@@@@
25471 - 14 - 020 - 00010100 @@ @@
25472 - fe - 254 - 11111110 @@@@@@@@@@@@@@
25473 - 00 - 000 - 00000000
という事で目的の文字の形状が取得出来ました。
#まとめ
フォーマットのリトルエンディアンをビッグエンディアンと勘違いし、ハマッてしまったのでメモとして残しました。。