Added wwarp.c and examples/wgt32.c to exercise it

This commit is contained in:
Adam Greenwood-Byrne 2021-03-19 11:49:02 +00:00
parent c0f33240cb
commit 9b494efa78
4 changed files with 352 additions and 0 deletions

137
part12-wgt/examples/wgt32.c Normal file
View file

@ -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<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 wgt32()
{
int i, t, c, b;
color pal[256];
block wgt1;
short top[320];
short bot[320];
set_clock_rate(get_max_clock());
mem_init();
vga256 (); /* Initialize graphics mode */
extern unsigned char _binary_bin_wgt1_pal_start[];
wloadpalette (&_binary_bin_wgt1_pal_start[0], pal);
wsetpalette (0, 255, pal);
extern unsigned char _binary_bin_wgt1_blk_start[];
wgt1 = wloadblock (&_binary_bin_wgt1_blk_start[0]);
wcls (vgapal[0]); /* Clear screen with black */
wclip (0, 0, 319, 199); /* Use full screen */
/* Note: wsline merely stores y coordinates of line in array. You may use
several calls with various x ranges to make curved lines */
wsline (0, 199, 319, 0, top); /* Set array top for diagonal line */
wsline (0, 199, 319, 199, bot); /* Array bot is horizontal line */
wwarp (0, 319, top, bot, wgt1, 0); /* Warp image between lines */
getch (); /* Wait for key */
// squish it
wcls (vgapal[0]); /* Clear screen */
wsline (0, 100, 100, 0, top); /* Now create arrow shape */
wsline (101, 70, 218, 70, top);
wsline (219, 0, 319, 100, top);
wsline (0, 100, 100, 199, bot);
wsline (101, 130, 218, 130, bot);
wsline (219, 199, 319, 100, bot);
wwarp (0, 319, top, bot, wgt1, 0); /* Warp image using arrays */
getch (); /* Wait for keypress */
// make a double arrow
wcls (vgapal[0]); /* Clear screen with black */
do {
b =rand() % 100;
c = (rand() % 100) + 100;
for (t = 0; t <= 319; t++)
{
i = rand() % 2;
if (i == 0)
b++;
else b--;
i = rand() % 2;
if (i == 0)
c++;
else c--;
if (b > 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);
}

View file

@ -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); short wloadsprites (color *pal, unsigned char *file, block *image_array, short start, short end);
void wfreesprites (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 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);

View file

@ -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);
}
}
}

85
part12-wgt/wwarp.c Normal file
View file

@ -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;
}
}