Skip to content

day14高分辨率以及键盘输入

提高系统的分辨率

assembly
; 画面

		MOV		BX,0x4101		
		MOV		AX,0x4f02
		INT		0x10			; 使用这两个数字就可以进行调整
		MOV		BYTE [VMODE],8	; 保存画面的信息
		MOV		WORD [SCRNX],640
		MOV		WORD [SCRNY],480
		MOV		DWORD [VRAM],0xe0000000

在最初的时候, 所有的公司使用的是IBM公司的标准, 但是之后有的公司制作的显卡的性能超过了IBM, 使得自己设定显卡的模式设定, 之后VESA协会出台, 制作专门的BIOS, 可以利用它进行提高分辨率, 成为VBE

切换到不适用VBE的模式, 设置AH=0, AL=画面号码, 使用AH=0x4f02, BX=画面号码

  • 0x101 640x480 8bit
  • 0x103 800x600 8bit
  • 0x105 1024x768 8bit
  • 0x107 1280x1024 8bit

在虚拟机使用的时候需要加上0x4000

assembly
; 检测VBE是否存在

		MOV		AX,0x9000
		MOV		ES,AX
		MOV		DI,0
		MOV		AX,0x4f00
		INT		0x10
		CMP		AX,0x004f
		JNE		scrn320

存在的话AX会变为0x004f

assembly
		MOV		AX,[ES:DI+4]
		CMP		AX,0x0200
		JB		scrn320			; if (AX < 0x0200) goto scrn320

检测版本, 版本过低就进行跳转

assembly
		MOV		CX,VBEMODE
		MOV		AX,0x4f01
		INT		0x10
		CMP		AX,0x004f
		JNE		scrn320

在这里检测模式是否可用, 信息会被放在[ES:DI]开始的256个字节里面

  • [ES:DI + 0x00] 模式的属性, bit7是1, 因为在设置的时候需要加上0x4000
  • [ES:DI + 0x12] X的分辨率
  • [ES:DI + 0x14] Y的分辨率
  • [ES:DI + 0x19] 颜色数
  • [ES:DI + 0x1b] 颜色的指定方法, 必须为4
  • [ES:DI + 0x28] VRAM的地址
assembly
		CMP		BYTE [ES:DI+0x19],8
		JNE		scrn320
		CMP		BYTE [ES:DI+0x1b],4
		JNE		scrn320
		MOV		AX,[ES:DI+0x00]
		AND		AX,0x0080
		JZ		scrn320			; bit7是0所以放弃

对信息进行确认, 失败的话仍使用原来的模式

assembly
		MOV		BX,VBEMODE+0x4000
		MOV		AX,0x4f02
		INT		0x10
		MOV		BYTE [VMODE],8	; 进行切换
		MOV		AX,[ES:DI+0x12]
		MOV		[SCRNX],AX
		MOV		AX,[ES:DI+0x14]
		MOV		[SCRNY],AX
		MOV		EAX,[ES:DI+0x28]
		MOV		[VRAM],EAX
		JMP		keystatus

切换之后记录下各种信息

键盘输入

键盘按下抬起的时候传回去不同的数字

c
if (256 <= i && i <= 511) { /* 处理的数字来自键盘 */
    sprintf(s, "%02X", i - 256);
    putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);//打印出得到的数字
    if (i == 0x1e + 256) {
        putfonts8_asc_sht(sht_win, 40, 28, COL8_000000, COL8_C6C6C6, "A", 1);//获得的按键是A
    }
}

对键盘的数字进行处理

