3 刷新窗口(harib20c)
在写stars.hrb的时候突然想到一个问题,现在每次调用api_point画点,窗口都会被刷新一次,这样感觉会非常慢,还不如把星星都画好之后,最后再刷新一次窗口,这样应该会快一些。
于是,我们需要在所有的窗口绘图命令中设置一个“不自动刷新”的选项,然后再编写一个仅用来刷新的API。
这个选项要如何指定呢?窗口句柄归根到底是struct SHEET的地址,这一定是一个偶数,那么我们可以让程序在指定一个奇数(即在原来的数值上加1)的情况下不进行自动刷新。
仅用来刷新的API式样如下。
刷新窗口
EDX = 12
EBX = 窗口句柄
EAX = x0
ECX = y0
ESI = x1
EDI = y1
■■■■■
修改操作系统,具体如下。
本次的console.c节选
int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
{
(中略)
} else if (edx == 6) {
sht = (struct SHEET *) (ebx & 0xfffffffe);
putfonts8_asc(sht->buf, sht->bxsize, esi, edi, eax, (char *) ebp + ds_base);
if ((ebx & 1) == 0) {
sheet_refresh(sht, esi, edi, esi + ecx * 8, edi + 16);
}
} else if (edx == 7) {
sht = (struct SHEET *) (ebx & 0xfffffffe);
boxfill8(sht->buf, sht->bxsize, ebp, eax, ecx, esi, edi);
if ((ebx & 1) == 0) {
sheet_refresh(sht, eax, ecx, esi + 1, edi + 1);
}
} else if (edx == 8) {
(中略)
} else if (edx == 9) {
(中略)
} else if (edx == 10) {
(中略)
} else if (edx == 11) {
sht = (struct SHEET *) (ebx & 0xfffffffe);
sht->buf[sht->bxsize * edi + esi] = eax;
if ((ebx & 1) == 0) {
sheet_refresh(sht, esi, edi, esi + 1, edi + 1);
}
} else if (edx == 12) {
sht = (struct SHEET *) ebx;
sheet_refresh(sht, eax, ecx, esi, edi);
}
return 0;
}
在计算sht的地方,我们将ebx和0xfffffffe做了一个AND运算,即对其按2的倍数取整。然后在判断是否需要刷新的if语句中,我们将ebx最低的一个比特用AND取出,判断其是否为0,如为0则表示其除以2的余数为0,也就是偶数。
■■■■■
用上面的功能,我们来编写stars2.c。
本次的a_nask.nas节选
_api_refreshwin: ; void api_refreshwin(int win, int x0, int y0, int x1, int y1);
PUSH EDI
PUSH ESI
PUSH EBX
MOV EDX,12
MOV EBX,[ESP+16] ; win
MOV EAX,[ESP+20] ; x0
MOV ECX,[ESP+24] ; y0
MOV ESI,[ESP+28] ; x1
MOV EDI,[ESP+32] ; y1
INT 0x40
POP EBX
POP ESI
POP EDI
RET
本次的stars2.c
int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);
void api_boxfilwin(int win, int x0, int y0, int x1, int y1, int col);
void api_initmalloc(void);
char *api_malloc(int size);
void api_point(int win, int x, int y, int col);
void api_refreshwin(int win, int x0, int y0, int x1, int y1);
void api_end(void);
int rand(void); /*产生0~32767的随机数*/
void HariMain(void)
{
char *buf;
int win, i, x, y;
api_initmalloc();
buf = api_malloc(150 * 100);
win = api_openwin(buf, 150, 100, -1, "stars2");
api_boxfilwin(win + 1, 6, 26, 143, 93, 0 /*黑色*/);
for (i = 0; i < 50; i++) {
x = (rand() % 137) + 6;
y = (rand() % 67) + 26;
api_point(win + 1, x, y, 3 /*黄色*/);
}
api_refreshwin(win, 6, 26, 144, 94);
api_end();
}
好了,这个也很简单吧。大功告成,我们来“make run”试试看。运行成功了,画面和stars.hrb没区别,那到底速度有没有变快呢?嗯,两个都很快所以看不出来,肯定是变快了吧。