土木測量プログラムの開発 (文字のグラフィック表示)

2017/02/25


現場で使用しやすい土木測量用のプログラムをグラフ関数電卓の fx-9860GII を使用し作成します。

CASIO より土木測量用の電卓 fx-FD10pro が出ていますが、正直、搭載されている CASIO BASIC が使い物にならない(プログラムする気にならにないという意味)のでC言語での開発が行えるグラフ電卓を使用します。 既に fx-9860G でプログラムを作成して使用しているのですが、9860GII はわずかに幅が狭く持ちやすくなっています。 また、バックライトがついているので暗くなっても使用できます。

fx-FD10pro がアドインプログラムを使用できるようになれば最強なのですが、fx-FD10pro はプログラムにパスワードを設定してもプログラムの削除が容易にできてしまいます。これがプログラムする気にならない一番の理由です。

多分、fx-5800 等の関数電卓では裏コマンドでプログラムの保護ができるようになっていると思うのですが、即利用くんのメーカーなどのみに販売する転送プログラムがあると思います。 もしかして、fx-FD10pro にもそのようなプログラムが存在しているのかもしれませんが、守秘義務の契約を行わない一般ユーザーには手の出せないものになっているはずです。

fx-FD10pro の CASIO BASIC はグラフ電卓の BASIC とほぼ同じで、fx-5800 等の BASIC に比べ表示コマンドが強化されています。ただ、入力用のコマンドが使いづらく、fx-4850P の BASIC の方が使いやすかったので、次の関数電卓では fx-4850P の入力コマンドに戻してもらいたいものです。

愚痴の様な前置きが長くなりましたがこれからが本題です。

以前作成したプログラムのソースが見当たらないので、新規のプロジェクトを作成した時のサンプルと少しずつ改変してみて、思い出しながらまとめていきたいと思います。


文字変数の使用と表示。

初めに新規のプロジェクトを作成します。 作成方法は Hello World のページに書きましたので割愛します。 以下のプログラムでは、文字変数は使用していませんが文字の表示は行っています。

#include "fxlib.h"

//****************************************************************************
int AddIn_main(int isAppli, unsigned short OptionNum) {
    unsigned int key;

    Bdisp_AllClr_DDVRAM();

    locate(1,4);
    Print((unsigned char*)"This application is");
    locate(1,5);
    Print((unsigned char*)" sample Add-In.");

    while(1) {
        GetKey(&key);
    }

    return 1;
}

表示する文字列を変数にして表示します。

#include "fxlib.h"

//****************************************************************************
int AddIn_main(int isAppli, unsigned short OptionNum) {
    unsigned int key;
    unsigned char text1[] = "This application is";  // 文字変数に定義
    unsigned char text2[] = " sample Add-In.";

    Bdisp_AllClr_DDVRAM();

    locate(1,4);
    Print((unsigned char*)text1);  // 変数を使用
    locate(1,5);
    Print((unsigned char*)text2);

    while(1) {
        GetKey(&key);
    }

    return 1;
}

数値を文字列に変換して表示します。 数値を文字列に変換するときは sprintf 関数を使用します。 なお、"stdio.h" をインクルードしなくてもビルド行えますがエミュレータでは正常な動作が行われませんでしたのできちんと宣言しておきます。

#include <stdio.h>  // stdio.h をインクルード
#include "fxlib.h"

//****************************************************************************
int AddIn_main(int isAppli, unsigned short OptionNum) {
    unsigned int key;
    int num1 = 123;  // 数値を変数に代入
    int num2 = 456;
    unsigned char text1[24];
    unsigned char text2[24];

    Bdisp_AllClr_DDVRAM();

    sprintf(text1, "%d", num1);  // 数値を文字列に変換
    sprintf(text2, "%d", num2);


    locate(1,4);
    Print((unsigned char*)text1);
    locate(1,5);
    Print((unsigned char*)text2);

    while(1) {
        GetKey(&key);
    }

    return 1;
}

書式文字列は複雑で応用範囲が広いのでここのページにまとめています。解りにくかったら『書式文字列』で検索してみてください。


グラフィックで文字を表示。

CASIO BASIC には MENU 命令がありますが、この命令を使用した時と同じような形でメニュー表示を行うようにします。

