30天自制操作系統學習-第14天

1 提高分辨率

修改asmhead.nas畫面模式的設定,只考慮支持QEMU模擬器的顯卡:

; 設定畫面模式

		MOV		BX,0x4101		; VBE的640x480x8bi彩色
		MOV		AX,0x4f02
		INT		0x10
		MOV		BYTE [VMODE],8	; 記下畫面模式,參照C語言
		MOV		WORD [SCRNX],640
		MOV		WORD [SCRNY],480
		MOV		DWORD [VRAM],0xe0000000

運行:

2 提高分辨率(真機)

我們不能斷定真機上使用上的是什麼顯卡,有的公司尚未與VESA合作,如果是這種公司的產品,不能使用VBE。

asmhead.nas節選:

; 確認VBE是否存在

		MOV		AX,0x9000
		MOV		ES,AX
		MOV		DI,0
		MOV		AX,0x4f00
		INT		0x10
		CMP		AX,0x004f
		JNE		scrn320
; 檢查VBE的版本

		MOV		AX,[ES:DI+4]
		CMP		AX,0x0200
		JB		scrn320			; if (AX < 0x0200) goto scrn320
; 獲取畫面模式信息

		MOV		CX,VBEMODE
		MOV		AX,0x4f01
		INT		0x10
		CMP		AX,0x004f
		JNE		scrn320
; 畫面模式信息的確認

		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			; 模式屬性的bit是0,所以放棄
; 畫面模式的切換

		MOV		BX,VBEMODE+0x4000
		MOV		AX,0x4f02
		INT		0x10
		MOV		BYTE [VMODE],8	; 記下畫面模式,參考C語言
		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
scrn320:
		MOV		AL,0x13			; VGA圖,320x200x8bit彩色
		MOV		AH,0x00
		INT		0x10
		MOV		BYTE [VMODE],8	; 記下畫面模式(參考C語言)
		MOV		WORD [SCRNX],320
		MOV		WORD [SCRNY],200
		MOV		DWORD [VRAM],0x000a0000

不滿足顯卡的高分辨率設定時只能使用我們之前的scrn320模式了。

運行:

畫面還是蠻大的,而且分辨率也挺高的。

3 鍵盤輸入

我們按下鍵盤上的A鍵的時候我們希望它能顯示出a這個字符出來:

只需要判斷下鍵盤中斷髮送的數據是否爲A的通碼即可,運行:

4 顯示其他字符

我們將鍵盤輸入字符封裝在一個靜態字節數組中,靜態字節數組會被編譯爲DB命令,每當有鍵盤輸入時,我們去查這個靜態字節數組即可:

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', '.'
	};

運行:

5 追加內容

追加內容也沒那麼難,只需每次寫入一個字符的時候將光標往前移動一位,下一個字符寫入的位置即光標當前位置,對於退格鍵只需將當前字符設置爲" "後將光標後移1位即可:

其中bootpack.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;
}

運行:

6 移動窗體

只需在按下鼠標的左鍵,並且鼠標移動的狀態下重新繪製窗體即可實現移動效果:

運行效果: