3 增加窗口数量(harib13c)
在16.1节中我们已经对任务的新增做了简化,因此接下来我们要为系统增加更多的任务,即形成任务A、任务B0、任务B1和任务B2的格局。
任务B0~B2各自拥有自己的窗口,它们的功能都一样,即进行计数,这有点像在Windows中启动了一个应用程序及其2个副本的感觉。对了,任务A的3秒定时和10秒定时我们已经不需要了,因此将它们删去。
本次的bootpack.c节选
void HariMain(void)
{
(中略)
unsigned char *buf_back, buf_mouse[256], *buf_win, *buf_win_b;
struct SHEET *sht_back, *sht_mouse, *sht_win, *sht_win_b[3];
struct TASK *task_a, *task_b[3];
struct TIMER *timer;
(中略)
init_palette();
shtctl = shtctl_init(memman, binfo->vram, binfo->scrnx, binfo->scrny);
task_a = task_init(memman);
fifo.task = task_a;
/* sht_back */
sht_back = sheet_alloc(shtctl);
buf_back = (unsigned char *) memman_alloc_4k(memman, binfo->scrnx * binfo->scrny);
sheet_setbuf(sht_back, buf_back, binfo->scrnx, binfo->scrny, -1); /*无透明色 */
init_screen8(buf_back, binfo->scrnx, binfo->scrny);
/* sht_win_b */
for (i = 0; i < 3; i++) {
sht_win_b[i] = sheet_alloc(shtctl);
buf_win_b = (unsigned char *) memman_alloc_4k(memman, 144 * 52);
sheet_setbuf(sht_win_b[i], buf_win_b, 144, 52, -1); /*无透明色*/
sprintf(s, "task_b%d", i);
make_window8(buf_win_b, 144, 52, s, 0);
task_b[i] = task_alloc();
task_b[i]->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024 - 8;
task_b[i]->tss.eip = (int) &task_b_main;
task_b[i]->tss.es = 1 * 8;
task_b[i]->tss.cs = 2 * 8;
task_b[i]->tss.ss = 1 * 8;
task_b[i]->tss.ds = 1 * 8;
task_b[i]->tss.fs = 1 * 8;
task_b[i]->tss.gs = 1 * 8;
*((int *) (task_b[i]->tss.esp + 4)) = (int) sht_win_b[i];
task_run(task_b[i]);
}
/* sht_win */
sht_win = sheet_alloc(shtctl);
buf_win = (unsigned char *) memman_alloc_4k(memman, 160 * 52);
sheet_setbuf(sht_win, buf_win, 144, 52, -1); /*无透明色*/
make_window8(buf_win, 144, 52, "task_a", 1);
make_textbox8(sht_win, 8, 28, 128, 16, COL8_FFFFFF);
cursor_x = 8;
cursor_c = COL8_FFFFFF;
timer = timer_alloc();
timer_init(timer, &fifo, 1);
timer_settime(timer, 50);
/* sht_mouse */
sht_mouse = sheet_alloc(shtctl);
sheet_setbuf(sht_mouse, buf_mouse, 16, 16, 99);
init_mouse_cursor8(buf_mouse, 99);
mx = (binfo->scrnx - 16) / 2; /*计算坐标使其位于画面中央*/
my = (binfo->scrny - 28 - 16) / 2;
sheet_slide(sht_back, 0, 0);
sheet_slide(sht_win_b[0], 168, 56);
sheet_slide(sht_win_b[1], 8, 116);
sheet_slide(sht_win_b[2], 168, 116);
sheet_slide(sht_win, 8, 56);
sheet_slide(sht_mouse, mx, my);
sheet_updown(sht_back, 0);
sheet_updown(sht_win_b[0], 1);
sheet_updown(sht_win_b[1], 2);
sheet_updown(sht_win_b[2], 3);
sheet_updown(sht_win, 4);
sheet_updown(sht_mouse, 5);
sprintf(s, "(%3d, %3d)", mx, my);
putfonts8_asc_sht(sht_back, 0, 0, COL8_FFFFFF, COL8_008484, s, 10);
sprintf(s, "memory %dMB free : %dKB",
memtotal / (1024 * 1024), memman_total(memman) / 1024);
putfonts8_asc_sht(sht_back, 0, 32, COL8_FFFFFF, COL8_008484, s, 40);
for (;;) {
io_cli();
if (fifo32_status(&fifo) == 0) {
task_sleep(task_a);
io_sti();
} else {
i = fifo32_get(&fifo);
io_sti();
if (256 <= i && i <= 511) { /*键盘数据*/
(中略)
} else if (512 <= i && i <= 767) { /*光标用定时器*/
(中略)
} else if (i <= 1) { /*光标用定时器*/
(中略)
}
}
}
}
void make_window8(unsigned char *buf, int xsize, int ysize, char *title, char act)
{
(中略)
char c, tc, tbc;
if (act != 0) {
tc = COL8_FFFFFF;
tbc = COL8_000084;
} else {
tc = COL8_C6C6C6;
tbc = COL8_848484;
}
(中略)
boxfill8(buf, xsize, tbc, 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, tc, title);
for (y = 0; y < 14; y++) {
(中略)
}
return;
}
void task_b_main(struct SHEET *sht_win_b)
{
struct FIFO32 fifo;
struct TIMER *timer_1s;
int i, fifobuf[128], count = 0, count0 = 0;
char s[12];
fifo32_init(&fifo, 128, fifobuf, 0);
timer_1s = timer_alloc();
timer_init(timer_1s, &fifo, 100);
timer_settime(timer_1s, 100);
for (;;) {
count++;
io_cli();
if (fifo32_status(&fifo) == 0) {
io_sti();
} else {
i = fifo32_get(&fifo);
io_sti();
if (i == 100) {
sprintf(s, "%11d", count - count0);
putfonts8_asc_sht(sht_win_b, 24, 28, COL8_000000, COL8_C6C6C6, s, 11);
count0 = count;
timer_settime(timer_1s, 100);
}
}
}
}
这次的代码相当长,不过我们只是对之前的程序进行了整理,难度并没有提高。不要被代码的长度吓倒,只要静下心来仔细读一读,应该很快就会理解的。
在make_window8中我们增加了一个act变量。当act为1时,颜色不变,当为0时,窗口的标题栏(就是显示窗口名称的地方)会变成灰色。task_b_main中,去掉了每0.01秒显示一次count的部分,只保留每1秒显示速度的功能。
■■■■■
我们来运行一下,“make run”。怎么样,是不是感觉更像操作系统了呢?对了,现在只有任务A的窗口是可以拖动的(因为移动窗口的部分没有改写进去)。
任务B0~B2这3个任务基本上是以同样的速度在运行。在模拟器环境下它们的速度会有所差异,但在真机环境下还是十分接近的,如下:
4684200 4684800 4684800
4个任务在同时工作
看来运行非常成功。