Locate 命令で文字を表示するとメニューの枠線と被ってしまうため、文字の表示位置をピクセル単位で指定するようにします。

そのためには文字をグラフィックとして描画する必要があり、そのための関数を作成します。

初めに以下は ascii コード 0x20~0x7F の 6 x 8 の文字データです。 プログラムの先頭で文字配列に定義します。

// 6 x 8 フォント(アルファベット)
static const unsigned char AlphaFont[][8] = {
	 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // 20 (SPC)
	,{0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20, 0x00} // 21 !
	,{0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00} // 22 "
	,{0x50, 0x50, 0xF8, 0x50, 0xF8, 0x50, 0x50, 0x00} // 23 #
	,{0x20, 0x78, 0xA0, 0x70, 0x28, 0xF0, 0x20, 0x00} // 24 $
	,{0xC0, 0xC8, 0x10, 0x20, 0x40, 0x98, 0x18, 0x00} // 25 %
	,{0x60, 0x90, 0xA0, 0x40, 0xA8, 0x90, 0x68, 0x00} // 26 &
	,{0x60, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00} // 27 '
	,{0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00} // 28 (
	,{0x40, 0x20, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00} // 29 )
	,{0x00, 0x20, 0xA8, 0x70, 0xA8, 0x20, 0x00, 0x00} // 2A *
	,{0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, 0x00} // 2B +
	,{0x00, 0x00, 0x00, 0x00, 0x60, 0x20, 0x40, 0x00} // 2C 
	,{0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00} // 2D -
	,{0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00} // 2E .
	,{0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00} // 2F /
	,{0x70, 0x88, 0x98, 0xA8, 0xC8, 0x88, 0x70, 0x00} // 30 0
	,{0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00} // 31 1
	,{0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xF8, 0x00} // 32 2
	,{0xF8, 0x10, 0x20, 0x10, 0x08, 0x88, 0x70, 0x00} // 33 3
	,{0x10, 0x30, 0x50, 0x90, 0xF8, 0x10, 0x10, 0x00} // 34 4
	,{0xF8, 0x80, 0xF0, 0x08, 0x08, 0x88, 0x70, 0x00} // 35 5
	,{0x30, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70, 0x00} // 36 6
	,{0xF8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x40, 0x00} // 37 7
	,{0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00} // 38 8
	,{0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0x60, 0x00} // 39 9
	,{0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x00} // 3A :
	,{0x00, 0x60, 0x60, 0x00, 0x60, 0x20, 0x40, 0x00} // 3B ;
	,{0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x00} // 3C <
	,{0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00} // 3D =
	,{0x40, 0x20, 0x10, 0x08, 0x10, 0x20, 0x40, 0x00} // 3E >
	,{0x70, 0x88, 0x08, 0x10, 0x20, 0x00, 0x20, 0x00} // 3F ?
	,{0x70, 0x88, 0x08, 0x68, 0xA8, 0xA8, 0x70, 0x00} // 40 @
	,{0x70, 0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00} // 41 A
	,{0xF0, 0x88, 0x88, 0xF0, 0x88, 0x88, 0xF0, 0x00} // 42 B
	,{0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00} // 43 C
	,{0xE0, 0x90, 0x88, 0x88, 0x88, 0x90, 0xE0, 0x00} // 44 D
	,{0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8, 0x00} // 45 E
	,{0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80, 0x00} // 46 F
	,{0x70, 0x88, 0x80, 0xB8, 0x88, 0x88, 0x78, 0x00} // 47 G
	,{0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88, 0x00} // 48 H
	,{0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00} // 49 I
	,{0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00} // 4A J
	,{0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88, 0x00} // 4B K
	,{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF8, 0x00} // 4C L
	,{0x88, 0xD8, 0xA8, 0xA8, 0x88, 0x88, 0x88, 0x00} // 4D M
	,{0x88, 0x88, 0xC8, 0xA8, 0x98, 0x88, 0x88, 0x00} // 4E N
	,{0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00} // 4F O
	,{0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80, 0x00} // 50 P
	,{0x70, 0x88, 0x88, 0x88, 0xA8, 0x90, 0x68, 0x00} // 51 Q
	,{0xF0, 0x88, 0x88, 0xF0, 0xA0, 0x90, 0x88, 0x00} // 52 R
	,{0x78, 0x80, 0x80, 0x70, 0x08, 0x08, 0xF0, 0x00} // 53 S
	,{0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00} // 54 T
	,{0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00} // 55 U
	,{0x88, 0x88, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00} // 56 V
	,{0x88, 0x88, 0x88, 0xA8, 0xA8, 0xA8, 0x50, 0x00} // 57 W
	,{0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88, 0x00} // 58 X
	,{0x88, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x00} // 59 Y
	,{0xF8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xF8, 0x00} // 5A Z
	,{0x70, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70, 0x00} // 5B [
	,{0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00} // 5C (YEN)
	,{0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00} // 5D ]
	,{0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00} // 5E ^
	,{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00} // 5F _
	,{0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00} // 60 `
	,{0x00, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00} // 61 a
	,{0x80, 0x80, 0xB0, 0xC8, 0x88, 0x88, 0xF0, 0x00} // 62 b
	,{0x00, 0x00, 0x70, 0x80, 0x80, 0x88, 0x70, 0x00} // 63 c
	,{0x08, 0x08, 0x68, 0x98, 0x88, 0x88, 0x78, 0x00} // 64 d
	,{0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00} // 65 e
	,{0x30, 0x48, 0x40, 0xE0, 0x40, 0x40, 0x40, 0x00} // 66 f
	,{0x00, 0x78, 0x88, 0x88, 0x78, 0x08, 0x70, 0x00} // 67 g
	,{0x80, 0x80, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00} // 68 h
	,{0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00} // 69 i
	,{0x10, 0x00, 0x30, 0x10, 0x10, 0x90, 0x60, 0x00} // 6A j
	,{0x80, 0x80, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x00} // 6B k
	,{0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00} // 6C l
	,{0x00, 0x00, 0xD0, 0xA8, 0xA8, 0x88, 0x88, 0x00} // 6D m
	,{0x00, 0x00, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00} // 6E n
	,{0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00} // 6F o
	,{0x00, 0x00, 0xF0, 0x88, 0xF0, 0x80, 0x80, 0x00} // 70 p
	,{0x00, 0x00, 0x68, 0x98, 0x78, 0x08, 0x08, 0x00} // 71 q
	,{0x00, 0x00, 0xB0, 0xC8, 0x80, 0x80, 0x80, 0x00} // 72 r
	,{0x00, 0x00, 0x70, 0x80, 0x70, 0x08, 0xF0, 0x00} // 73 s
	,{0x40, 0x40, 0xE0, 0x40, 0x40, 0x48, 0x30, 0x00} // 74 t
	,{0x00, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00} // 75 u
	,{0x00, 0x00, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00} // 76 v
	,{0x00, 0x00, 0x88, 0x88, 0xA8, 0xA8, 0x50, 0x00} // 77 w
	,{0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00} // 78 x
	,{0x00, 0x00, 0x88, 0x88, 0x78, 0x08, 0x70, 0x00} // 79 y
	,{0x00, 0x00, 0xF8, 0x10, 0x20, 0x40, 0xF8, 0x00} // 7A z
	,{0x10, 0x20, 0x20, 0x40, 0x20, 0x20, 0x10, 0x00} // 7B {
	,{0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00} // 7C |
	,{0x40, 0x20, 0x20, 0x10, 0x20, 0x20, 0x40, 0x00} // 7D }
	,{0x00, 0x20, 0x10, 0xF8, 0x10, 0x20, 0x00, 0x00} // 7E (Right arrow)
	,{0x00, 0x20, 0x40, 0xF8, 0x40, 0x20, 0x00, 0x00} // 7F (Left arrow)
};

