Adding example 8 (region fill)

This commit is contained in:
Adam Greenwood-Byrne 2021-03-08 22:51:02 +00:00
parent 8ab5472711
commit a5fdf22a1d
5 changed files with 288 additions and 0 deletions

140
part12-wgt/fill.c Normal file
View file

@ -0,0 +1,140 @@
#include "wgt.h"
#include "include/mem.h"
static short start, end; /* Start and end x coords for filled line */
extern short bx, by, tx, ty; /* Clipping variables */
typedef struct {
short x, y, start, finish; /* values for filled scan line */
void *next; /* Points to next node in linked list */
} node;
static node *push (node *s, short x, short y)
{
node *newnode;
s->start = start; /* Store start of line */
s->finish = end; /* Store end of line */
newnode = (node *)malloc (sizeof (node));
/* Allocate new node */
newnode->next = (node *)s; /* Make it point to previous node */
newnode->x = x; /* Store current x and y */
newnode->y = y;
return newnode; /* Return pointer to new head node */
}
static node *pop (node *s, short *x, short *y)
{
node *headnode;
headnode = s; /* Store pointer to head node */
s = (node *)s->next; /* Go back in the chain */
*x = s->x;
/* Find out where we were last (in that row) */
*y = s->y;
start = s->start; /* Restore start and end of line */
end = s->finish;
free (headnode); /* Free head node, no longer needed */
return s; /* Return pointer to new head node */
}
void wregionfill (short x, short y)
{
short color2fill; /* Color to change */
node *s; /* Pointer to head of linked list */
block ptr; /* Used to scan through screen data */
if ((x >= tx) && (y >= ty) && (x <= bx) && (y <= by) &&
(abuf[WGT_SYS.xres * y + x] != currentcolor))
{
/* Only fill if within clipping region and color to fill isn't same as
color we're filling with */
color2fill = abuf[WGT_SYS.xres * y + x]; /* Find out color to fill */
s = (node *)malloc (sizeof (node));
/* Allocate head node */
s->next = NULL; /* No previous nodes */
s->x = x; /* Store current coords */
s->y = y;
filllabel1:
;
start = x;
/* Start of line will be our x position */
ptr = &abuf[WGT_SYS.xres * y + start - 1]; /* Make pointer to screen data */
while ((start > tx) && (*ptr == color2fill))
{
/* Now scan left until we hit a different color */
ptr--;
start--;
}
end = x;
/* End of line will be our y position */
ptr = &abuf[WGT_SYS.xres * y + end + 1];
while ((end < bx) && (*ptr == color2fill))
{
/* Scan right until we hit a different color */
end++;
ptr++;
}
memset (&abuf[WGT_SYS.xres * y + start], currentcolor, end - start + 1);
/* Fill line segment */
filllabel2:
;
if (y < by)
{
/* Proceed to check below every pixel in current line segment to see
if we can advance down a row and continue the fill */
ptr = &abuf[(y + 1) * WGT_SYS.xres + start];
for (x = start; x <= end; x++)
{
if (*ptr == color2fill)
{
/* We've found a way to 'leak' into next row, store our
position */
s = push (s, x, y + 1);
y++;
/* Now move down a row */
goto filllabel1;
}
ptr++;
}
}
/* The next area of code does the same thing, except checking upwards */
if (y > ty)
{
ptr = &abuf[(y - 1) * WGT_SYS.xres + start];
for (x = start; x <= end; x++)
{
if (*ptr == color2fill)
{
s = push (s, x, y - 1);
y--;
goto filllabel1;
}
ptr++;
}
}
/* Now we've filled all we can in one direction, move to previous node */
if (s->next != NULL)
{
s = pop (s, &x, &y);
/* Get data for previous node so we can continue scanning */
goto filllabel2;
}
/* Free the node now that we're done with it */
free (s);
}
}

3
part12-wgt/include/mem.h Normal file
View file

@ -0,0 +1,3 @@
void mem_init();
void *malloc(unsigned int size);
void free(void *ptr);

43
part12-wgt/lib/mem.c Normal file
View file

@ -0,0 +1,43 @@
extern unsigned char _end[];
// Define the heap
unsigned char *HEAP_START = &_end[0];
unsigned int HEAP_SIZE = 0x40000000; // Max heap size is 1Gb
unsigned char *HEAP_END;
// Set up some globals
unsigned char *freeptr;
unsigned int allocated = 0;
void mem_init()
{
// Align the start of heap to an 8-byte boundary
if ((long)&HEAP_START % 8 != 0) {
HEAP_START += 8 - ((long)&HEAP_START % 8);
}
HEAP_END = (unsigned char *)(HEAP_START + HEAP_SIZE);
}
void *malloc(unsigned int size)
{
if (size > 0) {
void *allocated = freeptr;
if ((unsigned char *)(allocated + size) > HEAP_END) {
return 0;
} else {
freeptr += size;
allocated += size;
return allocated;
}
}
return 0;
}
void free(void *ptr) {
// TODO
}

View file

@ -79,3 +79,4 @@ void wtextcolor (unsigned int col);
void wtextbackground (unsigned int col);
void wtexttransparent (short transparent);
void wtextgrid (short onoff);
void wregionfill (short x, short y);

101
part12-wgt/wgt08.c Normal file
View file

@ -0,0 +1,101 @@
#include "wgt.h"
// ######## REQUIRED FUNCTIONS ########
unsigned long state0 = 1000;
unsigned long state1 = 2000;
unsigned long rand(void)
{
unsigned long s1 = state0;
unsigned long s0 = state1;
state0 = s0;
s1 ^= s1 << 23;
s1 ^= s1 >> 17;
s1 ^= s0;
s1 ^= s0 >> 26;
state1 = s1;
return state0 + state1;
}
void wait_msec(unsigned int n)
{
register unsigned long f, t, r;
// Get the current counter frequency
asm volatile ("mrs %0, cntfrq_el0" : "=r"(f));
// Read the current counter
asm volatile ("mrs %0, cntpct_el0" : "=r"(t));
// Calculate expire value for counter
t+=((f/1000)*n)/1000;
do{asm volatile ("mrs %0, cntpct_el0" : "=r"(r));}while(r<t);
}
// ######## STUB FUNCTIONS ########
unsigned int kb = 0;
unsigned int kbhit(void) {
kb++;
return kb / 500;
}
void getch(void) {
wait_msec(0x500000);
kb = 0;
}
// ######## WGT EXAMPLES ########
void wgt08()
{
short x;
vga256 ();
wcls (vgapal[0]);
wsetcolor (vgapal[1]);
wcircle (960, 540, 270); /* try filling a circle */
getch ();
wsetcolor (vgapal[40]);
wregionfill (960, 540);
wsetcolor (vgapal[170]);
wregionfill (0, 0);
getch ();
wcls (0);
for (x = 1; x < 10000; x++) /* try filling 10,000 random pixels */
{
wsetcolor (vgapal[rand() % 255]);
wputpixel (rand() % 1920, rand() % 1080);
}
getch ();
wsetcolor (vgapal[40]);
wclip (300, 270, 1500, 810); /* fill works with clipping too! */
wregionfill (960, 540);
wsetcolor (vgapal[7]);
wclip (60, 54, 240, 216);
wregionfill (120, 108);
wsetcolor (vgapal[9]);
wclip (1560, 864, 1800, 1026);
wregionfill (1620, 918);
wsetcolor (vgapal[10]);
wclip (0, 0, 1919, 1079);
wregionfill (0, 0);
getch ();
}
void main()
{
wgt08();
while (1);
}