Rewrote MiniGrLib, fixes #40.

This commit is contained in:
GutPuncher 2023-03-17 17:49:19 -04:00
parent 87c6e59179
commit 86a390d9c6
No known key found for this signature in database
GPG key ID: 38CE0A7B6841D1C7
2 changed files with 120 additions and 72 deletions

View file

@ -1,94 +1,136 @@
#define VGAP_IDX 0x3C4
#define VGAP_DATA 0x3C5
#define VGAR_MAP_MASK 0x02
U8 rev[256], //The VGA bits are backward U32 image[GR_HEIGHT * GR_WIDTH];
image[640 * 480 / 8]; //We need read-modify write.
//0xA0000 alias memory can't be read.
U0 MGInit() U0 MGInit()
{ {
I64 i, j; MemSet(image, BLACK32, sizeof(image));
}
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() U0 MGUpdate()
{//Copy image to VGA memory {//Copy image to framebuffer memory
//For better performance we could only write what's changed. //For better performance we could only write what's changed.
//0xA0000 alias is slower than normal RAM. MemCopy(text.fb_alias, image, sizeof(image));
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) U0 MGPlot(I64 x,I64 y)
{ {
if (0 <= x < 640 && 0 <= y < 480) if (0 <= x < GR_WIDTH && 0 <= y < GR_HEIGHT)
Bts(image,y * 640 + x ^ 7); image[x + y * GR_WIDTH] = WHITE32;
} }
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;
U0 MGHLine(I64 x1, I64 x2, I64 y)
{//No clipping
I64 x;
if (y >= GR_HEIGHT)
return;
if (x2 < x1) if (x2 < x1)
SwapI64(&x1, &x2); SwapI64(&x1, &x2);
ptr = image + y * 640 / 8 + x1 >> 3; if (x1 < 0)
w = x2 - x1 + 1; x1 = 0;
leading = 8 - x1 & 7; if (x2 < x1)
trailing = (x2 + 1) & 7; SwapI64(&x1, &x2);
if (leading + trailing > w) x = x1;
*ptr |= rev[(0xFF00 >> leading & (0x00FF << trailing) >> 8)];
else while (x <= x2 && x < GR_WIDTH)
{ {
whole_bytes = (w - leading - trailing) >> 3; image[x + y * GR_WIDTH] = WHITE32;
if (leading) x++;
*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) U0 MGLine(I64 x1,I64 y1,I64 x2,I64 y2)
{//Warning! No clipping {//No clipping
I64 dx=x2-x1,dy=y2-y1; I64 x_start, x_end, y_start, y_end, x, y, dx, dy, c;
x1 <<= 32; x2 <<= 32; c = 0;
y1 <<= 32; y2 <<= 32; x_start = MinI64(x1, x2);
if (AbsI64(dx) > AbsI64(dy))
if (x_start == x1)
{ {
dy = dy << 32 / AbsI64(dx); y_start = y1;
dx = SignI64(dx) << 32; x_end = x2;
while (x1 != x2) y_end = y2;
}
else // x2
{
y_start = y2;
x_end = x1;
y_end = y1;
}
x = x_start;
y = y_start;
dx = x_end - x_start;
if (y_end < y_start)
{
dy = y_start - y_end;
if (dx >= dy)
{ {
MGPlot(x1.i32[1], y1.i32[1]); while (x <= x_end)
x1 += dx; y1 += dy; {
MGPlot(x, y);
c += dy;
if (c >= dx)
{
c -= dx;
y--;
}
x++;
}
}
else
{
while (y > y_end)
{
MGPlot(x, y);
c += dx;
if (c >= dy)
{
c -= dy;
x++;
}
y--;
}
} }
} }
else else
{ {
dx = dx << 32 / AbsI64(dy); dy = y_end - y_start;
dy = SignI64(dy) << 32;
while (y1 != y2) if (dx >= dy)
{ {
MGPlot(x1.i32[1], y1.i32[1]); while (x <= x_end)
x1 += dx; {
y1 += dy; MGPlot(x, y);
c += dy;
if (c >= dx)
{
c -= dx;
y++;
}
x++;
}
}
else
{
while (y <= y_end)
{
MGPlot(x, y);
c += dx;
if (c >= dy)
{
c -= dy;
x++;
}
y++;
}
} }
} }
MGPlot(x1.i32[1], y1.i32[1]);
} }
U0 MGCircle(I64 x, I64 y, F64 r) U0 MGCircle(I64 x, I64 y, F64 r)
{ {
F64 s, c, x1, y1, x2, y2; F64 s, c, x1, y1, x2, y2;
@ -118,31 +160,34 @@ U0 MGCircle(I64 x, I64 y, F64 r)
MGPlot(x+x1,y+y1); MGPlot(x+x1,y+y1);
} }
} }
U0 MiniGrLibDemo() U0 MiniGrLibDemo()
{ {
I64 i; I64 i;
MGInit; MGInit;
for (i = 0; i < 100; i++) for (i = 0; i < 100; i++)
MGHLine(200 + i, 400 + i, 300 + i); MGHLine(200 + i, 400 + i, 400 + i);
for (i = 0; i < 500; i += 10) for (i = 0; i < GR_HEIGHT + 20; i += 10)
MGLine(i, 0, 0, 480 - i); MGLine(i, 0, 0, GR_HEIGHT - i);
for (i = 0; i < 300; i += 4) for (i = 0; i < 300; i += 4)
MGCircle(200, 100 + i, i); MGCircle(400, 200 + i, i);
MGUpdate; MGUpdate;
Busy(1500000); Busy(1500000);
/* /*
We are returning graphics to normal operations under ZealOS. We are returning graphics to normal operations under ZealOS.
It is not normal to by-pass the ZealOS graphcis routines. It is not normal to by-pass the ZealOS graphcis routines.
The ZealOS graphics don't know VGA has changed. The ZealOS graphics don't know the framebuffer has changed.
This bit tells ZealOS to update whole screen. This function tells ZealOS to update whole screen.
*/ */
//<CTRL-ALT-v> will flush screen VGA cache. //<CTRL-ALT-v> will flush screen VGA cache and un-set framebuffer-busy bit.
LFBFlush; LFBFlush;
} }
MiniGrLibDemo; MiniGrLibDemo;

View file

@ -1,4 +1,7 @@
$WW,1$$FG,5$$TX+CX,"ChangeLog"$$FG$ $WW,1$$FG,5$$TX+CX,"ChangeLog"$$FG$
$IV,1$----03/17/23 17:44:24----$IV,0$
* Rewrote $LK+PU,"MiniGrLib",A="FI:::/Demo/Lectures/MiniGrLib.ZC"$, replaced old VGA-specific code to work with 32-bit framebuffer.
$IV,1$----03/14/23 03:23:46----$IV,0$ $IV,1$----03/14/23 03:23:46----$IV,0$
* Created %o Bool $LK+PU,"StrPrint",A="FF:::/Kernel/StrPrint.ZC,'o':"$ format code, updated $LK+PU,"Print.DD",A="FI:::/Doc/Print.DD"$ with new %o code and previously undocumented format codes. * Created %o Bool $LK+PU,"StrPrint",A="FF:::/Kernel/StrPrint.ZC,'o':"$ format code, updated $LK+PU,"Print.DD",A="FI:::/Doc/Print.DD"$ with new %o code and previously undocumented format codes.