30天自制操作系统日志第11天文档格式.docx
- 文档编号:16174154
- 上传时间:2022-11-21
- 格式:DOCX
- 页数:18
- 大小:1.53MB
30天自制操作系统日志第11天文档格式.docx
《30天自制操作系统日志第11天文档格式.docx》由会员分享,可在线阅读,更多相关《30天自制操作系统日志第11天文档格式.docx(18页珍藏版)》请在冰豆网上搜索。
xsize){vx1=ctl->
xsize;
if(vy1>
ysize){vy1=ctl->
ysize;
很好,这样就可以了,以后移动窗口到画面外也可以正确实现了。
诶,很多函数都有一个形参structSHTCTL*,每次调用函数都要传实参,有点麻烦,所以作者牺牲了一些内存,给每个图层都定义一个指向图层管理的指针,这样就可以减少函数的一个形参了。
1、structSHEET中加入structSHTCTL*ctl
//在图层的结构体定义structSHEET中,加入图层控制结构体指针structSHTCTL*ctl
structSHEET{
unsignedchar*buf;
intbxsize,bysize,vx0,vy0,col_inv,height,flags;
structSHTCTL*ctl;
//图层控制结构体指针structSHTCTL*ctl
};
2、对函数shtclt_init进行追加
//追加内容:
将ctl初始化为图层控制结构体
for(i=0;
i<
MAX_SHEETS;
i++){
ctl->
sheets0[i].flags=0;
/*FLAG=0表示该图层未被使用*/
sheets0[i].ctl=ctl;
/*指针ctl指向图层控制结构体*/
}
3、对函数sheet_undown进行修改
//修改内容:
将ctl初始化为图层控制结构体
voidsheet_updown(structSHEET*sht,intheight)
{
structSHTCTL*ctl=sht->
ctl;
/*指针ctl指向图层控制结构体*/
inth,old=sht->
height;
/*记录设置前图层的高度*/
//........
这样我们再修改一下使用到structSHTCTL*作形参的函数,删掉这个形参就好了,就不用送实参进去了。
这样我们的窗口准备就完善了。
2、制作窗口
为制作窗口做了很多准备,所以制作起来并实现功能也简单了很多,我们效仿设计鼠标的显示方法,也开辟了一块跟buf_mouse[256]一样的缓冲区*buf_win(动态内存),用来保存像素值,需要显示时,可以从里面读出并写到对应的显存里。
voidmake_window8(unsignedchar*buf,intxsize,intysize,char*title)
staticcharclosebtn[14][16]={//窗口关闭按钮X的的数组
"
OOOOOOOOOOOOOOO@"
OQQQQQQQQQQQQQ$@"
OQQQ@@QQQQ@@QQ$@"
OQQQQ@@QQ@@QQQ$@"
OQQQQQ@@@@QQQQ$@"
OQQQQQQ@@QQQQQ$@"
O$$$$$$$$$$$$$$@"
@@@@@@@@@@@@@@@@"
};
intx,y;
charc;
//窗口的颜色填充,(应该是前景)
boxfill8(buf,xsize,COL8_C6C6C6,0,0,xsize-1,0);
boxfill8(buf,xsize,COL8_FFFFFF,1,1,xsize-2,1);
boxfill8(buf,xsize,COL8_C6C6C6,0,0,0,ysize-1);
boxfill8(buf,xsize,COL8_FFFFFF,1,1,1,ysize-2);
boxfill8(buf,xsize,COL8_848484,xsize-2,1,xsize-2,ysize-2);
boxfill8(buf,xsize,COL8_000000,xsize-1,0,xsize-1,ysize-1);
boxfill8(buf,xsize,COL8_C6C6C6,2,2,xsize-3,ysize-3);
boxfill8(buf,xsize,COL8_000084,3,3,xsize-4,20);
boxfill8(buf,xsize,COL8_848484,1,ysize-2,xsize-2,ysize-2);
boxfill8(buf,xsize,COL8_000000,0,ysize-1,xsize-1,ysize-1);
putfonts8_asc(buf,xsize,24,4,COL8_FFFFFF,title);
//显示窗口的额标题
for(y=0;
y<
14;
y++){
for(x=0;
x<
16;
x++){ //这里对关闭按钮的颜色进行设定
c=closebtn[y][x];
//关闭按钮数组中不同的字符用特定的显示颜色来显示出来
if(c=='
@'
){
c=COL8_000000;
}elseif(c=='
$'
c=COL8_848484;
Q'
c=COL8_C6C6C6;
}else{
c=COL8_FFFFFF;
buf[(5+y)*xsize+(xsize-21+x)]=c;
//把这个颜色的值,给VRAM缓冲区
return;
这里就写好了制作窗口的函数,接下来我们只要在主函数上实现就好了:
//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=(unsignedchar*)memman_alloc_4k(memman,binfo->
scrnx*binfo->
buf_win=(unsignedchar*)memman_alloc_4k(memman,160*68);
sheet_setbuf(sht_back,buf_back,binfo->
scrny,-1);
/*设置图层缓冲区,没有透明色*/
sheet_setbuf(sht_mouse,buf_mouse,16,16,99);
sheet_setbuf(sht_win,buf_win,160,68,-1);
/*设置图层缓冲区,没有透明色*/
init_screen8(buf_back,binfo->
//初始化屏幕界面
init_mouse_cursor8(buf_mouse,99);
//X按钮的功能键
make_window8(buf_win,160,68,"
window"
);
//制作窗口图层buf_win
putfonts8_asc(buf_win,160,24,28,COL8_000000,"
Welcometo"
//在图层buf_win中显示两串字符串
putfonts8_asc(buf_win,160,24,44,COL8_000000,"
Haribote-OS!
"
sheet_slide(sht_back,0,0);
//图层上下滑动的函数,因为要让鼠标图层在窗口图层上方移动
mx=(binfo->
scrnx-16)/2;
/*这里把鼠标放在屏幕中间的位置*/
my=(binfo->
scrny-28-16)/2;
sheet_slide(sht_mouse,mx,my);
//设置鼠标图层的上下滑动
sheet_slide(sht_win,80,72);
//设置窗口图层sht_win的上下滑动
sheet_updown(sht_back,0);
//设定背景图层的高度为0(在最底层)
sheet_updown(sht_win,1);
//设置窗口图层的高度为1(在中间层)
sheet_updown(sht_mouse,2);
//设置鼠标图层的高度为2(在最上层)
sprintf(s,"
(%3d,%3d)"
mx,my);
//在背景层打印出坐标的位置
putfonts8_asc(buf_back,binfo->
scrnx,0,0,COL8_FFFFFF,s);
memory%dMBfree:
%dKB"
//打印出内存使用情况
memtotal/(1024*1024),memman_total(memman)/1024);
scrnx,0,32,COL8_FFFFFF,s);
sheet_refresh(sht_back,0,0,binfo->
scrnx,48);
//刷新屏幕显示
3、让窗口有个功能然后改进一下。
这里作者给窗口一个计数的功能,程序自动计数。
就是要让窗口里显示新定义的变量counter的值就好了。
然后数字改变就刷新一下窗口里数值的范围就好了。
make_window8(buf_win,160,52,"
counter"
//窗口标题:
counter
//设置背景图层的上下滑动
/*把鼠标放在屏幕中间*/
//鼠标图层的上下滑动
//窗口图层的上下滑动
//图层的高度
//输出坐标位置
memtotal/(1024*1024),memman_total(memman)/1024);
sheet_refresh(sht_back,0,0,binfo->
//刷新显示界面
诶,我们发现这里窗口其实改变的只有窗口里数值的内容,但是在这个范围内的图层全部都刷新了一遍,但其实我们只要刷新该图层以及它上边的图层(包括鼠标)就好了。
那么又要改sheet_refreshsub()了,让它从当前图层开始刷新,所以要加一个形参表示当前图层高度h0。
这样我们在循环处更改为:
for(h=h0;
h<
=ctl->
top;
h++)
就好了,然后再一次修改有调用到sheet_refreshsub()的函数就好了。
4、消除闪烁
map(地图)的定义和初始化:
开辟一块和VRAM大小一样的内存--map;
这块内存用来表示画面上的点是那个图层的像素,所以相当于是图层的地图。
我们要理解作者的用意:
map和VRAM设计成大小一样的,就是要把map当做一个中间的缓冲区域(相当于VRAM的一个缓存),这样可以对VRAM的操作进行加速。
//bootpack.h和sheet.c节选
//定义:
map定义在图层管理结构体中
structSHTCTL{
unsignedchar*vram,*map;
intxsize,ysize,top;
structSHEET*sheets[MAX_SHEETS];
structSHEETsheets0[MAX_SHEETS];
//初始化:
在图层管理初始化函数中做相应修改
structSHTCTL*shtctl_init(structMEMMAN*memman,unsignedchar*vram,intxsize,intysize)
//...函数节选:
................
//开辟一个4KB的内存空间,map指向这个空间起始地址
map=(unsignedchar*)memman_alloc_4k(memman,xsize*ysize);
if(ctl->
map==0){ //空间开辟失败,报错前先释放
memman_free_4k(memman,(int)ctl,sizeof(structSHTCTL));
gotoerr;
vram=vram;
//图层管理结构体其他变量的初始化
xsize=xsize;
ysize=ysize;
top=-1;
/*隐藏,表示现在没有任何图层*/
for(i=0;
/*图层标识FLAG=0表示该图层没有被使用*/
/*初始化图层ctl为图层管理结构体的地址*/
err:
returnctl;
在map中写入图层号码:
我们用当前图层的地址(sht)减去第一块图层的地址(ctl->
sheets0)的偏移量来表示该图层的号码sid(sheetID)
voidsheet_refreshmap(structSHTCTL*ctl,intvx0,intvy0,intvx1,intvy1,inth0)
inth,bx,by,vx,vy,bx0,by0,bx1,by1;
unsignedchar*buf,sid,*map=ctl->
map;
structSHEET*sht;
if(vx0<
if(vy0<
if(vx1>
if(vy1>
for(h=h0;
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->
by1=vy1-sht->
if(bx0<
0){bx0=0;
if(by0<
0){by0=0;
if(bx1>
sht->
bxsize){bx1=sht->
bxsize;
if(by1>
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;
对sheet_refreshsub进行改写,让它可以使用map
voidsheet_refreshsub(structSHTCTL*ctl,intvx0,intvy0,intvx1,intvy1,inth0,inth1)
unsignedchar*buf,*vram=ctl->
vram,*map=ctl->
map,sid;
/*refresh刷新的范围超出了画面*/
//.......................
=h1;
h++){//只对h0到h1的图层进行跟新操作
//当前图层的地址
//当前图层的缓冲区内容
//计算当前图层sid的值
/*倒推出刷新的范围(不懂看前一天的内容)*/
//只有当前sid和map中该像素处sid相等,才将缓存写到VRAM中
if(map[vy*ctl->
xsize+vx]==sid){
vram[vy*ctl->
xsize+vx]=buf[by*sht->
bxsize+bx];
二、遇到的问题及解决方法
1、我一开始真的真的不知道图层管理里面那个指针数组*sheets,到底是干什么用的,因为我一直找不到它指向结构体数组的地方。
当我以为这两可能真没什么联系的时候,我看到了这句:
天呐,sheets肯定指向sheets0,那到底是在哪里指向的,不应该初始化的时候就指向它了吗,为什么没有看见,看了半天,原来只有调用updown函数的时候,才让sheets指向sheets0,我一直以为top在图层分配进图层管理的时候就++了,原来是让图层开始显示,做这部初始化的时候才给sheets的用途。
如下:
看到这才终于明白这个的指向,这样我们队不同窗口进行独立管理的时候也能更方便的找出目前最顶层减1层的是哪一个窗口了。
2、添加窗口的步骤:
(1)开辟一块动态数组给窗口,定义一个指针指向该空间首地址;
(2)制作绘制窗口的函数,即对窗口大小、像素值等的初始化;
(3)将窗口图层分配进图层管理里,定义一个指针指向对应数组的首地址
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 30 自制 操作系统 日志 11