-
Notifications
You must be signed in to change notification settings - Fork 2
Graphics
テキスト画面とは別に、640x400 ドットのグラフィック画面があります。 プレーンごとに分かれた VRAM へ直接書き込んで描きます。
グラフィック VRAM は 色の成分ごとに別のアドレスに分かれています(プレーン方式)。
| アドレス | プレーン |
|---|---|
0xA8000 |
青 |
0xB0000 |
赤 |
0xB8000 |
緑 |
0xE0000 |
輝度(16色モードのときだけ有効) |
- 1バイトが横8ドット、bit7 が左端です
- 1行は80バイト(80 × 8 = 640ドット)
- 1プレーンは32000バイト(80 × 400)
ある点のアドレスとビットはこう求まります。
オフセット = y * 80 + x / 8
ビット = 0x80 >> (x & 7)
同じ位置のビットを複数のプレーンで立てると、その組み合わせが色になります。 3プレーンすべてを立てれば白、青プレーンだけなら青、という具合です。
- グラフィック表示は既定で消えています。 VRAM に書いても、表示を開始するまで何も見えません。
-
既定は3プレーン(8色)です。
0xE0000(輝度)は 16色モードにしないと効きません。 16色モードにせずに0xE0000へ書いても、エラーは出ず、ただ何も起こりません。
グラフィック用の GDC にコマンドを送ります。
mov al, 0x0D
out 0xA2, al ; グラフィック表示を開始
...
mov al, 0x0C
out 0xA2, al ; グラフィック表示を終了16色を使うときは、あわせてモードを切り替えます。
mov al, 0x01
out 0x6A, al ; 16色モード青プレーンに1点打つ例です。
; AX=x, BX=y
plot:
push ax
push bx
push cx
push dx
push di
mov cx, ax
and cx, 7
mov dl, 0x80
shr dl, cl ; ビットマスク
push dx ; MUL は DX を壊すので退避しておく
mov cl, 3
shr ax, cl ; x / 8
mov di, ax
mov ax, bx
mov cx, 80
mul cx ; DX:AX = y * 80
add di, ax
pop dx ; ビットマスクを戻す
mov ax, 0xA800 ; 青プレーン
mov es, ax
or [es:di], dl
pop di
pop dx
pop cx
pop bx
pop ax
retMUL は DX を壊します。 ビットマスクを DL に置いたまま y * 80 を計算すると、
マスクが 0 になって 何も描かれません。アセンブルは通り、コードも一見正しく見えるので
気づきにくい失敗です。
画面を消すときは、各プレーンを 32000 バイトぶん 0 で埋めます。
16色モードでは、色番号ごとの実際の色をパレットで決められます。
| ポート | 意味 |
|---|---|
0xA8 |
これから設定する色番号 |
0xAA |
緑の強さ(0〜15) |
0xAC |
赤の強さ(0〜15) |
0xAE |
青の強さ(0〜15) |
色番号は、その点のプレーンの組み合わせです(青=1, 赤=2, 緑=4, 輝度=8 の合計)。
mov al, 1
out 0xA8, al ; 色番号1を設定する
mov al, 0x0F
out 0xAC, al ; 赤を最大に
xor al, al
out 0xAA, al
out 0xAE, al ; 緑と青は0 → 色番号1が赤になる強さは 0〜15 で、画面に出る明るさはこの値にほぼ比例します (実測では 4 で約 68、8 で約 137、15 で 255)。
プレーンごとに4回書き込む代わりに、1回の書き込みで4プレーンすべてに書ける ハードウェアの支援機能があります。塗りつぶしや画面消去が4倍速くなります。
| ポート | 意味 |
|---|---|
0x7C |
モード。bit7 を立てると有効 |
0x7E |
タイルレジスタ。4回続けて書くと 青→赤→緑→輝度 の順に入る |
mov al, 0x80
out 0x7C, al ; GRCG を有効にする
mov al, 0xFF ; 青プレーンに書く値
out 0x7E, al
mov al, 0xFF ; 赤
out 0x7E, al
xor al, al ; 緑
out 0x7E, al
out 0x7E, al ; 輝度
; ここで VRAM へ1バイト書くと、上のタイルどおりに4プレーンへ同時に書かれる
mov ax, 0xA800
mov es, ax
xor di, di
mov al, 0xFF
mov cx, 32000
rep stosb ; 画面全体が「青+赤」で塗られる
xor al, al
out 0x7C, al ; 使い終わったら必ず無効に戻す書き込み先はどのプレーンのアドレスでもかまいません。 有効にしている間は、 アドレスではなくタイルレジスタが行き先を決めます。
使い終わったら必ず無効に戻してください。 有効のままにすると、 以降の普通の VRAM 書き込みがすべてタイルどおりに化けます。
PC-98 には GRCG よりさらに高機能な EGC という描画支援機能があります。 ラスタオペレーション、シフト、ビット単位のマスクなどが使えるものです。
この環境では EGC を有効にできませんでした。
0x6A へ 0x07 → 0x05 を書いて有効化を試み、0x4A0〜0x4A9 の各レジスタを
設定したうえで書き込みましたが、演算とモードの組み合わせ12通りをすべて試しても
EGC を使わない普通の書き込みと同じ結果(1プレーンだけ書かれる)でした。
モード切替が「現在値と同じなら何もしない」形式であることを考慮して、
一度落としてから立て直す手順でも試しましたが、結果は同じでした。
原因は分かっていません。 GRCG は動作しているので描画支援の機能が まるごと無いわけではありません。
→ このページでは EGC の使い方は未確定です。 下の「未検証」を参照してください。
-
VRAM に書いたのに何も出ない。 グラフィック表示は既定で消えています。
OUT 0xA2, 0x0Dを忘れていないか確認してください。 -
輝度プレーン(
0xE0000)に書いても何も起きない。 16色モード (OUT 0x6A, 0x01)にしていないと効きません。エラーは出ません。 -
MULでビットマスクを壊す。DXが上書きされ、何も描かれなくなります。 - GRCG を有効にしたまま放置する。 その後の普通の書き込みが全部タイルどおりに化けます。
- 1行を64バイトや100バイトで計算する。 1行は 80バイトです。
現時点で確認できているものはありません。 ただし このページの測定はすべて np2kai 上で行っています。 実機での確認は行っていません。
- EGC の使い方全般(この環境で有効にできなかったため)
- GRCG の
0x7Cの bit7 以外のビット(動作モードの違い) - 表示ページと描画ページの切り替え
- 400ライン以外の解像度、および画面モードの切り替え全般
- パレットの読み出し、8色モードでのパレット設定
- テキスト画面との重ね合わせの優先順位
検証: 2026-08-24 / WebNP2 327d061 (np2kai) + FreeDOS(98) /
再現: guest/probes/GIO2.ASM(測定用のブリッジ), guest/probes/WIKIEX5.ASM(上の点を打つ例)
使用例は実行して、対角線上の (0,0) (50,50) (100,100) (150,150) (199,199) が点灯し、 線から外れた位置が消灯していることを確認しています。
テキスト画面
キーボード
グラフィック画面
時間と割り込み
BIOS / DOS
ディスク
サウンド
メモリ