Display

漢字console

前々囘だったか、コンソールの機能を調べている時、FreeBSDのコンソールが国際化された事を知った。それって、漢字ROMに相当するフォントを設定すれば日本語を表示出来るよって事だねぇ。

かの昔、FM-11と言うパソコンを使ってた。日本語は貧弱なカタカナしか表示出来無いやつ。で、うん万円だか出して漢字ROMを装着すると、漢字が表示出来る。指を咥えてパソコンショップの前をうろうろしてたなあ。

現代なら無料で出来るはず。少し調べてみた。

フォントと FreeBSD

第3章 UNIX の基礎知識

Newcons とか newcons and CJK fonts

日本語BDFフォントを変換してFreeBSD 10.xのvt(4)コンソールで使う

こんな資料が出てきたぞ。肝心のROMは Index of ~emaste/newcons から b16.fnt を頂いてきて /usr/share/vt/fonts に装着すればよいらしい。まだ正式版数は出ていないからアングラ版だけど。

そして、下記でそのフォントを使うぜいって指示を出す。

# /usr/sbin/vidcontrol -f b16.fnt

いうまでもないけど、使えるのは指定した仮想コンソールのみだ。別の仮想コンソールに切り換えてしまうと、有効にはなっていない。何処でも漢字にしたかったら、 /etc/rc.conf に指定しておくと良いらしい。

font8x16="b16.fnt"
kldload vesa
kldload: can't load vesa: module already loaded or in kernel
vidcontrol -i mode
    mode#     flags   type    size       font      window      linear buffer
------------------------------------------------------------------------------

上の説明では、vesaをロードした後、vidcontrolすると、使えるモードが出てくるらしいんだけど、無しのつぶて。

VGA

で、気が付くと、コンソールの表示系については知識が全くない。前回はキーボードをやったので、今度は表示系。何の根拠も無いけど(qemuのdisplayを三田時、CRTコントローラの代わりにVGAが鎮座してたって野生の勘)調べてみる。 VGA Function

ThinkpadでFreeBSDを起動した時のデバイス探査の結果

[sakae@fb ~]$ dmesg | grep VGA
vtvga0: <VT VGA driver>
vgapci0: <VGA-compatible display> port 0x1800-0x1807 mem 0xf2400000-0xf27fffff,0xd0000000-0xdfffffff irq 16 at device 2.0 on pci0
agp0: <Intel GM45 SVGA controller> on vgapci0
vgapci1: <VGA-compatible display> mem 0xf2100000-0xf21fffff at device 2.1 on pci0

こんな風になってて、この状態でコンソールが漢字を表示してくれたから、VGAが表示器って事は確定だな。

詳しい事は、vga(4), vgl(3) だな。

[sakae@fb ~]$ sysctl -a | grep vga
VT(vga): resolution 640x480
machdep.vga_aspect_scale: 100
dev.vgapci.0.%pnpinfo: vendor=0x8086 device=0x2a42 subvendor=0x17aa subdevice=0x213a class=0x030000

vendorが8086ってのは、ごり押しで取得したナンバープレートみたいなもので、勿論それはインテルさんを表している。

何処に、ドライバーが有るか探してみる。

sakae@fbox:/sys/dev $ grep GM45 -rIl .
./drm2/drm_pciids.h
./agp/agp_i810.c

wsconsctl

そういう時は、OpenBSDで確認。と言っても全く同じコマンドが有るわけではないので、類似品で確認してみる。

ob$ doas wsconsctl -a
  :
display.type=vga-pci
display.fontwidth=8
display.fontheight=16
display.emulations=vt100
display.screentypes=80x25,80x25bf,80x40,80x40bf,80x50,80x50bf
 :

そうだよな、こういうのが出てきて欲かった。

frame buffer

取り敢えず、漢字コンソールでw3mが使えるようになったんで、これってX無しだよなとプチ感激してるんだけど、Xに有ったスクリーンセーバーはコンソール版にはないかな? かすかな記憶を辿って、見つけ出したドライバー。 splash(4)

Screen saver
     daemon_saver.ko   Animated BSD Daemon screen saver.
     dragon_saver.ko   Draws a random dragon curve.

     Screen saver modules can be loaded using kldload(8):
           kldload logo_saver
     The timeout value in seconds can be specified as follows:
           vidcontrol -t N

指示通りにやってみたけど、動かない。大体どこに入ってる? 例えば、こんな所に有った。ひょっとしてscじゃないと動かない? 野生の勘が冴えてる。vtでは、まだサポートされていないってさ。 /sys/dev/syscons/daemon/daemon_saver.c

