30天自制操作系统(第14天)

14天 高分辨率及键盘输入

14.1 提高分辨率(1

之前的分辨率为320*200*8彩色,VGA显卡。如果要使用新画面模式,就需要使用VBE画面模式。
切换到不使用 VBE 的画面模式时用 “AH = 0 AL= 画面模式号码; ”,而切换 到使用 VBE 的画面模式时用 “AX = 0x4f02 BX = 画面模式号码; ”。而这种必须使 用 VBE 才能利用的画面模式就称作 画面模式。
VBE 的画面模式号码如下:
0x101……640× 480× 8bit 彩色
0x103……800× 600× 8bit 彩色
0x105……1024× 768× 8bit 彩色
0x107……1280× 1024× 8bit 彩色
;画面设定 文件asmhead.nas
;修改前代码
;		MOV 	AL,0x13			;VGA显卡,320*200*8彩色
;		MOV		AH,0x00
;		INT		0x10
;		MOV		BYTE [VMODE],8	;记录画面模式
;		MOV		WORD [SCRNX],320;两个字节
;		MOV		WORD [SCRNY],200;两个字节
;		MOV		DWORD [VRAM],0x000a0000;VRAM是用来显示画面的内存,地址0xa0000~0xaffff的64KB

;修改后代码		
		MOV 	BX,0x4101		;VBE显卡,640x480*8彩色
		MOV		AX,0x4f02
		INT		0x10
		MOV		BYTE [VMODE],8	;记录画面模式
		MOV		WORD [SCRNX],640;两个字节
		MOV		WORD [SCRNY],480;两个字节
		MOV		DWORD [VRAM],0xe0000000;VRAM是用来显示画面的内存,地址0xa0000~0xaffff的64KB

14.2 提高分辨率(2

1° 首先确认VBE是否存在: VBE 的话, AX 就会变为0x004f;而且此显卡能利用的VBE信息要写入到内存中以ES:DI开始的512字节中。
2° 检查VBE版本: if (AX < 0x0200) goto scrn320
3° 取得画面模式信息:通过 VBE 来查看一下画面模式 0x105 能不能使用。如果AX是0x004f以外的值,就意味着所指定的画面模式不能使用。
4°  画面模式信息中,重要的信息有如下 6 个:
        WORD [ES : DI+0x00] :     模式属性 …… bit7 不是 1 就不好办 ( 能加上 0x4000 )
        WORD [ES : DI+0x12] :     X 的分辨率
        WORD [ES : DI+0x14] :     Y 的分辨率
        BYTE [ES : DI+0x19] :       颜色数 …… 必须为 8
        BYTE [ES : DI+0x1b] :       颜色的指定方法 …… 必须为 4 ( 4 是调色板模式 )
        DWORD [ES : DI+0x28] :   VRAM 的地址
5° 画面模式信息的确认:1)颜色数是否为8;2)是否为调色板模式;3)画面模式号码可否加上0x4000再进行指定。
6°  画面模式的切换
VBEMODE EQU		0x105			;1024 x  768 x 8bit
; 画面模式号码如下
;	0x100 :  640 x  400 x 8bit
;	0x101 :  640 x  480 x 8bit
;	0x103 :  800 x  600 x 8bit
;	0x105 : 1024 x  768 x 8bit
;	0x107 : 1280 x 1024 x 8bit

BOTPAK	EQU		0x00280000		
DSKCAC	EQU		0x00100000		
DSKCAC0	EQU		0x00008000		

;有关BOOT_INFO
CYLS	EQU		0x0ff0			;设定启动区
LEDS	EQU		0x0ff1
VMODE	EQU		0x0ff2			;关于色彩数目的信息,颜色位数
SCRNX	EQU		0x0ff4			;分辨率的x
SCRNY	EQU		0x0ff6			;分辨率的y
VRAM	EQU		0x0ff8			;图像缓冲区的开始地址

		ORG 	0xc200			;程序要装载到的位置,书本P79页已说明0xc200的由来
		
; 确认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			; 模式属性的bit7是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显卡,320*200*8彩色
		MOV		AH,0x00
		INT		0x10
		MOV		BYTE [VMODE],8	;记录画面模式
		MOV		WORD [SCRNX],320;两个字节
		MOV		WORD [SCRNY],200;两个字节
		MOV		DWORD [VRAM],0x000a0000;VRAM是用来显示画面的内存,地址0xa0000~0xaffff的64KB
		
		
