diff --git a/part12-wgt/examples/wgt32.c b/part12-wgt/examples/wgt32.c new file mode 100644 index 0000000..6951bc0 --- /dev/null +++ b/part12-wgt/examples/wgt32.c @@ -0,0 +1,137 @@ +#include "wgt.h" +#include "include/mem.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 100) + b = 100; + + if (b < 0) + b = 0; + if (c > 197) + c = 197; + if (c < 100) + c = 100; + + top[t] = b; /* Create random wavy lines */ + bot[t] = c; + } + wwarp (0, 319, top, bot, wgt1, 0); /* And warp image between them */ + getch (); /* Wait for keypress */ + wcls (vgapal[0]); /* Clear screen with black */ + } while (1); /* End program if Q pressed */ + + wfreeblock (wgt1); /* Free memory from image */ +} + +void main() +{ + wgt32(); + while (1); +} diff --git a/part12-wgt/wgt.h b/part12-wgt/wgt.h index a89ba1d..59041d1 100644 --- a/part12-wgt/wgt.h +++ b/part12-wgt/wgt.h @@ -123,3 +123,6 @@ void wskew (short x, short y, block image, short degrees); short wloadsprites (color *pal, unsigned char *file, block *image_array, short start, short end); void wfreesprites (block *image_array, short start, short end); void wcopyscreen (short x, short y, short x2, short y2, block source, short destx, short desty, block dest); +void wsline (short x, short y, short x2, short y2, short *y_array); +void wwarp (short sx, short ex, short *tpy, short *bty, block ptr, short mode); +void wresize_column (short x, short y, short y2, block image, short column, short mode); diff --git a/part12-wgt/wresize.c b/part12-wgt/wresize.c index 165b3fe..e583b6c 100644 --- a/part12-wgt/wresize.c +++ b/part12-wgt/wresize.c @@ -198,3 +198,130 @@ unsigned long xfrac; } } } + +int resize_width_asm; +int screen_width_asm; + +void resize_vertical_line (block src, block dest, unsigned int whole, unsigned long xfrac, unsigned short step, int length) +{ + int resize_width_asm2; + int screen_width_asm2; + + resize_width_asm2 = resize_width_asm; + screen_width_asm2 = screen_width_asm; + + unsigned int px; + + vresizeloop: + px = *src; + src += whole; + xfrac += step; + if (xfrac > 65535) { + xfrac %= 65536; + } else { + goto novres; + } + src += resize_width_asm2; + novres: + *dest = px; + dest += screen_width_asm2; + length--; + if (length != 0) goto vresizeloop; +} + +void resize_vertical_line_xray (block src, block dest, unsigned int whole, unsigned long xfrac, unsigned short step, int length) +{ + int resize_width_asm2; + int screen_width_asm2; + + resize_width_asm2 = resize_width_asm; + screen_width_asm2 = screen_width_asm; + + unsigned int px; + + vresizeloop: + px = *src; + src += whole; + xfrac += step; + if (xfrac > 4294967295) { + xfrac %= 4294967296; + goto novres; + } + src += resize_width_asm2; + novres: + if (px != 0) *dest = px; + dest += screen_width_asm2; + length--; + if (length != 0) goto vresizeloop; +} + +void wresize_column (short x, short y, short y2, block image, short column, short mode) +{ + int origheight; + int finalheight; + int endheight; + long ystepper; + long ywhole; + short ystep; + int yfrac; + + long ydif; + block dest; + block src; + + + /* Skip over the width/height integers */ + origheight = wgetblockheight (image); + resize_width_asm = wgetblockwidth (image); + src = image + 2 + column; + if (y2 < y) + { + src += (origheight - 1) * resize_width_asm; + origheight *= -1; + ydif = y; + y = y2; + y2 = ydif; + } + + finalheight = (y2 - y) + 1; + + if (finalheight > 0) + { + ystepper = (((long)origheight << 16) / (long)finalheight); + ywhole = ystepper >> 16; + ystep = ystepper - (ywhole << 16); + + dest = &abuf[y * WGT_SYS.xres + x]; + /* Make an initial pointer to the destination */ + + endheight = finalheight; + + /* Differences between actual coordinates and */ + ydif = 0; /* the clipped coordinates. */ + yfrac = 0; /* Reset step to 0 */ + + if (y < ty) + { + ydif = ty - y; + endheight = finalheight - ydif; + dest += ydif * WGT_SYS.xres; + yfrac = (ydif * ystep) % 65536; + + src += ((ydif * ystepper) >> 16) * resize_width_asm; + } + + if (y + finalheight > by + 1) + endheight -= ((y + finalheight) - by); + /* Clip the bottom edge by decreasing the number of pixels drawn. */ + + if (endheight > 0) + { + screen_width_asm = WGT_SYS.xres; + ywhole *= resize_width_asm; + if (mode == NORMAL) + resize_vertical_line (src, dest, ywhole, yfrac, ystep, endheight); + else + resize_vertical_line_xray (src, dest, ywhole, yfrac, ystep, endheight); + } + } +} diff --git a/part12-wgt/wwarp.c b/part12-wgt/wwarp.c new file mode 100644 index 0000000..fbc0133 --- /dev/null +++ b/part12-wgt/wwarp.c @@ -0,0 +1,85 @@ +#include "wgt.h" + +void wsline (short x, short y, short x2, short y2, short *y_array) +{ + short t, distance; + short wx, wy, dx, dy, bdx, bdy, incx, incy; + + dx = x2 - x; + dy = y2 - y; + t = 0; wx = 0; wy = 0; + if (dy < 0) incy = - 1; + else incy = 1; + if (dx < 0) incx = - 1; + else incx = 1; + bdx = abs (dx); + bdy = abs (dy); + if (bdx > bdy) distance = bdx; + else distance = bdy; + y_array += x; + if (distance == bdx) + { + while (t <= distance) + { + if ((x >= tx) && (y >= ty) && (y <= by) && (x <= bx)) + *y_array = y; + /* instead of plotting pixels, just store the y value in an array */ + + wy += bdy; + x += incx; + y_array++; + t ++; + if (wy >= distance) + { + wy -= distance; + y += incy; + } + } + } + else + { + while (t <= distance) + { + if ((x >= tx) && (y >= ty) && (y <= by) && (x <= bx)) + *y_array = y; + wx += bdx; + if (wx >= distance) + { + wx -= distance; + x += incx; + y_array++; + } + y += incy; + t ++; + } + } +} + +void wwarp (short sx, short ex, short *tpy, short *bty, block ptr, short mode) +{ + long column; + int wid; + + short finalwidth; + short origwidth; + long xstepper; + + origwidth = wgetblockwidth (ptr); + /* Get the original width of the block */ + + finalwidth = abs (ex - sx) + 1; + /* Find the new width */ + + xstepper = ((long)(origwidth) << 16) / ((long)(finalwidth)); + /* Calculate the amount to add to the source bitmap for every pixel across. + This is done using a fixed point number by multiplying it by 65536 (<<16) + and using 0-65535 as a fractional amount. */ + + column = 0; + + for (wid = sx; wid <= ex; wid++) + { + wresize_column (wid, tpy[wid], bty[wid], ptr, column >> 16, mode); + column += xstepper; + } +}