次に一文字表示するための関数を作成します。

引数はドット単位での指定が正しい方法だと思いますが、ここは Locate 命令と同じ引数とし、ずれる値をオフセット値で指定する方法をとります。

void CharacterPrint(char x, char y, unsigned char c, char ox, char oy) {

// 描画で使用する構造体の定義
    DISPGRAPH cFont;
    GRAPHDATA cFont_info;

    x = x * 6 - 6 + ox;  // 位置をドット単位に変換
    y = y * 8 - 8 + oy;
    c = c - 0x20;  // キャラクタコードを変換

// 構造体にデータを登録
    cFont_info.width = 6;                // 描画する横サイズ
    cFont_info.height = 8;               // 描画する縦サイズ
    cFont_info.pBitmap = AlphaFont[c];   // 文字データ(6x8)
    cFont.x = x;                         // 描画位置 (X)
    cFont.y = y;                         // 描画位置 (Y)
    cFont.GraphData = cFont_info;        // 描画データ変数名
    cFont.WriteModify = IMB_WRITEMODIFY_NORMAL;    // 描画方法
    cFont.WriteKind = IMB_WRITEKIND_OVER;          // 上書き方法

    Bdisp_WriteGraph_DDVRAM(&cFont);  // 描画を実行
}

グラフィック表示のコマンドを以下にまとめます。

