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
image[640 * 480 / 8]; //We need read-modify write.
//0xA0000 alias memory can't be read.
U32 image[GR_HEIGHT * GR_WIDTH];
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()
{//Copy image to VGA memory
{//Copy image to framebuffer 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
MemCopy(text.fb_alias, image, sizeof(image));
}
U0 MGPlot(I64 x,I64 y)
{
if (0 <= x < 640 && 0 <= y < 480)
Bts(image,y * 640 + x ^ 7);
if (0 <= x < GR_WIDTH && 0 <= y < GR_HEIGHT)
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)
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
if (x1 < 0)
x1 = 0;
if (x2 < x1)
SwapI64(&x1, &x2);
x = x1;
while (x <= x2 && x < GR_WIDTH)
{
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];
image[x + y * GR_WIDTH] = WHITE32;
x++;
}
}
U0 MGLine(I64 x1,I64 y1,I64 x2,I64 y2)
{//Warning! No clipping
I64 dx=x2-x1,dy=y2-y1;
{//No clipping
I64 x_start, x_end, y_start, y_end, x, y, dx, dy, c;
x1 <<= 32; x2 <<= 32;
y1 <<= 32; y2 <<= 32;
if (AbsI64(dx) > AbsI64(dy))
c = 0;
x_start = MinI64(x1, x2);
if (x_start == x1)
{
dy = dy << 32 / AbsI64(dx);
dx = SignI64(dx) << 32;
while (x1 != x2)
y_start = y1;
x_end = 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]);
x1 += dx; y1 += dy;
while (x <= x_end)
{
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
{
dx = dx << 32 / AbsI64(dy);
dy = SignI64(dy) << 32;
while (y1 != y2)
dy = y_end - y_start;
if (dx >= dy)
{
MGPlot(x1.i32[1], y1.i32[1]);
x1 += dx;
y1 += dy;
while (x <= x_end)
{
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)
{
F64 s, c, x1, y1, x2, y2;
@ -118,31 +160,34 @@ U0 MGCircle(I64 x, I64 y, F64 r)
MGPlot(x+x1,y+y1);
}
}
U0 MiniGrLibDemo()
{
I64 i;
MGInit;
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)
MGLine(i, 0, 0, 480 - i);
for (i = 0; i < GR_HEIGHT + 20; i += 10)
MGLine(i, 0, 0, GR_HEIGHT - i);
for (i = 0; i < 300; i += 4)
MGCircle(200, 100 + i, i);
MGCircle(400, 200 + 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.
The ZealOS graphics don't know the framebuffer has changed.
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;
}
MiniGrLibDemo;
MiniGrLibDemo;

View file

@ -1,4 +1,7 @@
$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$
* 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.