【 *** 作系统】30天自制 *** 作系统--

【 *** 作系统】30天自制 *** 作系统--,第1张

        上一章介绍了键盘与鼠标的中断以及 *** 作码的读入,这一章将用鼠标的 *** 作码,结合之前绘制的鼠标箭头,实现鼠标的移动。

另外,再说明一下前文略过的asmhead.nas的内容。

一 鼠标移动

        鼠标在中断中的存储的 *** 作码包含三位的信息,即[ *** 作,X坐标,Y坐标],我们在主函数中读取的时候,可以三位三位地读取。

        这边鼠标数据的解读分为三个阶段,首先要把最初读到的0xfa舍弃掉。

之后,每次从鼠标那里送过来的数据都应该是3个字节一组的,所以每当数据累 积到3个字节,就把它显示在屏幕上

        对鼠标数据的解读如下:

struct MOUSE_DEC {
    unsigned char buf[3], phase;
};

void HariMain(void)
{
    //(中略)
    struct MOUSE_DEC mdec;
    //(中略)
    enable_mouse(&mdec);
    for (;;) {
	    io_cli();
        if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {
            io_stihlt();
        } else {
            if (fifo8_status(&keyfifo) != 0) {
                // 键盘的 *** 作
            } else if (fifo8_status(&mousefifo) != 0) {
                i = fifo8_get(&mousefifo);
                io_sti();
                if (mouse_decode(&mdec, i) != 0) {
                    /* 3字节都凑齐了,所以把它们显示出来*/
                    sprintf(s, "%02X %02X %02X", mdec.buf[0], mdec.buf[1], mdec.buf[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);
                }
            }
        }
    }
}


/**
 * @brief 获取鼠标状态
 */
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat)
{
	if (mdec->phase == 0) {
		/* 等待鼠标的0xfa的阶段 */
		if (dat == 0xfa) {
			mdec->phase = 1;
		}
		return 0;
	}
	if (mdec->phase == 1) {
		mdec->buf[0] = dat;
		mdec->phase = 2;
		return 0;
	}
	if (mdec->phase == 2) {
		mdec->buf[1] = dat;
		mdec->phase = 3;
		return 0;
	}
	if (mdec->phase == 3) {
		mdec->buf[2] = dat;
		mdec->phase = 1;
		return 1;
	}
	// shit value
	return -1;
}

        再从上面接收到地模糊信息中提取到鼠标真正地 *** 作信息(扩充 struct MOUSE_DEC 中的信息,加入 x, y, btn 表示移动信息和鼠标按下的状态):

struct MOUSE_DEC {
    unsigned char buf[3], phase;
	int x, y, btn;
};

if (mdec->phase == 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;
    return 1;
}

        在主函数中,将鼠标的 *** 作具象地打印出来,原本显示lcr,当左键按下,l变成L,当右键按下,r变成R,当中键按下,c变成C:

if (mouse_decode(&mdec, i) != 0) {
    sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
    if ((mdec.btn & 0x01) != 0) {
    	s[1] = 'L';
    }
    if ((mdec.btn & 0x02) != 0) {
    	s[3] = 'R';
    }
    if ((mdec.btn & 0x04) != 0) {
    	s[2] = 'C';
    }
    boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31);
    putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
}

        鼠标的移动就更简单了,原理就是在中断中读取到鼠标的最新位置处,重绘鼠标的图形区域。

	/* 显示鼠标图形 */						
	// 隐藏鼠标
    boxfill8(binfo->vram, binfo->scrnx, COL8_008484, mx, my, mx + 15, my + 15);
    // 对鼠标位置的限制条件
    mx += mdec.x;
    my += mdec.y;
    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;
    }
    // 显示
    sprintf(s, "(%3d, %3d)", mx, my);
    // 隐藏坐标
    boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 0, 79, 15); 
    // 显示坐标
    putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s); 
    // 插画鼠标
    putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16); 

        实际运行效果如下:

         由图中可以看出,界面中的鼠标能够很好地响应实际鼠标的 *** 作,包括点按 *** 作和位置移动。

但是仍有不足,就是当鼠标移动到下面菜单栏时,重绘的 *** 作会将下面菜单栏也一并重绘了,具体的解决办法在后面的重叠区域处理中会有介绍,这边就不展开讲了。

二 32位切换

        历史遗留问题,阐述了asmhead.nas中新添加的100多行内容的具体含义(大意就是按照一定的步骤将某些寄存器(CR0等)设置为特定的值),这边比较难懂,而且感觉也没有必要全搞懂,这边就贴一张作者目前 *** 作系统设计的内存分布图:

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/673557.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-19
下一篇 2022-04-19

发表评论

登录后才能评论

评论列表(0条)

保存