OS学習メモ11(30日OS自作入門11日)
やっていきましょう。
スタートはここから。
11日目から pic.twitter.com/md94FLc9sU
— Yamahiro (@ymhr_s) 2018年6月8日
ご覧の有様です。
右端に行ったら変な動きをしているので、画面外に出てしまった時には値を補正するようにします。このくらいであれば本を読まなくても自分で直せました。 そんなに大きな変更も加えてないのでプログラムは省略します。
次に「shtctlの指定を省略する」ということをやります。難しいことは特になくて(前回作ったsheet_updown関数を見てもらえればわかるんですけど)下敷きを上げ下げするために毎回ctlを指定しているのが面倒くさいからそれを改良しようというだけのことです。
(久しぶりなので前回作ったsheet_updown関数を簡単におさらいしておくと、この関数はまず引数として「SHTCTL型の*ctl」「SHEET型の*sht (高さを変更したい下敷きの情報)」「int型のheight(変更後の下敷きの高さ)」の3つを受け取ります。受け取ったheightによって、ctlの情報をどんどん書き換えて行くことで下敷きの高さ関係を変更していくというのが、このsheet_updown関数でした。)
SHEET構造体の中にSHTCTL型の構造体を追加して、sheet_updownやらshtctl_unitやら関係するところを書き換えていくだけです。詳しい説明は省略しますね。
struct SHEET { unsigned char *buf; int bxsize, bysize, vx0, vy0, col_inv, height, flags; struct SHTCTL *ctl; };
void sheet_updown(struct SHEET *sht, int height) { struct SHTCTL *ctl = sht->ctl; int h, old = sht->height; /*略*/ for (h = old; h > height; h--) { ctl->sheets[h]=ctl->sheets[h - 1]; //こんな感じで使ってます ctl->sheets[h]->height = h; } ctl->sheets[height] = sht; /*略*/ }
引数の数が3つ→2つになったり、プログラムがちょびっとコンパクトになりました。
さてここからが本当の11日目という所でしょう。ウィンドウを出していきます。…とは言っても、すでに土台は出来上がっているのでそれらを駆使するだけです。プログラムはコピペさせてください。
init_palette(); shtctl = shtctl_init(memman, binfo->vram, binfo->scrnx, binfo->scrny); sht_back = sheet_alloc(shtctl); sht_mouse = sheet_alloc(shtctl); sht_win = sheet_alloc(shtctl); buf_back = (unsigned char *) memman_alloc_4k(memman, binfo->scrnx * binfo->scrny); buf_win = (unsigned char *) memman_alloc_4k(memman, 160 * 68); sheet_setbuf(sht_back, buf_back, binfo->scrnx, binfo->scrny, -1); sheet_setbuf(sht_mouse, buf_mouse, 16, 16, 99); sheet_setbuf(sht_win, buf_win, 160, 68, -1); init_screen8(buf_back, binfo->scrnx, binfo->scrny); init_mouse_cursor8(buf_mouse, 99); make_window8(buf_win, 160, 68, "window"); putfonts8_asc(buf_win, 160, 24, 28, COL8_000000, "Welcome to"); putfonts8_asc(buf_win, 160, 24, 44, COL8_000000, " Haribote-OS!"); sheet_slide(sht_back, 0, 0); mx = (binfo->scrnx - 16) ; my = (binfo->scrny - 28 - 16) / 2; sheet_slide(sht_mouse, mx, my); sheet_slide(sht_win, 80, 72); sheet_updown(sht_back, 0); sheet_updown(sht_mouse, 1); sheet_updown(sht_win, 2); sprintf(s, "(%3d, %3d)", mx, my); putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s); sprintf(s, "memory %dMB free : %dKB", memtotal / (1024 * 1024), memman_total(memman) / 1024); putfonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s); sheet_refresh(sht_back, 0, 0, binfo->scrnx, 48);
特に理由は無いんですけど、なんとなくsheet_updown関数が好きです。
実行結果↓
ここまで順調にやってこれました。次はカウンタを作ります。その名の通り0から数を数えていうというもので、ループの中でsheet_refreshとカウントを行います。文字が出力できるのだから、当然こういうこともできるよなぁという感じですね。
unsigned int memtotal, count = 0; for (;;) { count+=20000; sprintf(s, "%010d", count); boxfill8(buf_win, 160, COL8_C6C6C6, 40, 28, 119, 43); putfonts8_asc(buf_win, 160, 40, 28, COL8_000000, s); sheet_refresh(sht_win, 40, 28, 120, 44); }
で、動かしてみると
チラチラチラチラしてる。 pic.twitter.com/JgzGlkeSUq
— Yamahiro (@ymhr_s) 2018年6月8日
書き換える必要のない背景の下敷きまで書き換えてるからこういったことが起きてしまってます。というわけで、必要な部分だけ書き換えるように書き換えたものがこれです。高さを指定してます。
void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0) { /*略*/ for (h = h0; h <= ctl->top; h++) { /*略*/ } return; }
動画は載せませんが、さっきみたいにカウントする度にちらちらする現象は直りました。が、これでもまだ不十分で、カウントのところにマウスをもっていくとマウスがちらちらしてしまいます。マウスまで一緒に描いて消してを繰り返しているのが原因なので、これを直すためにはウィンドウを描画する際にマウスカーソル部分を避けて描き込むしかありません。
一応自分でも解決方法を数分考えてみたのですが、どうにも思いつかないので本に沿ってやっていくことに。今回は”map”を使う方法です。言葉でうまく説明できませんが下の図が全てです。
例えば図中で一番下の下敷きをリフレッシュするなら、右側で”1”になっているところだけを書き変えればいい(2の所まで書き直す必要はない)というわけです。これを使ってマウスカーソルの所を避けて画面をリフレッシュしようというわけですね。
...と、いうのが仕組みの話で….ここまではわかったのですが…、正直、実装の所はコードを読んで考えても良くわかりませんでした。この本、後になって読み返したらすっと分かるとかよくあるのでちょっとこの辺り一旦スキップしようと思います。というわけで半端ですがここまで。