;用BIOS取得键盘上各种LED指示灯的状态
keystatus:
		MOV		AH,0x02
		INT		0x16			;keyboard BIOS
		MOV		[LEDS],AL

14.3 键盘输入(1

在窗口中打印通过键盘输入的字符‘A’。
for (;;) {
    io_cli();
    if (fifo32_status(&fifo) == 0) {
        io_stihlt();
    } else {
        i = fifo32_get(&fifo);
        io_sti();
        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);
            }
        } else if (512 <= i && i <= 767) { /* 鼠标数据 */
            (中略)
        } else if (i == 10) { /* 10秒定时器 */
            putfonts8_asc_sht(sht_back, 0, 64, COL8_FFFFFF, COL8_008484, "10[sec]", 7);
        } else if (i == 3) { /* 3秒定时器 */
            putfonts8_asc_sht(sht_back, 0, 80, COL8_FFFFFF, COL8_008484, "3[sec]", 6);
        } else if (i == 1) { /* 光标用定时器 */
            (中略)
        } else if (i == 0) { /* 光标用定时器 */
            (中略)
        }
    }
}

14.4 键盘输入(2

创建字符串数组,如果通过键盘按下对应字符,则在窗口中显示。
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;// 回车符,理解成'\n',表示字符串终止符
            putfonts8_asc_sht(sht_win, 40, 28, COL8_000000, COL8_C6C6C6, s, 1);
        }
    }
} else if (512 <= i && i <= 767) { /* 鼠标数据 */

14.5 追记内容(1)

通过14.4节中已经实现在窗口中显示一个键盘输入的字符,下面将在窗口中实现连续输入字符。
有以下要求:1.将输入的位置存在光标,2.实时输入,3.可以删除字符。
思路:首先在窗口中画一个白底的输入框,再判断键盘中断产生时按下的字符是否在字符串keytable中。如果在,进一步确认是否为退格符,如果是则用空字符进行覆盖,否则显示该字符。光标用计时器也需要更新,调用boxfill8和sheet_refresh函数进行刷新光标。
// 绘制白底文本输入框
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;
}


void HariMain(void)
{
	(中略)
	int cursor_x, cursor_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', '.'
	};

	(中略)
	make_textbox8(sht_win, 8, 28, 144, 16, COL8_FFFFFF);
	cursor_x = 8;
	cursor_c = COL8_FFFFFF;
	(中略)
	for (;;) {
		io_cli();
		if (fifo32_status(&fifo) == 0) {
			io_stihlt();
		} else {
			i = fifo32_get(&fifo);
			io_sti();
			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 == 0x0e + 256 && 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);
			} else if (512 <= i && i <= 767) {/* 鼠标数据 */
				(中略)
				}
			} else if (i == 10) {/* 10s计时器 */
				(中略)
			} else if (i == 3) {/* 3s计时器 */
				(中略)
			} else if (i <= 1) {/* 光标用计时器 */
				if( i == 1){
					timer_init(timer3, &fifo, 0); /* 设定为0 */
					cursor_c = COL8_000000;
				}else{
					timer_init(timer3, &fifo, 1); /* 设定为1 */
					cursor_c = COL8_FFFFFF;
				}
				timer_settime(timer3, 50);
				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);
			} 
		}
	}
}