構造体  GRAPHDATA 変数名
     int       変数名.windth    画像データの表示幅
     int       変数名.height    画像データの表示高さ
     unsigned char  変数名.pBitmap   画像データ本体のポインタ

構造体  DISPGRAPH 変数名
     int       変数名.x      表示位置 x (左上 0~127)
     int       変数名.y      表示位置 y (左上 0~ 63)
     GRAPHDATA    変数名.GrapData   画像データ構造体のポインタ
     WRITEMODIFY   変数名.WriteModify 表示タイプ
              = IMB_WRITEMODIFY_NORMAL   標準
              = IMB_WRITEMODIFY_REVERSE  反転
              = IMB_WRITEMODIFY_MESH    ハーフトーン
     WRITEKIND    変数名.WriteKind  上書き方法
              = IMB_WRITEKIND_OVER     上書き
              = IMB_WRITEKIND_OR OR    OR
              = IMB_WRITEKIND_AND AND   AND
              = IMB_WRITEKIND_XOR XOR   XOR

以上の変数をセットし描画の命令を行います。

    Bdisp_WriteGraph_DD(&GRAPHDATA の変数名);   ディスプレイドライバに描画
    Bdisp_WriteGraph_VRAM(&GRAPHDATA の変数名);  VRAM に描画
    Bdisp_WriteGraph_DDVRAM(&GRAPHDATA の変数名); 両方に描画

上記のフォントデータと関数を書き込んでサンプルを実行してみます。

サンプルなので必要な文字データのみ配列に入れています。 よって関数を呼び出すときに 0x21 を加算しています。

#include "fxlib.h"

// Font 6x8
static const unsigned char AlphaFont[][8] = {
     {0x70, 0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00} // 41 A
    ,{0xF0, 0x88, 0x88, 0xF0, 0x88, 0x88, 0xF0, 0x00} // 42 B
    ,{0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00} // 43 C
};

// Function
void CharacterPrint(char x, char y, unsigned char c, char ox, char oy) {

    DISPGRAPH cFont;
    GRAPHDATA cFont_info;

    x = x * 6 - 6 + ox;
    y = y * 8 - 8 + oy;
    c = c - 0x20;

    cFont_info.width = 6;
    cFont_info.height = 8;
    cFont_info.pBitmap = AlphaFont[c];
    cFont.x = x;
    cFont.y = y;
    cFont.GraphData = cFont_info;
    cFont.WriteModify = IMB_WRITEMODIFY_NORMAL;
    cFont.WriteKind = IMB_WRITEKIND_OVER;
    Bdisp_WriteGraph_VRAM(&cFont);
}


//****************************************************************************
int AddIn_main(int isAppli, unsigned short OptionNum) {
    unsigned int key;

    CharacterPrint(5, 3, 0x41 - 0x21, 0, 0);
    CharacterPrint(6, 3, 0x42 - 0x21, 1, 1);
    CharacterPrint(7, 3, 0x43 - 0x21, 2, 2);

    while(1) { GetKey(&key); }
    return 1;
}

正しく実行されるとアルファベットがオフセット分ずれて表示されます。

上記の一文字表示関数をカナに対応させます。 カタカナ用の文字配列の宣言を追加します。

