squeezed another 680 bytes

This commit is contained in:
Christian Kroll 2011-01-30 22:47:44 +00:00
parent af4ff63f2b
commit 3affa5c9a3
19 changed files with 424 additions and 498 deletions

View File

@ -73,8 +73,8 @@ void matrix() {
}
}
for(y=0;y<NUM_ROWS;y++)
for(x=0;x<NUM_COLS;x++){
for(y=NUM_ROWS;y--;)
for(x=NUM_COLS;x--;){
setpixel((pixel){x,y}, get_bright(&matrix_bright,x,y));
}

View File

@ -286,9 +286,9 @@ void off()
#ifdef ANIMATION_SPIRALE
void walk(cursor* cur, unsigned char steps, unsigned int delay){
static void walk(cursor* cur, unsigned char steps, unsigned int delay){
unsigned char x;
for(x=0;x<steps;x++){
for(x=steps;x--;){
set_cursor(cur, next_pixel(cur->pos, 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;

View File

@ -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();

View File

@ -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);
}
}
}

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
/**

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);
/**

View File

@ -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;

View File

@ -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))
{

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -8,24 +8,6 @@
#include <inttypes.h>
/*
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_*/

View File

@ -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<NUM_ROWS;y++){
for(z=0;z<LINEBYTES;z++){
for(y=NUM_ROWS;y--;){
for(z=LINEBYTES;z--;){
(*text_pixmap)[y][z] = 0;
}
}
@ -65,9 +65,9 @@ void clear_text_pixmap(unsigned char value){
void update_pixmap(){
unsigned char x, y, z;
for(x=0;x<NUMPLANE;x++){
for(y=0;y<NUM_ROWS;y++){
for(z=0;z<LINEBYTES;z++){
for(x=NUMPLANE;x--;){
for(y=NUM_ROWS;y--;){
for(z=LINEBYTES;z--;){
pixmap[x][y][z] = (*text_pixmap)[y][z];
}
}