/* Arduino/RetroBSD Tetris Copyright (C) 2015 João André Esteves Vilaça https://github.com/vilaca/Handheld-Color-Console Adapted for RetroBSD by Alexey Frunze. Required Hardware: - PICadillo-35T board - Funduino joystick shield v1.a This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include volatile int quit = 0; volatile int jx = 0, jy = 0; #include #include #include int fd = -1; int fdx = -1; int fdy = -1; struct timeval start_time; unsigned long millis(void) { static int init; struct timeval t; unsigned long ms; if (!init) { gettimeofday(&start_time, 0); init = 1; return 0; } gettimeofday(&t, 0); ms = (t.tv_sec - start_time.tv_sec) * 1000UL; ms += t.tv_usec / 1000; ms -= start_time.tv_usec / 1000; return ms; } void delay(unsigned long ms) { usleep(ms * 1000); } #define PIX_BUF_SIZ 128 // 28 fps on full-screen continuous box() void fill(unsigned count, unsigned short color) { unsigned short data[1 + PIX_BUF_SIZ]; unsigned cnt = (count < PIX_BUF_SIZ) ? count : PIX_BUF_SIZ; while (cnt) data[cnt--] = color; while (count) { cnt = (count < PIX_BUF_SIZ) ? count : PIX_BUF_SIZ; *data = cnt; ioctl(fd, 0xDADA, data); count -= cnt; } } void lineh(unsigned x, unsigned y, unsigned length, unsigned short color) { unsigned short wincoo[4]; wincoo[0] = x; wincoo[1] = wincoo[3] = y; wincoo[2] = x + length - 1; ioctl(fd, 0xC0C0, wincoo); fill(length, color); } void linev(unsigned x, unsigned y, unsigned length, unsigned short color) { unsigned short wincoo[4]; wincoo[0] = wincoo[2] = x; wincoo[1] = y; wincoo[3] = y + length - 1; ioctl(fd, 0xC0C0, wincoo); fill(length, color); } void box(unsigned x, unsigned y, unsigned width, unsigned height, unsigned short color, int solid) { if (solid) { unsigned short wincoo[4]; wincoo[0] = x; wincoo[1] = y; wincoo[2] = x + width - 1; wincoo[3] = y + height - 1; ioctl(fd, 0xC0C0, wincoo); fill(width * height, color); } else { lineh(x, y, width, color); lineh(x, y + height - 1, width, color); linev(x, y, height, color); linev(x + width - 1, y, height, color); } } void beep(int frq, int d) { (void)frq; // TBD??? delay(d); } void boxb(unsigned x, unsigned y, unsigned w, unsigned h, unsigned short c) { box(x, y, w, h - 1, c, 1); box(x, y + h - 1, 1, 1, c, 1); } int Joystick_fire(void) { return 0; // TBD??? } int Joystick_getX(void) { char buf[21] = { 0 }; jx = 512; if (read(fdx, buf, sizeof buf - 1) > 0) jx = strtol(buf, 0, 0); jx -= 512; jx = -jx; if (-128 < jx && jx < 128) jx = 0; return jx; } int Joystick_getY(void) { char buf[21] = { 0 }; jy = 512; if (read(fdy, buf, sizeof buf - 1) > 0) jy = strtol(buf, 0, 0); jy -= 512; jy = -jy; if (-128 < jy && jy < 128) jy = 0; return jy; } void Joystick_waitForRelease(int howLong) { int c = 0; do { delay(10); c += 10; } while ((Joystick_fire() || Joystick_getY() || Joystick_getX()) && c < howLong); } void randomizer(void); void score(void); void scoreBoard(void); void draw(void); void moveDown(void); void userInput(unsigned long now); void chooseNewShape(void); int touches(int xi, int yi, int roti); //TFT resolution 480x320 #define LCD_WIDTH 480//320//480 #define LCD_HEIGHT 320//200//320 #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) #define FONT_SPACE 6 #define FONT_X 8 extern unsigned char simpleFont[][8]; enum { BOARD_WIDTH = 11, BOARD_HEIGHT = 20, BLOCK_SIZE = MIN(LCD_WIDTH / BOARD_WIDTH - 1, LCD_HEIGHT / BOARD_HEIGHT - 1), BOARD_LEFT = (LCD_WIDTH - BOARD_WIDTH * BLOCK_SIZE) / 4 * 3, BOARD_RIGHT = BOARD_LEFT + BLOCK_SIZE * BOARD_WIDTH, BOARD_TOP = (LCD_HEIGHT - BOARD_HEIGHT * BLOCK_SIZE) / 2, BOARD_BOTTOM = BOARD_TOP + BOARD_HEIGHT * BLOCK_SIZE }; //Basic Colors #define BLACK 0x0000 #define BLUE 0x001f #define CYAN 0x07ff #define DARKCYAN 0x03EF /* 0, 128, 128 */ #define DARKGREEN 0x03E0 #define DARKGREY 0x7BEF /* 128, 128, 128 */ #define GRAY1 0x8410 #define GRAY2 0x4208 #define GRAY3 0x2104 #define GREEN 0x07e0 #define LIGHTGREEN 0xAFE5 /* 173, 255, 47 */ #define LIGHTGREY 0xC618 /* 192, 192, 192 */ #define MAGENTA 0xF81F /* 255, 0, 255 */ #define MAROON 0x7800 /* 128, 0, 0 */ #define NAVY 0x000F /* 0, 0, 128 */ #define OLIVE 0x7BE0 /* 128, 128, 0 */ #define ORANGE 0xFD20 /* 255, 165, 0 */ #define PURPLE 0x780F /* 128, 0, 128 */ #define RED 0xf800 #define WHITE 0xffff #define YELLOW 0xffe0 #define PIT_COLOR CYAN #define BG_COLOR BLACK typedef unsigned char byte; // used to clear the position from the screen typedef struct { byte x, y, rot; } Backup; #define DROP_WAIT_INIT 1100 #define INPUT_WAIT_ROT 200 #define INPUT_WAIT_MOVE 100 #define INPUT_WAIT_NEW_SHAPE 400 // shapes definitions byte l_shape[4][4][2] = { { {0, 0}, {0, 1}, {0, 2}, {1, 2} }, { {0, 1}, {1, 1}, {2, 0}, {2, 1} }, { {0, 0}, {1, 0}, {1, 1}, {1, 2} }, { {0, 0}, {0, 1}, {1, 0}, {2, 0} }, }; byte j_shape[4][4][2] = { { {1, 0}, {1, 1}, {0, 2}, {1, 2} }, { {0, 0}, {1, 0}, {2, 0}, {2, 1} }, { {0, 0}, {1, 0}, {0, 1}, {0, 2} }, { {0, 0}, {0, 1}, {1, 1}, {2, 1} }, }; byte o_shape[1][4][2] = { { {0, 0}, {0, 1}, {1, 0}, {1, 1} } }; byte s_shape[2][4][2] = { { {0, 1}, {1, 0}, {1, 1}, {2, 0} }, { {0, 0}, {0, 1}, {1, 1}, {1, 2} } }; byte z_shape[2][4][2] = { { {0, 0}, {1, 0}, {1, 1}, {2, 1} }, { {1, 0}, {0, 1}, {1, 1}, {0, 2} } }; byte t_shape[4][4][2] = { { {0, 0}, {1, 0}, {2, 0}, {1, 1} }, { {0, 0}, {0, 1}, {1, 1}, {0, 2} }, { {1, 0}, {0, 1}, {1, 1}, {2, 1} }, { {1, 0}, {0, 1}, {1, 1}, {1, 2} } }; byte i_shape[2][4][2] = { { {0, 0}, {1, 0}, {2, 0}, {3, 0} }, { {0, 0}, {0, 1}, {0, 2}, {0, 3} } // TBD??? rotate at the center }; // All game shapes and their colors byte* all_shapes[7] = { l_shape[0][0], j_shape[0][0], o_shape[0][0], s_shape[0][0], z_shape[0][0], t_shape[0][0], i_shape[0][0] }; unsigned short colors[7] = { ORANGE, BLUE, YELLOW, GREEN, RED, MAGENTA, CYAN }; // how many rotated variations each shape has byte shapes[7] = { 4, 4, 1, 2, 2, 4, 2 }; // game progress int lines, level; // current shapes byte current; // tetris guidelines have all 7 shapes // selected in sequence to avoid // long runs without a shape byte next[7]; byte next_c; unsigned long lastInput, lastDrop; byte board[BOARD_HEIGHT][BOARD_WIDTH]; byte x, y, rot; Backup old; int newShape; unsigned long dropWait; void drawChar(byte ascii, unsigned poX, unsigned poY, unsigned size, unsigned short fgcolor) { if ((ascii < 32) || (ascii > 127)) ascii = '?' - 32; for (int i = 0; i < FONT_X; i++) { byte temp = simpleFont[ascii - 32][i]; for (byte f = 0; f < 8; f++) if ((temp >> f) & 1) box(poX + i * size, poY + f * size, size, size, fgcolor, 1); } } void drawString(char* string, unsigned poX, unsigned poY, unsigned size, unsigned short fgcolor) { while (*string) { drawChar(*string++, poX, poY, size, fgcolor); poX += FONT_SPACE * size; } } void drawCenteredString(char* string, unsigned poY, unsigned size, unsigned short fgcolor) { unsigned len = strlen(string) * FONT_SPACE * size; unsigned left = (LCD_WIDTH - len) / 2; drawString(string, left, poY, size, fgcolor); } void drawNumber(long long_num, unsigned poX, unsigned poY, unsigned size, unsigned short fgcolor) { char buf[12], *p = buf + sizeof buf; int neg = long_num < 0; unsigned long n = neg ? -(unsigned long)long_num : (unsigned long)long_num; *--p = '\0'; do { *--p = '0' + n % 10; n /= 10; } while (n); if (neg) *--p = '-'; drawString(p, poX, poY, size, fgcolor); } void bcackground(void) { // draw black-blue gradient background for (int i = 0; i < LCD_HEIGHT; i++) { int c = 31 - i * 31 / (LCD_HEIGHT - 1); if (i < BOARD_BOTTOM) { lineh(0, i, BOARD_LEFT - 1, c); lineh(BOARD_RIGHT, i, LCD_WIDTH - BOARD_RIGHT, c); } else { lineh(0, i, LCD_WIDTH, c); } } // draw the board left limit linev(BOARD_LEFT - 1, BOARD_TOP, BOARD_BOTTOM - BOARD_TOP, PIT_COLOR); // draw the board right limit linev(BOARD_RIGHT - 1, BOARD_TOP, BOARD_BOTTOM - BOARD_TOP, PIT_COLOR); // draw the board bottom limit lineh(BOARD_LEFT - 1, BOARD_BOTTOM - 1, BOARD_RIGHT - BOARD_LEFT + 1, PIT_COLOR); // draw the grid for (int i = BOARD_LEFT + BLOCK_SIZE - 1; i < BOARD_RIGHT - 1; i += BLOCK_SIZE) linev(i, BOARD_TOP, BOARD_BOTTOM - BOARD_TOP - 1, GRAY2); for (int i = BOARD_TOP + BLOCK_SIZE - 1; i < BOARD_BOTTOM - 1; i += BLOCK_SIZE) lineh(BOARD_LEFT, i, BOARD_RIGHT - BOARD_LEFT - 1, GRAY2); } void scoreBoard(void) { box(6, 3, 128, 50, BLACK, 1); drawString("Level", 8, 8, 2, YELLOW); drawString("Lines", 8, 32, 2, 0x3f); drawNumber(level, 74, 8, 2, YELLOW); drawNumber(lines, 74, 32, 2, 0x3f); box(5, 2, 130, 52, WHITE, 0); } void hint(void) { // draw next shape hint box box(30, 100, BLOCK_SIZE * 6, BLOCK_SIZE * 5, BLACK, 1); box(29, 99, BLOCK_SIZE * 6 + 1, BLOCK_SIZE * 5 + 1, WHITE, 0); byte* shape = all_shapes[next[next_c]]; for (int i = 0; i < 4; i++) { byte* block = shape + i * 2; boxb(30 + BLOCK_SIZE + block[0] * BLOCK_SIZE, 100 + BLOCK_SIZE + block[1] * BLOCK_SIZE, BLOCK_SIZE - 1, BLOCK_SIZE - 1, colors[next[next_c]]); } } void gameLoop(void) { box(0, 0, LCD_WIDTH, LCD_HEIGHT, BG_COLOR, 1); // initialize game logic newShape = 1; lines = 0; lastInput = 0; lastDrop = 0; dropWait = DROP_WAIT_INIT; level = 1; // clean board for (int i = 0; i < BOARD_WIDTH; i++) for (int j = 0; j < BOARD_HEIGHT; j++) board[j][i] = 0; // next shape randomizer(); bcackground(); scoreBoard(); do { // get clock unsigned long now = millis(); // display new shape if (newShape) { Joystick_waitForRelease(INPUT_WAIT_NEW_SHAPE); newShape = 0; // a new shape enters the game chooseNewShape(); // draw next shape hint box hint(); // check if new shape is placed over other shape(s) // on the board if (touches(0, 0, 0)) { // draw shape to screen draw(); // game over return; } // draw shape to screen draw(); } else { // check if enough time has passed since last time the shape // was moved down the board if (now - lastDrop > dropWait || Joystick_getY() > 0) { // update clock lastDrop = now; moveDown(); } } if (!newShape && now - lastInput > INPUT_WAIT_MOVE) { userInput(now); } } while (!quit); } void chooseNewShape(void) { current = next[next_c]; next_c++; if (next_c == 7) randomizer(); // new shape must be postioned at the middle of // the top of the board // with zero rotation rot = 0; y = 0; x = BOARD_WIDTH / 2 - 1; old.rot = rot; old.y = y; old.x = x; } void userInput(unsigned long now) { int jx = Joystick_getX(); if (jx < 0 && x > 0 && !touches(-1, 0, 0)) { x--; } else if (jx > 0 && x < BOARD_WIDTH && !touches(1, 0, 0)) { x++; } else if (Joystick_fire()) { while (!touches(0, 1, 0)) y++; } else if (now - lastInput > INPUT_WAIT_ROT) { if (Joystick_getY() < 0 && !touches(0, 0, 1)) { rot++; rot %= shapes[current]; } } else { return; } lastInput = now; draw(); } void moveDown(void) { // prepare to move down // check if board is clear bellow if (touches(0, 1, 0)) { // moving down touches another shape newShape = 1; // this shape wont move again // add it to the board byte* shape = all_shapes[current]; for (int i = 0; i < 4; i++) { byte* block = shape + (rot * 4 + i) * 2; board[block[1] + y][block[0] + x] = current + 1; } // check if lines were made score(); beep(1500, 25); } else { // move shape down y++; draw(); } } void draw(void) { byte* shape = all_shapes[current]; for (int i = 0; i < 4; i++) { byte* block = shape + (rot * 4 + i) * 2; boxb(BOARD_LEFT + block[0] * BLOCK_SIZE + BLOCK_SIZE * x, BOARD_TOP + block[1] * BLOCK_SIZE + BLOCK_SIZE * y, BLOCK_SIZE - 1, BLOCK_SIZE - 1, colors[current]); board[block[1] + y][block[0] + x] = 255; } // erase old for (int i = 0; i < 4; i++) { byte* block = shape + (old.rot * 4 + i) * 2; if (board[block[1] + old.y][block[0] + old.x] == 255) continue; boxb(BOARD_LEFT + block[0] * BLOCK_SIZE + BLOCK_SIZE * old.x, BOARD_TOP + block[1] * BLOCK_SIZE + BLOCK_SIZE * old.y, BLOCK_SIZE - 1, BLOCK_SIZE - 1, BG_COLOR); } for (int i = 0; i < 4; i++) { byte* block = shape + (rot * 4 + i) * 2; board[block[1] + y][block[0] + x] = 0; } old.x = x; old.y = y; old.rot = rot; } int touches(int xi, int yi, int roti) { byte* shape = all_shapes[current]; for (int i = 0; i < 4; i++) { byte* block = shape + (((rot + roti) % shapes[current]) * 4 + i) * 2; int x2 = x + block[0] + xi; int y2 = y + block[1] + yi; if (y2 == BOARD_HEIGHT || x2 == BOARD_WIDTH || board[y2][x2]) return 1; } return 0; } void score(void) { // we scan a max of 4 lines int ll = y + 3; // BUG!!! was uninitialized if (y + 3 >= BOARD_HEIGHT) ll = BOARD_HEIGHT - 1; // scan board from current position for (int l = y; l <= ll; l++) { // check if there's a complete line on the board int line = 1; for (int c = 0; c < BOARD_WIDTH; c++) { if (board[l][c] == 0) { line = 0; break; } } if (!line) { // move to next line continue; } beep(3000, 50); lines++; if (lines % 10 == 0) { level++; dropWait /= 2; } scoreBoard(); // move board down for (int row = l; row > 0; row --) { for (int c = 0; c < BOARD_WIDTH; c++) { byte v = board[row - 1][c]; board[row][c] = v; boxb(BOARD_LEFT + BLOCK_SIZE * c, BOARD_TOP + BLOCK_SIZE * row, BLOCK_SIZE - 1, BLOCK_SIZE - 1, v == 0 ? BLACK : colors[v - 1]); } } // clear top line for (int c = 0; c < BOARD_WIDTH; c++) board[0][c] = 0; box(BOARD_LEFT, 0, BOARD_RIGHT - BOARD_LEFT, BLOCK_SIZE, BLACK, 1); } delay(350); } // create a sequence of 7 random shapes void randomizer(void) { // randomize 7 shapes for (byte i = 0; i < 7; i ++) { int retry; byte shape; do { shape = rand() % 7; // check if already in sequence retry = 0; for (int j = 0; j < i; j++) { if (shape == next[j]) { retry = 1; break; } } } while (retry); next[i] = shape; } next_c = 0; } void drawPreGameScreen(void) { box(0, 0, LCD_WIDTH, LCD_HEIGHT, WHITE, 1); drawCenteredString("Tetris", 40, 8, BLUE); drawCenteredString("Move joystick to start", 110, 2, BLACK); drawCenteredString("http://vilaca.eu", 220, 2, PURPLE); } void gameOver(void) { box(32, LCD_HEIGHT / 2 - 24, LCD_WIDTH - 64, 48, BLACK, 1); drawCenteredString("Game Over", LCD_HEIGHT / 2 - 16, 4, WHITE); box(32, LCD_HEIGHT / 2 - 24, LCD_WIDTH - 64, 48, RED, 0); beep(600, 200); delay(300); beep(600, 200); delay(300); beep(200, 600); delay(1500); } unsigned char simpleFont[][8] = { {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, {0x00,0x00,0x5F,0x00,0x00,0x00,0x00,0x00}, {0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00}, {0x00,0x14,0x7F,0x14,0x7F,0x14,0x00,0x00}, {0x00,0x24,0x2A,0x7F,0x2A,0x12,0x00,0x00}, {0x00,0x23,0x13,0x08,0x64,0x62,0x00,0x00}, {0x00,0x36,0x49,0x55,0x22,0x50,0x00,0x00}, {0x00,0x00,0x05,0x03,0x00,0x00,0x00,0x00}, {0x00,0x1C,0x22,0x41,0x00,0x00,0x00,0x00}, {0x00,0x41,0x22,0x1C,0x00,0x00,0x00,0x00}, {0x00,0x08,0x2A,0x1C,0x2A,0x08,0x00,0x00}, {0x00,0x08,0x08,0x3E,0x08,0x08,0x00,0x00}, {0x00,0xA0,0x60,0x00,0x00,0x00,0x00,0x00}, {0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00}, {0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00}, {0x00,0x20,0x10,0x08,0x04,0x02,0x00,0x00}, {0x00,0x3E,0x51,0x49,0x45,0x3E,0x00,0x00}, {0x00,0x00,0x42,0x7F,0x40,0x00,0x00,0x00}, {0x00,0x62,0x51,0x49,0x49,0x46,0x00,0x00}, {0x00,0x22,0x41,0x49,0x49,0x36,0x00,0x00}, {0x00,0x18,0x14,0x12,0x7F,0x10,0x00,0x00}, {0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00}, {0x00,0x3C,0x4A,0x49,0x49,0x30,0x00,0x00}, {0x00,0x01,0x71,0x09,0x05,0x03,0x00,0x00}, {0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00}, {0x00,0x06,0x49,0x49,0x29,0x1E,0x00,0x00}, {0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00}, {0x00,0x00,0xAC,0x6C,0x00,0x00,0x00,0x00}, {0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00}, {0x00,0x14,0x14,0x14,0x14,0x14,0x00,0x00}, {0x00,0x41,0x22,0x14,0x08,0x00,0x00,0x00}, {0x00,0x02,0x01,0x51,0x09,0x06,0x00,0x00}, {0x00,0x32,0x49,0x79,0x41,0x3E,0x00,0x00}, {0x00,0x7E,0x09,0x09,0x09,0x7E,0x00,0x00}, {0x00,0x7F,0x49,0x49,0x49,0x36,0x00,0x00}, {0x00,0x3E,0x41,0x41,0x41,0x22,0x00,0x00}, {0x00,0x7F,0x41,0x41,0x22,0x1C,0x00,0x00}, {0x00,0x7F,0x49,0x49,0x49,0x41,0x00,0x00}, {0x00,0x7F,0x09,0x09,0x09,0x01,0x00,0x00}, {0x00,0x3E,0x41,0x41,0x51,0x72,0x00,0x00}, {0x00,0x7F,0x08,0x08,0x08,0x7F,0x00,0x00}, {0x00,0x41,0x7F,0x41,0x00,0x00,0x00,0x00}, {0x00,0x20,0x40,0x41,0x3F,0x01,0x00,0x00}, {0x00,0x7F,0x08,0x14,0x22,0x41,0x00,0x00}, {0x00,0x7F,0x40,0x40,0x40,0x40,0x00,0x00}, {0x00,0x7F,0x02,0x0C,0x02,0x7F,0x00,0x00}, {0x00,0x7F,0x04,0x08,0x10,0x7F,0x00,0x00}, {0x00,0x3E,0x41,0x41,0x41,0x3E,0x00,0x00}, {0x00,0x7F,0x09,0x09,0x09,0x06,0x00,0x00}, {0x00,0x3E,0x41,0x51,0x21,0x5E,0x00,0x00}, {0x00,0x7F,0x09,0x19,0x29,0x46,0x00,0x00}, {0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x00}, {0x00,0x01,0x01,0x7F,0x01,0x01,0x00,0x00}, {0x00,0x3F,0x40,0x40,0x40,0x3F,0x00,0x00}, {0x00,0x1F,0x20,0x40,0x20,0x1F,0x00,0x00}, {0x00,0x3F,0x40,0x38,0x40,0x3F,0x00,0x00}, {0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x00}, {0x00,0x03,0x04,0x78,0x04,0x03,0x00,0x00}, {0x00,0x61,0x51,0x49,0x45,0x43,0x00,0x00}, {0x00,0x7F,0x41,0x41,0x00,0x00,0x00,0x00}, {0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00}, {0x00,0x41,0x41,0x7F,0x00,0x00,0x00,0x00}, {0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x00}, {0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00}, {0x00,0x01,0x02,0x04,0x00,0x00,0x00,0x00}, {0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x00}, {0x00,0x7F,0x48,0x44,0x44,0x38,0x00,0x00}, {0x00,0x38,0x44,0x44,0x28,0x00,0x00,0x00}, {0x00,0x38,0x44,0x44,0x48,0x7F,0x00,0x00}, {0x00,0x38,0x54,0x54,0x54,0x18,0x00,0x00}, {0x00,0x08,0x7E,0x09,0x02,0x00,0x00,0x00}, {0x00,0x18,0xA4,0xA4,0xA4,0x7C,0x00,0x00}, {0x00,0x7F,0x08,0x04,0x04,0x78,0x00,0x00}, {0x00,0x00,0x7D,0x00,0x00,0x00,0x00,0x00}, {0x00,0x80,0x84,0x7D,0x00,0x00,0x00,0x00}, {0x00,0x7F,0x10,0x28,0x44,0x00,0x00,0x00}, {0x00,0x41,0x7F,0x40,0x00,0x00,0x00,0x00}, {0x00,0x7C,0x04,0x18,0x04,0x78,0x00,0x00}, {0x00,0x7C,0x08,0x04,0x7C,0x00,0x00,0x00}, {0x00,0x38,0x44,0x44,0x38,0x00,0x00,0x00}, {0x00,0xFC,0x24,0x24,0x18,0x00,0x00,0x00}, {0x00,0x18,0x24,0x24,0xFC,0x00,0x00,0x00}, {0x00,0x00,0x7C,0x08,0x04,0x00,0x00,0x00}, {0x00,0x48,0x54,0x54,0x24,0x00,0x00,0x00}, {0x00,0x04,0x7F,0x44,0x00,0x00,0x00,0x00}, {0x00,0x3C,0x40,0x40,0x7C,0x00,0x00,0x00}, {0x00,0x1C,0x20,0x40,0x20,0x1C,0x00,0x00}, {0x00,0x3C,0x40,0x30,0x40,0x3C,0x00,0x00}, {0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00}, {0x00,0x1C,0xA0,0xA0,0x7C,0x00,0x00,0x00}, {0x00,0x44,0x64,0x54,0x4C,0x44,0x00,0x00}, {0x00,0x08,0x36,0x41,0x00,0x00,0x00,0x00}, {0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00}, {0x00,0x41,0x36,0x08,0x00,0x00,0x00,0x00}, {0x00,0x02,0x01,0x01,0x02,0x01,0x00,0x00}, {0x00,0x02,0x05,0x05,0x02,0x00,0x00,0x00} }; int main(void) { // get TFT display handle if ((fd = open("/dev/tft0", O_RDWR)) < 0) { perror("/dev/tft0"); return 1; } // get joystick's x ADC handle if ((fdx = open("/dev/adc0", O_RDWR)) < 0) { perror("/dev/adc0"); return 1; } // get joystick's y ADC handle if ((fdy = open("/dev/adc1", O_RDWR)) < 0) { perror("/dev/adc1"); return 1; } srand(time(NULL)); drawPreGameScreen(); while (!Joystick_fire() && !Joystick_getY() && !Joystick_getX()); gameLoop(); gameOver(); while (!Joystick_fire() && !Joystick_getY() && !Joystick_getX()); box(0, 0, LCD_WIDTH, LCD_HEIGHT, BLACK, 1); }