// 6 x 8 フォント(カタカナ)
static const unsigned char KanaFont[][8] = {
	 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // A0 (SPC)
	,{0x00, 0x00, 0xE0, 0xA0, 0xE0, 0x00, 0x00, 0x00} // A1 。
	,{0x38, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00} // A2 「
	,{0x00, 0x00, 0x20, 0x20, 0x20, 0xE0, 0x00, 0x00} // A3 」
	,{0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x00, 0x00} // A4 、
	,{0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00} // A5 ・
	,{0x00, 0xF8, 0x08, 0xF8, 0x08, 0x10, 0x20, 0x00} // A6 ヲ
	,{0x00, 0x00, 0xF8, 0x08, 0x30, 0x20, 0x40, 0x00} // A7 ァ
	,{0x00, 0x00, 0x10, 0x20, 0x60, 0xA0, 0x20, 0x00} // A8 ィ
	,{0x00, 0x20, 0xF8, 0x88, 0x08, 0x30, 0x00, 0x00} // A9 ゥ
	,{0x00, 0x00, 0x00, 0xF8, 0x20, 0x20, 0xF8, 0x00} // AA ェ
	,{0x00, 0x00, 0x10, 0xF8, 0x30, 0x50, 0x90, 0x00} // AB ォ
	,{0x00, 0x00, 0x40, 0xF8, 0x48, 0x50, 0x40, 0x00} // AC ャ
	,{0x00, 0x00, 0x00, 0xF0, 0x10, 0xF8, 0x00, 0x00} // AD ュ
	,{0x00, 0x00, 0xF0, 0x10, 0xF0, 0x10, 0xF0, 0x00} // AE ュ
	,{0x00, 0x00, 0xA8, 0xA8, 0x08, 0x30, 0x00, 0x00} // AF ッ
	,{0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00} // B0 ー
	,{0xF8, 0x08, 0x28, 0x30, 0x20, 0x20, 0x40, 0x00} // B1 ア
	,{0x08, 0x10, 0x20, 0x60, 0xA0, 0x20, 0x20, 0x00} // B2 イ
	,{0x20, 0xF8, 0x88, 0x08, 0x08, 0x10, 0x20, 0x00} // B3 ウ
	,{0x00, 0xF8, 0x20, 0x20, 0x20, 0x20, 0xF8, 0x00} // B4 エ
	,{0x10, 0xF8, 0x10, 0x30, 0x50, 0x90, 0x10, 0x00} // B5 オ
	,{0x40, 0xF8, 0x48, 0x48, 0x48, 0x48, 0x90, 0x00} // B6 カ
	,{0x20, 0xF8, 0x20, 0xF8, 0x20, 0x20, 0x20, 0x00} // B7 キ
	,{0x78, 0x48, 0x88, 0x08, 0x08, 0x10, 0x60, 0x00} // B8 ク
	,{0x40, 0x78, 0x90, 0x10, 0x10, 0x10, 0x20, 0x00} // B9 ケ
	,{0xF8, 0x08, 0x08, 0x08, 0x08, 0x08, 0xF8, 0x00} // BA コ
	,{0x50, 0xF8, 0x50, 0x50, 0x10, 0x20, 0x40, 0x00} // BB サ
	,{0x00, 0xC0, 0x08, 0xC8, 0x10, 0xE0, 0x00, 0x00} // BC シ
	,{0x00, 0xF8, 0x08, 0x10, 0x20, 0x50, 0x88, 0x00} // BD ス
	,{0x40, 0xF8, 0x48, 0x50, 0x40, 0x40, 0x38, 0x00} // BE セ
	,{0x00, 0x88, 0x88, 0x48, 0x08, 0x10, 0x60, 0x00} // BF ソ
	,{0x78, 0x48, 0xA8, 0x18, 0x10, 0x60, 0x00, 0x00} // C0 タ
	,{0x10, 0xE0, 0x20, 0xF8, 0x20, 0x20, 0x40, 0x00} // C1 チ
	,{0xA8, 0xA8, 0xA8, 0x08, 0x10, 0x20, 0x00, 0x00} // C2 ツ
	,{0x70, 0x00, 0xF8, 0x20, 0x20, 0x20, 0x40, 0x00} // C3 テ
	,{0x40, 0x40, 0x40, 0x60, 0x50, 0x40, 0x40, 0x00} // C4 ト
	,{0x20, 0x20, 0xF8, 0x20, 0x20, 0x40, 0x80, 0x00} // C5 ナ
	,{0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00} // C6 ニ
	,{0x00, 0xF8, 0x08, 0x50, 0x20, 0x50, 0x80, 0x00} // C7 ヌ
	,{0x20, 0xF8, 0x10, 0x20, 0x70, 0xA8, 0x20, 0x00} // C8 ネ
	,{0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00} // C9 ノ
	,{0x00, 0x20, 0x10, 0x88, 0x88, 0x88, 0x88, 0x00} // CA ハ
	,{0x80, 0x80, 0xF8, 0x80, 0x80, 0x80, 0x78, 0x00} // CB ヒ
	,{0x00, 0xF8, 0x08, 0x08, 0x08, 0x10, 0x60, 0x00} // CC フ
	,{0x00, 0x40, 0xA0, 0x10, 0x08, 0x08, 0x00, 0x00} // CD ヘ
	,{0x20, 0xF8, 0x20, 0x20, 0xA8, 0xA8, 0x20, 0x00} // CE ホ
	,{0x00, 0xF8, 0x08, 0x08, 0x50, 0x20, 0x10, 0x00} // CF マ
	,{0x70, 0x00, 0x70, 0x00, 0x70, 0x08, 0x00, 0x00} // D0 ミ
	,{0x00, 0x20, 0x40, 0x80, 0x88, 0xF8, 0x08, 0x00} // D1 ム
	,{0x00, 0x08, 0x08, 0x50, 0x20, 0x50, 0x80, 0x00} // D2 メ
	,{0x00, 0xF8, 0x40, 0xF8, 0x40, 0x40, 0x38, 0x00} // D3 モ
	,{0x40, 0x40, 0xF8, 0x48, 0x50, 0x40, 0x40, 0x00} // D4 ヤ
	,{0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0xF8, 0x00} // D5 ユ
	,{0x00, 0xF8, 0x08, 0xF8, 0x08, 0x08, 0xF8, 0x00} // D6 ヨ
	,{0x70, 0x00, 0xF8, 0x08, 0x08, 0x10, 0x20, 0x00} // D7 ラ
	,{0x90, 0x90, 0x90, 0x90, 0x10, 0x20, 0x40, 0x00} // D8 リ
	,{0x00, 0x20, 0x20, 0xA0, 0xA8, 0xA8, 0xB0, 0x00} // D9 ル
	,{0x00, 0x80, 0x80, 0x88, 0x90, 0xA0, 0xC0, 0x00} // DA レ
	,{0x00, 0xF8, 0x88, 0x88, 0x88, 0x88, 0xF8, 0x00} // DB ロ
	,{0x00, 0xF8, 0x88, 0x88, 0x08, 0x10, 0x20, 0x00} // DC ワ
	,{0x00, 0xC0, 0x00, 0x08, 0x08, 0x10, 0xE0, 0x00} // DD ン
	,{0x20, 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00} // DE ゙
	,{0xE0, 0xA0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00} // DF ゚
};

