#define VGAP_IDX 0x3C4 #define VGAP_DATA 0x3C5 #define VGAR_MAP_MASK 0x02 U8 rev[256], //The VGA bits are backward image[640 * 480 / 8]; //We need read-modify write. //0xA0000 alias memory can't be read. U0 MGInit() { I64 i, j; MemSet(image, 0, sizeof(image)); MemSet(rev, 0, sizeof(rev)); for (i = 0; i < 256; i++) for (j = 0; j < 8; j++) if (Bt(&i, j)) Bts(&rev[i], 7 - j); } U0 MGUpdate() {//Copy image to VGA memory //For better performance we could only write what's changed. //0xA0000 alias is slower than normal RAM. OutU8(VGAP_IDX, VGAR_MAP_MASK); OutU8(VGAP_DATA, 0xF);//All color planes at once -- Black and White MemCopy(text.vga_alias, image,sizeof(image)); //Alias of 0xA0000 } U0 MGPlot(I64 x,I64 y) { if (0 <= x < 640 && 0 <= y < 480) Bts(image,y * 640 + x ^ 7); } U0 MGHLine(I64 x1, I64 x2, I64 y) {//Warning! No clipping //For performance, we do as many whole-bytes as possible. U8 *ptr; I64 i, w, leading, trailing, whole_bytes; if (x2 < x1) SwapI64(&x1, &x2); ptr = image + y * 640 / 8 + x1 >> 3; w = x2 - x1 + 1; leading = 8 - x1 & 7; trailing = (x2 + 1) & 7; if (leading + trailing > w) *ptr |= rev[(0xFF00 >> leading & (0x00FF << trailing) >> 8)]; else { whole_bytes = (w - leading - trailing) >> 3; if (leading) *ptr++ |= rev[(0xFF00 >> leading) & 0xFF]; for (i = 0; i < whole_bytes; i++) *ptr++ = 0xFF; if (trailing) *ptr++ |= rev[(0x00FF << trailing) >> 8]; } } U0 MGLine(I64 x1,I64 y1,I64 x2,I64 y2) {//Warning! No clipping I64 dx=x2-x1,dy=y2-y1; x1 <<= 32; x2 <<= 32; y1 <<= 32; y2 <<= 32; if (AbsI64(dx) > AbsI64(dy)) { dy = dy << 32 / AbsI64(dx); dx = SignI64(dx) << 32; while (x1 != x2) { MGPlot(x1.i32[1], y1.i32[1]); x1 += dx; y1 += dy; } } else { dx = dx << 32 / AbsI64(dy); dy = SignI64(dy) << 32; while (y1 != y2) { MGPlot(x1.i32[1], y1.i32[1]); x1 += dx; y1 += dy; } } MGPlot(x1.i32[1], y1.i32[1]); } U0 MGCircle(I64 x, I64 y, F64 r) { F64 s, c, x1, y1, x2, y2; I64 len; if (r < 0) return; x1 = r; y1 = 0; c = Cos(1 / r); s = Sin(1 / r); len = 2 * r * pi; MGPlot(x + x1, y + y1); while (len-- >= 0) { //m1@a1 * m2@a2 = m1*m2@(arg1+arg2) //(x1+y1i)*(x2+y2i) = x1*x2+(x1*y1+x2*y2)i-y1*y2 // meti=mCos(t)+imSin(t) x2 = x1; y2 = y1; x1 = c * x2 - s * y2; y1 = s * x2 + c * y2; MGPlot(x+x1,y+y1); } } U0 MiniGrLibDemo() { I64 i; MGInit; for (i = 0; i < 100; i++) MGHLine(200 + i, 400 + i, 300 + i); for (i = 0; i < 500; i += 10) MGLine(i, 0, 0, 480 - i); for (i = 0; i < 300; i += 4) MGCircle(200, 100 + i, i); MGUpdate; Busy(1500000); /* We are returning graphics to normal operations under ZealOS. It is not normal to by-pass the ZealOS graphcis routines. The ZealOS graphics don't know VGA has changed. This bit tells ZealOS to update whole screen. */ //<CTRL-ALT-v> will flush screen VGA cache. LFBFlush; } MiniGrLibDemo;