《30天自制操作系统》11_day_学习笔记
harib08a:
鼠标的显示问题:我们可以看到,鼠标移到窗口最右侧之后就不能再移动了,而WIN中,鼠标是可以移动到最右边隐藏起来的。怎么办?把鼠标指针显示的范围扩宽就行!我们来修改一下HariMain来解决这个问题
//HariMain节选
if (mx > binfo->scrnx - ) { mx = binfo->scrnx - ; }//拓宽到右边界左边的一个像素
if (my > binfo->scrny - ) { my = binfo->scrny - ; }//拓宽到下边界上方的一个像素
harib08b:
我们发现图层到了画面外,就会出现问题。这里我们一起来吧sheet_refreshsub()函数进行改进,让它不刷新画面以外的内容。
方 法:在进行画面刷新之前,先判断是否已经超过了画面以外,超过画面外的部分不需要进行刷新操作(下面是关键部分的代码)
//sheet.c中sheet_refreshsub()节选
//判断,刷新像素的范围是否超出了画面
if (bx0 < ) { bx0 = ; }
if (by0 < ) { by0 = ; }
if (bx1 > sht->bxsize) { bx1 = sht->bxsize; }
if (by1 > sht->bysize) { by1 = sht->bysize; }
harib08c:
我们发现在图层移动sheet_undown()中指定ctl太麻烦,于是在这一部分对此做了一些修改,目的就是不在sheet_undown()中指定ctl.
1、struct SHEET中加入struct SHTCTL *ctl
//在图层的结构体定义struct SHEET中,加入图层控制结构体指针struct SHTCTL *ctl
struct SHEET {
unsigned char *buf;
int bxsize, bysize, vx0, vy0, col_inv, height, flags;
struct SHTCTL *ctl; //图层控制结构体指针struct SHTCTL *ctl
};
2、对函数shtclt_init进行追加
//追加内容: 将ctl初始化为图层控制结构体
for (i = ; i < MAX_SHEETS; i++) {
ctl->sheets0[i].flags = ; /* FLAG=0表示该图层未被使用 */
ctl->sheets0[i].ctl = ctl; /* 指针ctl指向图层控制结构体 */
}
3、对函数sheet_undown进行修改
//修改内容:将ctl初始化为图层控制结构体
void sheet_updown(struct SHEET *sht, int height)
{
struct SHTCTL *ctl = sht->ctl;/* 指针ctl指向图层控制结构体 */
int h, old = sht->height; /* 记录设置前图层的高度 */
//........
}
4、修改sheet_refresh()、sheet_slide()、sheet_free()
//一、修改函数的参数
//二、如果函数中使用了图层结构体SHEET,将结构体中指针ctl指向图层控制结构体
void sheet_refresh(struct SHEET *sht, int bx0, int by0, int bx1, int by1)
{
if (sht->height >= ) { /* 此时正在显示,按照新图层的信息进行刷新 */
sheet_refreshsub(sht->ctl, sht->vx0 + bx0, sht->vy0 + by0, sht->vx0 + bx1, sht->vy0 + by1);/* 这里修改了对sheet_refreshsub调用 */
}
return;
}
void sheet_slide(struct SHEET *sht, int vx0, int vy0)
{
int old_vx0 = sht->vx0, old_vy0 = sht->vy0;
sht->vx0 = vx0;
sht->vy0 = vy0;
if (sht->height >= ) { /* 此时正在显示,按照新图层的信息进行刷新 */
sheet_refreshsub(sht->ctl, old_vx0, old_vy0, old_vx0 + sht->bxsize, old_vy0 + sht->bysize);/* 这里修改了对sheet_refreshsub调用 */
sheet_refreshsub(sht->ctl, vx0, vy0, vx0 + sht->bxsize, vy0 + sht->bysize);/* 这里修改了对sheet_refreshsub调用 */
}
return;
}
void sheet_free(struct SHEET *sht)
{
if (sht->height >= ) {
sheet_updown(sht, -); /* 这里修改了对sheet_updown的调用,隐藏该图层 */
}
sht->flags = ; /* 图层被释放,flag置0 */
return;
}
harib08d:
到这里,优化工作完成的差不多了,接下来继续对系统进行拓展;接下来我们尝试制作一下窗口。
原 理:准备一张图层,在该图层的缓冲区描绘一个窗口的图像,接着把该缓冲区写到VRAM中,让界面刷新像素显示即可。
1、窗口图层制作函数make_windows8()
void make_window8(unsigned char *buf, int xsize, int ysize, char *title)
{
static char closebtn[][] = { //窗口关闭按钮X的的数组
"OOOOOOOOOOOOOOO@",
"OQQQQQQQQQQQQQ$@",
"OQQQQQQQQQQQQQ$@",
"OQQQ@@QQQQ@@QQ$@",
"OQQQQ@@QQ@@QQQ$@",
"OQQQQQ@@@@QQQQ$@",
"OQQQQQQ@@QQQQQ$@",
"OQQQQQ@@@@QQQQ$@",
"OQQQQ@@QQ@@QQQ$@",
"OQQQ@@QQQQ@@QQ$@",
"OQQQQQQQQQQQQQ$@",
"OQQQQQQQQQQQQQ$@",
"O$$$$$$$$$$$$$$@",
"@@@@@@@@@@@@@@@@"
};
int x, y;
char c;
//窗口的颜色填充,(应该是前景)
boxfill8(buf, xsize, COL8_C6C6C6, , , xsize - , );
boxfill8(buf, xsize, COL8_FFFFFF, , , xsize - , );
boxfill8(buf, xsize, COL8_C6C6C6, , , , ysize - );
boxfill8(buf, xsize, COL8_FFFFFF, , , , ysize - );
boxfill8(buf, xsize, COL8_848484, xsize - , , xsize - , ysize - );
boxfill8(buf, xsize, COL8_000000, xsize - , , xsize - , ysize - );
boxfill8(buf, xsize, COL8_C6C6C6, , , xsize - , ysize - );
boxfill8(buf, xsize, COL8_000084, , , xsize - , );
boxfill8(buf, xsize, COL8_848484, , ysize - , xsize - , ysize - );
boxfill8(buf, xsize, COL8_000000, , ysize - , xsize - , ysize - );
putfonts8_asc(buf, xsize, , , COL8_FFFFFF, title);//显示窗口的额标题
for (y = ; y < ; y++) {
for (x = ; x < ; x++) { //这里对关闭按钮的颜色进行设定
c = closebtn[y][x]; //关闭按钮数组中不同的字符用特定的显示颜色来显示出来
if (c == '@') {
c = COL8_000000;
} else if (c == '$') {
c = COL8_848484;
} else if (c == 'Q') {
c = COL8_C6C6C6;
} else {
c = COL8_FFFFFF;
}
buf[( + y) * xsize + (xsize - + x)] = c;//把这个颜色的值,给VRAM缓冲区
}
}
return;
}
2、在HariMain中进行相应的修改
//HariMain节选
init_palette(); //初始化调色板
shtctl = shtctl_init(memman, binfo->vram, binfo->scrnx, binfo->scrny);
sht_back = sheet_alloc(shtctl);
sht_mouse = sheet_alloc(shtctl);
sht_win = sheet_alloc(shtctl); //为窗口分配内存空间
buf_back = (unsigned char *) memman_alloc_4k(memman, binfo->scrnx * binfo->scrny);
buf_win = (unsigned char *) memman_alloc_4k(memman, * );
sheet_setbuf(sht_back, buf_back, binfo->scrnx, binfo->scrny, -); /* 设置图层缓冲区,没有透明色 */
sheet_setbuf(sht_mouse, buf_mouse, , , );
sheet_setbuf(sht_win, buf_win, , , -); /* 设置图层缓冲区,没有透明色 */
init_screen8(buf_back, binfo->scrnx, binfo->scrny); //初始化屏幕界面
init_mouse_cursor8(buf_mouse, ); //X按钮的功能键
make_window8(buf_win, , , "window"); //制作窗口图层buf_win
putfonts8_asc(buf_win, , , , COL8_000000, "Welcome to");//在图层buf_win中显示两串字符串
putfonts8_asc(buf_win, , , , COL8_000000, " Haribote-OS!");
sheet_slide(sht_back, , ); //图层上下滑动的函数,因为要让鼠标图层在窗口图层上方移动
mx = (binfo->scrnx - ) / ; /* 这里把鼠标放在屏幕中间的位置 */
my = (binfo->scrny - - ) / ;
sheet_slide(sht_mouse, mx, my); //设置鼠标图层的上下滑动
sheet_slide(sht_win, , ); //设置窗口图层sht_win的上下滑动
sheet_updown(sht_back, ); //设定背景图层的高度为0(在最底层)
sheet_updown(sht_win, ); //设置窗口图层的高度为1(在中间层)
sheet_updown(sht_mouse, ); //设置鼠标图层的高度为2(在最上层)
sprintf(s, "(%3d, %3d)", mx, my); //在背景层打印出坐标的位置
putfonts8_asc(buf_back, binfo->scrnx, , , COL8_FFFFFF, s);
sprintf(s, "memory %dMB free : %dKB", //打印出内存使用情况
memtotal / ( * ), memman_total(memman) / );
putfonts8_asc(buf_back, binfo->scrnx, , , COL8_FFFFFF, s);
sheet_refresh(sht_back, , , binfo->scrnx, ); //刷新屏幕显示
harib08e:
小实验:我们在上面一共有了3个图层:背景、窗口、鼠标。让我们抽一下风把这三个图层的高度改一下,看看会怎么样?我们把鼠标图层放在窗口下面,背景图层在最底下(上图运行成功,说明程序没问题)
//修改HariMain中的图层高度设置
sheet_updown(sht_back, );//背景最底层
sheet_updown(sht_mouse, );//鼠标中间层
sheet_updown(sht_win, );//窗口最高层
harib08f:
我们已经能顺利的制作出窗口了,现在我们来做个好玩的东西---计数器。在上一步,我们已经成功的绘制出了窗口,接下来只需要对窗口图层的内容做一些修改(这部分比较简单,直接上代码)
//HariMain节选
make_window8(buf_win, , , "counter"); //窗口标题:counter
sheet_slide(sht_back, , ); //设置背景图层的上下滑动
mx = (binfo->scrnx - ) / ; /* 把鼠标放在屏幕中间 */
my = (binfo->scrny - - ) / ;
sheet_slide(sht_mouse, mx, my); //鼠标图层的上下滑动
sheet_slide(sht_win, , ); //窗口图层的上下滑动
sheet_updown(sht_back, ); //图层的高度
sheet_updown(sht_win, );
sheet_updown(sht_mouse, );
sprintf(s, "(%3d, %3d)", mx, my); //输出坐标位置
putfonts8_asc(buf_back, binfo->scrnx, , , COL8_FFFFFF, s);
sprintf(s, "memory %dMB free : %dKB",
memtotal / ( * ), memman_total(memman) / );
putfonts8_asc(buf_back, binfo->scrnx, , , COL8_FFFFFF, s);
sheet_refresh(sht_back, , , binfo->scrnx, );//刷新显示界面
harib08g:
我们make run一下,发现窗口中的内容在不断的闪烁。到这里位置,我们每次刷新显示都是从最低图层开始,一直向上把所有的图层都王VRAM中写一遍。但是很多图层的内容是没有变化的(比如背景图层);在这里我们做以下消除闪烁的优化处理:仅对refresh对象及以上的图层进行刷新就行了。
1、修改完成刷新工作的sheet_refreshsub()函数:追加一个参数h0表示需要刷新的最低图层。这样在循环处加一个判断条件:for (h = h0; h <= ctl->top; h++)只对层数比h0高的图层进行刷新;
2、修改相关的函数:上面我们对sheet_refreshsub()函数追加了h0参数,接下来我们把所有调用了sheet_refreshsub()的函数都修改一下。
sheet_refreshsub(sht->ctl, sht->vx0 + bx0, sht->vy0 + by0, sht->vx0 + bx1, sht->vy0 + by1, sht->height);
harib08h:
上面我们已经消除了窗口刷新时的闪烁,接下来我们来消除鼠标的闪烁!
1、map(地图)的定义和初始化:开辟一块和VRAM大小一样的内存--map;这块内存用来表示画面上的点是那个图层的像素,所以相当于是图层的地图。我们要理解作者的用意:map和VRAM设计成大小一样的,就是要把map当做一个中间的缓冲区域(相当于VRAM的一个缓存),这样可以对VRAM的操作进行加速。
//bootpack.h和sheet.c节选
//定 义:map定义在图层管理结构体中
struct SHTCTL {
unsigned char *vram, *map;
int xsize, ysize, top;
struct SHEET *sheets[MAX_SHEETS];
struct SHEET sheets0[MAX_SHEETS];
};
//初始化:在图层管理初始化函数中做相应修改
struct SHTCTL *shtctl_init(struct MEMMAN *memman, unsigned char *vram, int xsize, int ysize)
{
//...函数节选: ................
//开辟一个4KB的内存空间,map指向这个空间起始地址
ctl->map = (unsigned char *) memman_alloc_4k(memman, xsize * ysize);
if (ctl->map == ) { //空间开辟失败,报错前先释放
memman_free_4k(memman, (int) ctl, sizeof (struct SHTCTL));
goto err;
}
ctl->vram = vram; //图层管理结构体其他变量的初始化
ctl->xsize = xsize;
ctl->ysize = ysize;
ctl->top = -; /* 隐藏,表示现在没有任何图层 */
for (i = ; i < MAX_SHEETS; i++) {
ctl->sheets0[i].flags = ; /* 图层标识FLAG=0表示该图层没有被使用 */
ctl->sheets0[i].ctl = ctl; /* 初始化图层ctl为图层管理结构体的地址 */
}
err:
return ctl;
}
2、在map中写入图层号码:我们用当前图层的地址(sht)减去第一块图层的地址(ctl->sheets0)的偏移量来表示该图层的号码sid(sheet ID)
图片P215的图片来一个;
void sheet_refreshmap(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0)
{
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
unsigned char *buf, sid, *map = ctl->map;
struct SHEET *sht;
if (vx0 < ) { vx0 = ; }
if (vy0 < ) { vy0 = ; }
if (vx1 > ctl->xsize) { vx1 = ctl->xsize; }
if (vy1 > ctl->ysize) { vy1 = ctl->ysize; }
for (h = h0; h <= ctl->top; h++) {
sht = ctl->sheets[h];
//前图层的地址(sht)减去第一块图层的地址(ctl->sheets0)的偏移量
sid = sht - ctl->sheets0; /* 将进行减法运算的地址作为图层号码使用 */
buf = sht->buf;
bx0 = vx0 - sht->vx0;
by0 = vy0 - sht->vy0;
bx1 = vx1 - sht->vx0;
by1 = vy1 - sht->vy0;
if (bx0 < ) { bx0 = ; }
if (by0 < ) { by0 = ; }
if (bx1 > sht->bxsize) { bx1 = sht->bxsize; }
if (by1 > sht->bysize) { by1 = sht->bysize; }
for (by = by0; by < by1; by++) {
vy = sht->vy0 + by;
for (bx = bx0; bx < bx1; bx++) {
vx = sht->vx0 + bx;
if (buf[by * sht->bxsize + bx] != sht->col_inv) {
//在对需要刷新的部分进行刷新时,不再是写到VRAM中,而是将该像素的sid写到map中
map[vy * ctl->xsize + vx] = sid;
}
}
}
}
return;
}
3、对sheet_refreshsub进行改写,让它可以使用map
void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0, int h1)
{
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
unsigned char *buf, *vram = ctl->vram, *map = ctl->map, sid;
struct SHEET *sht;
/* refresh刷新的范围超出了画面 */
//.......................
for (h = h0; h <= h1; h++) { //只对h0到h1的图层进行跟新操作
sht = ctl->sheets[h]; //当前图层的地址
buf = sht->buf; //当前图层的缓冲区内容
sid = sht - ctl->sheets0;//计算当前图层sid的值
/* 倒推出刷新的范围(不懂看前一天的内容) */
bx0 = vx0 - sht->vx0;
by0 = vy0 - sht->vy0;
bx1 = vx1 - sht->vx0;
by1 = vy1 - sht->vy0;
if (bx0 < ) { bx0 = ; }
if (by0 < ) { by0 = ; }
if (bx1 > sht->bxsize) { bx1 = sht->bxsize; }
if (by1 > sht->bysize) { by1 = sht->bysize; }
for (by = by0; by < by1; by++) {
vy = sht->vy0 + by;
for (bx = bx0; bx < bx1; bx++) {
vx = sht->vx0 + bx;
//只有当前sid和map中该像素处sid相等,才将缓存写到VRAM中
if (map[vy * ctl->xsize + vx] == sid) {
vram[vy * ctl->xsize + vx] = buf[by * sht->bxsize + bx];
}
}
}
}
return;
}
4、修改调用了sheet_refreshsub()的3个函数:在函数sheet_refresh()\sheet_slide()\sheet-updown中都对函数sheet_refreshsub()有调用,我们找到这三个函数的相应位置,按照sheet_refreshsub()新的参数,重写一下调用.
《30天自制操作系统》11_day_学习笔记的更多相关文章
- 《30天自制操作系统》学习笔记--Mac下工具的使用
现在来介绍官网上下的工具怎么用首先是官网地址,书上有个注释上有:hrb.osask.jp 翻译成中文大概是这个样子滴. 上面有两个文件可以下载,一个是工具,一个是工具的源代码,很好的学习资料 下面把工 ...
- 《30天自制操作系统》学习笔记--Mac环境搭建
弄了三天了,终于弄好了,先说结果,就是作者在网站上放了os x的工具(hrb.osask.jp,也有linux下的工具,可以自己去下载),也就是说我白忙活了三天... 再说一下这几天都干啥了,主要是想 ...
- 《30天自制操作系统》学习笔记--番外篇之Mac环境下的工具介绍
这几天又有点不务正业了,书也没看,一直在搞这个破环境,尝试各种做法,网上各种垃圾信息,浪费了很多时间,说的基本都是废话,不过还是找到了一些,赶紧写下来,不然这个过几天又忘了 首先是环境,我用的是Max ...
- 《30天自制操作系统》读书笔记(5) GDT&IDT
梳理项目结构 项目做到现在, 前头的好多东西都忘了, 还是通过Makefile重新理解一下整个项目是如何编译的: 现在我们拥有这么9个文件: ipl10.nas InitialProgramLo ...
- 《30天自制操作系统》读书笔记(3) 引入C语言
这一次的学习相当曲折, 主要是因为粗心, Makefile里面的错误导致了文件生成出现各种奇奇怪怪的问题, 弄得心力交瘁, 因此制作过程还是尽量按着作者的路子来吧. 作者提供的源码的注释在中文系统下是 ...
- 《30天自制操作系统》读书笔记(2)hello, world
让系统跑起来 要写一个操作系统,我们首先要有一个储存系统的介质,原版书似乎是06年出版的,可惜那时候没有电脑,没想到作者用的还是软盘,现在的电脑谁有软驱?不得已我使用一张128M的SD卡来代替,而事实 ...
- 30天自制操作系统第九天学习笔记(u盘软盘双启动版本)
暑假学习小日本的那本书:30天自制操作系统 qq交流群:122358078 ,更多学习中的问题.资料,群里分享 environment:开发环境:ubuntu 第九天的课程已学完,确实有点不想写 ...
- 从你的u盘启动:30天自制操作系统第四天u盘启动学习笔记
暑假学习小日本的那本书:30天自制操作系统 qq交流群:122358078 ,更多学习中的问题.资料,群里分享 developing environment:ubuntu 关于u盘启动自己做的操 ...
- 30天自制操作系统第八天学习笔记(u盘软盘双启动版本)
暑假学习小日本的那本书:30天自制操作系统 qq交流群:122358078 ,更多学习中的问题.资料,群里分享 environment:开发环境:ubuntu 第八天的学习思考: 关于鼠标是怎么 ...
- 《30天自制操作系统》笔记(03)——使用Vmware
<30天自制操作系统>笔记(03)——使用Vmware 进度回顾 在上一篇,实现了用IPL加载OS程序到内存,然后JMP到OS程序这一功能:并且总结出下一步的OS开发结构.但是遇到了真机测 ...
随机推荐
- Bootstrap页面布局2 - 包含BS文件
如图所示: bootstrap布局基于HTML5,为了使IE8以下也能使用某些HTML5的标签,必须要引入文件:http://html5shiv.googlecode.com/svn/trunk/ht ...
- Asp.net 服务器Application,Session,Cookie,ViewState和Cache区别
2.8 Context 的使用Context 对象包含与当前页面相关的信息,提供对整个上下文的访问,包括请求.响应.以及上文中的Session 和Application 等信息.可以使用此对象在网页之 ...
- Android 网络连接判断与处理
Android网络连接判断与处理 获取网络信息需要在AndroidManifest.xml文件中加入相应的权限. <uses-permission android:name="and ...
- 将真彩色转换成增强色的方法(即RGB32位或RGB24位颜色转换成RGB16位颜色的函数)
今天由于程序需要,需要将真彩色转换成增强色进行颜色匹配,上网搜了一下没搜到相应函数,于是研究了一下RGB16位的增强色,写了这个函数: public static int RGB16(int argb ...
- 面向对象之abstract
1.abstract class,抽象类不能被实例化,只能被继承:抽象类中可以包含非抽象方法 2.abstract method();抽象方法只能在抽象类中进行声明,并且没有方法体,非抽象继承子类中必 ...
- Android 4.2蓝牙介绍
蓝牙一词源于公元十世纪丹麦国王HaraldBlatand名字中的Blatand.Blatand的英文之意就是Blue tooth.这是因为这位让丹麦人引以为傲的国王酷爱吃蓝莓以至于牙龈都被染成蓝色.由 ...
- Git and Xcode
1.web site "New Repository" 2.为本地 git 管理的项目添加 Repository $ cd ~/ProjectName$ git remote ad ...
- javaScript中的单引号与双引号
javaScript中的单引号与双引号没有什么区别.但因为xhtml规范要求所有xhtml属性要用双引号括起来.所以在javaScript中使用单引号. var html = '<h2 clas ...
- background和background-size
今天偶遇一个小问题. 添加logo图片时, 由于不需要重新定位图片位置,就准备偷懒在间歇属性中省略background-position的属性,然而很不幸的是,结果却是酱紫的(谷歌浏览器): 不能加载 ...
- Win7局域网文件共享方法
右击桌面网络----属性----更改高级共享设置 (注释:查看当前网络 比如:家庭网络.公共网络 等!) "我这里为公共网络" 选择 公共网络---选择以下选项:启动网络发 ...