マウス制御〜32ビット〜メモリ管理まで@自作OS入門
〜30日間でできる自作OS〜
8日目
- マウスの解読
- 関数化
- マウスの解読2
- マウスカーソルを動かす
- アセンブラの解説(32ビットモードへ)
9日目(序)
- ソースの整理
- メモリ容量チェック1
マウスの解読
マウスが有効化されると、1バイト(0xfa)が送信されます。
その後、マウスが移動すると3バイト(3ボタン+x移動量+y移動量)づつ送信されてくるので、
1バイトづつ読み込んで表示しました。
//mouse_phase = 1 マウス接続状態 //mouse_phase = 2 マウス状態取得 1バイト目 //mouse_phase = 3 マウス状態取得 2バイト目 //mouse_phase = 4 マウス状態取得 3バイト目 //i = バイト値 if (mouse_phase == 0) { /* マウスの0xfaを待っている段階 */ if (i == 0xfa) { mouse_phase = 1; } } else if (mouse_phase == 1) { /* マウスの1バイト目を待っている段階 */ mouse_dbuf[0] = i; mouse_phase = 2; } else if (mouse_phase == 2) { /* マウスの2バイト目を待っている段階 */ mouse_dbuf[1] = i; mouse_phase = 3; } else if (mouse_phase == 3) { /* マウスの3バイト目を待っている段階 */ mouse_dbuf[2] = i; mouse_phase = 1;//状態を1バイト目取得状態へ戻す /* データが3バイト揃ったので表示 */ sprintf(s, "%02X %02X %02X", mouse_dbuf[0], mouse_dbuf[1], mouse_dbuf[2]); boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 8 * 8 - 1, 31); putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s); }
関数化
上のロジックを関数化しました。同時にマウス状態を構造化しました。
//buf[0]=マウス状態1バイト目 //buf[1]=マウス状態2バイト目 //buf[2]=マウス状態3バイト目 //phase = マウス状態取得状態 struct MOUSE_DEC { unsigned char buf[3], phase; }; int mouse_decode(struct MOUSE_DEC*, unsigned char);//関数化 int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat){ 〜処理〜 }
関数化のところ"MOUSE_DEC*"の"*"を忘れて若干ハマりました。
マウスの解読2
まず、バイトチェックを入れました。
if((dat & 0xc8) == 0x08){ 〜マウス〜 }
1バイト目をチェックしています。
0xc8で上位4ビットが0〜3(マウス移動方向=0〜3が割り当てられる)
0xc8で下位4ビットが8〜F(マウスボタン=8〜Fが割り当てられる)
の範囲内かどうかチェックしています。それ以外の値の場合は、読み捨てます。
(つまり、上位2ビットが0で、上位から5ビット目が1あることをチェックしています。)
あと、ボタンと移動値をわかりやすくしました。
今までの"[A9 FF 00]"などの表記から"[lcr -1 2]"などの表記になりました。
"lcr"はボタンに対応していて、押したボタンによって大文字になります。
右ボタンだけ押すと"lcR"。
マウスでは、移動量の符号が反対なのだそうです。
mdec->y = -mdec->y;
マウスカーソル動かす
前のプログラムで移動量を取得できたので、移動量から描画すべきマウスカーソルのx,y座標を算出。
既に描かれているマウスカーソルを消して、再描画するロジックです。
boxfill8(binfo->vram,binfo->scrnx,COL8_008484,mx,my,mx+15,my+15);//マウス消 す mx += mdec.x;//X移動量を足しこむ my += mdec.y;//Y移動量を足しこむ putblock8_8(binfo->vram,binfo->scrnx,16,16,mx,my,mcursor,16);//マウス描画
画面外へマウスカーソルがはみ出ないようにしました。
//画面外へはみ出ない if(mx < 0){ mx = 0; } if(my < 0){ my = 0; } if(mx > binfo->scrnx - 16){ mx = binfo->scrnx - 16; } if(my > binfo->scrny - 16){ my = binfo->scrny - 16; }
アセンブラの解説
説明されていないアセンブラ部分の説明がなされていました。
まず、画面モード切替直後のロジック。ここでは、PICとCPUの割り込みを禁止しています。
MOV AL,0xff OUT 0x21,AL ; マスターPICの割り込みを禁止 NOP ; OUT命令を連続させるとうまくいかない機種があるらしいので OUT 0xa1,AL ; スレーブPICの割り込みを禁止 CLI ; さらにCPUレベルでも割り込み禁止
キーボードコントローラーのおまけ出力ポート(0xd1)に(0xdf)を出力すると、1MB以上のメモリが使用できます。
CALL waitkbdout MOV AL,0xd1 OUT 0x64,AL CALL waitkbdout MOV AL,0xdf ; enable A20 OUT 0x60,AL CALL waitkbdout ; さらにCPUレベルでも割り込み禁止
CR0の最上位ビットを0にすると、ページング禁止。
最下位ビットを1にすることで、プロテクトモードに・・・。
プロテクトモードとは、GDTを使って仮想的に番地へアクセスする方法です。
ページングについてはこの章では触れられていませんでした。
MOV EAX,CR0 AND EAX,0x7fffffff ; ビット31を0にする(ページング禁止のため) OR EAX,0x00000001 ; ビット0を1にする(プロテクトモード移行のため) MOV CR0,EAX
あとは、メモリマップの紹介がありました。作者が考えたそうです。
ソース整理
ソースの整理で割り込み処理を一括処理していたソースを、キーボードとマウス用に分けました。