mirror of
https://github.com/isometimes/rpi4-osdev
synced 2024-11-22 02:00:40 +00:00
Adding example 8 (region fill)
This commit is contained in:
parent
8ab5472711
commit
a5fdf22a1d
5 changed files with 288 additions and 0 deletions
140
part12-wgt/fill.c
Normal file
140
part12-wgt/fill.c
Normal 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
3
part12-wgt/include/mem.h
Normal 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
43
part12-wgt/lib/mem.c
Normal 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
|
||||||
|
}
|
|
@ -79,3 +79,4 @@ void wtextcolor (unsigned int col);
|
||||||
void wtextbackground (unsigned int col);
|
void wtextbackground (unsigned int col);
|
||||||
void wtexttransparent (short transparent);
|
void wtexttransparent (short transparent);
|
||||||
void wtextgrid (short onoff);
|
void wtextgrid (short onoff);
|
||||||
|
void wregionfill (short x, short y);
|
||||||
|
|
101
part12-wgt/wgt08.c
Normal file
101
part12-wgt/wgt08.c
Normal 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);
|
||||||
|
}
|
Loading…
Reference in a new issue