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相当于二进制的00000111,因此通过与运算(&),可以很顺利地取出低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语句也都这样理解吧。
■■■■■
执行一下看看。
反应都很正常,心情大好。