blob: 5b994b28debafbb06fabb7037baea8098eb03e5b [file] [log] [blame]
// Screen base = 0x4000
// Width = 320/8 = 40
// 0x4000 + X/8 + Y*40
#define C2A(X, Y) (unsigned char*)(0x4000 + (X) / 8 + (Y) * 40)
volatile unsigned* DUREE = (volatile unsigned*)0x6033;
struct guy;
struct span {
unsigned char* where;
unsigned char height;
};
struct guy {
const struct guy* left;
const struct guy* right;
struct span span[6];
};
const struct span eggs[4][8] = {
{ { C2A(88, 32), 7 }, { C2A(88, 46), 7 }, { C2A(88, 59), 7 },
{ C2A(88, 73), 7 }, { C2A(88, 88), 7 }, { C2A(88, 103), 7 },
{ C2A(88, 116), 7 }, { C2A(88, 129), 7 },},
{ { C2A(144, 32), 7 }, { C2A(144, 46), 7 }, { C2A(144, 59), 7 },
{ C2A(144, 73), 7 }, { C2A(144, 88), 7 }, { C2A(144, 103), 7 },
{ C2A(144, 116), 7 }, { C2A(144, 129), 7 },},
{ { C2A(200, 32), 7 }, { C2A(200, 46), 7 }, { C2A(200, 59), 7 },
{ C2A(200, 73), 7 }, { C2A(200, 88), 7 }, { C2A(200, 103), 7 },
{ C2A(200, 116), 7 }, { C2A(200, 129), 7 },},
{ { C2A(256, 32), 7 }, { C2A(256, 46), 7 }, { C2A(256, 59), 7 },
{ C2A(256, 73), 7 }, { C2A(256, 88), 7 }, { C2A(256, 103), 7 },
{ C2A(256, 116), 7 }, { C2A(256, 129), 7 },},
};
const struct span* liveeggs[4];
const struct guy guyPos[4] = {
{
.left = &guyPos[0], .right = &guyPos[1],
{ {C2A(64,145), 16}, {C2A(72, 122), 38}, {C2A(80, 121), 37},
{C2A(88,137), 5}, {C2A(88, 151), 7}, {C2A(96, 137), 3}}
},
{
.left = &guyPos[0], .right = &guyPos[2],
{ {C2A(120,124), 6}, {C2A(120, 139), 21}, {C2A(128, 121), 36},
{C2A(136, 122), 39}, {C2A(144, 141), 5}, {C2A(152,140), 4}}
},
{
.left = &guyPos[1], .right = &guyPos[3],
{ {C2A(176,130), 31}, {C2A(184, 121), 40}, {C2A(192, 121), 37},
{C2A(200, 137), 5}, {C2A(200,153), 6}, {C2A(208, 137), 3}}
},
{
.left = &guyPos[2], .right = &guyPos[3],
{ {C2A(224,151), 9}, {C2A(232, 123), 5}, {C2A(232, 131), 29},
{C2A(240, 121), 40}, {C2A(248, 122), 22}, {C2A(256,137), 5}}
},
};
const struct guy* theGuy = &guyPos[1];
#define hw_color() { \
asm("LDA \t0xE7C3\n " \
"ANDA \t#0xFE\n " \
"STA \t0xE7C3\n " \
:::"a"); \
}
#define mon_putc(car) { \
asm("JSR \t0xE803 \t; TO8 PUTC\n"\
::"B" ((unsigned char) (car))\
); \
}
#define mon_note(note) { \
asm("JSR \t0xE81E \t; TO8 NOTE\n"\
::"B" ((unsigned char) (note))\
); \
}
#define test_joystick(b) { \
asm(" LDA \t%1\n" \
" JSR \t0xE827 \t; TO8 JOYS\n" \
: "=B"((unsigned char)b) : "K" (0)); \
}
static void erase_span(const struct span* span)
{
unsigned char y;
unsigned char* p;
y = span->height;
p = span->where;
while (y != 0) {
*p = 0xC0;
p += 40;
y--;
}
}
static void draw_span(const struct span* span)
{
unsigned char y;
unsigned char* p;
y = span->height;
p = span->where;
while (y != 0) {
*p = 0xC8;
p += 40;
y--;
}
}
static void erase(const struct guy* what)
{
unsigned char i;
for (i = 0; i < 6; i++) {
erase_span(&what->span[i]);
}
}
static void draw(const struct guy* what)
{
unsigned char i;
for (i = 0; i < 6; i++) {
draw_span(&what->span[i]);
}
}
enum key {
left,
right
};
void abort()
{
for(;;);
}
void disp(unsigned int score)
{
mon_putc(0xD);
mon_putc(' ');
if (score >= 100) {
unsigned char h = score / 100;
mon_putc(h + '0');
score -= 100 * h;
} else
mon_putc(' ');
if (score >= 10) {
unsigned char h = score / 10;
mon_putc(h + '0');
score -= 10 * h;
} else
mon_putc(' ');
mon_putc(score + '0');
mon_note(0x35);
if (DUREE != 0)
DUREE--;
}
int start(void)
{
mon_putc(0xA);
mon_putc(0xA);
mon_putc(0xA);
unsigned int backup = DUREE;
asm(" ORCC \t#0x55\n");
for(;;) {
unsigned char step = 0;
unsigned char key = 0;
unsigned char egg = 0;
unsigned int score = 0;
liveeggs[0] = 0;
liveeggs[1] = 0;
liveeggs[2] = 0;
liveeggs[3] = 0;
DUREE = backup;
disp(0);
// Clear all eggs
// Clear all characters
hw_color()
erase(&guyPos[0]);
erase(&guyPos[2]);
erase(&guyPos[3]);
const struct span* foo = &eggs[0][0];
for (key = 0; key < 32; key++)
erase_span(foo + key);
// MAIN LOOP
for (;;) {
if (step == 0) {
egg++;
if (egg > 3) egg = 0;
}
test_joystick(key);
if (key == 7) {
mon_putc(7);
hw_color()
erase(theGuy);
theGuy = theGuy->left;
draw(theGuy);
} else if (key == 3) {
mon_putc(7);
hw_color()
erase(theGuy);
theGuy = theGuy->right;
draw(theGuy);
} else {
if (liveeggs[step] == 0) {
if (egg == 0) {
// New egg
liveeggs[step] = &eggs[step][0];
egg++;
draw_span(liveeggs[step]);
}
} else {
// Advance egg
erase_span(liveeggs[step]);
liveeggs[step]++;
if ((liveeggs[step] == &eggs[1][0])) {
if (theGuy == &guyPos[0]) {
// 1 point
score++;
disp(score);
liveeggs[step] = 0;
} else {
// Game over
break;
}
} else if ((liveeggs[step] == &eggs[2][0])) {
if (theGuy == &guyPos[1]) {
// 1 point
score++;
disp(score);
liveeggs[step] = 0;
} else {
// Game over
break;
}
} else if ((liveeggs[step] == &eggs[3][0])) {
if (theGuy == &guyPos[2]) {
// 1 point
score++;
disp(score);
liveeggs[step] = 0;
} else {
// Game over
break;
}
} else if ((liveeggs[step] == &eggs[4][0])) {
if (theGuy == &guyPos[3]) {
// 1 point
score++;
disp(score);
liveeggs[step] = 0;
} else {
// Game over
break;
}
} else
{
draw_span(liveeggs[step]);
}
}
}
asm(" SYNC\n");
mon_note(0x30);
step++;
if (step > 3) step = 0;
}
for (int i = 0; i < 3; i++) {
erase_span(liveeggs[step] - 1);
asm(" SYNC\n");
mon_note(0x31);
draw_span(liveeggs[step] - 1);
asm(" SYNC\n");
mon_note(0x30);
}
}
}