3 鼠标解读(2)(harib05c)
程序已经很清晰了,我们继续解读程序。首先对mouse_decode函数略加修改。
bootpack.c 节选
struct MOUSE_DEC {
unsigned char buf[3], phase;
int x, y, btn;
};
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) {
/* 等待鼠标第一字节的阶段 */
if ((dat & 0xc8) == 0x08) {
/* 如果第一字节正确 */
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;
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; /* 应该不会到这儿来 */
}
■■■■■
结构体里增加的几个变量用于存放解读结果。这几个变量是x、y和btn,分别用于存放移动信息和鼠标按键状态。
另外,笔者还修改了if(mdec—>phase==1)语句。这个if语句,用于判断第一字节对移动有反应的部分是否在0~3的范围内;同时还要判断第一字节对点击有反应的部分是否在8~F的范围内。如果这个字节的数据不在以上范围内,它就会被舍去。
虽说基本上不这么做也行,但鼠标连线偶尔也会有接触不良、即将断线的可能,这时就会产生不该有的数据丢失,这样一来数据会错开一个字节。数据一旦错位,就不能顺利解读,那问题可就大了。而如果添加上对第一字节的检查,就算出了问题,鼠标也只是动作上略有失误,很快就能纠正过来,所以笔者加上了这项检查。
■■■■■
最后的if(mdec—>phase==3)部分,是解读处理的核心。鼠标键的状态,放在buf[0]的低3位,我们只取出这3位。十六进制的0x07相当于二进制的0000 0111,因此通过与运算(&),可以很顺利地取出低3位的值。
x和y,基本上是直接使用buf[1]和buf[2] ,但是需要使用第一字节中对鼠标移动有反应的几位(参考第一节的叙述)信息,将x和y的第8位及第8位以后全部都设成1,或全部都保留为0。这样就能正确地解读x和y。
在解读处理的最后,对y的符号进行了取反的操作。这是因为,鼠标与屏幕的y方向正好相反,为了配合画面方向,就对y符号进行了取反操作。
■■■■■
这样,鼠标数据的解读就完成了。现在我们来修改一下显示部分。
HariMain 节选
} else if (fifo8_status(&mousefifo) != 0) {
i = fifo8_get(&mousefifo);
io_sti();
if (mouse_decode(&mdec, i) != 0) {
/* 数据的3个字节都齐了,显示出来 */
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);
}
}
虽然程序中会检查mdec.btn的值,用3个if语句将s的值置换成相应的字符串,不过这一部分,暂时先不要管了。这样,程序就变成以下这样。
sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
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);
这与以前的程序很相似,仅仅用来显示字符串。现在加上刚才的if语句:
if ((mdec.btn & 0x01) != 0) {
s[1] = 'L';
}
这行程序的意思是,如果mdec.btn的最低位是1,就把s的第2个字符(注:第1个字符是s[0] )换成‘L’。这就是将小写字符置换成大写字符。其他的if语句也都这样理解吧。
■■■■■
执行一下看看。
![]() | |
移动鼠标 | 点击鼠标 |
反应都很正常,心情大好。