diff --git a/part12-wgt/fill.c b/part12-wgt/fill.c new file mode 100644 index 0000000..48f1202 --- /dev/null +++ b/part12-wgt/fill.c @@ -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); + } +} diff --git a/part12-wgt/include/mem.h b/part12-wgt/include/mem.h new file mode 100644 index 0000000..1aa9777 --- /dev/null +++ b/part12-wgt/include/mem.h @@ -0,0 +1,3 @@ +void mem_init(); +void *malloc(unsigned int size); +void free(void *ptr); diff --git a/part12-wgt/lib/mem.c b/part12-wgt/lib/mem.c new file mode 100644 index 0000000..ac509fc --- /dev/null +++ b/part12-wgt/lib/mem.c @@ -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 +} diff --git a/part12-wgt/wgt.h b/part12-wgt/wgt.h index 3f978ea..6217f30 100644 --- a/part12-wgt/wgt.h +++ b/part12-wgt/wgt.h @@ -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); diff --git a/part12-wgt/wgt08.c b/part12-wgt/wgt08.c new file mode 100644 index 0000000..e233f1d --- /dev/null +++ b/part12-wgt/wgt08.c @@ -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