c
static char keytable[0x54] = {
    0,   0,   '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '^', 0,   0,
    'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '@', '[', 0,   0,   'A', 'S',
    'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', ':', 0,   0,   ']', 'Z', 'X', 'C', 'V',
    'B', 'N', 'M', ',', '.', '/', 0,   '*', 0,   ' ', 0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   '7', '8', '9', '-', '4', '5', '6', '+', '1',
    '2', '3', '0', '.'
};

if (256 <= i && i <= 511) { /* キーボードデータ */
    sprintf(s, "%02X", i - 256);
    putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);
    if (i < 256 + 0x54) {
        if (keytable[i - 256] != 0) {
            s[0] = keytable[i - 256];
            s[1] = 0;
            putfonts8_asc_sht(sht_win, 40, 28, COL8_000000, COL8_C6C6C6, s, 1);
        }
    }
}

实现退格

c
if (256 <= i && i <= 511) { /* キーボードデータ */
    sprintf(s, "%02X", i - 256);
    putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);
    if (i < 0x54 + 256) {
        if (keytable[i - 256] != 0 && cursor_x < 144) { /* 通常文字 */
            /* 文字进行显示 */
            s[0] = keytable[i - 256];
            s[1] = 0;
            putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, s, 1);
            cursor_x += 8;//设置打印的位置
        }
    }
    if (i == 256 + 0x0e && cursor_x > 8) { /* バックスペース */
        /* 如果这个是退格键, 这是为了删去光标 */
        putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, " ", 1);
        cursor_x -= 8;
    }
    /* 光标再次显示 */
    boxfill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43);
    sheet_refresh(sht_win, cursor_x, 28, cursor_x + 8, 44);
}
c
// 这个函数是在窗口中绘制一个文本框
void make_textbox8(struct SHEET *sht, int x0, int y0, int sx, int sy, int c)
{
	int x1 = x0 + sx, y1 = y0 + sy;
	boxfill8(sht->buf, sht->bxsize, COL8_848484, x0 - 2, y0 - 3, x1 + 1, y0 - 3);
	boxfill8(sht->buf, sht->bxsize, COL8_848484, x0 - 3, y0 - 3, x0 - 3, y1 + 1);
	boxfill8(sht->buf, sht->bxsize, COL8_FFFFFF, x0 - 3, y1 + 2, x1 + 1, y1 + 2);
	boxfill8(sht->buf, sht->bxsize, COL8_FFFFFF, x1 + 2, y0 - 3, x1 + 2, y1 + 2);
	boxfill8(sht->buf, sht->bxsize, COL8_000000, x0 - 1, y0 - 2, x1 + 0, y0 - 2);
	boxfill8(sht->buf, sht->bxsize, COL8_000000, x0 - 2, y0 - 2, x0 - 2, y1 + 0);
	boxfill8(sht->buf, sht->bxsize, COL8_C6C6C6, x0 - 2, y1 + 1, x1 + 0, y1 + 1);
	boxfill8(sht->buf, sht->bxsize, COL8_C6C6C6, x1 + 1, y0 - 2, x1 + 1, y1 + 1);
	boxfill8(sht->buf, sht->bxsize, c,           x0 - 1, y0 - 1, x1 + 0, y1 + 0);
	return;
}

增加鼠标移动窗口

c
if (512 <= i && i <= 767) { /* マウスデータ */
    if (mouse_decode(&mdec, i - 512) != 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';
        }
        putfonts8_asc_sht(sht_back, 32, 16, COL8_FFFFFF, COL8_008484, s, 15);
        /* 记录鼠标的移动 */
        mx += mdec.x;
        my += mdec.y;
        if (mx < 0) {
            mx = 0;
        }
        if (my < 0) {
            my = 0;
        }
        if (mx > binfo->scrnx - 1) {
            mx = binfo->scrnx - 1;
        }
        if (my > binfo->scrny - 1) {
            my = binfo->scrny - 1;
        }
        sprintf(s, "(%3d, %3d)", mx, my);
        putfonts8_asc_sht(sht_back, 0, 0, COL8_FFFFFF, COL8_008484, s, 10);
        sheet_slide(sht_mouse, mx, my);
        if ((mdec.btn & 0x01) != 0) {
            /* 鼠标左键按下 */
            sheet_slide(sht_win, mx - 80, my - 8);
        }
    }
}