PC-8001 にはセミグラフィックというグラフィック機能があります。正確にはキャラクタコード 0-255 を 2x4 ドットの組み合わせとして置き換える事で実現しています。このセミグラフィックをどう扱うのか、今回は解説していきます。
無事、表示されました。マシン語でも同様に処理すれば、そのままセミグラフィックの文字として、画面に表示されます。画面の初期化はこちらで説明した BASIC ROM内ルーチンを使用します。
- 2進数のビットがドットになっている
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 を意味しています。
例えば 0xC2 の場合は 2進数で 11000010 となります。そのため、セミグラフィックはこのような幾何学模様になります。この 2x4 の単位で 80文字×25行並ぶ事で、グラフィックとして描画するというわけです。
- 任意の画像をデータ化する
横16ドットですから、横に8キャラとなります。縦は 12ドットですので、3行分となります。合わせて 24バイトのデータ列となります。左上から右下に向かって、順次走査してデータ化してみます。赤枠で示した左上は…
0xC0 ですね。このまま変換していくと以下のデータが得られます。
□□ => b0,b4 => 0,0 => 11000000 => 0xC0
□□ b1,b5 0,0
□■ b2,b6 0,1
□■ b3,b7 0,1
これが本当に変換元の文字となって表示されるのか、N-BASIC から試してみます。
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,
無事、表示されました。マシン語でも同様に処理すれば、そのままセミグラフィックの文字として、画面に表示されます。画面の初期化はこちらで説明した 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# のソースと、ドラッグするだけで変換する簡単なツールをこちらから受け取れるようにしておきました。宜しければお使いください。
// セミグラフィックドットオフセット
// -------------------------------------------------------------
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();
}
コメント