引数のキャラクタコードが 0xA0 以上の場合カタカナの文字データを表示させます。

void CharacterPrint(char x, char y, unsigned char c, char ox, char oy) {

    DISPGRAPH cFont;
    GRAPHDATA cFont_info;

    cFont_info.width = 6;
    cFont_info.height = 8;
    cFont.x = x * 6 - 6 + ox;
    cFont.y = y * 8 - 8 + oy;
    if (c < 0xA0) {
        c = c - 0x20;
        cFont_info.pBitmap = AlphaFont[c];
    } else {
        c = c - 0xA0;
        cFont_info.pBitmap = KanaFont[c];
    }
    cFont.GraphData = cFont_info;
    cFont.WriteModify = IMB_WRITEMODIFY_NORMAL;
    cFont.WriteKind = IMB_WRITEKIND_OVER;
    Bdisp_WriteGraph_VRAM(&cFont);
}

カナ交じりの文字列を表示させる関数を作成します。 引数にオフセット値を加えてます。

本来なら引数のエラーチェックを行うべきなのですが省略します。

void CPrint(char x, char y, char *c, char ox, char oy) {
    while(*c) {
        CharacterPrint(x, y, *c++, ox, oy);
        x++;
    }
}

上記の関数を使用したサンプルコードを実行してみます。

以下のコードでは省略していますが、文字データの宣言を加えてください。

#include "fxlib.h"