static u_char *daemon_pic[] = {
        "             ,        ,",
        "            /(        )`",
        "            \\ \\___   / |",
        "            /- _  `-/  '",
        "           (/\\/ \\ \\   /\\",
        "           / /   | `    \\",
        "           O O   ) /    |",
        "           `-^--'`<     '",
        "          (_.)  _  )   /",
        "           `.___/`    /",
        "             `-----' /",
        "<----.     __ / __   \\",
        "<----|====O)))==) \\) /====",
        "<----'    `--' `.__,' \\",
        "             |        |",
        "              \\       /       /\\",
        "         ______( (_  / \\______/",
        "       ,'  ,-----'   |",
        "       `--{__________)",
        NULL
};

だったら、古い奴に切り換えてみよう。切り換えはsysctlじゃ出来無くてて、起動時に設定だ。

sakae@fbox:~ $ cat /boot/loader.conf
kern.vty=sc

後は任意なタイミングで

kldload daemon_saver
vidcontrol -t 600

とかやると、10分何もしなければ、ダエモン君が動き出す。右から左へ、左の壁にぶつかると向きを反転してジャンプしながら動く。ついでに、ホスト名とuname -or 相当の案内がフローティングで表示されたよ。これは楽しい。

vidcontrol -i mode
    mode#     flags   type    size       font      window      linear buffer
------------------------------------------------------------------------------
 24 (0x018) 0x00000021 T 80x25           8x16  0xb8000 32k 32k 0x00000000 32k
 30 (0x01e) 0x00000021 T 80x50           8x8   0xb8000 32k 32k 0x00000000 32k
256 (0x100) 0x0000000f G 640x400x8 P     8x16  0xa0000 64k 64k 0xe0000000 250k
257 (0x101) 0x0000000f G 640x480x8 P     8x16  0xa0000 64k 64k 0xe0000000 300k
258 (0x102) 0x0000000b G 800x600x4 4     8x16  0xa0000 64k 64k 0x00000000 234k
  :
330 (0x14a) 0x0000000f G 1152x864x16 D   8x16  0xa0000 64k 64k 0xe0000000 1944k
331 (0x14b) 0x0000000f G 1152x864x24 D   8x16  0xa0000 64k 64k 0xe0000000 2916k
332 (0x14c) 0x0000000f G 1152x864x32 D   8x16  0xa0000 64k 64k 0xe0000000 3888k

vtの時には動かなかった、モード表示が出来るようになった。

vidcontrol MODE_279

とかやると、1024x768x16の設定になる。

vidcontrol -i adapter
fb0:
    vga0, type:VESA VGA (5), flags:0x2700ff
    initial mode:24, current mode:24, BIOS mode:3
    frame buffer window:0xb8000, buffer size:0x8000
    window size:0x8000, origin:0x0
    display start address (0, 0), scan line width:80
    reserved:0x0

これも、前回やったminixの時に出て来た、CRTコントローラに似た説明だなあ。

今度はコンソールの画面ダンプをやってみる。-pは、アトリビュートも付いたフルダンプ。-Pの方は、テキスト情報だけのダンプ。

root@fbox:/tmp # vidcontrol -p < /dev/ttyv0 >ZZZ
root@fbox:/tmp # vidcontrol -P < /dev/ttyv0 > YYY
sakae@fbox:/tmp $ hd ZZZ|head -4
00000000  53 43 52 53 48 4f 54 5f  01 02 50 19 72 07 6f 07  |SCRSHOT_..P.r.o.|
00000010  6f 07 74 07 40 07 66 07  62 07 6f 07 78 07 3a 07  |o.t.@.f.b.o.x.:.|
00000020  2f 07 74 07 6d 07 70 07  20 07 23 07 20 07 76 07  |/.t.m.p. .#. .v.|
00000030  69 07 64 07 63 07 6f 07  6e 07 74 07 72 07 6f 07  |i.d.c.o.n.t.r.o.|

SCRSHOT_ と言うヘッダーに続いて、スクリーンの内容、root@fvox:/tmp # vidcontroっていう文字列が伺える。アトリビュートの解説は、vidcontrolに載っていて、概要は、

The vidcontrol output contains a small header which includes additional
information which may be useful to utilities processing the output.

The first 10 bytes are always arranged as follows:

      Byte Range    Contents
      1 - 8         Literal text “SCRSHOT_”
      9             File format version number
      10            Remaining number of bytes in the header

Subsequent bytes depend on the version number.

      Version    Byte         Meaning
      1          11           Terminal width, in characters
                 12           Terminal depth, in characters
                 13 and up    The snapshot data

The VGA color attribute byte looks like this:

bits#                width    meaning
7      <X0000000>    1        character blinking
6:4    <0XXX0000>    3        background color
3      <0000X000>    1        bright foreground color
2:0    <00000XXX>    3        foreground color

