mirror of
https://github.com/isometimes/rpi4-osdev
synced 2024-11-25 11:40:40 +00:00
469 lines
10 KiB
C
469 lines
10 KiB
C
#include "include/wgtspr.h"
|
|
#include "include/mem.h"
|
|
#include "include/multicore.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;
|
|
}
|
|
|
|
// ######## STUB FUNCTIONS ########
|
|
|
|
unsigned int kb = 0;
|
|
|
|
unsigned int kbhit(void) {
|
|
kb++;
|
|
return kb / 500;
|
|
}
|
|
|
|
void getch(void) {
|
|
wait_msec(0x500000);
|
|
kb = 0;
|
|
}
|
|
|
|
// ######## WGT EXAMPLES ########
|
|
|
|
/* Large example demonstrating many functions from WGT */
|
|
|
|
#define MAXEXPLOS 220
|
|
#define MAXALIEN 170
|
|
|
|
void scrolldown (void); /* scrolls the screen down */
|
|
void credits (void);
|
|
void changepalette256 (void);
|
|
void colorloop (void);
|
|
void play (void);
|
|
|
|
block scr, scr2;
|
|
block sprites[21];
|
|
|
|
typedef struct {
|
|
int x, y;
|
|
int dirx, diry;
|
|
int shootx, shooty;
|
|
int power;
|
|
} spaceship;
|
|
|
|
typedef struct {
|
|
int x, y;
|
|
int num;
|
|
} explosion;
|
|
explosion explos[MAXEXPLOS];
|
|
|
|
spaceship aliens[MAXALIEN];
|
|
int numaliens, aliensleft;
|
|
|
|
int shoot[10], sx[10], sy[10];
|
|
int ship; /* Sprite to show */
|
|
int shipx[MAXALIEN], shipy[MAXALIEN]; /* Ship coordinates */
|
|
float incx, incy, yourx, youry;
|
|
|
|
int cd;
|
|
int i, j, k; /* Loop control */
|
|
int scrll = 1; /* scrll is a counter for the scroll offset */
|
|
int ix = 30, iy = 0, ix2 = 251, iy2 = 199; /* coords of scrolling area */
|
|
int speed; /* the scrolling speed */
|
|
/* try changing speed and sign */
|
|
int nextlevel; /* Performing level change = 1 */
|
|
int leveltextx; /* X coordinate of next level text */
|
|
int level;
|
|
|
|
color palette[256];
|
|
|
|
void strrev(char *str)
|
|
{
|
|
int i;
|
|
int j;
|
|
unsigned char a;
|
|
unsigned len = strlen((const char *)str);
|
|
for (i = 0, j = len - 1; i < j; i++, j--) {
|
|
a = str[i];
|
|
str[i] = str[j];
|
|
str[j] = a;
|
|
}
|
|
}
|
|
|
|
int itoa(int num, char* str, int base)
|
|
{
|
|
int sum = num;
|
|
int i = 0;
|
|
int digit;
|
|
|
|
do {
|
|
digit = sum % base;
|
|
if (digit < 0xA) str[i++] = '0' + digit;
|
|
else str[i++] = 'A' + digit - 0xA;
|
|
sum /= base;
|
|
} while (sum);
|
|
|
|
str[i] = '\0';
|
|
strrev(str);
|
|
return 0;
|
|
}
|
|
|
|
void initialize_aliens (int numaliens)
|
|
/* Sets the initial positions of the aliens when starting a level. */
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < numaliens; i++)
|
|
{
|
|
aliens[i].x = rand() % 200 + 30;
|
|
aliens[i].y = rand() % 50;
|
|
aliens[i].dirx = rand() % 8 - 4;
|
|
aliens[i].diry = rand() % 8 - 4;
|
|
aliens[i].power = numaliens / 3;
|
|
aliens[i].shootx = -1;
|
|
}
|
|
}
|
|
|
|
void make_starfield (void)
|
|
/* Gets two virtual screens and puts the star sprites on them to make
|
|
a starfield background. */
|
|
{
|
|
int i;
|
|
|
|
scr = wnewblock (0, 0, 319, 199); /* get two virtual screens */
|
|
scr2 = wnewblock (0, 0, 319, 199);
|
|
wsetscreen (scr2); /* go to second one */
|
|
wcls (vgapal[0]); /* clear it */
|
|
|
|
for (i = 1; i < 300; i++)
|
|
wputblock (rand() % 320, rand() % 200, sprites[5], 0);
|
|
/* sprite[5] is small stars */
|
|
|
|
for (i = 1; i < 5; i++)
|
|
wputblock (rand() % 320, rand() % 200, sprites[6], 0);
|
|
/* sprite[6] is a large star */
|
|
}
|
|
|
|
void play (void)
|
|
{
|
|
scrolldown (); /* Scroll the second
|
|
screen by copying it to
|
|
a different offset on
|
|
screen one. */
|
|
|
|
if (but == 1)
|
|
{ /* if you clicked the mouse */
|
|
for (i = 0; i <9; i++)
|
|
if (shoot[i] == 0) /* check to see if slot available */
|
|
{
|
|
shoot[i] = 1; /* make it unavailable */
|
|
sx[i] = yourx + 9; /* set coords for shot */
|
|
sy[i] = youry - 7;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 9; i++) /* if shot is active */
|
|
{
|
|
if (shoot[i] == 1) /* then show the sprite */
|
|
{
|
|
wputblock (sx[i], sy[i], sprites[4], 0); /* at the right coords */
|
|
sy[i] -= 8; /* make it go up */
|
|
if (sy[i] < 1) /* if it is at top, */
|
|
shoot[i] = 0; /* make it available again */
|
|
|
|
/* Now check to see if it hit an alien by seeing if their
|
|
rectangular regions overlap. */
|
|
for (j = 0; j < numaliens; j++)
|
|
if ((aliens[j].x != -255) &&
|
|
(sx[i] > aliens[j].x) && (sx[i] < aliens[j].x + 25) &&
|
|
(sy[i] > aliens[j].y) && (sy[i] < aliens[j].y + 20))
|
|
|
|
{
|
|
shoot[i] = 0; /* Turn off that missile */
|
|
|
|
aliens[j].power--;
|
|
if (aliens[j].power == 0)
|
|
{
|
|
aliensleft--;
|
|
if (aliensleft == 0)
|
|
{
|
|
nextlevel = 1;
|
|
leveltextx = ix2 + 100;
|
|
}
|
|
for (k = 0; k < MAXEXPLOS; k++) /* Add an explosion */
|
|
{
|
|
if (explos[k].num == 0)
|
|
{
|
|
explos[k].x = aliens[j].x;
|
|
explos[k].y = aliens[j].y;
|
|
explos[k].num = 8;
|
|
break;
|
|
}
|
|
}
|
|
aliens[j].x = -255;
|
|
}
|
|
} /* Collision */
|
|
} /* Shot active */
|
|
} /* for loop */
|
|
|
|
incx = (float)(mx - yourx) / 5.0; /* Move your spaceship according to the */
|
|
incy = (float)(my - youry) / 5.0; /* position of the mouse. */
|
|
yourx += incx;
|
|
youry += incy;
|
|
|
|
/* Tilt the ship */
|
|
if ((incx < 2) && (incx > -2))
|
|
ship = 2;
|
|
else if (incx > 5)
|
|
ship=3;
|
|
else if (incx < 5)
|
|
ship = 1;
|
|
|
|
wsetscreen (scr);
|
|
wputblock (yourx, youry, sprites[ship], 1); /* Put your ship on */
|
|
|
|
for (i = 0; i < numaliens; i++)
|
|
{
|
|
if (aliens[i].x != -255) /* Alien is still alive */
|
|
{
|
|
aliens[i].x += aliens[i].dirx; /* Make them move */
|
|
aliens[i].y += aliens[i].diry;
|
|
|
|
/* Make them bounce off the walls if they go too far in one direction. */
|
|
if (aliens[i].x <= ix)
|
|
aliens[i].dirx = rand() % 4;
|
|
else if (aliens[i].x > ix2 - 20)
|
|
aliens[i].dirx = -(rand() % 4);
|
|
|
|
if (aliens[i].y < 0)
|
|
aliens[i].diry = rand() % 4;
|
|
else if (aliens[i].y > 150)
|
|
aliens[i].diry = -(rand() % 4);
|
|
|
|
if ((aliens[i].shootx == -1) && (rand() % 10 == 1))
|
|
/* 1 in 10 chance of shooting */
|
|
{
|
|
aliens[i].shootx = aliens[i].x + 9;
|
|
aliens[i].shooty = aliens[i].y + 5;
|
|
}
|
|
|
|
if (aliens[i].power > 0)
|
|
wputblock (aliens[i].x, aliens[i].y, sprites[7], 1);
|
|
|
|
/* Display the alien's missile. */
|
|
if (aliens[i].shootx != -1)
|
|
{
|
|
wputblock (aliens[i].shootx, aliens[i].shooty, sprites[8], 1);
|
|
aliens[i].shooty += 4;
|
|
if (aliens[i].shooty > 199)
|
|
aliens[i].shootx = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Now draw any explosions on the screen. */
|
|
for (i = 0; i < MAXEXPLOS; i++)
|
|
{
|
|
if (explos[i].num > 0)
|
|
{
|
|
explos[i].num++;
|
|
if (explos[i].num > 14)
|
|
explos[i].num = 0;
|
|
else
|
|
wputblock (explos[i].x, explos[i].y, sprites[explos[i].num], 1);
|
|
}
|
|
}
|
|
|
|
if (nextlevel == 1)
|
|
{
|
|
leveltextx -= 5;
|
|
|
|
wouttextxy (leveltextx, 50, NULL, "LEVEL ");
|
|
|
|
char levelstr[10];
|
|
itoa(level + 1, levelstr, 10);
|
|
wouttextxy (leveltextx + (6 * 8), 50, NULL, levelstr);
|
|
|
|
if (leveltextx < -100)
|
|
{
|
|
level++;
|
|
if (level > MAXALIEN)
|
|
level = MAXALIEN;
|
|
numaliens = level + 5;
|
|
aliensleft = numaliens;
|
|
initialize_aliens (numaliens);
|
|
nextlevel = 0;
|
|
}
|
|
}
|
|
|
|
wait_msec(0x3E9F);
|
|
wcopyscreen (ix, iy, ix2, iy2, scr, ix, iy, NULL);
|
|
/* copy the first screen */
|
|
/* to the base screen */
|
|
}
|
|
|
|
void scrolldown (void)
|
|
{
|
|
wcopyscreen (ix, scrll, ix2, iy2, scr2, ix, iy, scr);
|
|
wcopyscreen (ix, iy, ix2, scrll, scr2, ix, iy2 - scrll, scr);
|
|
/* Cut the screen into two sections, then swap them vertically on the
|
|
destination page */
|
|
|
|
scrll += speed;
|
|
if ((scrll < iy) && (speed < 0))
|
|
scrll = iy2 + 1 - abs (scrll);
|
|
if ((scrll > iy2) && (speed > 0))
|
|
scrll = abs (iy2 - scrll);
|
|
}
|
|
|
|
void credits (void)
|
|
{
|
|
wnormscreen ();
|
|
wtextcolor (vgapal[1]);
|
|
wtextbackground (vgapal[0]);
|
|
|
|
cd = 2;
|
|
/* draw a pattern on the screen */
|
|
for (i = 0; i < 320; i++)
|
|
{
|
|
colorloop ();
|
|
wsetcolor (vgapal[cd]);
|
|
wfline (160, 100, i, 0);
|
|
}
|
|
for (i = 0; i < 200; i++)
|
|
{
|
|
colorloop ();
|
|
wsetcolor (vgapal[cd]);
|
|
wfline (160, 100, 319, i);
|
|
}
|
|
for (i = 319; i >= 0; i--)
|
|
{
|
|
colorloop ();
|
|
wsetcolor (vgapal[cd]);
|
|
wfline (160, 100, i, 199);
|
|
}
|
|
for (i = 199; i >= 0; i--)
|
|
{
|
|
colorloop ();
|
|
wsetcolor (vgapal[cd]);
|
|
wfline (160, 100, 0, i);
|
|
}
|
|
|
|
|
|
changepalette256 ();
|
|
|
|
wouttextxy (50, 20, NULL, "Shoot 'Em Up Sprite Example");
|
|
wouttextxy (50, 28, NULL, "Showing what YOU could do with");
|
|
wouttextxy (50, 36, NULL, "the WordUp Graphics Toolkit!");
|
|
wouttextxy (50, 44, NULL, "Use the mouse to move");
|
|
wouttextxy (50, 52, NULL, "Left button shoots");
|
|
wouttextxy (50, 60, NULL, "Right button quits");
|
|
wouttextxy (50, 68, NULL, "Right button to start");
|
|
wsetrgb (1, 63, 63, 63, palette);
|
|
// wfade_in (0, 255, 1, palette);
|
|
|
|
do {
|
|
/*
|
|
wcolrotate (2, 106, 0, palette);
|
|
wsetpalette (2, 106, palette);
|
|
*/
|
|
wait_msec(0x3E9F);
|
|
} while (!but);
|
|
|
|
noclick();
|
|
wcls (vgapal[0]);
|
|
}
|
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
/* change the palette to the right colours */
|
|
void changepalette256 (void)
|
|
{
|
|
wsetrgb (0, 0, 0, 0, palette);
|
|
|
|
for (i = 2; i < 54; i++)
|
|
wsetrgb (i, i, 0, 0, palette);
|
|
for (i = 54; i < 106; i++)
|
|
wsetrgb (i, 105 - i, 0, 0, palette);
|
|
|
|
wsetrgb (253, 60, 60, 60, palette);
|
|
wsetrgb (254, 45, 45, 45, palette);
|
|
wsetrgb (255, 30, 30, 30, palette);
|
|
wsetrgb (1, 63, 63, 63, palette);
|
|
}
|
|
|
|
void colorloop (void)
|
|
/* Simple loop for colours on credit screen */
|
|
{
|
|
cd++;
|
|
if (cd > 105)
|
|
cd = 2;
|
|
}
|
|
|
|
void wgt20()
|
|
{
|
|
set_clock_rate(get_max_clock());
|
|
mem_init();
|
|
vga256 (); /* Initializes WGT system */
|
|
|
|
start_core2(minit); // Start the comms engine (core 2)
|
|
while (!comms_up); // Wait for comms up
|
|
|
|
credits ();
|
|
|
|
extern unsigned char _binary_bin_space_spr_start[];
|
|
wloadsprites (palette, &_binary_bin_space_spr_start[0], sprites, 0, 20);
|
|
/* load first 10 sprites */
|
|
wsetpalette (0, 255, palette);
|
|
|
|
make_starfield ();
|
|
|
|
wnormscreen (); /* go back to normal screen */
|
|
wcls (vgapal[0]); /* clear it */
|
|
wbutt (0, 0, 29, 199); /* make some side panels */
|
|
wbutt (252, 0, 319, 199);
|
|
wtextbackground (vgapal[0]);
|
|
wtextcolor (vgapal[1]);
|
|
wtexttransparent (TEXTFG);
|
|
|
|
yourx = 128;
|
|
youry = 170;
|
|
|
|
wsetscreen (scr); /* go to first screen */
|
|
msetbounds (ix, 150, ix2 - 20, 179);
|
|
|
|
speed = -4;
|
|
|
|
nextlevel = 0;
|
|
level = 1;
|
|
numaliens = level + 5;
|
|
aliensleft = numaliens;
|
|
|
|
initialize_aliens (numaliens);
|
|
|
|
do {
|
|
play ();
|
|
} while (but != 2); /* until right button is pressed */
|
|
|
|
mdeinit (); /* Deinitialize the mouse handler */
|
|
wfreeblock (scr);
|
|
wfreeblock (scr2);
|
|
wfreesprites (sprites, 0, 20);
|
|
|
|
wnormscreen();
|
|
wcls(vgapal[0]);
|
|
}
|
|
|
|
void main()
|
|
{
|
|
wgt20();
|
|
while (1);
|
|
}
|