3 刷新窗口(harib20c)

在写stars.hrb的时候突然想到一个问题,现在每次调用api_point画点,窗口都会被刷新一次,这样感觉会非常慢,还不如把星星都画好之后,最后再刷新一次窗口,这样应该会快一些。

于是,我们需要在所有的窗口绘图命令中设置一个“不自动刷新”的选项,然后再编写一个仅用来刷新的API。

这个选项要如何指定呢?窗口句柄归根到底是struct SHEET的地址,这一定是一个偶数,那么我们可以让程序在指定一个奇数(即在原来的数值上加1)的情况下不进行自动刷新。

仅用来刷新的API式样如下。

刷新窗口

EDX = 12

EBX = 窗口句柄

EAX = x0

ECX = y0

ESI = x1

EDI = y1

■■■■■

修改操作系统,具体如下。

本次的console.c节选

  1. int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
  2. {
  3. (中略)
  4. } else if (edx == 6) {
  5. sht = (struct SHEET *) (ebx & 0xfffffffe);
  6. putfonts8_asc(sht->buf, sht->bxsize, esi, edi, eax, (char *) ebp + ds_base);
  7. if ((ebx & 1) == 0) {
  8. sheet_refresh(sht, esi, edi, esi + ecx * 8, edi + 16);
  9. }
  10. } else if (edx == 7) {
  11. sht = (struct SHEET *) (ebx & 0xfffffffe);
  12. boxfill8(sht->buf, sht->bxsize, ebp, eax, ecx, esi, edi);
  13. if ((ebx & 1) == 0) {
  14. sheet_refresh(sht, eax, ecx, esi + 1, edi + 1);
  15. }
  16. } else if (edx == 8) {
  17. (中略)
  18. } else if (edx == 9) {
  19. (中略)
  20. } else if (edx == 10) {
  21. (中略)
  22. } else if (edx == 11) {
  23. sht = (struct SHEET *) (ebx & 0xfffffffe);
  24. sht->buf[sht->bxsize * edi + esi] = eax;
  25. if ((ebx & 1) == 0) {
  26. sheet_refresh(sht, esi, edi, esi + 1, edi + 1);
  27. }
  28. } else if (edx == 12) {
  29. sht = (struct SHEET *) ebx;
  30. sheet_refresh(sht, eax, ecx, esi, edi);
  31. }
  32. return 0;
  33. }

在计算sht的地方,我们将ebx和0xfffffffe做了一个AND运算,即对其按2的倍数取整。然后在判断是否需要刷新的if语句中,我们将ebx最低的一个比特用AND取出,判断其是否为0,如为0则表示其除以2的余数为0,也就是偶数。

■■■■■

用上面的功能,我们来编写stars2.c。

本次的a_nask.nas节选

  1. _api_refreshwin: ; void api_refreshwin(int win, int x0, int y0, int x1, int y1);
  2. PUSH EDI
  3. PUSH ESI
  4. PUSH EBX
  5. MOV EDX,12
  6. MOV EBX,[ESP+16] ; win
  7. MOV EAX,[ESP+20] ; x0
  8. MOV ECX,[ESP+24] ; y0
  9. MOV ESI,[ESP+28] ; x1
  10. MOV EDI,[ESP+32] ; y1
  11. INT 0x40
  12. POP EBX
  13. POP ESI
  14. POP EDI
  15. RET

本次的stars2.c

  1. int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);
  2. void api_boxfilwin(int win, int x0, int y0, int x1, int y1, int col);
  3. void api_initmalloc(void);
  4. char *api_malloc(int size);
  5. void api_point(int win, int x, int y, int col);
  6. void api_refreshwin(int win, int x0, int y0, int x1, int y1);
  7. void api_end(void);
  8. int rand(void); /*产生0~32767的随机数*/
  9. void HariMain(void)
  10. {
  11. char *buf;
  12. int win, i, x, y;
  13. api_initmalloc();
  14. buf = api_malloc(150 * 100);
  15. win = api_openwin(buf, 150, 100, -1, "stars2");
  16. api_boxfilwin(win + 1, 6, 26, 143, 93, 0 /*黑色*/);
  17. for (i = 0; i < 50; i++) {
  18. x = (rand() % 137) + 6;
  19. y = (rand() % 67) + 26;
  20. api_point(win + 1, x, y, 3 /*黄色*/);
  21. }
  22. api_refreshwin(win, 6, 26, 144, 94);
  23. api_end();
  24. }

好了,这个也很简单吧。大功告成,我们来“make run”试试看。运行成功了,画面和stars.hrb没区别,那到底速度有没有变快呢?嗯,两个都很快所以看不出来,肯定是变快了吧。