// bootpack.c #include "bootpack.h" #include typedef struct _mouse_dec { unsigned char buf[3], phase; int x, y, btn; } MOUSE_DEC, *PMOUSE_DEC; extern FIFO8 keyfifo, mousefifo; void enable_mouse(PMOUSE_DEC mdec); void init_keyboard(void); int mouse_decode(PMOUSE_DEC mdec, unsigned char dat); void HariMain(void) { PBOOTINFO pbinfo = (PBOOTINFO) ADDR_BOOTINFO; char str[256], mcursor[256], keybuf[32], mousebuf[128]; int mx, my, i; MOUSE_DEC mdec; init_gdtidt(); init_pic(); io_sti(); // IDT/PICの初期化が終わったのでCPUの割り込み禁止を解除 // FIFO生成 fifo8_init(&keyfifo, 32, keybuf); fifo8_init(&mousefifo, 128, mousebuf); io_out8(PIC0_IMR, 0xf9); // 1111 1001(PIC1とキーボードを許可) io_out8(PIC1_IMR, 0xef); // 1110 1111(マウスを許可) init_keyboard(); set_palette(COL8_BLACK, COL8_DARKGRAY, init_palette()); init_screen8(pbinfo->vram, pbinfo->scrnx, pbinfo->scrny); // マウスの座標計算 mx = ((pbinfo->scrnx - 16) / 4) * 3; my = ((pbinfo->scrny - 28 - 16) / 4) * 3; // マウス描画 init_mouse_cursor8(mcursor, COL8_DARKWATER); putblock8_8(pbinfo->vram, pbinfo->scrnx, 16, 16, mx, my, mcursor, 16); // マウス位置を文字列で表示 sprintf(str, "mouse is (x, y) = (%d, %d)", mx, my); putfonts8_asc(pbinfo->vram, pbinfo->scrnx, 0, 0, COL8_WHITE, str); // 文字列を表示 sprintf(str, "I will make the hariboteOS after 25 days."); putfonts8_asc(pbinfo->vram, pbinfo->scrnx, 0, 32, COL8_YELLOW, str); enable_mouse(&mdec); while (1) { // 無限ループ(割り込みで取得したデータを監視) io_cli(); if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) { io_stihlt(); // マウスもキーボードもデータなしなら休む } else { if (fifo8_status(&keyfifo) != 0) { // キーボードデータがあるなら i = fifo8_get(&keyfifo); // FIFOから取得 io_sti(); sprintf(str, "%02X", i); // 出力 boxfill8(pbinfo->vram, pbinfo->scrnx, COL8_DARKWATER, 0, 16, 15, 31); putfonts8_asc(pbinfo->vram, pbinfo->scrnx, 0, 16, COL8_WHITE, str); } else if (fifo8_status(&mousefifo) != 0) { // マウスデータがあるなら i = fifo8_get(&mousefifo); // FIFOから取得 io_sti(); if (mouse_decode(&mdec, i) != 0) { // データが3バイト揃ったので表示 sprintf(str, "[lcr %4d %4d]", mdec.x, mdec.y); if ((mdec.btn & 0x01) != 0) str[1] = 'L'; if ((mdec.btn & 0x02) != 0) str[3] = 'R'; if ((mdec.btn & 0x04) != 0) str[2] = 'C'; boxfill8(pbinfo->vram, pbinfo->scrnx, COL8_DARKWATER, 32, 16, 32 + 15 * 8 - 1, 31); putfonts8_asc(pbinfo->vram, pbinfo->scrnx, 32, 16, COL8_WHITE, str); // マウスカーソルの移動 */ boxfill8(pbinfo->vram, pbinfo->scrnx, COL8_DARKWATER, mx, my, mx + 15, my + 15); // マウス消す mx += mdec.x; my += mdec.y; if (mx < 0) mx = 0; if (my < 0) my = 0; if (mx > pbinfo->scrnx - 16) mx = pbinfo->scrnx - 16; if (my > pbinfo->scrny - 16) my = pbinfo->scrny - 16; sprintf(str, "(%3d, %3d)", mx, my); boxfill8(pbinfo->vram, pbinfo->scrnx, COL8_DARKWATER, 0, 0, 79, 15); putfonts8_asc(pbinfo->vram, pbinfo->scrnx, 0, 0, COL8_WHITE, str); putblock8_8(pbinfo->vram, pbinfo->scrnx, 16, 16, mx, my, mcursor, 16); } } } } } #define PORT_KEYDAT 0x0060 #define PORT_KEYSTA 0x0064 #define PORT_KEYCMD 0x0064 #define KEYSTA_SEND_NOTREADY 0x02 #define KEYCMD_WRITE_MODE 0x60 #define KBC_MODE 0x47 void wait_KBC_sendready(void) { // キーボードコントローラがデータ送信可能になるのを待つ while ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) != 0); return; } void init_keyboard(void) { // キーボードコントローラの初期化 wait_KBC_sendready(); io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE); wait_KBC_sendready(); io_out8(PORT_KEYDAT, KBC_MODE); return; } #define KEYCMD_SENDTO_MOUSE 0xd4 #define MOUSECMD_ENABLE 0xf4 void enable_mouse(PMOUSE_DEC mdec) { // マウス有効 wait_KBC_sendready(); io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE); wait_KBC_sendready(); io_out8(PORT_KEYDAT, MOUSECMD_ENABLE); mdec->phase = 0; // マウスの0xfaを待っている段階 return; // うまくいくとACK(0xfa)が送信されてくる } int mouse_decode(PMOUSE_DEC mdec, unsigned char dat) { if (mdec->phase == 0) { // マウスの0xfaを待っている段階 if (dat == 0xfa) mdec->phase = 1; return 0; } if (mdec->phase == 1) { // マウスの1バイト目を待っている段階 if ((dat & 0xc8) == 0x08) { // 正しい1バイト目だった mdec->buf[0] = dat; mdec->phase = 2; } return 0; } if (mdec->phase == 2) { // マウスの2バイト目を待っている段階 mdec->buf[1] = dat; mdec->phase = 3; return 0; } if (mdec->phase == 3) { // マウスの3バイト目を待っている段階 mdec->buf[2] = dat; mdec->phase = 1; mdec->btn = mdec->buf[0] & 0x07; mdec->x = mdec->buf[1]; mdec->y = mdec->buf[2]; if ((mdec->buf[0] & 0x10) != 0) mdec->x |= 0xffffff00; if ((mdec->buf[0] & 0x20) != 0) mdec->y |= 0xffffff00; mdec->y = - mdec->y; // マウスではy方向の符号が画面と反対 return 1; } return -1; // ここに来ることはないはず }