// Font 6x8
//
//
//

// Function
void CharacterPrint(char x, char y, unsigned char c, char ox, char oy) {

    DISPGRAPH cFont;
    GRAPHDATA cFont_info;

    cFont_info.width = 6;
    cFont_info.height = 8;
    cFont.x = x * 6 - 6 + ox;
    cFont.y = y * 8 - 8 + oy;
    if (c < 0xA0) {
        c = c - 0x20;
        cFont_info.pBitmap = AlphaFont[c];
    } else {
        c = c - 0xA0;
        cFont_info.pBitmap = KanaFont[c];
    }
    cFont.GraphData = cFont_info;
    cFont.WriteModify = IMB_WRITEMODIFY_NORMAL;
    cFont.WriteKind = IMB_WRITEKIND_OVER;
    Bdisp_WriteGraph_VRAM(&cFont);
}

void CPrint(char x, char y, char *c, char ox, char oy) {
    while(*c) {
        CharacterPrint(x, y, *c++, ox, oy);
        x++;
    }
}


//****************************************************************************
int AddIn_main(int isAppli, unsigned short OptionNum) {
    unsigned int key;

    char text[] = "ABCアイウエオ";
    CPrint(5, 3, &text, 0, 0);

    while(1) { GetKey(&key); }
    return 1;
}

 


漢字も表示します。

調子に乗って漢字も表示しちゃいます。 実際のところメニュー表示した際に英数字や半角カタカナだとごちゃごちゃして視認性が良くありません。

やっぱり漢字は一目見ただけで意味が理解できるアイコンの役割のような物なのでメニュー表示だけは漢字の表示を行いたいと思います。

先の話ですが、入力値や計算の範囲外でのエラーメッセージは漢字の方が少ない文字数で表示することができます。

基本的に前項までの文字のグラフィック表示と同じ処理ですが、6x8 のデータでは漢字を表現できません。

16x16 だと十分表現できるのですが、アイコン的な使用方法なので 8x12 のデータを使用します。 漢字データは 東雲フォント を使用しています。

なお、表示位置の指定は Locate 命令の指定とは異なり、ドット単位での指定とします。

#include "fxlib.h"

// 8 x 12 フォント(漢字)
static const unsigned char KanjiFont[][12] = {
     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} //
    ,{0xBA, 0x2A, 0x3E, 0xAE, 0x3E, 0x2E, 0x2A, 0xBA, 0x82, 0xAA, 0xAA, 0x00} // 測
    ,{0x7C, 0x44, 0x7C, 0x44, 0xFE, 0x54, 0x7C, 0x54, 0x7C, 0x10, 0xFE, 0x00} // 量
    ,{0xE4, 0x04, 0xE4, 0x04, 0xFE, 0x04, 0xE4, 0x04, 0xE4, 0xA4, 0xE4, 0x00} // 計
    ,{0x48, 0x6E, 0xB4, 0x7C, 0x44, 0x7C, 0x44, 0x7C, 0x28, 0xFE, 0x48, 0x00} // 算
};

void KanjiPrint(int x, int y, unsigned char c) {

    DISPGRAPH Kanji;
    GRAPHDATA Kanji_info;

    Kanji_info.width = 8;
    Kanji_info.height = 12;
    Kanji.x = x;
    Kanji.y = y;
    Kanji_info.pBitmap = KanjiFont[c];
    Kanji.GraphData = Kanji_info;
    Kanji.WriteModify = IMB_WRITEMODIFY_NORMAL;
    Kanji.WriteKind = IMB_WRITEKIND_OVER;
    Bdisp_WriteGraph_VRAM(&Kanji);
}

void KPrint(int x, int y, char *c) {
    while(*c) {
        KanjiPrint(x, y, *c++);
        x = x + 8;
    }
}

//****************************************************************************
int AddIn_main(int isAppli, unsigned short OptionNum) {
    unsigned int key;
    char text[] ={1,2,3,4};

    KPrint(0,0,&text);

    while(1) { GetKey(&key); }
    return 1;
}

漢字データの 0番に空白のデータがありますが、文字配列に 0番を指定すると文字列の終わりと判断されるので、0番は使用されることがありません。 よって、空白の文字が必要な場合は 0番以外に空白のデータを作成する必要があります。