PC-8001 にはセミグラフィックというグラフィック機能があります。正確にはキャラクタコード 0-255 を 2x4 ドットの組み合わせとして置き換える事で実現しています。このセミグラフィックをどう扱うのか、今回は解説していきます。


  • 2進数のビットがドットになっている
まずは実機でテストしてみましょう。N-BASIC で以下のプログラムを実行してみます。

10 CONSOLE0,25,0,1:COLOR7,0,1:WIDTH80,25
20 PRINT CHR$(12);
30 FOR Y=0 TO 15:FOR X=0 TO 15
40 POKE &HF301+X+Y*120,X+Y*16
50 NEXT:NEXT:LOCATE0,16
セミグラフィック
ドット位置
グラフィック命令を使っていないのに、画面にはセミグラフィックが出ています。しかもなんとなく規則正しい感じがしますよね。そこで以前解説した 2進数を思い出してください。入力した数値を2進数に直した際の各ビット位置が、表示されるドット位置に対応しているのです。b0 が LSB、b7 が MSB を意味しています。
C2のドット
例えば 0xC2 の場合は 2進数で 11000010 となります。そのため、セミグラフィックはこのような幾何学模様になります。この 2x4 の単位で 80文字×25行並ぶ事で、グラフィックとして描画するというわけです。
うまく描くの禁止 ツラくないイラスト上達法

さいとうなおき
パイ インターナショナル
2021-04-26



  • 任意の画像をデータ化する
上記の制約により、PC-8001 のセミグラフィックは横方向は偶数、縦方向は4の倍数でデータを保持する事になります。とりあえずの例として、セミグラフィックで私の名前を表示してみます。こんなドットを用意してみました。
内藤時浩
横16ドットですから、横に8キャラとなります。縦は 12ドットですので、3行分となります。合わせて 24バイトのデータ列となります。左上から右下に向かって、順次走査してデータ化してみます。赤枠で示した左上は…

  □□  =>  b0,b4  =>  0,0  =>  11000000 => 0xC0
  □□     b1,b5     0,0
  □■     b2,b6     0,1
  □■     b3,b7     0,1
0xC0 ですね。このまま変換していくと以下のデータが得られます。

MOJI:   db      0xC0, 0x44, 0x4F, 0xC4, 0xA0, 0xFA, 0x7A, 0x2A,
        db      0xF0, 0x68, 0x61, 0xF8, 0xF0, 0xFA, 0x7A, 0x2A,
        db      0x70, 0x00, 0x00, 0x74, 0x70, 0x70, 0x72, 0x52,
これが本当に変換元の文字となって表示されるのか、N-BASIC から試してみます。
文字が出た
無事、表示されました。マシン語でも同様に処理すれば、そのままセミグラフィックの文字として、画面に表示されます。画面の初期化はこちらで説明した BASIC ROM内ルーチンを使用します。

        org     0xC000
START:  ld      bc, $00FF
        call    BIOS.FUNC_COLOR      ; カラーに
        ld      bc, 80 * 256 + 25
        call    BIOS.WIDTH           ; CRT 画面表示文字数の設定
        ld      hl, MOJI             ; HL 文字データ
        ld      de, 0xF301           ; DE 表示アドレス
        ld      bc, 8                ; BC 8文字
        ldir                         ; 転送する
        ld      de, 0xF301 + 1 * 120 ; DE 下の行に
        ld      c, 8                 ; C 8文字
        ldir                         ; 転送する
        ld      de, 0xF301 + 2 * 120 ; さらに下の行に
        ld      c, 8                 ; C 8文字
        ldir                         ; 転送する
        jp      BIOS.MONITOR         ; モニタに戻る
このプログラムでちゃんと動くのですが、なぜかセミグラフィックがテキスト文字に化けてしまいます。これはアトリビュートがテキストに置き換えられているためですが、この話は長くなるので次の機会に説明します。


  • 手変換は面倒なので C# に任せよう
こういう単純な変換作業は C# 等の便利なプログラムに任せた方が簡単ですよね。なんとなく C# 弄れる人なら簡単に作れるとは思いますが、黒と透明以外をドットとして見なして、セミグラフィックに変換するサンプルコードを記載しておきます。適当に改変してご活用ください。
// -------------------------------------------------------------
// セミグラフィックドットオフセット
// -------------------------------------------------------------
private Point[] offsetChr = new Point[8]
{
    new Point(0, 0), new Point(0, 1), new Point(0, 2), new Point(0, 3),
    new Point(1, 0), new Point(1, 1), new Point(1, 2), new Point(1, 3),
};

// -------------------------------------------------------------
// セミグラフィック画像をテキストにデータ変換する
// -------------------------------------------------------------
private int[] GetSemiGraphicsToVTextData(Bitmap bmp)
{
    List<int> vt = new List<int>();
    for (int y = 0; y < bmp.Height / 4; ++y)
    {
        for (int x = 0; x < bmp.Width / 2; ++x)
        {
            int chrCode = 0;
            for (int c = 0; c < 8; ++c)
            {
                Color col = bmp.GetPixel(
                        x * 2 + offsetChr[c].X,
                        y * 4 + offsetChr[c].Y);
                int br = col.A * (col.R + col.G + col.B);
                chrCode |= (br > 0 ? 1 : 0) << c;
            }
            vt.Add(chrCode);
        }
    }
    return vt.ToArray();
}
上記の処理を加えた C# のソースと、ドラッグするだけで変換する簡単なツールをこちらから受け取れるようにしておきました。宜しければお使いください。