30日OS自作本10日目
10日目はGUIの改善を行いました。これにより、下のバーをマウスが破壊する現象がなくなりました。
day9までのGUIの課題
- マウスを描画する範囲に正方形の影が出来てダサい
- 再描画を明示しない部分はマウスカーソルが通ったあと描画内容が消える
などの課題がありましが、10日目の内容で以下の機能を付け足します。
- 透明
- 画面要素のレイヤー(高さ)
この2つを組み合わせたシートという概念で実現します。
struct SHEET { unsigned char *buf; int bxsize, bysize, vx0, vy0, col_inv, height, flags; };
- bxsize,bysize = シートのサイズ
- vx0,vy0 = シートの座標
- col_inv = 透明色番号
- flags = 制御用の情報
という感じです。ちょっと変数名がわかりにくい気がしますがこの辺は慣れでしょう。
次にシートを管理する構造体です
#define MAX_SHEETS 256 struct SHTCTL { unsigned char *vram; int xsize, ysize, top; struct SHEET *sheets[MAX_SHEETS]; struct SHEET sheets0[MAX_SHEETS]; };
- vram = vramのアドレス
- xsize,ysize = vramの画面サイズ
こちらはBOOTINFOに入っているものをそのまま保持して使います。
気になるのがSHEETの
- ポインタの配列(sheets)
- 構造体の配列(sheets0)
の2種があることだと思いますが、 これはsheetsは高さでソートしたシートのオブジェクトの参照を持たせ、sheets0は特に高さの順番を意識せずに使うようです。
画面再描画の方法
マウスの情報を表示している画面2行目を書き換える処理です。
//sの内容は`[lcr 0000 0000]`こんな感じ。 sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y); -(略)- //sを背景(buf_backに書き込む) putfonts8_asc(buf_back, binfo->scrnx, 32, 16, COL8_FFFFFF, s); //sを書き込んだ後の背景(buf_back)を再描画 sheet_refresh(shtctl, sht_back, 32, 16, 32 + 15 * 8, 32);
[lcr %4d %4d]
%4dは幅を揃える記述になるので最終的に以下のような形式になります[lcr 0000 0000]
前日のやった通り、文字は16×8ピクセルで表現しているため、再描画が必要となる範囲は縦16ピクセル,横120ピクセル(8ピクセル×15文字)となります。
結果的に上記のコードは15文字 × 8ピクセル分の横幅、16文字文の縦幅を書き換えるようなコードになります。
画面描画の改善
思いつきで作った最初のバージョン(harib07b)はマウスを動かすたびに画面全体が再描画しているので、この部分の処理を段階的に改善します またまた動画を撮ってみました。
- 1.画面全体の再描画(harib07b)
- 2.シートの指定範囲のみ書き換え(harib07c)
- 3.描画時のfor文が指定範囲内のみになるよう改善(harib07d)
2.ではシートの再描画位置をせっかく指定しているのに、描画時にシートの全範囲に、描画必要の有無の条件判定を行なっているので無駄。 ということで3で描画時の範囲指定を指定範囲のみになるようリファクタリングしたという改善を行なっている。
相対位置と絶対位置の変換などをなんどもやっているため ここのコードが少し読みにくく、ちょっと混乱しました。
- bx,byの先頭のbは多分bufferを表していて、シート上の座標になります
- vx,vyの先頭のvはvramを表していて、VRAM上の座標になります
- bxn,bynはシート状のどの地点書き換えるかを外部から与える変数になります。(起点はvramではなくシートです)
vxが絶対座標、bxが相対座標のようになっている、と気をつけて読めばそこまで難しいソースではなかったのかもしれません。
ちなみに動画をご覧いただければわかりますが、パフォーマンスの改善前後の画面描画がそこまで変わらないので、いまいちこの恩恵を感じられません。 本書発売時のハードウェアスペックだと改善の実感を得られたのでしょうか。ハードウェアの進化ってすげーってことなんでしょうか(笑)
感想
そういえば、大学時代iOSのアプリを作っていたのですが*1、iOSでは画面の原点が左上にあることを思い出しました。これが何かと食い違ってて、凄く違和感を持ってやってた思い出があります。hariboteOSも原点左上でしたね。こういうのって標準的な考え方とかあるのかな。
https://qiita.com/wheel/items/a26f7cb1464aff60940a
*1:リリースはしてない