25日目の内容になります。
この章でコンソールを増やします。
Beep
12日目にBeepを試そうとしていましたが、なんと本章に動くプログラムが書かれていました。 QEMUだと鳴らないようです(笑)
色数増加 16 → 232
graphic.cに16色のRGBと色番号の対応付けがしてある配列がハードコードされていますが、これを増やします。
static unsigned char table_rgb[16 * 3] = { 0x00, 0x00, 0x00, /* 0:黒 */ 0xff, 0x00, 0x00, /* 1:明るい赤 */ 0x00, 0xff, 0x00, /* 2:明るい緑 */ ・・・(省略)・・・ 0x84, 0x84, 0x84 /* 15:暗い灰色 */ };
今回追加する色の配列を作成しているプログラムの一部を抜き出して色番号とRGBの対応を画面に出して見ました。
#include <stdio.h> int main(void){ unsigned char table2[216 * 3]; int r, g, b; int i=0; for (b = 0; b < 6; b++) { for (g = 0; g < 6; g++) { for (r = 0; r < 6; r++) { table2[(r + g * 6 + b * 36) * 3 + 0] = r * 51; table2[(r + g * 6 + b * 36) * 3 + 1] = g * 51; table2[(r + g * 6 + b * 36) * 3 + 2] = b * 51; printf("%d\tr=%d\tg=%d\tb=%d\t:\t%d\t%d\t%d\n",i,r,g,b,r * 51,g * 51,b * 51); i++; } } } }
結果
0 r=0 g=0 b=0 : 0 0 0 1 r=1 g=0 b=0 : 51 0 0 2 r=2 g=0 b=0 : 102 0 0 ・・・(中略)・・・ 121 r=1 g=2 b=3 : 51 102 153 ・・・(中略)・・・ 215 r=5 g=5 b=5 : 255 255 255
これをビデオDAコンバータのパレットに追加しています。 復習ですが色は特定のレジスタではなく、ハードウェア(ビデオDAコンバータ)に持っているんですね。 4日目に色の登録に使ったコードを再度利用します。
void set_palette(int start, int end, unsigned char *rgb) { int i, eflags; eflags = io_load_eflags(); /* 割り込み許可フラグの値を記録する */ io_cli(); /* 許可フラグを0にして割り込み禁止にする */ io_out8(0x03c8, start); for (i = start; i <= end; i++) { io_out8(0x03c9, rgb[0] / 4); io_out8(0x03c9, rgb[1] / 4); io_out8(0x03c9, rgb[2] / 4); rgb += 3; } io_store_eflags(eflags); /* 割り込み許可フラグを元に戻す */ return; }
0x3c8
:パレット番号0x3c9
:RGB(色のデータ)
ここにどかっと作った216色分のデータが入った配列を突っ込みます。
set_palette(0, 15, table_rgb); //今まで使っていた色のやつ ・・・(中略(table2を作る処理))・・・ set_palette(16, 231, table2); //今回追加する配列分
36色しか出していないようでしたので、自分で改造して全色(232色)出して見ました。
void HariMain(void) { char *buf; int win, x, y, r, g, b; api_initmalloc(); int box_size = 8; //色のボックのサイズ(px) int box_amt_x = 32; //色のボックスを水平に何個置くか int box_amt_y = 8; //色のボックスを縦に何個置くか int content_x = box_size * box_amt_x; int content_y = box_size * box_amt_y; int win_bar_height = 20; //バーの高さ int padding = 8; //コンテンツの余白 int bar_space = win_bar_height + padding; //コンテンツの描画が始まる高さ int win_x_siz = 256 + padding *2; int win_y_siz = content_y + win_bar_height + padding * 2; buf = api_malloc(win_x_siz * win_y_siz); win = api_openwin(buf, win_x_siz, win_y_siz, -1, "color"); for(y = 0; y < content_y; y++){ for(x = 0; x < content_x; x++){ buf[(x + padding) + (y + bar_space) * win_x_siz ] = (x / box_size) +(y / box_size) * box_amt_x; } } api_refreshwin(win, padding,bar_space , content_x+padding,content_y+bar_space); api_getkey(1); api_end(); }
32列 * 8行=256色で出して見ました。 当然232色しか登録してないので、登録していない残りの24色はありません。
何も設定せず表示したところ、233色以降、変な色?が出たのでgraphic.cを改造して赤色で埋めて見ました。
一行目左端から16個分は昔に登録した色が出ています。
コンソールを増やす(2個にする)
コンソールを増やすというより、まず2個作ってみて問題のある箇所を探す、という感じでインクリメンタルに改修していきます。
diffツール
sdiffというコマンドでかなりわかりやすくソースの差分が見れます。 ちょっと色塗ってくれればwinmergeみたいに使えますね。
sdiffは-wオプションで表示幅を変更できるようですが、 ネストが深すぎて私のノートPCだと最高解像度でも収まりませんでした。
$ sdiff -l -w 240 -W ../harib22d/bootpack.c bootpack.c |nkf
- 使ってるオプション
- l:変更のない行は左ファイルのみ表示
- -w <数字>:一行あたりの文字数
- -W :空白の変更を無視
-lは変更有無がちょっと見にくいので抜いたほうがいいかもしれません。
他にもdiffツールを探して見たところvimdiffというものがあるようです(vimが使えるならこれが最強?)
再起動現象再現せず(harib22i)
harib22iの再起動現象が再現しませんでした。一応証拠動画(エビデンス(笑))みたいなの撮って見た。
感想
この章はさらなるGUI機能強化のためのリファクタリング + バグ回収という趣旨が強いと思います。 最初から綺麗に設計していないこともあり、ソースを弄るたびになんらかのバグが発生しますが、 あまり手がかりのない状態で的確にバグの原因を見つけて行っている印象があります。
うまくいかなくなった原因は書き足したり削除した部分のどこかにあると考えて、元に戻して見たりして探すのである。
だそうですがprint文デバッグであったり,Eclipseのデバッガのようなものがないと私には難しいです。 一般保護例外の表示を拡張しましたが、そもそもそれが出ずにOS自体がシャットダウンしてしまうこともよく起こります。