From 3affa5c9a37f531919f2a891bbbc5e9c2fad79a4 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Sun, 30 Jan 2011 22:47:44 +0000 Subject: [PATCH] squeezed another 680 bytes --- animations/matrix.c | 4 +- animations/programm.c | 6 +- games/breakout/breakout.c | 6 +- games/snake/snake_game.c | 172 ++++++++++------- games/space_invaders/invader_draw.c | 14 +- games/space_invaders/invader_init.c | 16 +- games/space_invaders/invader_proc.c | 15 +- games/tetris/bucket.c | 155 ++++++++------- games/tetris/bucket.h | 19 +- games/tetris/highscore.c | 55 ++---- games/tetris/input.c | 4 +- games/tetris/piece.c | 2 +- games/tetris/piece.h | 2 +- games/tetris/tetris_main.c | 8 +- games/tetris/variant_bastet.c | 70 ++----- games/tetris/view.c | 55 ++---- menu/menu.c | 288 ++++++++++++++-------------- menu/menu.h | 21 -- scrolltext/scrolltext3.c | 10 +- 19 files changed, 424 insertions(+), 498 deletions(-) diff --git a/animations/matrix.c b/animations/matrix.c index 8a5e81f..afa7a49 100644 --- a/animations/matrix.c +++ b/animations/matrix.c @@ -73,8 +73,8 @@ void matrix() { } } - for(y=0;ypos, cur->dir)); wait(delay); } @@ -350,7 +350,7 @@ unsigned char i, j, x; #ifdef ANIMATION_SCHACHBRETT void schachbrett(unsigned char times){ clear_screen(0); - for (unsigned char i = 0; i < times; ++i) { + for (unsigned char i = times; i--;) { for (unsigned char row = 0; row < NUM_ROWS; ++row) { for (unsigned char col = 0; col < LINEBYTES; ++col) { pixmap[2][row][col] = ((i ^ row) & 0x01) ? 0x55 : 0xAA; diff --git a/games/breakout/breakout.c b/games/breakout/breakout.c index f484692..f788451 100644 --- a/games/breakout/breakout.c +++ b/games/breakout/breakout.c @@ -50,17 +50,17 @@ void borg_breakout(uint8_t demomode) ball_spawn_default(&(balls[0])); balls[0].strength = START_LIFES; level_init(level); - uint8_t tick_divider = 0; + uint8_t tick_divider = 1; rebound_init(); while (cycles != 0) { wait(25); - if ((tick_divider % 2) || JOYISFIRE) + if (tick_divider || JOYISFIRE) rebound_tick(demomode ? &balls[0] : NULL); - if (tick_divider % 2) + if (tick_divider) { ball_think(&(balls[0])); playfield_draw(); diff --git a/games/snake/snake_game.c b/games/snake/snake_game.c index e9ce1a7..d77fab0 100644 --- a/games/snake/snake_game.c +++ b/games/snake/snake_game.c @@ -1,4 +1,3 @@ - #include "../../config.h" #include "../../compat/pgmspace.h" #include "../../menu/menu.h" @@ -17,146 +16,175 @@ void snake_game(); #ifdef MENU_SUPPORT // MSB is leftmost pixel static uint8_t icon[8] PROGMEM = - {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xad, 0xa1, 0xbf}; // Snake icon +{0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xad, 0xa1, 0xbf}; // Snake icon -game_descriptor_t snake_game_descriptor __attribute__((section(".game_descriptors"))) ={ - &snake_game, - icon, -}; +game_descriptor_t snake_game_descriptor __attribute__((section(".game_descriptors"))) = + {&snake_game, icon}; #endif -void snake_game() { - pixel pixels[64] = {{4, NUM_ROWS-2},{4, NUM_ROWS-3}}; - pixel * head = &pixels[1]; - pixel * tail = &pixels[0]; +void snake_game() +{ + pixel pixels[64] = {{4, NUM_ROWS - 2}, {4, NUM_ROWS - 3}}; + pixel *head = &pixels[1]; + pixel *tail = &pixels[0]; pixel old_head; - pixel apples[10]; - uint8_t joy, joy_old=0xff, joy_cmd=0xff; - unsigned char x, y, dead = 0; + pixel apples[10]; unsigned char apple_num = 0; direction dir = up; - + + clear_screen(0); + unsigned char apple_found = 0; unsigned char j; - clear_screen(0); - + unsigned char x, y, dead = 0; + uint8_t joy, joy_old = 0xff, joy_cmd = 0xff; + // zeichne Rahmen - for (x = 0; x < NUM_COLS; x++) { - for (y = 0; y < NUM_ROWS; y++) { - if (((x == 0) || (x == NUM_COLS-1)) || - ((y == 0) || (y == NUM_ROWS-1))) { + for (x = 0; x < NUM_COLS; x++) + { + for (y = 0; y < NUM_ROWS; y++) + { + if (((x == 0) || (x == NUM_COLS - 1)) || ((y == 0) || (y + == NUM_ROWS - 1))) + { setpixel((pixel) {x, y}, 3); } } } - - x = 0; - while (1) { + x = 0; + while (1) + { x++; old_head = *head; - ++head; - if (head == pixels + 64) - head = pixels; + if (++head == pixels + 64) + head = pixels; #ifdef GAME_SNAKE_NEWCONTROL if (joy_cmd != 0xff) { - if ( (dir == left && joy_cmd != right) || - (dir == right && joy_cmd != left) || - (dir == up && joy_cmd != down) || - (dir == down && joy_cmd != up) ) + if ((dir == left && joy_cmd != right) || (dir == right && joy_cmd + != left) || (dir == up && joy_cmd != down) || (dir == down + && joy_cmd != up)) dir = joy_cmd; } #else - if (joy_cmd == right) { - dir = direction_r(dir); - joy_cmd = 0xff; - } else if (joy_cmd == left) { - dir = direction_r(dir); - dir = direction_r(dir); - dir = direction_r(dir); - joy_cmd = 0xff; - } + if (joy_cmd == right) + { + dir = direction_r(dir); + joy_cmd = 0xff; + } + else if (joy_cmd == left) + { + dir = direction_r(dir); + dir = direction_r(dir); + dir = direction_r(dir); + joy_cmd = 0xff; + } #endif - + // kopf einen weiter bewegen *head = next_pixel(old_head, dir); - - apple_found = 0; - + + apple_found = 0; + // pr?fen ob man auf nen Apfel drauf ist - for (j = 0; j < apple_num; j++) { - if ( ( head->x == apples[j].x) && - (head->y == apples[j].y) ){ + for (j = 0; j < apple_num; j++) + { + if ((head->x == apples[j].x) && (head->y == apples[j].y)) + { apple_found = 1; - for(; j < apple_num - 1; j++) { - apples[j] = apples[j+1]; + for (; j < apple_num - 1; j++) + { + apples[j] = apples[j + 1]; } apple_num--; goto apple_se; } } - if (get_pixel(*head)) { + if (get_pixel(*head)) + { dead = 1; } apple_se: - if (!dead) { + if (!dead) + { setpixel(*head, 3); - + // setze neue ?pfel - if ( (apple_num < 9) && (random8() < 10) ) { + if ((apple_num < 9) && (random8() < 10)) + { pixel new_apple = (pixel) {(random8() % (NUM_COLS-2))+1, (random8() % (NUM_ROWS-2))+1}; - if (!get_pixel(new_apple)){ + if (!get_pixel(new_apple)) + { apples[apple_num++] = new_apple; } } - // l?sche Ende - if (!apple_found && !dead) { + // l?sche Ende + if (!apple_found && !dead) + { clearpixel(*tail); - if (++tail == pixels + 64) + if (++tail == pixels + 64) tail = pixels; } - } else { - while (tail != head) { + } + else + { + while (tail != head) + { clearpixel(*tail); - if ((++tail) > pixels + 64) + if ((++tail) > pixels + 64) tail = pixels; - wait (60); + wait(60); } break; } - - for (j = 0; j < apple_num; j++) { - if (x % 2) { + + for (j = 0; j < apple_num; j++) + { + if (x % 2) + { setpixel(apples[j], 3); - } else { + } + else + { clearpixel(apples[j]); } } - for(j=0;j<20;j++){ - if(JOYISLEFT){ + for (j = 0; j < 20; j++) + { + if (JOYISLEFT) + { joy = left; - }else if(JOYISRIGHT){ + } + else if (JOYISRIGHT) + { joy = right; #ifdef GAME_SNAKE_NEWCONTROL - }else if(JOYISUP) { + } + else if (JOYISUP) + { joy = up; - } else if(JOYISDOWN) { + } + else if (JOYISDOWN) + { joy = down; #endif - }else{ + } + else + { joy = 0xff; } - if(joy != joy_old){ + if (joy != joy_old) + { joy_cmd = joy; } joy_old = joy; - wait (5); + wait(5); } } } diff --git a/games/space_invaders/invader_draw.c b/games/space_invaders/invader_draw.c index bbdea2c..07457bf 100644 --- a/games/space_invaders/invader_draw.c +++ b/games/space_invaders/invader_draw.c @@ -43,7 +43,7 @@ void draw(Invaders * iv, Spaceship * sc, Player * pl, Cannon * cn, { clearScreen (); - int x, y; + unsigned char x, y; /*---SPACESHIP---*/ if (sc->pos < RIGHT_BORDER) @@ -56,9 +56,11 @@ void draw(Invaders * iv, Spaceship * sc, Player * pl, Cannon * cn, } /*---INVADERS--*/ - for (y = 0; y < MAX_INVADER_HEIGHT; y++) +// for (y = 0; y < MAX_INVADER_HEIGHT; y++) + for (y = MAX_INVADER_HEIGHT; y--;) { - for (x = 0; x < MAX_INVADER_WIDTH; x++) +// for (x = 0; x < MAX_INVADER_WIDTH; x++) + for (x = MAX_INVADER_WIDTH; x--;) { //mal in oder statement umwandeln ;-) if (iv->map[x][y] == 0) @@ -73,7 +75,7 @@ void draw(Invaders * iv, Spaceship * sc, Player * pl, Cannon * cn, } /*---GUARDS---*/ - for (x = 0; x < BORG_WIDTH; ++x) + for (x = BORG_WIDTH; x--;) { if (guards[x] != 0) { @@ -82,8 +84,8 @@ void draw(Invaders * iv, Spaceship * sc, Player * pl, Cannon * cn, } /*---SHOTS--*/ - int i; - for (i = 0; i < MAX_SHOTS; ++i) + unsigned char i; + for (i = MAX_SHOTS; i--;) { if (st[i].x < BORG_WIDTH && st[i].y < BORG_HEIGHT) { diff --git a/games/space_invaders/invader_init.c b/games/space_invaders/invader_init.c index 15ca77b..80f067e 100644 --- a/games/space_invaders/invader_init.c +++ b/games/space_invaders/invader_init.c @@ -26,8 +26,8 @@ uint8_t const hans[8][11] PROGMEM = void initGuards(unsigned char guards[BORG_WIDTH]) { - int x; - for (x = 0; x < BORG_WIDTH; ++x) + unsigned char x; + for (x = BORG_WIDTH; x--;) { guards[x] = 0; } @@ -44,9 +44,9 @@ void initInvaders(Invaders * iv, unsigned char lv) unsigned char x, y; // first zero out map! - for (x = 0; x < MAX_INVADER_WIDTH; ++x) + for (x = MAX_INVADER_WIDTH; x--;) { - for (y = 0; y < MAX_INVADER_HEIGHT; ++y) + for (y = MAX_INVADER_HEIGHT; y--;) { iv->map[x][y] = 0; } @@ -112,9 +112,9 @@ void initInvaders(Invaders * iv, unsigned char lv) break; case 3: - for (x = 0; x < 11; ++x) + for (x = 11; x--;) { - for (y = 0; y < 8; ++y) + for (y = 8; y--;) { if (pgm_read_byte(&hans[y][x]) != 0) { @@ -132,9 +132,9 @@ void initInvaders(Invaders * iv, unsigned char lv) break; case 4: - for (x = 0; x < 11; ++x) + for (x = 11; x--;) { - for (y = 0; y < 8; ++y) + for (y = 8; y--;) { if (pgm_read_byte(&peter[y][x]) != 0) { diff --git a/games/space_invaders/invader_proc.c b/games/space_invaders/invader_proc.c index d4698f0..ceb151c 100644 --- a/games/space_invaders/invader_proc.c +++ b/games/space_invaders/invader_proc.c @@ -45,7 +45,7 @@ void procCannon(Cannon * cn, uPixel * shot) unsigned char areAtBorder(Invaders * iv) { - int y; + unsigned char y; for (y = SPACESHIP_LINE + 1; y <= GUARD_LINE; ++y) { if (getInvaderPixel(iv, LEFT_BORDER, y) || getInvaderPixel(iv, @@ -113,8 +113,7 @@ void procInvaders(Invaders * iv, uPixel st[MAX_SHOTS]) void procShots(Invaders * iv, Player * pl, Cannon * cn, Spaceship * sc, unsigned char guards[BORG_WIDTH], uPixel st[MAX_SHOTS], uPixel * shot) { - - int i; + unsigned char i; static unsigned char cmv = 0, imv = 0; // shuß mit einen struct mit dem shuß!! @@ -136,7 +135,7 @@ void procShots(Invaders * iv, Player * pl, Cannon * cn, Spaceship * sc, { imv = 0; - for (i = 0; i < MAX_SHOTS; ++i) + for (i = MAX_SHOTS; i--;) { if ( /*st[i].x < BORG_WIDTH && */st[i].y < BORG_HEIGHT) { @@ -157,7 +156,7 @@ void procShots(Invaders * iv, Player * pl, Cannon * cn, Spaceship * sc, unsigned char tmp; if (!(cn->ready)) { - for (i = 0; i < MAX_SHOTS; ++i) + for (i = MAX_SHOTS; i--;) { if (shot->x == st[i].x && shot->y == st[i].y) { @@ -282,9 +281,9 @@ unsigned char getStatus(Invaders * iv) //count Invader! unsigned char x, y, inv = 0; - for (x = 0; x < MAX_INVADER_WIDTH; ++x) + for (x = MAX_INVADER_WIDTH; x--;) { - for (y = 0; y < MAX_INVADER_HEIGHT; ++y) + for (y = MAX_INVADER_HEIGHT; y--;) { if (iv->map[x][y] != 0) inv++; @@ -296,7 +295,7 @@ unsigned char getStatus(Invaders * iv) return 1; //INVADERS REACHED EARTH - for (x = 0; x < BORG_WIDTH; ++x) + for (x = BORG_WIDTH; x--;) { if (getInvaderPixel(iv, x, GUARD_LINE + 1)) return 2; diff --git a/games/tetris/bucket.c b/games/tetris/bucket.c index de106c3..580ca7a 100644 --- a/games/tetris/bucket.c +++ b/games/tetris/bucket.c @@ -12,11 +12,83 @@ * non-interface functions * ***************************/ +/** + * detects if piece collides with s.th. at a given position + * @param pBucket bucket to perform action on + * @param nColumn column where the piece should be moved + * @param nRow row where the piece should be moved + * @return 1 for collision, 0 otherwise + */ +static uint8_t tetris_bucket_collision(tetris_bucket_t *pBucket, + int8_t nCol, + int8_t nRow) +{ + // A piece is represented by 16 bits (4 bits per row where the LSB marks the + // left most position). The part of the bucket which is covered by the piece + // is converted to this format (including the bucket borders) so that a + // simple bitwise 'AND' tells us if the piece and the dump overlap. + + // only allow coordinates which are within sane ranges + assert(pBucket != NULL); + assert((nCol > -4) && (nCol < pBucket->nWidth)); + assert((nRow > -4) && (nRow < pBucket->nHeight)); + + // left and right borders + uint16_t const nPieceMap = tetris_piece_getBitmap(pBucket->pPiece); + uint16_t nBucketPart = 0; + if (nCol < 0) + { + static uint16_t const nLeftPart[] PROGMEM = {0x7777, 0x3333, 0x1111}; + nBucketPart = pgm_read_word(&nLeftPart[nCol + 3]); + } + else if (nCol >= pBucket->nWidth - 3) + { + static uint16_t const nRightPart[] PROGMEM = {0xEEEE, 0xCCCC, 0x8888}; + nBucketPart = pgm_read_word(&nRightPart[pBucket->nWidth - nCol - 1]); + } + // lower border + if (nRow > pBucket->nHeight - 4) + { + nBucketPart |= 0xFFFF << ((pBucket->nHeight - nRow) * 4); + } + + // return if the piece already collides with the border + if (nPieceMap & nBucketPart) + { + // collision + return 1; + } + + // range for inspecting the piece row by row (starting at the bottom) + int8_t const nStart = nRow + tetris_piece_getBottomOffset(nPieceMap); + int8_t const nStop = nRow >= 0 ? nRow : 0; + // mask those blocks which are not covered by the piece + uint16_t const nDumpMask = nCol >= 0 ? 0x000F << nCol : 0x000F >> -nCol; + // value for shifting blocks to the corresponding part of the piece + int8_t nShift = 12 - nCol - 4 * (nRow + 3 - nStart); + // compare piece with dump + for (int8_t y = nStart; y >= nStop; --y) + { + uint16_t nTemp = pBucket->dump[y] & nDumpMask; + nBucketPart |= nShift >= 0 ? nTemp << nShift : nTemp >> -nShift; + if (nPieceMap & nBucketPart) + { + // collision + return 1; + } + nShift -= 4; + } + + // if we reach here, no collision was detected + return 0; +} + + /** * determines if piece is either hovering or gliding and sets the bucket's state * @param pBucket the bucket we want information from */ -inline static void tetris_bucket_hoverStatus(tetris_bucket_t *pBucket) +static void tetris_bucket_hoverStatus(tetris_bucket_t *pBucket) { assert(pBucket != NULL); @@ -109,11 +181,10 @@ void tetris_bucket_reset(tetris_bucket_t *pBucket) } -void tetris_bucket_insertPiece(tetris_bucket_t *pBucket, - tetris_piece_t *pPiece, - tetris_piece_t **ppOldPiece) +tetris_piece_t *tetris_bucket_insertPiece(tetris_bucket_t *pBucket, + tetris_piece_t *pPiece) { - assert((pBucket != NULL) && (pPiece != NULL) && (ppOldPiece != NULL)); + assert((pBucket != NULL) && (pPiece != NULL)); // a piece can only be inserted in state TETRIS_BUS_READY assert(pBucket->status == TETRIS_BUS_READY); @@ -121,10 +192,6 @@ void tetris_bucket_insertPiece(tetris_bucket_t *pBucket, // row mask is now meaningless pBucket->nRowMask = 0; - // replace old piece - *ppOldPiece = pBucket->pPiece; - pBucket->pPiece = pPiece; - // set horizontal start position (in the middle of the top line) pBucket->nColumn = (pBucket->nWidth - 2) / 2; @@ -132,6 +199,10 @@ void tetris_bucket_insertPiece(tetris_bucket_t *pBucket, pBucket->nRow = 1 - tetris_piece_getBottomOffset(tetris_piece_getBitmap(pPiece)); + // replace old piece + tetris_piece_t *pOldPiece = pBucket->pPiece; + pBucket->pPiece = pPiece; + // did we already collide with something? if (tetris_bucket_collision(pBucket, pBucket->nColumn, pBucket->nRow) == 1) { @@ -143,71 +214,7 @@ void tetris_bucket_insertPiece(tetris_bucket_t *pBucket, // bring it on! tetris_bucket_hoverStatus(pBucket); } -} - - -uint8_t tetris_bucket_collision(tetris_bucket_t *pBucket, - int8_t nCol, - int8_t nRow) -{ - // A piece is represented by 16 bits (4 bits per row where the LSB marks the - // left most position). The part of the bucket which is covered by the piece - // is converted to this format (including the bucket borders) so that a - // simple bitwise 'AND' tells us if the piece and the dump overlap. - - // only allow coordinates which are within sane ranges - assert(pBucket != NULL); - assert((nCol > -4) && (nCol < pBucket->nWidth)); - assert((nRow > -4) && (nRow < pBucket->nHeight)); - - // left and right borders - uint16_t const nPieceMap = tetris_piece_getBitmap(pBucket->pPiece); - uint16_t nBucketPart = 0; - if (nCol < 0) - { - static uint16_t const nLeftPart[] PROGMEM = {0x7777, 0x3333, 0x1111}; - nBucketPart = pgm_read_word(&nLeftPart[nCol + 3]); - } - else if (nCol >= pBucket->nWidth - 3) - { - static uint16_t const nRightPart[] PROGMEM = {0xEEEE, 0xCCCC, 0x8888}; - nBucketPart = pgm_read_word(&nRightPart[pBucket->nWidth - nCol - 1]); - } - // lower border - if (nRow > pBucket->nHeight - 4) - { - nBucketPart |= 0xFFFF << ((pBucket->nHeight - nRow) * 4); - } - - // return if the piece already collides with the border - if (nPieceMap & nBucketPart) - { - // collision - return 1; - } - - // range for inspecting the piece row by row (starting at the bottom) - int8_t const nStart = nRow + tetris_piece_getBottomOffset(nPieceMap); - int8_t const nStop = nRow >= 0 ? nRow : 0; - // mask those blocks which are not covered by the piece - uint16_t const nDumpMask = nCol >= 0 ? 0x000F << nCol : 0x000F >> -nCol; - // value for shifting blocks to the corresponding part of the piece - int8_t nShift = 12 - nCol - 4 * (nRow + 3 - nStart); - // compare piece with dump - for (int8_t y = nStart; y >= nStop; --y) - { - uint16_t nTemp = pBucket->dump[y] & nDumpMask; - nBucketPart |= nShift >= 0 ? nTemp << nShift : nTemp >> -nShift; - if (nPieceMap & nBucketPart) - { - // collision - return 1; - } - nShift -= 4; - } - - // if we reach here, no collision was detected - return 0; + return pOldPiece; } diff --git a/games/tetris/bucket.h b/games/tetris/bucket.h index a7a2fe2..bccbd99 100644 --- a/games/tetris/bucket.h +++ b/games/tetris/bucket.h @@ -134,23 +134,10 @@ void tetris_bucket_reset(tetris_bucket_t *pBucket); * inserts a new piece * @param pBucket bucket to perform action on * @param pPiece piece to be inserted - * @param ppOldPiece [out] indirect pointer to former piece for deallocation + * @return pointer to former piece for deallocation */ -void tetris_bucket_insertPiece(tetris_bucket_t *pBucket, - tetris_piece_t *pPiece, - tetris_piece_t** ppOldPiece); - - -/** - * detects if piece collides with s.th. at a given position - * @param pBucket bucket to perform action on - * @param nColumn column where the piece should be moved - * @param nRow row where the piece should be moved - * @return 1 for collision, 0 otherwise - */ -uint8_t tetris_bucket_collision(tetris_bucket_t *pBucket, - int8_t nColumn, - int8_t nRow); +tetris_piece_t *tetris_bucket_insertPiece(tetris_bucket_t *pBucket, + tetris_piece_t *pPiece); /** diff --git a/games/tetris/highscore.c b/games/tetris/highscore.c index c544844..8d0669a 100644 --- a/games/tetris/highscore.c +++ b/games/tetris/highscore.c @@ -17,35 +17,21 @@ uint16_t tetris_highscore_name[TETRIS_HISCORE_END] EEMEM; uint16_t tetris_highscore_inputName(void) { #ifdef SCROLLTEXT_SUPPORT - char pszNick[4], pszTmp[26]; - unsigned int nOffset; - uint8_t nPos = 0, nBlink = 0, nDone = 0, nHadfire = 0; + char pszNick[4] = {'A', 'A', 'A', '\0'}; + char pszTmp[26]; + uint8_t nPos = 0, nBlink = 0, nHadfire = 0; - strncpy(pszNick, "AAA", sizeof(pszNick)); - while (!nDone) + while (1) { // we need our own blink interval nBlink = (nBlink + 1) % 4; - // determine start position on screen depending on active character - switch (nPos) - { - case 0: - nOffset = 15; - break; - case 1: - nOffset = 19; - break; - default: - nOffset = 23; - break; - } - // construct command for scrolltext and execute + static uint8_t const nOffset[3] = {15, 19, 23}; snprintf(pszTmp, sizeof(pszTmp), "x%u+p1#%c#x%u+p1#%c#x%up1#%c", - nOffset , (!nBlink && nPos == 0) ? ' ' : pszNick[0], - nOffset - 8, (!nBlink && nPos == 1) ? ' ' : pszNick[1], - nOffset - 15, (!nBlink && nPos == 2) ? ' ' : pszNick[2]); + nOffset[nPos] , (!nBlink && nPos == 0) ? ' ' : pszNick[0], + nOffset[nPos] - 8, (!nBlink && nPos == 1) ? ' ' : pszNick[1], + nOffset[nPos] - 15, (!nBlink && nPos == 2) ? ' ' : pszNick[2]); scrolltext(pszTmp); // up and down control current char @@ -73,8 +59,9 @@ uint16_t tetris_highscore_inputName(void) pszNick[nPos] = 'Z'; } } + // left and right control char selections - else if (JOYISLEFT && nPos > 0) + if (JOYISLEFT && nPos > 0) { nPos--; } @@ -87,21 +74,13 @@ uint16_t tetris_highscore_inputName(void) if (JOYISFIRE && !nHadfire) { nHadfire = 1; - switch (nPos) + if (nPos++ == 2) { - case 0: - nPos = 1; - break; - case 1: - nPos = 2; - break; - case 2: - nDone = 1; break; } } - if (nHadfire && !JOYISFIRE) + if (!JOYISFIRE) { nHadfire = 0; } @@ -117,8 +96,8 @@ uint16_t tetris_highscore_inputName(void) uint16_t tetris_highscore_retrieveHighscore(tetris_highscore_index_t nIndex) { - uint16_t nHighscore = 0; - nHighscore = eeprom_read_word(&tetris_highscore[nIndex]); + uint16_t nHighscore = + eeprom_read_word(&tetris_highscore[nIndex]); // a score of 65535 is most likely caused by uninitialized EEPROM addresses if (nHighscore == 65535) @@ -142,10 +121,10 @@ void tetris_highscore_saveHighscore(tetris_highscore_index_t nIndex, uint16_t tetris_highscore_retrieveHighscoreName(tetris_highscore_index_t nIdx) { - uint16_t nHighscoreName = 0; - nHighscoreName = eeprom_read_word(&tetris_highscore_name[nIdx]); + uint16_t nHighscoreName = + eeprom_read_word(&tetris_highscore_name[nIdx]); - // a score of 65535 is most likely caused by uninitialized EEPROM addresses + // a value of 65535 is most likely caused by uninitialized EEPROM addresses if (nHighscoreName == 65535) { nHighscoreName = 0; diff --git a/games/tetris/input.c b/games/tetris/input.c index 4296994..4e63012 100644 --- a/games/tetris/input.c +++ b/games/tetris/input.c @@ -124,8 +124,8 @@ static void tetris_input_chatterProtect(tetris_input_t *pIn, if ((cmd == TETRIS_INCMD_ROT_CW) || (cmd == TETRIS_INCMD_DOWN)) { // helper variables (which the compiler hopefully optimizes away) - uint8_t nRotCw = pIn->nIgnoreCmdCounter[TETRIS_INCMD_ROT_CW]; - uint8_t nDown = pIn->nIgnoreCmdCounter[TETRIS_INCMD_DOWN]; + uint8_t const nRotCw = pIn->nIgnoreCmdCounter[TETRIS_INCMD_ROT_CW]; + uint8_t const nDown = pIn->nIgnoreCmdCounter[TETRIS_INCMD_DOWN]; pIn->nIgnoreCmdCounter[TETRIS_INCMD_PAUSE] = (nRotCw > nDown ? nRotCw : nDown); diff --git a/games/tetris/piece.c b/games/tetris/piece.c index 9a8a48a..a12ed68 100644 --- a/games/tetris/piece.c +++ b/games/tetris/piece.c @@ -66,7 +66,7 @@ void tetris_piece_rotate(tetris_piece_t *pPc, } -int8_t tetris_piece_getAngleCount(tetris_piece_t *pPc) +uint8_t tetris_piece_getAngleCount(tetris_piece_t *pPc) { assert(pPc != NULL); diff --git a/games/tetris/piece.h b/games/tetris/piece.h index a4ac8ff..70ca93c 100644 --- a/games/tetris/piece.h +++ b/games/tetris/piece.h @@ -143,7 +143,7 @@ inline static void tetris_piece_setAngle(tetris_piece_t *pPc, * @param pPc piece whose angle count we want to know * @return number of different angles */ -int8_t tetris_piece_getAngleCount(tetris_piece_t *pPc); +uint8_t tetris_piece_getAngleCount(tetris_piece_t *pPc); /** diff --git a/games/tetris/tetris_main.c b/games/tetris/tetris_main.c index c3e06ee..e60cc2f 100644 --- a/games/tetris/tetris_main.c +++ b/games/tetris/tetris_main.c @@ -55,13 +55,11 @@ void tetris_main(tetris_variant_t const *const pVariantMethods) // the bucket awaits a new piece case TETRIS_BUS_READY: pPiece = pVariantMethods->choosePiece(pVariantData); - tetris_piece_t *pOldPiece; - tetris_bucket_insertPiece(pBucket, pPiece, &pOldPiece); // destruct old piece (if it exists) since we don't need it anymore - if (pOldPiece != NULL) + tetris_piece_t *pOld; + if ((pOld = tetris_bucket_insertPiece(pBucket, pPiece)) != NULL) { - tetris_piece_destruct(pOldPiece); - pOldPiece = NULL; + tetris_piece_destruct(pOld); } break; diff --git a/games/tetris/variant_bastet.c b/games/tetris/variant_bastet.c index 4999948..17b66dd 100644 --- a/games/tetris/variant_bastet.c +++ b/games/tetris/variant_bastet.c @@ -116,7 +116,7 @@ static void tetris_bastet_predictColHeights(tetris_bastet_variant_t *pBastet, while (pDump != NULL) { uint16_t nColMask = 0x0001 << nStartCol; - for (uint8_t x = nStartCol; x <= nStopCol; ++x) + for (int8_t x = nStartCol; x <= nStopCol; ++x) { if ((*pDump & nColMask) != 0) { @@ -131,63 +131,23 @@ static void tetris_bastet_predictColHeights(tetris_bastet_variant_t *pBastet, /** - * this function is part of the heapsort algorithm for sorting pieces by score - * @param pBastet the Bastet instance whose evaluated pieces should be sorted - * @param nRoot start of the sift - * @param nEnd how far down the heap to sift - */ -static void tetris_bastet_siftDownPieces(tetris_bastet_variant_t *pBastet, - int8_t nRoot, - int8_t nEnd) -{ - while ((nRoot * 2 + 1) <= nEnd) - { - int8_t nChild = nRoot * 2 + 1; - int8_t nSwap = nRoot; - if (pBastet->nPieceScore[nSwap].nScore < - pBastet->nPieceScore[nChild].nScore) - { - nSwap = nChild; - } - if ((nChild < nEnd) && (pBastet->nPieceScore[nSwap].nScore < - pBastet->nPieceScore[nChild + 1].nScore)) - { - nSwap = nChild + 1; - } - if (nSwap != nRoot) - { - tetris_bastet_scorepair_t scTmp = pBastet->nPieceScore[nRoot]; - pBastet->nPieceScore[nRoot] = pBastet->nPieceScore[nSwap]; - pBastet->nPieceScore[nSwap] = scTmp; - nRoot = nSwap; - } - else - { - return; - } - } -} - - -/** - * sorts the evaluated pieces by score in ascending order (via heapsort algo) + * sorts the evaluated pieces by score in ascending order (via bubble sort) * @param pBastet the Bastet instance whose evaluated pieces should be sorted */ static void tetris_bastet_sortPieces(tetris_bastet_variant_t *pBastet) { - int8_t const nCount = 7; - // heapify - for (int8_t nStart = nCount / 2 - 1; nStart >= 0; --nStart) + for (uint8_t i = 7; i--;) { - tetris_bastet_siftDownPieces(pBastet, nStart, nCount - 1); - } - // sorting the heap - for (int8_t nEnd = nCount - 1; nEnd > 0; --nEnd) - { - tetris_bastet_scorepair_t scTmp = pBastet->nPieceScore[nEnd]; - pBastet->nPieceScore[nEnd] = pBastet->nPieceScore[0]; - pBastet->nPieceScore[0] = scTmp; - tetris_bastet_siftDownPieces(pBastet, 0, nEnd - 1); + for (uint8_t j = 0; j < i; ++j) + { + if (pBastet->nPieceScore[j].nScore > + pBastet->nPieceScore[j + 1].nScore) + { + tetris_bastet_scorepair_t tmp = pBastet->nPieceScore[j]; + pBastet->nPieceScore[j] = pBastet->nPieceScore[j + 1]; + pBastet->nPieceScore[j + 1] = tmp; + } + } } } @@ -238,11 +198,11 @@ static int16_t tetris_bastet_evaluateMove(tetris_bastet_variant_t *pBastet, } // predict column heights of this move - tetris_bastet_predictColHeights(pBastet, pPiece, nDeepestRow, nColumn, + tetris_bastet_predictColHeights(pBastet, pPiece, nDeepestRow, nColumn, nStartCol, nStopCol); // modify score based on predicted column heights - for (uint8_t x = 0; x < nWidth; ++x) + for (int8_t x = nWidth; x--;) { if ((x >= nStartCol) && (x <= nStopCol)) { diff --git a/games/tetris/view.c b/games/tetris/view.c index 3a07f20..a1dcb2b 100644 --- a/games/tetris/view.c +++ b/games/tetris/view.c @@ -132,6 +132,7 @@ static void tetris_view_setpixel(tetris_bearing_t nBearing, pixel px; switch (nBearing) { + default: case TETRIS_BEARING_0: px = (pixel){x, y}; break; @@ -158,10 +159,10 @@ static void tetris_view_setpixel(tetris_bearing_t nBearing, * @param nColor Color of the line */ inline static void tetris_view_drawHLine(tetris_bearing_t nBearing, - uint8_t x1, - uint8_t x2, - uint8_t y, - uint8_t nColor) + uint8_t x1, + uint8_t x2, + uint8_t y, + uint8_t nColor) { assert(x1 <= x2); @@ -434,11 +435,10 @@ static void tetris_view_drawBorders(tetris_view_t *pV, */ static void tetris_view_blinkBorders(tetris_view_t *pV) { - for (uint8_t i = 0; i < TETRIS_VIEW_BORDER_BLINK_COUNT; ++i) + for (uint8_t i = TETRIS_VIEW_BORDER_BLINK_COUNT * 2; i--;) { - tetris_view_drawBorders(pV, TETRIS_VIEW_COLORPIECE); - wait(TETRIS_VIEW_BORDER_BLINK_DELAY); - tetris_view_drawBorders(pV, TETRIS_VIEW_COLORBORDER); + tetris_view_drawBorders(pV, (i & 0x01) ? + TETRIS_VIEW_COLORBORDER : TETRIS_VIEW_COLORPIECE); wait(TETRIS_VIEW_BORDER_BLINK_DELAY); } } @@ -453,8 +453,6 @@ static void tetris_view_blinkLines(tetris_view_t *pV) // reduce necessity of pointer arithmetic int8_t nRow = tetris_bucket_getRow(pV->pBucket); - uint8_t nRowMask = tetris_bucket_getRowMask(pV->pBucket); - int8_t nMask = 0x01; tetris_bearing_t nBearing = pV->pVariantMethods->getBearing(pV->pVariant); @@ -470,14 +468,14 @@ static void tetris_view_blinkLines(tetris_view_t *pV) for (uint8_t nColIdx = 0; nColIdx < 2; ++nColIdx) { // iterate through the possibly complete lines - for (uint8_t j = 0; j <= nDeepestRowOffset; ++j) + for (uint8_t j = 0, nMask = 0x01; j <= nDeepestRowOffset; ++j) { // is current line a complete line? - if ((nRowMask & (nMask << j)) != 0) + if ((tetris_bucket_getRowMask(pV->pBucket) & nMask) != 0) { // draw line in current color - uint8_t y = nRow + j; - for (uint8_t x = 0; x < 10; ++x) + int8_t y = nRow + j; + for (int8_t x = tetris_bucket_getWidth(pV->pBucket); x--;) { uint8_t nColor = (nColIdx == 0 ? TETRIS_VIEW_COLORFADE @@ -488,6 +486,7 @@ static void tetris_view_blinkLines(tetris_view_t *pV) nColor); } } + nMask <<= 1; } // wait a few ms to make the blink effect visible wait(TETRIS_VIEW_LINE_BLINK_DELAY); @@ -511,9 +510,9 @@ static void tetris_view_drawLineCounter(tetris_view_t *pV) uint16_t nLines = pV->pVariantMethods->getLines(pV->pVariant); // get decimal places - int8_t nOnes = nLines % 10; - int8_t nTens = (nLines / 10) % 10; - int8_t nHundreds = (nLines / 100) % 10; + uint8_t nOnes = nLines % 10; + uint8_t nTens = (nLines / 10) % 10; + uint8_t nHundreds = (nLines / 100) % 10; // draws the decimal places as 3x3 squares with 9 pixels for (uint8_t i = 0, x = 0, y = 0; i < 9; ++i) @@ -560,24 +559,13 @@ static void tetris_view_drawLineCounter(tetris_view_t *pV) static void tetris_view_formatHighscoreName(uint16_t nHighscoreName, char *pszName) { - pszName[0] = ((nHighscoreName >> 10) & 0x1F) + 65; - if (pszName[0] == '_') + for (uint8_t i = 3; i--; nHighscoreName >>= 5) { - pszName[0] = ' '; + if ((pszName[i] = (nHighscoreName & 0x1F) + 65) == '_') + { + pszName[i] = ' '; + } } - - pszName[1] = ((nHighscoreName >> 5) & 0x1F) + 65; - if (pszName[1] == '_') - { - pszName[1] = ' '; - } - - pszName[2] = (nHighscoreName & 0x1F) + 65; - if (pszName[2] == '_') - { - pszName[2] = ' '; - } - pszName[3] = '\0'; } /*@}*/ @@ -665,7 +653,6 @@ void tetris_view_update(tetris_view_t *pV) tetris_view_blinkBorders(pV); pV->nOldLevel = nLevel; } - } diff --git a/menu/menu.c b/menu/menu.c index ac9eb2d..8656e6b 100644 --- a/menu/menu.c +++ b/menu/menu.c @@ -35,6 +35,150 @@ extern game_descriptor_t _game_descriptors_end__[]; #define MENU_NEXTITEM(item) ((item + 1) % MENU_ITEM_MAX) #define MENU_PREVITEM(item) ((item + MENU_ITEM_MAX - 1) % MENU_ITEM_MAX) + +typedef enum menu_direction_t +{ + MENU_DIRECTION_LEFT, + MENU_DIRECTION_RIGHT, + MENU_DIRECTION_STILL +} +menu_direction_t; + + +static void menu_setpixel(uint8_t x, uint8_t y, uint8_t isSet) +{ + uint8_t nColor; + + // mirror mirror on the wall, what's the quirkiest API of them all... + x = NUM_COLS - 1 - x; + uint8_t nMiddle = (NUM_COLS - MENU_WIDTH_ICON) / 2; + + if (isSet != 0) + { + if ((x >= nMiddle - MENU_WIDTH_DELIMITER) && (x < (nMiddle + + MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER))) + { + nColor = 3; + } + else if ((x == (nMiddle - MENU_WIDTH_DELIMITER - 1)) || (x == (nMiddle + + MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER))) + { + nColor = 2; + } + else + { + nColor = 1; + } + } + else + { + nColor = 0; + } + + setpixel((pixel){x, y}, nColor); +} + + +static uint8_t menu_getIconPixel(uint8_t item, uint8_t x, uint8_t y) +{ + // is x within the icon or do we have reached the delimiter? + if (x < MENU_WIDTH_ICON) + { + // return pixel + return (0x80 >> x) & + pgm_read_word(&_game_descriptors_start__[item].icon[y]); + } + else + { + // delimiter + return 0; + } +} + + +static void menu_animate(uint8_t miInitial, menu_direction_t direction) +{ + int16_t nWait = MENU_WAIT_INITIAL; + + // space between left border and the icon in the middle + uint8_t nWidthSide = (NUM_COLS - MENU_WIDTH_ICON) / 2; + + // determine the icon at the leftmost position + uint8_t mi = miInitial + MENU_ITEM_MAX; + uint8_t nBack = nWidthSide / (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER); + if ((nWidthSide % (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)) != 0) + { + ++nBack; + } + mi = (mi + MENU_ITEM_MAX - (nBack % MENU_ITEM_MAX)) % MENU_ITEM_MAX; + + // start and stop offsets for the scrolling icons (both are 0 for stills) + uint8_t nStart, nStop; + if (direction == MENU_DIRECTION_STILL) + { + nStart = 0; + nStop = 0; + } + else + { + nStart = 1; + nStop = MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER; + } + + // draw menu screen for each offset within the nStart/nStop range + uint8_t i; + for (i = nStart; i <= nStop; ++i) + { + // offset of the left most icon if it is cut by the left border + uint8_t nInitialSideOffset = (((MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER) + - (nWidthSide % (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER))) + + (direction == MENU_DIRECTION_LEFT ? i : -i) + + (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)) + % (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER); + + // an initial side offset of 0 means the leftmost icon was changed + // if we are scrolling to the left, increment value for leftmost item + if (direction == MENU_DIRECTION_LEFT && nInitialSideOffset == 0) + { + mi = MENU_NEXTITEM(mi); + } + + // draw the icons from the leftmost position (line by line) + uint8_t y; + for (y = 0; y < MENU_HEIGHT_ICON; ++y) + { + uint8_t miCurrent = mi; + uint8_t nIconOffset = nInitialSideOffset; + uint8_t x; + for (x = 0; x < NUM_COLS; ++x) + { + uint8_t nPixel = menu_getIconPixel(miCurrent, nIconOffset, y); + + menu_setpixel(x, ((NUM_ROWS - MENU_HEIGHT_ICON) / 2) + y, + nPixel); + if (++nIconOffset >= (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)) + { + nIconOffset = 0; + miCurrent = MENU_NEXTITEM(miCurrent); + } + } + } + + // an initial side offset of 0 means the leftmost icon was changed + // if we are scrolling to the right, decrement value for leftmost item + if (direction == MENU_DIRECTION_RIGHT && nInitialSideOffset == 0) + { + mi = MENU_PREVITEM(mi); + } + + // wait between the frames so that the animation can be seen + wait(nWait); + // animation speed can be throttled + nWait += MENU_WAIT_INCREMENT; + } +} + + void menu() { if (MENU_ITEM_MAX != 0) @@ -107,147 +251,3 @@ void menu() } return; } - - -uint8_t menu_getIconPixel(uint8_t item, int8_t x, int8_t y) -{ - // is x within the icon or do we have reached the delimiter? - if (x < MENU_WIDTH_ICON) - { - // return pixel - return (0x80 >> x) & - pgm_read_word(&_game_descriptors_start__[item].icon[y]); - } - else - { - // delimiter - return 0; - } -} - -void menu_animate(uint8_t miInitial, menu_direction_t direction) -{ - int16_t nWait= MENU_WAIT_INITIAL; - - // space between left border and the icon in the middle - int8_t nWidthSide = (NUM_COLS - MENU_WIDTH_ICON) / 2; - - // determine the icon at the leftmost position - uint8_t mi = miInitial + MENU_ITEM_MAX; - int8_t nBack = nWidthSide / (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER); - if ((nWidthSide % (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)) != 0) - { - ++nBack; - } - mi = (mi + MENU_ITEM_MAX - (nBack % MENU_ITEM_MAX)) % MENU_ITEM_MAX; - - // start and stop offsets for the scrolling icons (both are 0 for stills) - int8_t nStart, nStop; - if (direction == MENU_DIRECTION_STILL) - { - nStart = 0; - nStop = 0; - } - else - { - nStart = 1; - nStop = MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER; - } - - // draw menu screen for each offset within the nStart/nStop range - int8_t i; - for (i = nStart; i <= nStop; ++i) - { - int8_t nOffset; - if (direction == MENU_DIRECTION_LEFT) - nOffset = i; - else - nOffset = -i; - - // offset of the left most icon if it is cut by the left border - int8_t nInitialSideOffset = (((MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER) - - (nWidthSide % (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER))) - + nOffset + (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)) - % (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER); - - // an initial side offset of 0 means the leftmost icon was changed - // if we are scrolling to the left, increment value for leftmost item - if (direction == MENU_DIRECTION_LEFT) - { - if (nInitialSideOffset == 0) - { - mi = MENU_NEXTITEM(mi); - } - } - - // draw the icons from the leftmost position (line by line) - int8_t y; - for (y = 0; y < MENU_HEIGHT_ICON; ++y) - { - uint8_t miCurrent = mi; - int8_t nIconOffset = nInitialSideOffset; - int8_t x; - for (x = 0; x < NUM_COLS; ++x) - { - int8_t nPixel = menu_getIconPixel(miCurrent, nIconOffset, y); - - menu_setpixel(x, ((NUM_ROWS - MENU_HEIGHT_ICON) / 2) + y, - nPixel); - if (++nIconOffset >= (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)) - { - nIconOffset = 0; - miCurrent = MENU_NEXTITEM(miCurrent); - } - } - } - - // an initial side offset of 0 means the leftmost icon was changed - // if we are scrolling to the right, decrement value for leftmost item - if (direction == MENU_DIRECTION_RIGHT) - { - if (nInitialSideOffset == 0) - { - mi = MENU_PREVITEM(mi); - } - } - - // wait between the frames so that the animation can be seen - wait(nWait); - // animation speed can be throttled - nWait += MENU_WAIT_INCREMENT; - } -} - -void menu_setpixel(int8_t x, int8_t y, int8_t isSet) -{ - uint8_t nColor; - - // mirror mirror on the wall, what's the quirkiest API of them all... - x = NUM_COLS - 1 - x; - uint8_t nMiddle = (NUM_COLS - MENU_WIDTH_ICON) / 2; - - if (isSet != 0) - { - if ((x >= nMiddle - MENU_WIDTH_DELIMITER) && (x < (nMiddle - + MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER))) - { - nColor = 3; - } - else if ((x == (nMiddle - MENU_WIDTH_DELIMITER - 1)) || (x == (nMiddle - + MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER))) - { - nColor = 2; - } - else - { - nColor = 1; - } - } - else - { - nColor = 0; - } - - setpixel((pixel){x, y}, nColor); -} - diff --git a/menu/menu.h b/menu/menu.h index b43ca94..873b565 100644 --- a/menu/menu.h +++ b/menu/menu.h @@ -8,24 +8,6 @@ #include -/* -typedef enum menu_item_t -{ - MENU_ITEM_SNAKE, - MENU_ITEM_SPACEINVADERS, - MENU_ITEM_TETRIS, - MENU_ITEM_MAX // fake entry to mark the end -} -menu_item_t; -*/ - -typedef enum menu_direction_t -{ - MENU_DIRECTION_LEFT, - MENU_DIRECTION_RIGHT, - MENU_DIRECTION_STILL -} -menu_direction_t; typedef struct{ void(*run)(void); @@ -34,9 +16,6 @@ typedef struct{ void menu(); -void menu_animate(uint8_t currentItem, menu_direction_t direction); -uint8_t menu_getIconPixel(uint8_t item, int8_t x, int8_t y); -void menu_setpixel(int8_t x, int8_t y, int8_t isSet); #endif /*MENU_H_*/ diff --git a/scrolltext/scrolltext3.c b/scrolltext/scrolltext3.c index cc4dbf0..10348f1 100644 --- a/scrolltext/scrolltext3.c +++ b/scrolltext/scrolltext3.c @@ -55,8 +55,8 @@ void text_setpixel(pixel p, unsigned char value ){ void clear_text_pixmap(unsigned char value){ unsigned char y, z; - for(y=0;y