Here is a list of the three bit wide base colors:

      0       Black
      1       Blue
      2       Green
      3       Cyan
      4       Red
      5       Magenta
      6       Brown
      7       Light Grey

これを読み取ると、forgroundは、普通の明るい灰色なんて事が分る。 尚、-Hを付けると、tmuxのヒストリー参照宜しく、過去に遡って、画面の内容を確認出来る。

                                                 /                          /
    Options:                                     .-                        -.
    6. Kernel: default/kernel (1 of 2)            --                      -.
    7. Boot Options                                `:`                  `:`
                                                     .--             `--.
                                                        .---.....----.

   Autoboot in 0 seconds. [Space] to pause

Loading kernel...
/boot/kernel/kernel text=0xfc084 text=0xb391e0 text=0x5b5110 data=0xb0 data=0x10

9290+0x2d5540 syms=[0x4+0xe91c0+0x4+0x17caac]
Loading configured modules...
/etc/hostid size=0x25
/boot/entropy size=0x1000
---<<BOOT>>---
Copyright (c) 1992-2021 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
        The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 13.1-RELEASE-p2 GENERIC i386
 :

こんな起動時のサーと流れてしまう部分も、記録してたぞ。

/sys/dev/syscons/sctermvar.h

static __inline void
sc_term_up(scr_stat *scp, int n, int head)
{
        if (n < 1)
                n = 1;
        n = imin(n, scp->ypos - head);
        if (n <= 0)
                return;
        sc_move_cursor(scp, scp->xpos, scp->ypos - n);
}

ヘッダーファイルと侮るなかれ、minixの時に魅た画面制御と同様のコードが出てきた。

GUI の無い環境での画像表示

Days of WINE and Struggles again[1] やっぱり、表示って事で捉えると、コンソールもXも陸続きになってるんだなあ。ってな事で、Xの環境をログでチェックしてみる。

/var/log/Xorg.0.log

[   537.520] (II) Loading /usr/local/lib/xorg/modules/extensions/libglx.so
[   537.664] (II) Loading /usr/local/lib/xorg/modules/drivers/modesetting_drv.so
[   537.670] (II) Loading /usr/local/lib/xorg/modules/drivers/scfb_drv.so
[   537.681] (II) Loading /usr/local/lib/xorg/modules/drivers/vesa_drv.so
[   537.712] (II) Loading /usr/local/lib/xorg/modules/libvbe.so
[   537.726] (II) Loading /usr/local/lib/xorg/modules/libint10.so
[   537.871] (II) Loading /usr/local/lib/xorg/modules/libshadow.so
[   537.872] (II) Loading /usr/local/lib/xorg/modules/libfb.so
[   537.899] (II) Loading /usr/local/lib/xorg/modules/libint10.so
[   541.552] (II) Loading /usr/local/lib/xorg/modules/input/libinput_drv.so
[   542.414] (II) Loading /usr/local/lib/xorg/modules/input/synaptics_drv.so

インテル入ってるなんだけど、使われていない。 lib/xorg/modules/drivers/intel_drv.so が足りない気がする。xf86-video-intelを入れればいいのかな? 今更だけど。

入れたらちゃんと使ってくれた。アスペクト比が正しくなったぞ。vesaだと、横に長い間延びした表示だったけど、今度はキリリとした表示になった。

Linuxでは、どうかと思って調べてみたら、vesaを使ってた。そんなんで委員会。

daemon

ダエモン君が元気よく跳ね回っているので、その活動環境を調べてみる。

前述したようにFreeBSDでのコンソールは2系統有る。元々有ったのは、scと呼ばれるやつ。日本語とかは知りませんと言う欧米向け。それじゃあんまりだってんで、utfをサポートしたvtというのが新に開発された。このおかげで漢字ROMを装着すれば、日本語OKっとなった。 デフォでは、vtに設定されてる。けど、完全にscの機能を引き継いだ訳ではない。 ダエモン君の躍動を感じたかったら、scに切り換えると言う屈辱がまっている。

vt or not vt, that is the question.

で、どこでその切り換えが行われる? 答は、 /sys/kern/kern_cons.c

/*
 * Temporary support for sc(4) to vt(4) transition.
 */
static unsigned vty_prefer;
static char vty_name[16];
SYSCTL_STRING(_kern, OID_AUTO, vty, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, vty_name,
    0, "Console vty driver");

int
vty_enabled(unsigned vty)
{
        static unsigned vty_selected = 0;

        if (vty_selected == 0) {
                TUNABLE_STR_FETCH("kern.vty", vty_name, sizeof(vty_name));
                do {
#if defined(DEV_SC)
                        if (strcmp(vty_name, "sc") == 0) {
                                vty_selected = VTY_SC;
                                break;
                        }
#endif
#if defined(DEV_VT)
                        if (strcmp(vty_name, "vt") == 0) {
                                vty_selected = VTY_VT;
                                break;
                        }
#endif

こんな注意書きが付いて、コードが掲載されてた。開発者が忙しくて、余分な機能はまだ実装されていない。んなもんだから、昔のコードも使えるようになってんだね。

How to show daemon

表示されるダエモン君は、赤が基調で、目玉や足が青、フォークの部分は黄色だったりする。ああ、forkがさりげなく出てきたけど、これってUNIXの大事な特徴だね。普通はフォークとナイフだけど、unixの場合は、forkとexecveが超大事なシステムコールだ。これ無しでは、1日としてならず。

上であげた、/* Who is the author of this ASCII pic? */ な、ダエモン君の御姿の他に

static u_char *daemon_attr[] = {
        "             R        R",
        "            RR        RR",
        "            R RRRR   R R",
        "            RR W  RRR  R",
        "           RWWW W R   RR",
        "           W W   W R    R",
        "           B B   W R    R",
        "           WWWWWWRR     R",
        "          RRRR  R  R   R",
        "           RRRRRRR    R",
        "             RRRRRRR R",
        "YYYYYY     RR R RR   R",
        "YYYYYYYYYYRRRRYYR RR RYYYY",
        "YYYYYY    RRRR RRRRRR R",
        "             R        R",
        "              R       R       RR",
        "         CCCCCCR RR  R RRRRRRRR",
        "       CC  CCCCCCC   C",
        "       CCCCCCCCCCCCCCC",
        NULL
};

こんな、色使いの指示書が付属してる。フォークの部分は黄色って理解してくれって事。

実際に描画してる部分は、こうなっている。

static void
draw_daemon(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
            int xlen, int ylen)
{
                          :
                        switch (daemon_attr[y][px]) {
                        case 'R': attr = FG_LIGHTRED | BG_BLACK; break;
                        case 'Y': attr = FG_YELLOW | BG_BLACK; break;
                        case 'B': attr = FG_LIGHTBLUE | BG_BLACK; break;
                        case 'W': attr = FG_LIGHTGREY | BG_BLACK; break;
                        case 'C': attr = FG_CYAN | BG_BLACK; break;
                        default: attr = FG_WHITE | BG_BLACK; break;
                        }
                        if (dxdir < 0) {        /* Moving left */
                                sc_vtb_putc(&sc->cur_scp->scr,
                                            (ypos + y)*sc->cur_scp->xsize
                                                 + xpos + x,
                                            sc->scr_map[daemon_pic[y][px]],
                                            ATTR(attr));
                        } else {                /* Moving right */
                           :

ダエモン君のサイズは、結構巨大だ。この巨大な矩形が、表示枠の中を跳ね回る、バウンス・ボールごときのプログラムになってる。

#define DAEMON_MAX_WIDTH        32
#define DAEMON_MAX_HEIGHT       19

実際の描画は、scvtb.c

void
sc_vtb_putc(sc_vtb_t *vtb, int at, int c, int a)
{
        if (vtb->vtb_type == VTB_FRAMEBUFFER)
                writew(sc_vtb_pointer(vtb, at), a | c);
        else
                *(u_int16_t *)sc_vtb_pointer(vtb, at) = a | c;
}

vm_offset_t
sc_vtb_pointer(sc_vtb_t *vtb, int at)
{
        return (vtb->vtb_buffer + sizeof(u_int16_t)*(at));
}

フレームバッファーエリアへの書込みが行われる。

待て

お座りじゃ、ポチへの指示になっちゃうけど、ダエモン君が舞台へ登場する待ち時間は、どうやってる? いわゆるタイム・キーパーの事ね。

vidconrolコマンドの該当部分

static void
set_screensaver_timeout(char *arg)
                :
                nsec = atoi(arg);
                 :
        if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) {

今気が付いたんだけど、ioctlの第一引数は全てZEROだなあ。標準入力に対しての設定って事か。中には明かに標準出力系もあるのになあ。面倒くさい疑惑があるぞ。まあ、心情としては、オイラーもそうするだろうね。

syscons.c

#define DEFAULT_BLANKTIME (5 * 60) /* 5 minutes */
#define MAX_BLANKTIME (7 * 24 * 60 * 60) /* 7 days!? */

static int
sctty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
{
           :
        switch (cmd) { /* process console hardware related ioctl's */
           :
        case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */
                if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME)
                        return EINVAL;
                s = spltty();
                scrn_blank_time = *(int *)data;
                run_scrn_saver = (scrn_blank_time != 0);
                splx(s);
                return 0;

最長7日まで設定出来るって十分過ぎるな。


This year's Index

Home