官术网_书友最值得收藏!

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語句也都這樣理解吧。

■■■■■

執行一下看看。

反應都很正常,心情大好。

主站蜘蛛池模板: 井研县| 综艺| 扎兰屯市| 新平| 江口县| 怀宁县| 宝坻区| 五指山市| 芜湖市| 彰化县| 漳平市| 罗城| 拜城县| 宁德市| 泌阳县| 策勒县| 明星| 宁津县| 多伦县| 乐陵市| 怀远县| 黎川县| 文山县| 平定县| 饶河县| 莱西市| 重庆市| 绥阳县| 正宁县| 四子王旗| 安图县| 开封市| 得荣县| 新余市| 阿鲁科尔沁旗| 扶风县| 泸州市| 深圳市| 兴国县| 肇东市| 岗巴县|