summaryrefslogtreecommitdiff
path: root/apps/plugins/bubbles.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/bubbles.c')
-rw-r--r--apps/plugins/bubbles.c130
1 files changed, 75 insertions, 55 deletions
diff --git a/apps/plugins/bubbles.c b/apps/plugins/bubbles.c
index d5d9987f68..ebf2051f1c 100644
--- a/apps/plugins/bubbles.c
+++ b/apps/plugins/bubbles.c
@@ -36,12 +36,13 @@ PLUGIN_HEADER
36/* files */ 36/* files */
37#define SCORE_FILE PLUGIN_GAMES_DIR "/bubbles.score" 37#define SCORE_FILE PLUGIN_GAMES_DIR "/bubbles.score"
38#define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save" 38#define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save"
39#define DATA_FILE PLUGIN_GAMES_DIR "/bubbles.data"
39 40
40/* final game return status */ 41/* final game return status */
41enum { 42enum {
42 BB_LOSE, 43 BB_LOSE,
43 BB_QUIT, 44 BB_QUIT,
44 BB_QUIT_AND_SAVE, 45 BB_SAVE_AND_QUIT,
45 BB_USB, 46 BB_USB,
46 BB_END, 47 BB_END,
47 BB_WIN, 48 BB_WIN,
@@ -1241,7 +1242,6 @@ struct tile {
1241/* the game context struct 1242/* the game context struct
1242 * score is the current score 1243 * score is the current score
1243 * level is the current level 1244 * level is the current level
1244 * highlevel is the highest level beaten
1245 * angle is the current cannon direction 1245 * angle is the current cannon direction
1246 * shots is the number of shots fired since last compression 1246 * shots is the number of shots fired since last compression
1247 * compress is the height of the compressor 1247 * compress is the height of the compressor
@@ -1252,13 +1252,11 @@ struct tile {
1252 * elapsedlvl is level elapsed time in 1/100s of seconds 1252 * elapsedlvl is level elapsed time in 1/100s of seconds
1253 * elapsedshot is the shot elapsed time in 1/100s of seconds 1253 * elapsedshot is the shot elapsed time in 1/100s of seconds
1254 * startedshot is when the current shot began 1254 * startedshot is when the current shot began
1255 * resume denotes whether to resume the currently loaded game
1256 * playboard is the game playing board 1255 * playboard is the game playing board
1257 */ 1256 */
1258struct game_context { 1257struct game_context {
1259 unsigned int score; 1258 unsigned int score;
1260 unsigned int level; 1259 unsigned int level;
1261 unsigned int highlevel;
1262 int angle; 1260 int angle;
1263 int shots; 1261 int shots;
1264 int compress; 1262 int compress;
@@ -1276,6 +1274,8 @@ struct highscore highscores[NUM_SCORES];
1276 1274
1277/* used to denote available resume info */ 1275/* used to denote available resume info */
1278static bool resume = false; 1276static bool resume = false;
1277static unsigned int highlevel = 0; /* the highest level beaten */
1278static unsigned int last_highlevel = 0;
1279 1279
1280static void bubbles_init(struct game_context* bb); 1280static void bubbles_init(struct game_context* bb);
1281static bool bubbles_nextlevel(struct game_context* bb); 1281static bool bubbles_nextlevel(struct game_context* bb);
@@ -1291,7 +1291,6 @@ static void bubbles_anchored(struct game_context* bb, int row, int col);
1291static int bubbles_fall(struct game_context* bb); 1291static int bubbles_fall(struct game_context* bb);
1292static int bubbles_checklevel(struct game_context* bb); 1292static int bubbles_checklevel(struct game_context* bb);
1293static void bubbles_recordscore(struct game_context* bb); 1293static void bubbles_recordscore(struct game_context* bb);
1294static void bubbles_savescores(struct game_context* bb);
1295static bool bubbles_loadgame(struct game_context* bb); 1294static bool bubbles_loadgame(struct game_context* bb);
1296static void bubbles_savegame(struct game_context* bb); 1295static void bubbles_savegame(struct game_context* bb);
1297static inline void bubbles_setcolors(void); 1296static inline void bubbles_setcolors(void);
@@ -1326,15 +1325,14 @@ static void bubbles_init(struct game_context* bb) {
1326static bool bubbles_nextlevel(struct game_context* bb) { 1325static bool bubbles_nextlevel(struct game_context* bb) {
1327 int i, j, pos; 1326 int i, j, pos;
1328 1327
1329 /* save highest level */
1330 if (bb->level > bb->highlevel)
1331 bb->highlevel = bb->level;
1332
1333 bb->level++; 1328 bb->level++;
1334 1329
1335 /* check if there are no more levels */ 1330 /* check if there are no more levels */
1336 if(bb->level > NUM_LEVELS) return false; 1331 if(bb->level > NUM_LEVELS) return false;
1337 1332
1333 /* save highest level */
1334 if (bb->level-1 > highlevel)
1335 highlevel = bb->level-1;
1338 1336
1339 /* set up the play board */ 1337 /* set up the play board */
1340 rb->memset(bb->playboard, 0, sizeof(bb->playboard)); 1338 rb->memset(bb->playboard, 0, sizeof(bb->playboard));
@@ -2165,7 +2163,7 @@ static void bubbles_recordscore(struct game_context* bb) {
2165 2163
2166 int position; 2164 int position;
2167 2165
2168 position = highscore_update(bb->score, bb->level, "", 2166 position = highscore_update(bb->score, bb->level-1, "",
2169 highscores, NUM_SCORES); 2167 highscores, NUM_SCORES);
2170 if (position==0) 2168 if (position==0)
2171 rb->splash(HZ*2, "New High Score"); 2169 rb->splash(HZ*2, "New High Score");
@@ -2174,36 +2172,43 @@ static void bubbles_recordscore(struct game_context* bb) {
2174} 2172}
2175 2173
2176/***************************************************************************** 2174/*****************************************************************************
2177* bubbles_loadscores() loads the high scores saved file. 2175* bubbles_loaddata() loads highest level beaten.
2178******************************************************************************/ 2176******************************************************************************/
2179static void bubbles_loadscores(struct game_context* bb) { 2177static void bubbles_loaddata(void) {
2178 int fd;
2180 2179
2181 int i; 2180 last_highlevel = highlevel = 0;
2182 int highlevel = 0; 2181 /* open data file */
2183 /* highlevel and highscores */ 2182 fd = rb->open(DATA_FILE, O_RDONLY);
2184 highscore_load(SCORE_FILE, highscores, NUM_SCORES); 2183 if (fd < 0) return;
2185 2184
2186 /* level X in the high scores means one succeeded the level before (X-1) */ 2185 /* read in saved game */
2187 for (i = 0; i < NUM_SCORES; i++) 2186 if (rb->read(fd, &highlevel, sizeof(highlevel)) < (long)sizeof(highlevel))
2188 { 2187 {
2189 if (highscores[i].level-1 > highlevel) 2188 highlevel = 0;
2190 {
2191 highlevel = highscores[i].level-1;
2192 }
2193 } 2189 }
2190 if (highlevel >= NUM_LEVELS)
2191 highlevel = NUM_LEVELS-1;
2192 last_highlevel = highlevel;
2194 2193
2195 if (bb->highlevel < (unsigned)highlevel) 2194 rb->close(fd);
2196 bb->highlevel = highlevel;
2197} 2195}
2198 2196
2199/***************************************************************************** 2197/*****************************************************************************
2200* bubbles_savescores() saves the high scores saved file. 2198* bubbles_savedata() saves the current game state.
2201******************************************************************************/ 2199******************************************************************************/
2202static void bubbles_savescores(struct game_context* bb) { 2200static void bubbles_savedata(void) {
2201 int fd;
2203 2202
2204 /* highscores */ 2203 if (last_highlevel >= highlevel) /* no need to save */
2205 (void)bb; 2204 return;
2206 highscore_save(SCORE_FILE, highscores, NUM_SCORES+1); 2205
2206 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT);
2207 if (fd < 0) return;
2208
2209 rb->write(fd, &highlevel, sizeof(highlevel));
2210
2211 rb->close(fd);
2207} 2212}
2208 2213
2209/***************************************************************************** 2214/*****************************************************************************
@@ -2225,6 +2230,9 @@ static bool bubbles_loadgame(struct game_context* bb) {
2225 } 2230 }
2226 2231
2227 rb->close(fd); 2232 rb->close(fd);
2233
2234 /* delete saved file */
2235 rb->remove(SAVE_FILE);
2228 return ret; 2236 return ret;
2229} 2237}
2230 2238
@@ -2266,8 +2274,8 @@ static inline void bubbles_setcolors(void) {
2266* on usb connect and shutdown. 2274* on usb connect and shutdown.
2267******************************************************************************/ 2275******************************************************************************/
2268static void bubbles_callback(void* param) { 2276static void bubbles_callback(void* param) {
2269 struct game_context* bb = (struct game_context*) param; 2277 (void) param;
2270 bubbles_savescores(bb); 2278 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
2271} 2279}
2272 2280
2273/***************************************************************************** 2281/*****************************************************************************
@@ -2353,23 +2361,20 @@ static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
2353} 2361}
2354 2362
2355/***************************************************************************** 2363/*****************************************************************************
2356* bubbles() is the main game subroutine, it returns the final game status. 2364* bubbles_menu() is the initial menu at the start of the game.
2357******************************************************************************/ 2365******************************************************************************/
2358static int bubbles(struct game_context* bb) { 2366static int bubbles_menu(struct game_context* bb) {
2359 int buttonres; 2367 static unsigned int startlevel = 0;
2360 unsigned int startlevel = 0; 2368 int selected = resume?0:1;
2361 bool startgame = false; 2369 bool startgame = false;
2362 long timeout;
2363 2370
2364 /********************
2365 * menu *
2366 ********************/
2367 MENUITEM_STRINGLIST(menu,"Bubbles Menu",NULL, 2371 MENUITEM_STRINGLIST(menu,"Bubbles Menu",NULL,
2368 "Resume Game", "Start New Game", 2372 "Resume Game", "Start New Game",
2369 "Level", "High Scores", "Playback Control", 2373 "Level", "High Scores", "Playback Control",
2370 "Quit", "Quit and Save"); 2374 "Quit", "Save and Quit");
2375
2371 while(!startgame){ 2376 while(!startgame){
2372 switch (rb->do_menu(&menu, NULL, NULL, false)) 2377 switch (rb->do_menu(&menu, &selected, NULL, false))
2373 { 2378 {
2374 case 0: /* resume game */ 2379 case 0: /* resume game */
2375 if (!resume) 2380 if (!resume)
@@ -2379,11 +2384,8 @@ static int bubbles(struct game_context* bb) {
2379 } 2384 }
2380 else 2385 else
2381 { 2386 {
2382 startlevel = bb->level - 1;
2383 startgame = true; 2387 startgame = true;
2384 } 2388 }
2385 /* delete saved file */
2386 rb->remove(SAVE_FILE);
2387 break; 2389 break;
2388 case 1: /* new game */ 2390 case 1: /* new game */
2389 bb->level = startlevel; 2391 bb->level = startlevel;
@@ -2393,7 +2395,7 @@ static int bubbles(struct game_context* bb) {
2393 case 2: /* choose level */ 2395 case 2: /* choose level */
2394 startlevel++; 2396 startlevel++;
2395 rb->set_int("Choose start level", "", UNIT_INT, &startlevel, 2397 rb->set_int("Choose start level", "", UNIT_INT, &startlevel,
2396 NULL, 1, 1, MIN(NUM_LEVELS,bb->highlevel+1), NULL); 2398 NULL, 1, 1, highlevel+1, NULL);
2397 startlevel--; 2399 startlevel--;
2398 break; 2400 break;
2399 case 3: /* High scores */ 2401 case 3: /* High scores */
@@ -2404,13 +2406,30 @@ static int bubbles(struct game_context* bb) {
2404 break; 2406 break;
2405 case 5: /* quit */ 2407 case 5: /* quit */
2406 return BB_QUIT; 2408 return BB_QUIT;
2407 case 6: /* quit and save */ 2409 case 6: /* save and quit */
2408 return BB_QUIT_AND_SAVE; 2410 return BB_SAVE_AND_QUIT;
2409 case MENU_ATTACHED_USB: 2411 case MENU_ATTACHED_USB:
2410 bubbles_callback(bb); 2412 bubbles_callback(bb);
2411 return BB_USB; 2413 return BB_USB;
2412 } 2414 }
2413 } 2415 }
2416 return 0;
2417}
2418
2419/*****************************************************************************
2420* bubbles() is the main game subroutine, it returns the final game status.
2421******************************************************************************/
2422static int bubbles(struct game_context* bb) {
2423 int buttonres;
2424 long timeout;
2425
2426 /********************
2427 * menu *
2428 ********************/
2429 buttonres = bubbles_menu(bb);
2430 if(buttonres != 0)
2431 return buttonres;
2432
2414 /******************** 2433 /********************
2415 * init * 2434 * init *
2416 ********************/ 2435 ********************/
@@ -2464,13 +2483,12 @@ enum plugin_status plugin_start(const void* parameter) {
2464 bool exit = false; 2483 bool exit = false;
2465 enum plugin_status ret = PLUGIN_OK; 2484 enum plugin_status ret = PLUGIN_OK;
2466 2485
2467 /* plugin init */
2468 (void)parameter; 2486 (void)parameter;
2469 /* end of plugin init */
2470 2487
2471 /* load files */ 2488 /* load files */
2472 resume = bubbles_loadgame(&bb); 2489 resume = bubbles_loadgame(&bb);
2473 bubbles_loadscores(&bb); 2490 bubbles_loaddata();
2491 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
2474 rb->lcd_clear_display(); 2492 rb->lcd_clear_display();
2475 2493
2476 /* start app */ 2494 /* start app */
@@ -2484,7 +2502,7 @@ enum plugin_status plugin_start(const void* parameter) {
2484 case BB_WIN: 2502 case BB_WIN:
2485 rb->splash(HZ*2, "You Win!"); 2503 rb->splash(HZ*2, "You Win!");
2486 /* record high level */ 2504 /* record high level */
2487 bb.highlevel = NUM_LEVELS; 2505 highlevel = NUM_LEVELS-1;
2488 /* record high score */ 2506 /* record high score */
2489 bubbles_recordscore(&bb); 2507 bubbles_recordscore(&bb);
2490 break; 2508 break;
@@ -2501,15 +2519,17 @@ enum plugin_status plugin_start(const void* parameter) {
2501 2519
2502 case BB_USB: 2520 case BB_USB:
2503 ret = PLUGIN_USB_CONNECTED; 2521 ret = PLUGIN_USB_CONNECTED;
2522 exit = true;
2504 break; 2523 break;
2505 2524
2506 case BB_QUIT_AND_SAVE: 2525 case BB_SAVE_AND_QUIT:
2507 rb->splash(HZ/2, "Saving Game and Scors"); 2526 rb->splash(HZ/2, "Saving Game ...");
2508 bubbles_savescores(&bb);
2509 bubbles_savegame(&bb); 2527 bubbles_savegame(&bb);
2510 /* fall through */ 2528 /* fall through */
2511 2529
2512 case BB_QUIT: 2530 case BB_QUIT:
2531 bubbles_savedata();
2532 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
2513 exit = true; 2533 exit = true;
2514 break; 2534 break;
2515 2535