#include #include #include #include #include #include #include "system.h" #include "GPU.h" #define msleep(msec) usleep(1000*msec); static void pio_write (unsigned int data) { IOWR (PIO_0_BASE, 0, data); } static void gpu_write (unsigned int reg, unsigned int data) { IOWR (GPU_0_BASE, reg << 2, data); } static void update_gpu (int x, int y, int bat0, int bat1) { // set locations gpu_write (GPU_REG_SPRITE_X, x + GPU_OFFSET); gpu_write (GPU_REG_SPRITE_Y, y + GPU_OFFSET); gpu_write (GPU_REG_BAT0_Y, bat0 + GPU_OFFSET); gpu_write (GPU_REG_BAT1_Y, bat1 + GPU_OFFSET); // enable video gpu_write (GPU_REG_BLANK, 0); } static void show_score (int score) { const uint8_t lookup[10] = { 0x3F, 0x6, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x7, 0x7F, 0x6F }; uint8_t ss = 0; if (score < 0) { ss |= 0x80; score = -score; } if (score > 9) score = 9; ss |= lookup[score]; pio_write (ss); } static void load_sprite (void) { const uint16_t sprite[16] = { 0x00C0, 0x03E0, 0x0FF8, 0x1FFE, 0x3FC7, 0x3F83, 0x3933, 0x3987, 0x3D37, 0x3D37, 0x3D87, 0x3FFF, 0x1FFE, 0x07F8, 0x01E0, 0x00C0 }; const unsigned int n = sizeof (sprite) / sizeof (uint16_t); unsigned int i; // RRR GGG BBB // set the sprite color 111 010 000 - orange gpu_write (GPU_REG_SPRITE_COLOUR, 0x01D0); // squirt the bromium logo into the sprite for (i = 0; i < n; ++i) gpu_write (GPU_REG_SPRITE_BASE + i, sprite[i]); } static int dir (int a, int b) { if (a > b) return 1; if (a < b) return -1; return 0; } static void move_bat (int *b, int db) { *b += dir (db, *b); } static int squish (int *v, int min, int max) { if (*v < min) { *v = min; return 1; } if (*v >= max) { *v = max - 1; return 1; } return 0; } static int find_intersection (int x, int y, int xd, int yd, int t) { // super lazy - we should use the power of MATHS while (x != t) { x += xd; y += yd; if (squish (&y, 0, GPU_HEIGHT)) yd = -yd; if (squish (&x, 0, GPU_WIDTH)) xd = -xd; } return y; } static int has_missed (int y1, int y2) { y1 = y1 - y2; if (y1 < 0) y1 = -y1; if (y1 > 20) return 1; return 0; } static int x_speed (void) { return (rand () % 10) + 1; } static int y_speed (void) { return (rand () % 9) - 4; } int main (void) { int x, y, xd, yd; int bat0, dbat0; int bat1, dbat1; int score = 0; int serve = 0; int i; printf ("Working...\n"); srand (12392184); bat0 = GPU_HEIGHT / 2; bat1 = GPU_HEIGHT / 2; load_sprite (); for (;;) { xd = x_speed (); yd = y_speed (); show_score (score); if (!serve) { x = 1; y = bat0; dbat0 = GPU_HEIGHT / 2; dbat1 = find_intersection (x + xd, y + yd, xd, yd, GPU_WIDTH - 1); } else { x = GPU_WIDTH - 2; y = bat1; yd = -yd; dbat0 = find_intersection (x + xd, y + yd, xd, yd, 0); dbat1 = GPU_HEIGHT / 2; } serve = !serve; for (;;) { x += xd; y += yd; if (squish (&y, 0, GPU_HEIGHT)) yd = -yd; if (squish (&x, 0, GPU_WIDTH)) { xd = x_speed (); if (x) xd = -xd; yd = y_speed (); if (x) { if (has_missed (y, bat1)) { score++; break; } dbat0 = find_intersection (x + xd, y + yd, xd, yd, 0); dbat1 = GPU_HEIGHT / 2; } else { if (has_missed (y, bat0)) { score--; break; } dbat0 = GPU_HEIGHT / 2; dbat1 = find_intersection (x + xd, y + yd, xd, yd, GPU_WIDTH - 1); } } move_bat (&bat0, dbat0); move_bat (&bat1, dbat1); update_gpu (x, y, bat0, bat1); msleep (2); } if (!serve) { dbat1 = GPU_HEIGHT / 2; dbat0 = bat0; } else { dbat0 = GPU_HEIGHT / 2; dbat1 = bat1; } for (i = 0; i < 200; ++i) { if (i == 100) show_score (score); move_bat (&bat0, dbat0); move_bat (&bat1, dbat1); update_gpu (x, y, bat0, bat1); msleep (2); } } }