30日OS自作入門24日目(Win10)
はじめに
目次
ウィンドウの操作
ウィンドウの切り替え(1)(harib21a)
ウィンドウがいろいろ出せるようにはなったわけですが、一番上のウィンドウがアプリのものしか出せずにtask_aが見えないし、コンソールも見えずらいという状況です。それを解消するために、ウィンドウのレイヤーを入れ替えるコマンドを実装するようです。ここで、一瞬console.cをいじるかと思いましたが、console.cの内容でなく、HariMainの内容なのでbootpack.cですね(APIと勘違いしていた…)。
修正する箇所は、ほんと少なかったようです。
if (i == 256 + 0x57 && shtctl->top > 2) { /* F11+下敷きが2枚以上 */ sheet_updown(shtctl->sheets[1], shtctl->top - 1); /* arg1:背景の一個上の下敷き、arg2:マウスの一個下の下敷き */
これだけのようで、下敷きの枚数を確認してF11コマンドを受け入れた後、マウスと背景を除いた下敷きを操作しているようです。
実行してみると
30日自作OS本(harib21a)
— 猫(1010) (@Wagahaiha_toto) 2020年2月12日
これが2行の修正で済むのって、下地がしっかりしてるからなんだろうなぁ… pic.twitter.com/zPdmuYoX9x
ウィンドウの切り替え(2)(harib21b)
今度は、クリックで対応させるようです。仕組みは、マウスと重なっているかつ、透明ではない下敷きを探して、もし見つかればF11 と同じ処理を行うといった仕組みのようです。
if ((mdec.btn & 0x01) != 0) { /* 左ボタンを押していたら、sht_winを動かす */ /* 上の下じきから順番にマウスが指している下敷きを探す */ for (j = shtctl->top - 1; j > 0; j--) { sht = shtctl->sheets[j]; x = mx - sht->vx0; y = my - sht->vy0; if (0 <= x && x < sht->bxsize && 0 <= y && y < sht->bysize) { if (sht->buf[y * sht->bxsize + x] != sht->col_inv) { sheet_updown(sht, shtctl->top - 1); break; } } } }
実行すると
30日自作OS本(harib21b)
— 猫(1010) (@Wagahaiha_toto) 2020年2月12日
クリックでtask_aを動かす機能を失った代わりに、マウスでウィンドウのupdownができるようになった。自分はF11で操作する方が好きですね。 pic.twitter.com/icVUKvm9GH
ウィンドウの移動(harib21c)
今回は背景とマウス以外の下敷きをすべて移動できるようにしようといった感じのようです。
その際に、通常モードとウィンドウ移動モードの2種類のモードがあると考え、左クリックでモード移行をしています。その際に、フラグとして用いているのはmmxであり、マウスが画面外に行かないのを利用してフラグに兼用しているようです。
実行してみると
30日自作OS本(harib21c)
— 猫(1010) (@Wagahaiha_toto) 2020年2月12日
記録用の動画まちがえてたので… pic.twitter.com/deNeQqJ85h
ウィンドウをマウスで閉じる(harib21d)
「目の前に×ボタンがある…心が押せと叫んでいる!!!!」といったことに対応するようです(自分で考えておいて意味不明)
とりあえず、ウィンドウ移動のように×ボタンとマウスが重なっている場合に、クリックされたらウィンドウを閉じるようにするようです。
これだと、コンソールとtask_aは反応しないのですが、これはコンソールの強制終了と同じやり方でやっているから反応しないのだと思います。そもそもSHEET内のTASKはアプリケーションを制御するためのものだったはずなので…
実行すると
30日自作OS本(harib21d)
— 猫(1010) (@Wagahaiha_toto) 2020年2月12日
アプリだけXボタンで終了できるようになった。 pic.twitter.com/mmIdYoDSDe
アプリケーションの入力切り替え(harib21e)
実行すると
30日自作OS本(harib21e)
— 猫(1010) (@Wagahaiha_toto) 2020年2月12日
アプリもTabで選択可能になった。 pic.twitter.com/MBzLg9rYAp
入力ウィンドウをマウスで切り替える(harib21f)
修正したコードは以下のようで
if (sht != key_win) { /* クリックに入力切り替えの紐づけ */ cursor_c = keywin_off(key_win, sht_win, cursor_c, cursor_x); key_win = sht; cursor_c = keywin_on(key_win, sht_win, cursor_c); }
まず、選択前に点灯していたカーソルを消して、key_winにWindowの管理を渡し選択の青色を点灯させる処理
実行すると
30日自作OS本(harib21f)
— 猫(1010) (@Wagahaiha_toto) 2020年2月13日
クリックで選択できるようになった。でもF11だと変わらないから、今後出なかったら修正したいっすね。 pic.twitter.com/aeUVLsALCy
タイマAPI(harib21g)
タイマ関連のコードは
if (i >= 256) { /* キーボードデータ(タスクA経由) */ reg[7] = i - 256; return 0; /* 無限ループぬけ */ } } } else if (edx == 16) { /* タイマの取得 */ reg[7] = (int) timer_alloc(); } else if (edx == 17) { /* タイマの送信データ設定 */ timer_init((struct TIMER *) ebx, &task->fifo, eax + 256); } else if (edx == 18) { /* タイマの時間設定 */ timer_settime((struct TIMER *) ebx, eax); } else if (edx == 19) { /* タイマの解放 */ timer_free((struct TIMER *) ebx); } return 0; }
a_naskは
_api_alloctimer: ; int api_alloctimer(void); MOV EDX,16 INT 0x40 RET _api_inittimer: ; void api_inittimer(int timer, int data); PUSH EBX MOV EDX,17 MOV EBX,[ESP+ 8] ; timer MOV EAX,[ESP+12] ; data INT 0x40 POP EBX RET _api_settimer: ; void api_settimer(int timer, int time); PUSH EBX MOV EDX,18 MOV EBX,[ESP+ 8] ; timer MOV EAX,[ESP+12] ; time INT 0x40 POP EBX RET _api_freetimer: ; void api_freetimer(int timer); PUSH EBX MOV EDX,19 MOV EBX,[ESP+ 8] ; timer INT 0x40 POP EBX RET
noodle.cのコードは
void HariMain(void) { char *buf, s[12]; int win, timer, sec = 0, min = 0, hou = 0; api_initmalloc(); buf = api_malloc(150 * 50); win = api_openwin(buf, 150, 50, -1, "noodle"); timer = api_alloctimer(); api_inittimer(timer, 128); for (;;) { sprintf(s, "%5d:%02d:%02d", hou, min, sec); api_boxfilwin(win, 28, 27, 115, 41, 7 /* 白 */); api_putstrwin(win, 28, 27, 0 /* 黒 */, 11, s); api_settimer(timer, 100); /* 1秒間 */ if (api_getkey(1) != 128) { break; } sec++; if (sec == 60) { sec = 0; min++; if (min == 60) { min = 0; hou++; } } } api_end(); }
コードを見るほうがわかりやすいですね。
api_getkeyの512の制限を取っ払ったのは、キーデータ以外も受け取るようにしたからのようですね。api_getkeyというAPIはFIFOバッファから流れてきたデータを拾って、条件分岐に従って分類しているわけだからできる芸当ですね。
実行すると
30日自作OS本(harib21g)
— 猫(1010) (@Wagahaiha_toto) 2020年2月13日
パスタ麺やカップヌードルの時間計測に対応…ハラヘッタ pic.twitter.com/RE9Vulqp7b
タイマのキャンセル(harib21h)
Cという表示が遅れて表示されてしまっていた不具合を直すようです。
不具合の原因は、タスクにタイマがデータを送っていたわけなのです。しかし、アプリが終了した際にタスクに送るはずだったデータがタスクがないために、コンソールに送られるという不具合が発生していたようです。
実行すると
30日自作OS本(harib21h)
— 猫(1010) (@Wagahaiha_toto) 2020年2月13日
Cが出てた不具合が治った。 pic.twitter.com/TOBD7sw8em
メモ
・アプリケーションはコンソールの上で動いているので、コンソール上に操作が移っていないと使えない。
・struct SHEET *sht = 0;
はNULLポインタをしている
最後に
なんか、気力が出ずにから元気でやってしまった感があるので、今後コードを見直したいと思います。