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 wtexttransparent (short transparent);
|
||||
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