436 lines
7.2 KiB
C
436 lines
7.2 KiB
C
#include <c64/vic.h>
|
|
#include <c64/memmap.h>
|
|
#include <c64/sprites.h>
|
|
#include <c64/joystick.h>
|
|
#include <c64/rasterirq.h>
|
|
#include <gfx/mcbitmap.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#pragma region(main, 0x0a00, 0xc800, , , {code, data, bss, heap, stack} )
|
|
|
|
const char MissileSprites[] = {
|
|
#embed "../resources/missilesprites.bin"
|
|
};
|
|
|
|
const char MissileChars[] = {
|
|
#embed "../resources/missilechars.bin"
|
|
};
|
|
|
|
#define Color1 ((char *)0xc800)
|
|
#define Color2 ((char *)0xd800)
|
|
#define Hires ((char *)0xe000)
|
|
#define Sprites ((char *)0xd000)
|
|
#define Charset ((char *)0xd800)
|
|
|
|
int CrossX = 160, CrossY = 100;
|
|
bool CrossP = false;
|
|
char CrossDelay = 0;
|
|
|
|
Bitmap sbm;
|
|
const ClipRect scr = { 0, 0, 320, 200 };
|
|
|
|
struct Explosion
|
|
{
|
|
int x, y;
|
|
char r;
|
|
Explosion * next;
|
|
};
|
|
|
|
struct Missile
|
|
{
|
|
int sx, sy, tx, ty, x, y, dx, dy;
|
|
int d;
|
|
char cnt;
|
|
Missile * next;
|
|
};
|
|
|
|
Explosion explosions[16];
|
|
Explosion * efree, * eused;
|
|
|
|
Missile missiles[8];
|
|
Missile * mfree, * mused;
|
|
|
|
Missile icbms[16];
|
|
Missile * ifree, * iused;
|
|
|
|
bool cities[6];
|
|
|
|
|
|
void explosion_init(void)
|
|
{
|
|
eused = nullptr;
|
|
efree = explosions;
|
|
for(char i=0; i<15; i++)
|
|
explosions[i].next = explosions + i + 1;
|
|
explosions[15].next = nullptr;
|
|
}
|
|
|
|
void explosion_start(int x, int y)
|
|
{
|
|
if (efree)
|
|
{
|
|
Explosion * e = efree;
|
|
efree = e->next;
|
|
e->next = eused;
|
|
eused = e;
|
|
|
|
e->r = 0;
|
|
e->x = x;
|
|
e->y = y;
|
|
}
|
|
}
|
|
|
|
void explosion_animate(void)
|
|
{
|
|
Explosion * e = eused, * ep = nullptr;
|
|
while (e)
|
|
{
|
|
Explosion * en = e->next;
|
|
e->r++;
|
|
if (!(e->r & 3))
|
|
{
|
|
if (e->r <= 64)
|
|
bmmc_circle(&sbm, &scr, e->x, e->y, e->r >> 2, 1);
|
|
else
|
|
bmmc_circle(&sbm, &scr, e->x, e->y, 33 - (e->r >> 2), 0);
|
|
}
|
|
if (e->r == 128)
|
|
{
|
|
if (ep)
|
|
ep->next = e->next;
|
|
else
|
|
eused = e->next;
|
|
e->next = efree;
|
|
efree = e;
|
|
}
|
|
else
|
|
ep = e;
|
|
|
|
e = en;
|
|
}
|
|
}
|
|
|
|
void missile_init(void)
|
|
{
|
|
mused = nullptr;
|
|
mfree = missiles;
|
|
for(char i=0; i<7; i++)
|
|
missiles[i].next = missiles + i + 1;
|
|
missiles[7].next = nullptr;
|
|
}
|
|
|
|
void missile_start(int sx, int sy, int tx, int ty)
|
|
{
|
|
if (mfree)
|
|
{
|
|
Missile * m = mfree;
|
|
mfree = m->next;
|
|
m->next = mused;
|
|
mused = m;
|
|
|
|
m->sx = sx >> 1; m->x = sx >> 1;
|
|
m->sy = sy; m->y = sy;
|
|
m->tx = tx >> 1;
|
|
m->ty = ty;
|
|
|
|
m->dy = m->sy - m->ty;
|
|
m->dx = m->tx - m->sx;
|
|
if (m->dx < 0)
|
|
m->dx = -m->dx;
|
|
|
|
m->d = m->dy - m->dx;
|
|
m->dx *= 2;
|
|
m->dy *= 2;
|
|
}
|
|
}
|
|
|
|
void missile_animate(void)
|
|
{
|
|
Missile * m = mused, * mp = nullptr;
|
|
while (m)
|
|
{
|
|
Missile * mn = m->next;
|
|
|
|
if (m->d >= 0)
|
|
{
|
|
m->y--;
|
|
m->d -= m->dx;
|
|
}
|
|
if (m->d < 0)
|
|
{
|
|
if (m->tx < m->sx)
|
|
m->x--;
|
|
else
|
|
m->x++;
|
|
m->d += m->dy;
|
|
}
|
|
|
|
if (bmmc_get(&sbm, m->x, m->y) == 1 || m->y == m->ty)
|
|
{
|
|
bmmcu_line(&sbm, m->sx * 2, m->sy, m->tx * 2, m->ty, 0);
|
|
explosion_start(m->x * 2, m->y);
|
|
|
|
if (mp)
|
|
mp->next = m->next;
|
|
else
|
|
mused = m->next;
|
|
m->next = mfree;
|
|
mfree = m;
|
|
}
|
|
else
|
|
{
|
|
bmmc_put(&sbm, m->x * 2, m->y, 3);
|
|
mp = m;
|
|
}
|
|
|
|
m = mn;
|
|
}
|
|
}
|
|
|
|
void icbm_init(void)
|
|
{
|
|
iused = nullptr;
|
|
ifree = icbms;
|
|
for(char i=0; i<15; i++)
|
|
icbms[i].next = icbms + i + 1;
|
|
icbms[15].next = nullptr;
|
|
}
|
|
|
|
void icbm_start(int sx, int sy, int tx, int ty)
|
|
{
|
|
if (ifree)
|
|
{
|
|
Missile * m = ifree;
|
|
ifree = m->next;
|
|
m->next = iused;
|
|
iused = m;
|
|
|
|
m->sx = sx >> 1; m->x = sx >> 1;
|
|
m->sy = sy; m->y = sy;
|
|
m->tx = tx >> 1;
|
|
m->ty = ty;
|
|
m->cnt = 4;
|
|
|
|
m->dy = m->ty - m->sy;
|
|
m->dx = m->tx - m->sx;
|
|
if (m->dx < 0)
|
|
m->dx = -m->dx;
|
|
|
|
m->d = m->dy - m->dx;
|
|
m->dx *= 2;
|
|
m->dy *= 2;
|
|
}
|
|
}
|
|
|
|
void icbm_animate(void)
|
|
{
|
|
Missile * m = iused, * mp = nullptr;
|
|
while (m)
|
|
{
|
|
Missile * mn = m->next;
|
|
|
|
m->cnt--;
|
|
|
|
if (!m->cnt)
|
|
{
|
|
bmmc_put(&sbm, m->x * 2, m->y, 2);
|
|
|
|
m->cnt = 4;
|
|
|
|
if (m->d >= 0)
|
|
{
|
|
m->y++;
|
|
m->d -= m->dx;
|
|
}
|
|
if (m->d < 0)
|
|
{
|
|
if (m->tx < m->sx)
|
|
m->x--;
|
|
else
|
|
m->x++;
|
|
m->d += m->dy;
|
|
}
|
|
|
|
if (bmmc_get(&sbm, m->x * 2, m->y) == 1 || m->y == m->ty)
|
|
{
|
|
bmmcu_line(&sbm, m->sx * 2, m->sy, m->tx * 2, m->ty, 0);
|
|
explosion_start(m->x * 2, m->y);
|
|
|
|
if (m->y == m->ty)
|
|
{
|
|
int x = m->x * 2;
|
|
char ix;
|
|
if (x > 160)
|
|
ix = (x - 202) / 32 + 3;
|
|
else
|
|
ix = (x - 58) / 32;
|
|
cities[ix] = false;
|
|
spr_show(ix + 1, false);
|
|
}
|
|
|
|
|
|
if (mp)
|
|
mp->next = m->next;
|
|
else
|
|
iused = m->next;
|
|
m->next = ifree;
|
|
ifree = m;
|
|
}
|
|
else
|
|
{
|
|
bmmc_put(&sbm, m->x * 2, m->y, 1);
|
|
mp = m;
|
|
}
|
|
}
|
|
else
|
|
mp = m;
|
|
|
|
m = mn;
|
|
}
|
|
}
|
|
|
|
void mountains_init(void)
|
|
{
|
|
bmmcu_rect_fill(&sbm, 0, 192, 320, 8, 3);
|
|
bmmc_quad_fill(&sbm, &scr, 0, 192, 16, 184, 32, 184, 48, 192, MixedColors[3][3]);
|
|
bmmc_quad_fill(&sbm, &scr, 136, 192, 152, 184, 176, 184, 192, 192, MixedColors[3][3]);
|
|
bmmc_quad_fill(&sbm, &scr, 272, 192, 288, 184, 304, 184, 320, 192, MixedColors[3][3]);
|
|
}
|
|
|
|
__interrupt void joy_interrupt()
|
|
{
|
|
joy_poll(1);
|
|
|
|
CrossX += joyx[1]; CrossY += joyy[1];
|
|
|
|
if (CrossX < 8)
|
|
CrossX = 8;
|
|
else if (CrossX > 312)
|
|
CrossX = 312;
|
|
if (CrossY < 16)
|
|
CrossY = 16;
|
|
else if (CrossY > 172)
|
|
CrossY = 172;
|
|
|
|
spr_move(0, CrossX + 14, CrossY + 40);
|
|
|
|
if (joyb[1])
|
|
{
|
|
if (CrossDelay == 0)
|
|
{
|
|
CrossP = true;
|
|
CrossDelay = 4;
|
|
}
|
|
}
|
|
else if (CrossDelay > 0)
|
|
CrossDelay--;
|
|
}
|
|
|
|
RIRQCode bottom, top;
|
|
|
|
int main(void)
|
|
{
|
|
mmap_trampoline();
|
|
|
|
mmap_set(MMAP_RAM);
|
|
memcpy(Sprites, MissileSprites, 1024);
|
|
memcpy(Charset, MissileChars, 2048);
|
|
mmap_set(MMAP_NO_ROM);
|
|
|
|
vic_setmode(VICM_HIRES_MC, Color1, Hires);
|
|
spr_init(Color1);
|
|
|
|
// initialize raster IRQ
|
|
rirq_init(true);
|
|
|
|
vic.color_back = VCOL_BLACK;
|
|
vic.color_border = VCOL_BLACK;
|
|
|
|
memset(Color1, 0x18, 1000);
|
|
memset(Color2, 0x06, 1000);
|
|
memset(Hires, 0, 8000);
|
|
memset(Color2 + 40 * 23, 0x07, 80);
|
|
|
|
bm_init(&sbm, Hires, 40, 25);
|
|
missile_init();
|
|
explosion_init();
|
|
icbm_init();
|
|
mountains_init();
|
|
|
|
spr_set(0, true, CrossX + 14, CrossY + 40, 64, 1, false, false, false);
|
|
|
|
for(char i=0; i<3; i++)
|
|
{
|
|
spr_set(i + 1, true, 70 + 32 * i, 222, 65, 15, false, false, false);
|
|
spr_set(i + 4, true, 214 + 32 * i, 222, 65, 15, false, false, false);
|
|
|
|
cities[i + 0] = true;
|
|
cities[i + 3] = true;
|
|
}
|
|
|
|
// Build the switch to normal IRQ
|
|
rirq_build(&top, 3);
|
|
// Change color for ceiling
|
|
rirq_delay(&top, 10);
|
|
rirq_write(&top, 1, &vic.ctrl1, VIC_CTRL1_BMM | VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3);
|
|
rirq_write(&top, 2, &vic.memptr, 0x28);
|
|
// place this at the bottom
|
|
rirq_set(0, 57, &top);
|
|
|
|
// Build the switch to normal IRQ
|
|
rirq_build(&bottom, 3);
|
|
rirq_write(&bottom, 0, &vic.memptr, 0x27);
|
|
rirq_write(&bottom, 1, &vic.ctrl1, VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3);
|
|
// Change color for ceiling
|
|
rirq_call(&bottom, 2, joy_interrupt);
|
|
// place this at the bottom
|
|
rirq_set(1, 250, &bottom);
|
|
|
|
// sort the raster IRQs
|
|
rirq_sort();
|
|
|
|
// start raster IRQ processing
|
|
rirq_start();
|
|
|
|
bool launched = false;
|
|
for(;;)
|
|
{
|
|
if (CrossP)
|
|
{
|
|
int sx = 160;
|
|
if (CrossX < 120)
|
|
sx = 24;
|
|
else if (CrossX > 200)
|
|
sx = 296
|
|
missile_start(sx, 184, CrossX, CrossY);
|
|
CrossP = false;
|
|
}
|
|
|
|
if (!(rand() & 63))
|
|
{
|
|
char ci;
|
|
do {
|
|
ci = rand() & 7;
|
|
} while (ci >= 6 || !cities[ci]);
|
|
|
|
int cx;
|
|
if (ci < 3)
|
|
cx = 58 + 32 * ci;
|
|
else
|
|
cx = 202 + 32 * (ci - 3);
|
|
|
|
icbm_start((rand() & 0xff) + 32, 0, cx, 184);
|
|
}
|
|
|
|
for(char i=0; i<4; i++)
|
|
missile_animate();
|
|
icbm_animate();
|
|
explosion_animate();
|
|
|
|
vic_waitFrame();
|
|
}
|
|
|
|
return 0;
|
|
}
|