30天自制操作系统 杂谈2
Quote
作者: “所谓开发操作系统,就是想办法制作一张‘含有操作系统的,能够自动启动的 磁盘’。
作者:一上来要求太多的话,就没有办法往前进展了。
小恶魔·兰尼斯特:…我们一次只玩一个游戏。
显示字符
由于我们采用的是32位模式,不能依赖BIOS,只能自力更生了。假定采用8x16的像素点阵去表示:
易得字符输出函数:
void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
{
int i;
char *p, d;
for (i = 0; i < 16; i++) {
p = vram + (y + i) * xsize + x;
d = font[i];
if ((d & 0x80) != 0) { p[0] = c; } //x80=1000 0000
if ((d & 0x40) != 0) { p[1] = c; } //x40=0100 0000
if ((d & 0x20) != 0) { p[2] = c; } //...
if ((d & 0x10) != 0) { p[3] = c; }
if ((d & 0x08) != 0) { p[4] = c; }
if ((d & 0x04) != 0) { p[5] = c; }
if ((d & 0x02) != 0) { p[6] = c; }
if ((d & 0x01) != 0) { p[7] = c; }
}
return;
}
//主函数内:
static char font_A[16] = {
0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24,
0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00
};
putfont8(binfo->vram, binfo->scrnx, 10, 10, COL8_FFFFFF, font_A);
为了能输出其他字符我们用到hankaku.txt,里面还有其他字符的字体数据,且按照ASCLL字符编码。
例如,A的字体数据放在“hankaku+0x41*16"开始的16字节里面。所以我们可以改变主函数的内容。
putfont8(binfo->vram, binfo->scrnx, 8, 8, COL8_FFFFFF, hankaku + 'A' * 16);
更进一步,从显示一个字符到显示一个字符串,我们可以写一个函数:
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
{
extern char hankaku[4096];
for (; *s != 0x00; s++) {
putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
x += 8;
}
return;
}
#当然在Makefile文件生成规则里加上:
hankaku.bin : hankaku.txt Makefile
$(MAKEFONT) hankaku.txt hankaku.bin
hankaku.obj : hankaku.bin Makefile
$(BIN2OBJ) hankaku.bin hankaku.obj _hankaku #实现和其他obj文件编译链接
描绘鼠标指针
既然能显示字符,鼠标指针也不是难事(而且我们可以自行DIY字体和鼠标指针样式)。我们假定用16x16的方阵去表示:
void init_mouse_cursor8(char *mouse, char bc)
{
static char cursor[16][16] = {
"**************..",
"*OOOOOOOOOOO*...",
"*OOOOOOOOOO*....",
"*OOOOOOOOO*.....",
"*OOOOOOOO*......",
"*OOOOOOO*.......",
"*OOOOOOO*.......",
"*OOOOOOOO*......",
"*OOOO**OOO*.....",
"*OOO*..*OOO*....",
"*OO*....*OOO*...",
"*O*......*OOO*..",
"**........*OOO*.",
"*..........*OOO*",
"............*OO*",
".............***"
};
int x, y;
for (y = 0; y < 16; y++) {
for (x = 0; x < 16; x++) {
if (cursor[y][x] == '*') {
mouse[y * 16 + x] = COL8_000000;
}
if (cursor[y][x] == 'O') {
mouse[y * 16 + x] = COL8_FFFFFF;
}
if (cursor[y][x] == '.') {
mouse[y * 16 + x] = bc;
}
}
}
return;
}
//显示背景色
void putblock8_8(char *vram, int vxsize, int pxsize,
int pysize, int px0, int py0, char *buf, int bxsize)
{
int x, y;
for (y = 0; y < pysize; y++) {
for (x = 0; x < pxsize; x++) {
vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
}
}
return;
}
init_mouse_cursor8(mcursor, COL8_008484);
putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);
最后附上效果图(变量也是同理输出):
void HariMain(void)
{
struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
char s[40], mcursor[256];
int mx, my;
init_gdtidt();
init_palette();
init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);
mx = (binfo->scrnx - 16) / 2;
my = (binfo->scrny - 28 - 16) / 2;
init_mouse_cursor8(mcursor, COL8_008484);
putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);
sprintf(s, "(%d, %d)", mx, my);
putfonts8_asc(binfo->vram, binfo->scrnx, 6, 1, COL8_000000, "SNNOPY OS"); //阴影效果
putfonts8_asc(binfo->vram, binfo->scrnx, 5, 0, COL8_FFFFFF, "SNNOPY OS");
putfonts8_asc(binfo->vram, binfo->scrnx, 6, 19, COL8_000000, s); //阴影效果
putfonts8_asc(binfo->vram, binfo->scrnx, 5, 18, COL8_FFFFFF, s);
for (;;) {
io_hlt();
}
}
这里笔者就给第一个OS取名SNNOPY了,个人觉得阴影效果还是很赞的。当然我们还没有实现鼠标的移动功能,在此之前我们还需要完成分段,中断处理,以后再说吧。