diff --git a/games/tetris/Makefile b/games/tetris/Makefile index 0d53203..e27d714 100644 --- a/games/tetris/Makefile +++ b/games/tetris/Makefile @@ -4,9 +4,9 @@ TOPDIR = ../.. include $(TOPDIR)/defaults.mk ifeq ($(GAME_BASTET),y) - SRC = piece.c playfield.c view.c logic.c input.c bast.c + SRC = piece.c playfield.c view.c logic.c input.c highscore.c bast.c else - SRC = piece.c playfield.c view.c logic.c input.c + SRC = piece.c playfield.c view.c logic.c input.c highscore.c endif include $(TOPDIR)/rules.mk diff --git a/games/tetris/highscore.c b/games/tetris/highscore.c new file mode 100644 index 0000000..b19bad0 --- /dev/null +++ b/games/tetris/highscore.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include "../../config.h" +#include "../../scrolltext/scrolltext.h" +#include "../../joystick/joystick.h" +#include "highscore.h" + +/* Function: tetris_highscore_inputName + * Description: let user input a three character name + * Return value: name packed into a uint16_t + */ +uint16_t tetris_highscore_inputName(void) +{ + char nick[4], tmp[40]; + uint8_t xpos; + uint8_t pos=0, blink=0, done=0, hadfire=0; + + sprintf(nick, "AAA"); + while(!done) + { + + // We need to do our own blink interval + blink = (blink+1) % 4; + + // Determine start position on screen + // depending on active character + switch (pos) + { + case 0: xpos = 15; break; + case 1: xpos = 19; break; + case 2: xpos = 23; break; + } + + // Construct command for scrolltext and execute + sprintf(tmp, "x%d+p1#%c#x%d+p1#%c#x%dp1#%c", + xpos, (!blink && pos == 0) ? ' ' : nick[0], + xpos-8, (!blink && pos == 1 ) ? ' ' : nick[1], + xpos-15, (!blink && pos == 2 ) ? ' ' : nick[2]); + scrolltext(tmp); + + + // up and down control current char + if (JOYISUP) + { + nick[pos]++; + if (nick[pos] == '`') nick[pos] = 'A'; + if (nick[pos] == '[') nick[pos] = '_'; + } + if (JOYISDOWN) + { + nick[pos]--; + if (nick[pos] == '@') nick[pos] = '_'; + if (nick[pos] == '^') nick[pos] = 'Z'; + } + + // left and right control char selections + if (JOYISLEFT && pos > 0) pos--; + if (JOYISRIGHT && pos < 2) pos++; + + // fire switches to next char or exits + if (JOYISFIRE&&!hadfire) + { + hadfire=1; + switch (pos) + { + case 0: pos=1; break; + case 1: pos=2; break; + case 2: done=1; break; + } + } + + if (hadfire&&!JOYISFIRE) + hadfire=0; + } + + // return result + return( + (nick[0]-65)<<10 | + (nick[1]-65)<<5 | + (nick[2]-65) + ); +} diff --git a/games/tetris/highscore.h b/games/tetris/highscore.h new file mode 100644 index 0000000..1602d93 --- /dev/null +++ b/games/tetris/highscore.h @@ -0,0 +1,6 @@ +#ifndef TETRIS_HIGHSCORE_H_ +#define TETRIS_HIGHSCORE_H_ + +uint16_t tetris_highscore_inputName(void); + +#endif /*TETRIS_HIGHSCORE_H_*/ diff --git a/games/tetris/logic.c b/games/tetris/logic.c index ab53939..be8a130 100644 --- a/games/tetris/logic.c +++ b/games/tetris/logic.c @@ -19,9 +19,13 @@ #include "playfield.h" #include "view.h" #include "input.h" +#include "highscore.h" #ifdef GAME_BASTET #include "bast.h" +#define NUMHIGHSCORES 2 +#else +#define NUMHIGHSCORES 1 #endif @@ -30,7 +34,8 @@ * Highscore in EEPROM * ***********************/ -uint16_t tetris_logic_nHighscore EEMEM; +uint16_t tetris_logic_nHighscore[NUMHIGHSCORES] EEMEM; +uint16_t tetris_logic_nHighscoreName[NUMHIGHSCORES] EEMEM; #endif // Tetris icon, MSB is leftmost pixel @@ -82,11 +87,11 @@ uint8_t tetris_logic_calculateLines(uint8_t nRowMask) return nLines; } -uint16_t tetris_logic_retrieveHighscore(void) +uint16_t tetris_logic_retrieveHighscore(uint8_t nHighscoreIndex) { #ifdef EEMEM uint16_t nHighscore = 0; - nHighscore = eeprom_read_word(&tetris_logic_nHighscore); + nHighscore = eeprom_read_word(&tetris_logic_nHighscore[nHighscoreIndex]); // a score of 65535 is most likely caused by uninitialized EEPROM addresses if (nHighscore == 65535) @@ -100,30 +105,57 @@ uint16_t tetris_logic_retrieveHighscore(void) #endif } -void tetris_logic_saveHighscore(uint16_t nHighscore) +void tetris_logic_saveHighscore(uint8_t nHighscoreIndex, uint16_t nHighscore) { #ifdef EEMEM - if (nHighscore > tetris_logic_retrieveHighscore()) + if (nHighscore > tetris_logic_retrieveHighscore(nHighscoreIndex)) { - eeprom_write_word(&tetris_logic_nHighscore, nHighscore); + eeprom_write_word(&tetris_logic_nHighscore[nHighscoreIndex], nHighscore); } #endif } +uint16_t tetris_logic_retrieveHighscoreName(uint8_t nHighscoreIndex) +{ +#ifdef EEMEM + uint16_t nHighscoreName = 0; + nHighscoreName = eeprom_read_word(&tetris_logic_nHighscoreName[nHighscoreIndex]); + + // a score of 65535 is most likely caused by uninitialized EEPROM addresses + if (nHighscoreName == 65535) + { + nHighscoreName = 0; + } + + return nHighscoreName; +#else + return 0; +#endif +} + +void tetris_logic_saveHighscoreName(uint8_t nHighscoreIndex, uint16_t nHighscoreName) +{ +#ifdef EEMEM + eeprom_write_word(&tetris_logic_nHighscoreName[nHighscoreIndex], nHighscoreName); +#endif +} + /**************************** * construction/destruction * ****************************/ -/* Function: tetris_logic_construct - * Description: constructs a logic object - * Return value: pointer to a newly created logic object +/* Function: tetris_logic_construct + * Description: constructs a logic object + * Argument nBastet: 0 for normal tetris, 1 for bastet + * Return value: pointer to a newly created logic object */ -tetris_logic_t *tetris_logic_construct() +tetris_logic_t *tetris_logic_construct(uint8_t nBastet) { tetris_logic_t *pLogic = (tetris_logic_t *) malloc(sizeof(tetris_logic_t)); assert(pLogic != NULL); memset(pLogic, 0, sizeof(tetris_logic_t)); + pLogic->nBastet = nBastet; return pLogic; } @@ -179,7 +211,7 @@ void tetris_main(int8_t nBastet) tetris_input_command_t inCmd; // prepare data structures that drive the game... - tetris_logic_t *pLogic = tetris_logic_construct(); + tetris_logic_t *pLogic = tetris_logic_construct(nBastet); tetris_playfield_t *pPl = tetris_playfield_construct(nWidth, nHeight); tetris_input_t *pIn = tetris_input_construct(); tetris_view_t *pView = tetris_view_construct(pLogic, pPl); @@ -192,10 +224,16 @@ void tetris_main(int8_t nBastet) // retrieve highscore static uint16_t nHighscore = 0; + static uint16_t nHighscoreName = 0; +#ifndef GAME_BASTET if (nHighscore == 0) { - nHighscore = tetris_logic_retrieveHighscore(); +#endif + nHighscore = tetris_logic_retrieveHighscore(nBastet); + nHighscoreName = tetris_logic_retrieveHighscoreName(nBastet); +#ifndef GAME_BASTET } +#endif // initialize current and next piece tetris_piece_t *pPiece; @@ -220,6 +258,7 @@ void tetris_main(int8_t nBastet) // status so we must put information like the next piece or the current // highscore to a place where the view can find it tetris_logic_setHighscore(pLogic, nHighscore); + tetris_logic_setHighscoreName(pLogic, nHighscoreName); // pace flag tetris_input_pace_t inPace; @@ -392,7 +431,9 @@ void tetris_main(int8_t nBastet) if (nScore > nHighscore) { nHighscore = nScore; - tetris_logic_saveHighscore(nHighscore); + nHighscoreName = tetris_highscore_inputName(); + tetris_logic_saveHighscore(nBastet, nHighscore); + tetris_logic_saveHighscoreName(nBastet, nHighscoreName); } // clean up @@ -421,6 +462,9 @@ void tetris_logic_singleDrop(tetris_logic_t *pLogic, uint8_t nLines) { assert(pLogic != 0); +#ifdef GAME_BASTET + if (pLogic->nBastet) return; +#endif pLogic->nScore += nLines; } @@ -435,6 +479,9 @@ void tetris_logic_completeDrop(tetris_logic_t *pLogic, uint8_t nLines) { assert(pLogic != 0); +#ifdef GAME_BASTET + if (pLogic->nBastet) return; +#endif pLogic->nScore += nLines * 2; } @@ -454,6 +501,13 @@ void tetris_logic_removedLines(tetris_logic_t *pLogic, pLogic->nLevel = ((pLogic->nLines / 10) < TETRIS_INPUT_LEVELS) ? (pLogic->nLines / 10) : (TETRIS_INPUT_LEVELS - 1); +#ifdef GAME_BASTET + if (pLogic->nBastet) + { + pLogic->nScore += nLines; + return; + } +#endif switch (nLines) { case 1: @@ -514,6 +568,32 @@ void tetris_logic_setHighscore(tetris_logic_t *pLogic, } +/* Function: tetris_logic_getHighscoreName + * Description: returns the current highscore name + * Argument pLogic: the logic object we want information from + * Return value: the highscore name packed as uint16_t + */ +uint16_t tetris_logic_getHighscoreName(tetris_logic_t *pLogic) +{ + assert(pLogic != NULL); + return pLogic->nHighscoreName; +} + + + +/* Function: tetris_logic_setHighscoreName + * Description: set highscore name + * Argument pLogic: the logic object we want to modify + * Argmument nHighscoreName: highscore name + */ +void tetris_logic_setHighscoreName(tetris_logic_t *pLogic, + uint16_t nHighscoreName) +{ + assert(pLogic != NULL); + pLogic->nHighscoreName = nHighscoreName; +} + + /* Function: tetris_logic_getLevel * Description: returns the current level * Argument pLogic: the logic object we want information from diff --git a/games/tetris/logic.h b/games/tetris/logic.h index caeed3a..9e4000a 100644 --- a/games/tetris/logic.h +++ b/games/tetris/logic.h @@ -10,8 +10,10 @@ typedef struct tetris_logic_t { + uint8_t nBastet; // is gametype bastet? uint16_t nScore; // score of the player uint16_t nHighscore; // highscore + uint16_t nHighscoreName; // name of the person who achieved highscore uint8_t nLevel; // current level uint16_t nLines; // number of completed lines tetris_piece_t *pPreviewPiece; // the piece intended to be the next one @@ -22,11 +24,12 @@ tetris_logic_t; * construction/destruction * ****************************/ -/* Function: tetris_logic_construct - * Description: constructs a logic object - * Return value: pointer to a newly created logic object +/* Function: tetris_logic_construct + * Description: constructs a logic object + * Argument nBastet: 0 for normal tetris, 1 for bastet + * Return value: pointer to a newly created logic object */ -tetris_logic_t *tetris_logic_construct(); +tetris_logic_t *tetris_logic_construct(uint8_t nBastet); /* Function: tetris_logic_destruct * Description: destructs a logic object @@ -119,6 +122,23 @@ void tetris_logic_setHighscore(tetris_logic_t *pLogic, uint16_t nHighscore); +/* Function: tetris_logic_getHighscoreName + * Description: returns the current highscore name + * Argument pLogic: the logic object we want information from + * Return value: the highscore name packed as uint16_t + */ +uint16_t tetris_logic_getHighscoreName(tetris_logic_t *pLogic); + + +/* Function: tetris_logic_setHighscoreName + * Description: set highscore name + * Argument pLogic: the logic object we want to modify + * Argmument nHighscoreName: highscore name + */ +void tetris_logic_setHighscoreName(tetris_logic_t *pLogic, + uint16_t nHighscoreName); + + /* Function: tetris_logic_getLevel * Description: returns the current level * Argument pLogic: the logic object we want information from diff --git a/games/tetris/view.c b/games/tetris/view.c index a8b3696..7e4e1a8 100644 --- a/games/tetris/view.c +++ b/games/tetris/view.c @@ -434,6 +434,28 @@ void tetris_view_update(tetris_view_t *pV) } +/* Function: tetris_view_formatHighscoreName + * Description: convert uint16_t into ascii Highscore + * (only used internally in view.c) + * Argument nHighscoreName: packed integer with highscoreName + * Argument pszName: pointer to a char array where result is stored + * Return value: void + */ +void tetris_view_formatHighscoreName(uint16_t nHighscoreName, char *pszName) +{ + pszName[0] = ((nHighscoreName>>10)&0x1F) + 65; + if (pszName[0] == '_') pszName[0] = ' '; + + pszName[1] = ((nHighscoreName>> 5)&0x1F) + 65; + if (pszName[1] == '_') pszName[1] = ' '; + + pszName[2] = ( nHighscoreName &0x1F) + 65; + if (pszName[2] == '_') pszName[2] = ' '; + + pszName[3] = 0; +} + + /* Function: tetris_view_showResults * Description: shows results after game * Argument pV: pointer to the view which should show the reults @@ -441,20 +463,23 @@ void tetris_view_update(tetris_view_t *pV) */ void tetris_view_showResults(tetris_view_t *pV) { - char pszResults[48]; + char pszResults[54], pszHighscoreName[4]; uint16_t nScore = tetris_logic_getScore(pV->pLogic); uint16_t nHighscore = tetris_logic_getHighscore(pV->pLogic); uint16_t nLines = tetris_logic_getLines(pV->pLogic); + uint16_t nHighscoreName = tetris_logic_getHighscoreName(pV->pLogic); + tetris_view_formatHighscoreName(nHighscoreName, pszHighscoreName); + if (nScore <= nHighscore) { - snprintf(pszResults, 48 * sizeof(char), - "