14.6 追记内容(2

实现鼠标拖动窗口移动的功能,思路为当按下鼠标左键时,调用sheet_slide函数将sht_win的位置修改为(mx-80, my-8) 。
for (;;) {
    io_cli();
    if (fifo32_status(&fifo) == 0) {
        io_stihlt();
    } else {
        i = fifo32_get(&fifo);
        io_sti();
        if (256 <= i && i <= 511) { /* 键盘数据 */
            (中略)
        } else if (512 <= i && i <= 767) { /* 鼠标数据 * */
            if (mouse_decode(&mdec, i - 512) != 0) {
            /* 收集了3字节的数据,所以显示出来 */
            (中略)
            /* 光标移动 */
            (中略)
            sheet_slide(sht_mouse, mx, my);
            /* 从这里开始! */ 
            if ((mdec.btn & 0x01) != 0) {
                /* 按下左键、移动sht_win */
                sheet_slide(sht_win, mx - 80, my - 8);
/* 到这里结束! */ }
            }
        } else if (i == 10) { /* 10秒定时器 */
            putfonts8_asc_sht(sht_back, 0, 64, COL8_FFFFFF, COL8_008484, "10[sec]", 7);
        } else if (i == 3) { /* 3秒定时器 */
            putfonts8_asc_sht(sht_back, 0, 80, COL8_FFFFFF, COL8_008484, "3[sec]", 6);
        } else if (i <= 1) { /* 光标用定时器 */
            (中略)
        }
    }
}
  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在现有省、市港口信息化系统进行有效整合基础上,借鉴新 一代的感知-传输-应用技术体系,实现对码头、船舶、货物、重 大危险源、危险货物装卸过程、航管航运等管理要素的全面感知、 有效传输和按需定制服务,为行政管理人员和相关单位及人员提 供高效的管理辅助,并为公众提供便捷、实时的水运信息服务。 建立信息整合、交换和共享机制,建立健全信息化管理支撑 体系,以及相关标准规范和安全保障体系;按照“绿色循环低碳” 交通的要求,搭建高效、弹性、高可扩展性的基于虚拟技术的信 息基础设施,支撑信息平台低成本运行,实现电子政务建设和服务模式的转变。 实现以感知港口、感知船舶、感知货物为手段,以港航智能 分析、科学决策、高效服务为目的和核心理念,构建“智慧港口”的发展体系。 结合“智慧港口”相关业务工作特点及信息化现状的实际情况,本项目具体建设目标为: 一张图(即GIS 地理信息服务平台) 在建设岸线、港口、港区、码头、泊位等港口主要基础资源图层上,建设GIS 地理信息服务平台,在此基础上依次接入和叠加规划建设、经营、安全、航管等相关业务应用专题数据,并叠 加动态数据,如 AIS/GPS/移动平台数据,逐步建成航运管理处 "一张图"。系统支持扩展框架,方便未来更多应用资源的逐步整合。 现场执法监管系统 基于港口(航管)执法基地建设规划,依托统一的执法区域 管理和数字化监控平台,通过加强对辖区内的监控,结合移动平 台,形成完整的多维路径和信息追踪,真正做到问题能发现、事态能控制、突发问题能解决。 运行监测和辅助决策系统 对区域港口与航运业务日常所需填报及监测的数据经过科 学归纳及分析,采用统一平台,消除重复的填报数据,进行企业 输入和自动录入,并进行系统智能判断,避免填入错误的数据, 输入的数据经过智能组合,自动生成各业务部门所需的数据报 表,包括字段、格式,都可以根据需要进行定制,同时满足扩展 性需要,当有新的业务监测数据表需要产生时,系统将分析新的 需求,将所需字段融合进入日常监测和决策辅助平台的统一平台中,并生成新的所需业务数据监测及决策表。 综合指挥调度系统 建设以港航应急指挥中心为枢纽,以各级管理部门和经营港 口企业为节点,快速调度、信息共享的通信网络,满足应急处置中所需要的信息采集、指挥调度和过程监控等通信保障任务。 设计思路 根据项目的建设目标和“智慧港口”信息化平台的总体框架、 设计思路、建设内容及保障措施,围绕业务协同、信息共享,充 分考虑各航运(港政)管理处内部管理的需求,平台采用“全面 整合、重点补充、突出共享、逐步完善”策略,加强重点区域或 运输通道交通基础设施、运载装备、运行环境的监测监控,完善 运行协调、应急处置通信手段,促进跨区域、跨部门信息共享和业务协同。 以“统筹协调、综合监管”为目标,以提供综合、动态、实 时、准确、实用的安全畅通和应急数据共享为核心,围绕“保畅通、抓安全、促应急"等实际需求来建设智慧港口信息化平台。 系统充分整合和利用航运管理处现有相关信息资源,以地理 信息技术、网络视频技术、互联网技术、移动通信技术、云计算 技术为支撑,结合航运管理处专网与行业数据交换平台,构建航 运管理处与各部门之间智慧、畅通、安全、高效、绿色低碳的智 慧港口信息化平台。 系统充分考虑航运管理处安全法规及安全职责今后的变化 与发展趋势,应用目前主流的、成熟的应用技术,内联外引,优势互补,使系统建设具备良好的开放性、扩展性、可维护性。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值