1、本次主要进展
>_<" 这次主要学习了系统内存管理和窗口叠加~由于上两篇都做了详细的框架说明和介绍,这里直接上代码!
2、文件及函数构成
>_<" 这里和第二篇相比,把鼠标和键盘的相关函数独立出来放进各自相应的文件中,并主要在内存管理和窗口叠加进行探索,同时还有部分代码整理~
bootpack.h
PS: 这里因为多了几个.c文件,所以makeFile中OBJS_BOOTPACK要把他们加进来~
OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj int.obj fifo.obj keyboard.obj mouse.obj memory.obj sheet.obj
PS: 为了整体清晰,上面的结构图把bootpack.h和字库文件没有列入~
3、主函数分析
1 /* bootpack */ 2 3 #include "bootpack.h" 4 #include <stdio.h> 5 6 void make_window8(unsigned char *buf, int xsize, int ysize, char *title); 7 8 void HariMain(void) 9 { 10 struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; 11 char s[40], keybuf[32], mousebuf[128]; 12 int mx, my, i; 13 unsigned int memtotal, count = 0; 14 struct MOUSE_DEC mdec; 15 struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR; 16 struct SHTCTL *shtctl; 17 struct SHEET *sht_back, *sht_mouse, *sht_win; 18 unsigned char *buf_back, buf_mouse[256], *buf_win; 19 20 init_gdtidt();//在dsctbl.c中,负责分区和中断分区初始化[包括键盘和鼠标中断设定] 21 init_pic();//在int.c中,负责中断初始化(硬件) 22 io_sti();//在naskfunc.nas中,仅仅执行STI指令,是CLI的逆指令,前者是开中断,后者是禁止中断 23 fifo8_init(&keyfifo, 32, keybuf);//在fifo.c中,负责缓冲区初始化(缓冲区结构体,大小,缓冲区首址) 24 fifo8_init(&mousefifo, 128, mousebuf); 25 /*这里IMR是(interrupt mask register),意思是“中断屏蔽寄存器”,是8位寄存器,分别对应8路IRQ信号,如果一路是1则该路被屏蔽,因为键盘中断是IRQ1,鼠标中断是IRQ12,且PIC分主从2个,从PIC连接主PIC的IRQ2,所以想要有鼠标和键盘中断,要PIC0的IRQ1和IRQ2,和PIC1的IRQ4*/ 26 io_out8(PIC0_IMR, 0xf9); /* (11111001) */ 27 io_out8(PIC1_IMR, 0xef); /* (11101111) */ 28 29 init_keyboard();//初始化键盘控制电路 30 enable_mouse(&mdec);//使能鼠标 31 //memman需要32KB内存 32 memtotal = memtest(0x00400000, 0xbfffffff);//计算总量memtatal 33 memman_init(memman); 34 memman_free(memman, 0x00001000, 0x0009e000); /* 0x00001000 - 0x0009efff 将现在不用的字节以0x1000个字节为单位注册到memman里*/ 35 memman_free(memman, 0x00400000, memtotal - 0x00400000); 36 37 init_palette();//调色板 38 shtctl = shtctl_init(memman, binfo->vram, binfo->scrnx, binfo->scrny);//图层初始化函数 39 sht_back = sheet_alloc(shtctl);//分配一个背景窗口 40 sht_mouse = sheet_alloc(shtctl);//分配一个鼠标窗口 41 sht_win = sheet_alloc(shtctl);//分配一个小窗口 42 buf_back = (unsigned char *) memman_alloc_4k(memman, binfo->scrnx * binfo->scrny);//为背景窗口和普通小窗口分配缓存空间 43 buf_win = (unsigned char *) memman_alloc_4k(memman, 160 * 52); 44 sheet_setbuf(sht_back, buf_back, binfo->scrnx, binfo->scrny, -1); /* 设定涂层缓冲区的大小和透明色的函数 */ 45 sheet_setbuf(sht_mouse, buf_mouse, 16, 16, 99); 46 sheet_setbuf(sht_win, buf_win, 160, 52, -1); /* 设定涂层缓冲区的大小和透明色的函数 */ 47 init_screen8(buf_back, binfo->scrnx, binfo->scrny);//初始化屏幕,画矩形,形成最初的窗口界面 48 init_mouse_cursor8(buf_mouse, 99);//准备鼠标指针(16*16),99是窗口背景颜色 49 make_window8(buf_win, 160, 52, "counter");//就像制作背景和鼠标一样,先准备一张图,然后在图层内描绘一个貌似窗口的图就可以了 50 sheet_slide(sht_back, 0, 0);//上下左右移动窗口,即移动窗口至0,0 51 mx = (binfo->scrnx - 16) / 2; /* 计算鼠标初始位置 */ 52 my = (binfo->scrny - 28 - 16) / 2; 53 sheet_slide(sht_mouse, mx, my);//移动鼠标窗口 54 sheet_slide(sht_win, 80, 72);//移动消息窗口 55 sheet_updown(sht_back, 0);//设置窗口对的高度,背景在最下面 56 sheet_updown(sht_win, 1); 57 sheet_updown(sht_mouse, 2); 58 sprintf(s, "(%3d, %3d)", mx, my);//显示鼠标位置 59 putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s); 60 sprintf(s, "memory %dMB free : %dKB", 61 memtotal / (1024 * 1024), memman_total(memman) / 1024); 62 putfonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s); 63 sheet_refresh(sht_back, 0, 0, binfo->scrnx, 48); 64 65 for (;;) { 66 count++; 67 sprintf(s, "%010d", count); 68 boxfill8(buf_win, 160, COL8_C6C6C6, 40, 28, 119, 43);//将消息窗口画出来 69 putfonts8_asc(buf_win, 160, 40, 28, COL8_000000, s);//显示计数器的值 70 sheet_refresh(sht_win, 40, 28, 120, 44);//刷新对应区域 71 72 io_cli(); 73 if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) { 74 io_sti(); 75 } else { 76 if (fifo8_status(&keyfifo) != 0) { 77 i = fifo8_get(&keyfifo);//获取按键消息并显示 78 io_sti(); 79 sprintf(s, "%02X", i); 80 boxfill8(buf_back, binfo->scrnx, COL8_008484, 0, 16, 15, 31); 81 putfonts8_asc(buf_back, binfo->scrnx, 0, 16, COL8_FFFFFF, s); 82 sheet_refresh(sht_back, 0, 16, 16, 32); 83 } else if (fifo8_status(&mousefifo) != 0) { 84 i = fifo8_get(&mousefifo); 85 io_sti(); 86 if (mouse_decode(&mdec, i) != 0) { 87 sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y); 88 if ((mdec.btn & 0x01) != 0) { 89 s[1] = 'L'; 90 } 91 if ((mdec.btn & 0x02) != 0) { 92 s[3] = 'R'; 93 } 94 if ((mdec.btn & 0x04) != 0) { 95 s[2] = 'C'; 96 } 97 boxfill8(buf_back, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31); 98 putfonts8_asc(buf_back, binfo->scrnx, 32, 16, COL8_FFFFFF, s); 99 sheet_refresh(sht_back, 32, 16, 32 + 15 * 8, 32); 100 /* 移动鼠标 */ 101 mx += mdec.x; 102 my += mdec.y; 103 if (mx < 0) { 104 mx = 0; 105 } 106 if (my < 0) { 107 my = 0; 108 } 109 if (mx > binfo->scrnx - 1) { 110 mx = binfo->scrnx - 1; 111 } 112 if (my > binfo->scrny - 1) { 113 my = binfo->scrny - 1; 114 } 115 sprintf(s, "(%3d, %3d)", mx, my); 116 boxfill8(buf_back, binfo->scrnx, COL8_008484, 0, 0, 79, 15); /* 嵗昗徚偡 */ 117 putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s); /* 嵗昗彂偔 */ 118 sheet_refresh(sht_back, 0, 0, 80, 16); 119 sheet_slide(sht_mouse, mx, my); 120 } 121 } 122 } 123 } 124 } 125 ///////////////////////////////////////////////////////////////////////////////////// 126 //功能:就像制作背景和鼠标一样,先准备一张图,然后在图层内描绘一个貌似窗口的图就可以了 127 //参数: 128 void make_window8(unsigned char *buf, int xsize, int ysize, char *title) 129 { 130 static char closebtn[14][16] = { 131 "OOOOOOOOOOOOOOO@", 132 "OQQQQQQQQQQQQQ$@", 133 "OQQQQQQQQQQQQQ$@", 134 "OQQQ@@QQQQ@@QQ$@", 135 "OQQQQ@@QQ@@QQQ$@", 136 "OQQQQQ@@@@QQQQ$@", 137 "OQQQQQQ@@QQQQQ$@", 138 "OQQQQQ@@@@QQQQ$@", 139 "OQQQQ@@QQ@@QQQ$@", 140 "OQQQ@@QQQQ@@QQ$@", 141 "OQQQQQQQQQQQQQ$@", 142 "OQQQQQQQQQQQQQ$@", 143 "O$$$$$$$$$$$$$$@", 144 "@@@@@@@@@@@@@@@@" 145 }; 146 int x, y; 147 char c; 148 boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, xsize - 1, 0 ); 149 boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, xsize - 2, 1 ); 150 boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, 0, ysize - 1); 151 boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, 1, ysize - 2); 152 boxfill8(buf, xsize, COL8_848484, xsize - 2, 1, xsize - 2, ysize - 2); 153 boxfill8(buf, xsize, COL8_000000, xsize - 1, 0, xsize - 1, ysize - 1); 154 boxfill8(buf, xsize, COL8_C6C6C6, 2, 2, xsize - 3, ysize - 3); 155 boxfill8(buf, xsize, COL8_000084, 3, 3, xsize - 4, 20 ); 156 boxfill8(buf, xsize, COL8_848484, 1, ysize - 2, xsize - 2, ysize - 2); 157 boxfill8(buf, xsize, COL8_000000, 0, ysize - 1, xsize - 1, ysize - 1); 158 putfonts8_asc(buf, xsize, 24, 4, COL8_FFFFFF, title); 159 for (y = 0; y < 14; y++) { 160 for (x = 0; x < 16; x++) { 161 c = closebtn[y][x]; 162 if (c == '@') { 163 c = COL8_000000; 164 } else if (c == '$') { 165 c = COL8_848484; 166 } else if (c == 'Q') { 167 c = COL8_C6C6C6; 168 } else { 169 c = COL8_FFFFFF; 170 } 171 buf[(5 + y) * xsize + (xsize - 21 + x)] = c; 172 } 173 } 174 return; 175 }
>_<" 具体执行流程如下:
4、全部代码(含注释)
ipl10.nas [引导]
asmhead.nas [汇编通向C语言的准备]
bootpack.c [C文件主函数在此]
bootpack.h [其他.c文件函数声明及相关结构体的定义]
dsctbl.c [分段,中断分段,类似调色板那里的分法,少对多方式]
int.c [中断函数,键盘和鼠标放在他们自己的文件里了,一般中断是从对应汇编开始中间引用这个句柄函数,然后返回结束还是在汇编]
fifo.c [用数组实现的一个循化链表数据结构,用于存放鼠标键盘等消息]
keyboard.c [键盘初始化及中断等]
mouse.c [鼠标初始化及中断相关等]
memory.c [内存管理相关,新!]
graphic.c [界面相关函数,包括画窗口,画鼠标,显示字符等]
sheet.c [窗口管理,用指针实现的链表,加快插入速度,加速中断,实现窗口叠加,新!]
naskfunc.nas [用汇编写的相关函数,c语言比较难或者不能实现的]
hankaku.txt [字库]
Makefile [编译脚本相关,不属于程序部分]
make.bat [编译脚本,不属于程序部分]
5、效果及说明
>_<" 已经实现了窗口叠加和内存管理,这里有背景窗口,消息窗口和鼠标窗口~本次比上次多了内存管理和窗口管理,因为要加速中断,所以我们要想方设法地优化程序,内存管理中努力去除不必要的条件判断,窗口管理中用指针链表加快插入速度...同时这也为阅读这两部分的代码带来了很大的不便,建议结合以前学的数据结构的知识,可能就会有种他乡遇故知的感觉呢!哈哈~
本文转自beautifulzzzz博客园博客,原文链接:http://www.cnblogs.com/zjutlitao/p/3979306.html,如需转载请自行联系原作者