7
11

More than 5 years have passed since last update.

マイコンで日本語を表示させる為にFONTX2の仕様を調べました

Posted at

概要

8x8のドットマトリクスLEDに日本語を表示させる為、マイコンで扱える形にする必要があったので、FONTX2の仕様を調べてハマったのでメモとして残す。

使ったフォント

8x8ドットの日本語フォント、美咲フォントを使わせていただきました。
8×8 ドット日本語フォント「美咲フォント」

参考にしたサイト

FONTXの使いかた
Arduino Unoで漢字を扱う(2) FONTX形式のフォントを扱う

解析する簡単なスクリプト

美咲フォントのウェブサイトよりFONTX2形式のzipファイルをダウンロードします。
zipファイルの中のMISAKIMN.FNTを下記の簡単なPerlスクリプトで中身を見てみました。

font.pl
#!/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+(3135*8)=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

という事で目的の文字の形状が取得出来ました。

まとめ

フォーマットのリトルエンディアンをビッグエンディアンと勘違いし、ハマッてしまったのでメモとして残しました。。

7
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
11