// ***************************************************************************
// main
// ***************************************************************************
// This file was developed by Prof. Dr. Peer Johannsen as part of the
// "Retro-Programming" and "Advanced C Programming" class at
// Pforzheim University, Germany.
//
// It can freely be used, but at one's own risk and for non-commercial
// purposes only. Please respect the copyright and credit the origin of
// this file.
//
// Feedback, suggestions and bug-reports are welcome and can be sent to:
// peer.johannsen@pforzheim-university.de
// ---------------------------------------------------------------------------
#include <vectrex.h>
#define jsrx(v, func) asm("ldx %0\n\t" "jsr " #func "\n\t" : : "g" (v) : "d", "x")
#define Draw_VLp(ra) jsrx(ra, 0xF410) // (pattern y x)* 0x01
static inline void displaylist (const int *list)
{
Draw_VLp (list);
}
static inline void wait_retrace (void)
{
Wait_Recal ();
}
static inline void set_scale (int scale)
{ /* VIA_t1_cnt_lo */
*(volatile int *) 0xD004 = scale;
}
// ---------------------------------------------------------------------------
// cold reset: the vectrex logo is shown, all ram data is cleared
// warm reset: skip vectrex logo and keep ram data
// ---------------------------------------------------------------------------
// at system startup, when powering up the vectrex, a cold reset is performed
// if the reset button is pressed, then a warm reset is performed
// ---------------------------------------------------------------------------
// after each reset, the cartridge title is shown and then main() is called
// ---------------------------------------------------------------------------
// We will be updating the x and y positions in situ, and extending the array dynamically by
// poking a '1' into the first element of the entry after the last active object. All
// asteroids must be the same number of vectors or use moves to pad. (the Procustean option)
// make the move/remove into a single separate ram array
// and just have one copy of each asteroid. use pointers to it...
// (although that stops working when we use rotation)
#define ASTEROIDS 19
#define BIG -1,120,120, -1,120,0, -1,120,-120, -1,0,-120, -1,-120,-120, -1,-120,0, -1,-120,120, -1,0,120, 1
#define MEDIUM -1,80,80, -1,80,0, -1,80,-80, -1,0,-80, -1,-80,-80, -1,-80,0, -1,-80,80, -1,0,80, 1
#define SMALL -1,60,60, -1,60,0, -1,60,-60, -1,0,-60, -1,-60,-60, -1,-60,0, -1,-60,60, -1,0,60, 1
const int vector[((unsigned long) ASTEROIDS) * 10UL * 3UL + 1UL] = { /* octagons for now, later asteroids */
/* 0 */ BIG,
/* 1 */ BIG,
/* 2 */ MEDIUM,
/* 3 */ MEDIUM,
/* 4 */ MEDIUM,
/* 5 */ MEDIUM,
/* 6 */ SMALL,
/* 7 */ SMALL,
/* 8 */ SMALL,
/* 9 */ SMALL,
/* 10 */ SMALL,
/* 11 */ SMALL,
/* 12 */ SMALL,
/* 13 */ SMALL,
/* 14 */ SMALL,
/* 15 */ SMALL,
/* 16 */ BIG,
/* 17 */ BIG,
/* 18 */ MEDIUM,
};
int x[ASTEROIDS], y[ASTEROIDS], size2[ASTEROIDS];
int dx[ASTEROIDS * 2] = {
1, 1, 2, 1, 1, 2, 1, 1, 1, 2, -1, -1, -2, -1, -1, -2, -1, -2, -1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
};
int dy[ASTEROIDS * 2] = {
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
-1, 2, -2, 1, -2, 2, -2, 1, -2, 2, -2, 1, -2, 2, -1, 2, -2, 2, -2,
};
static unsigned long rseed;
static int random (void)
{
// VECTREX HAS A BUILT-IN RANDOM THAT WE CAN USE!
// (though it doesn't seem very good - this may be better and faster)
return (int) (rseed = (rseed * 2053UL) + 13849UL);
}
int main (void) {
int base, row, tmp1; // , tmp2, other, diffx, diffy;
int *vec;
vec = (int *) (vector + 3);
for (row = 0; row < ASTEROIDS; row++) {
x[row] = random ();
y[row] = random ();
size2[row] = *vec * *vec;
vec += 3 * 8 + 1;
}
base = 0;
for (;;) {
Wait_Recal ();
vec = (int *) vector;
for (row = 0; row < ASTEROIDS; row++) {
Reset0Ref ();
Intensity_a (0x7f);
set_scale (0x58);
Moveto_d (y[row], x[row]);
set_scale (0x01);
displaylist (vec);
vec += 3 * 8 + 1;
}
// now move asteroids around
for (row = 0; row < ASTEROIDS; row++) {
// Bounce off walls? Marginally more expensive than wrapping.
tmp1 = x[row] + dx[base + row];
if ((dx[base + row] > 0 && x[row] > 0 && tmp1 < 0)
|| (dx[base + row] < 0 && x[row] < 0 && tmp1 > 0)) {
dx[base + row] = -dx[base + row];
} else {
x[row] = tmp1;
}
tmp1 = y[row] + dy[base + row];
if ((dy[base + row] > 0 && y[row] > 0 && tmp1 < 0)
|| (dy[base + row] < 0 && y[row] < 0 && tmp1 > 0)) {
dy[base + row] = -dy[base + row];
} else {
y[row] = tmp1;
}
// Bump asteroid?
#ifdef NEVER
for (other = row + 1; other < ASTEROIDS; other++) {
tmp1 = x[row] ^ x[other];
tmp2 = y[row] ^ y[other];
if ((tmp1 < 0) || (tmp2 < 0)) {
diffx = x[row] - x[other];
diffy = y[row] - y[other];
diffx *= diffx;
diffy *= diffy;
if (diffx + diffy < size2[row] + size2[other]) {
if (tmp1 < 0)
dx[row] = -dx[row];
if (tmp2 < 0)
dy[row] = -dy[row];
}
}
}
#endif
}
base ^= ASTEROIDS;
}
// if return value is <= 0, then a warm reset will be performed,
// otherwise a cold reset will be performed
return 0;
}
// ***************************************************************************
// end of file
// ***************************************************************************