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.c189
1 files changed, 102 insertions, 87 deletions
diff --git a/apps/plugins/bubbles.c b/apps/plugins/bubbles.c
index 4ed15bd124..1f1e3ac905 100644
--- a/apps/plugins/bubbles.c
+++ b/apps/plugins/bubbles.c
@@ -38,12 +38,15 @@ PLUGIN_HEADER
38#define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save" 38#define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save"
39 39
40/* final game return status */ 40/* final game return status */
41#define BB_NONE 5 41enum {
42#define BB_WIN 4 42 BB_LOSE,
43#define BB_END 3 43 BB_QUIT,
44#define BB_USB 2 44 BB_QUIT_AND_SAVE,
45#define BB_QUIT 1 45 BB_USB,
46#define BB_LOSE 0 46 BB_END,
47 BB_WIN,
48 BB_NONE,
49};
47 50
48/* play board dimension */ 51/* play board dimension */
49#define BB_HEIGHT 12 52#define BB_HEIGHT 12
@@ -1223,7 +1226,6 @@ struct tile {
1223 * score is the current score 1226 * score is the current score
1224 * level is the current level 1227 * level is the current level
1225 * highlevel is the highest level beaten 1228 * highlevel is the highest level beaten
1226 * highscores is the list of high scores
1227 * angle is the current cannon direction 1229 * angle is the current cannon direction
1228 * shots is the number of shots fired since last compression 1230 * shots is the number of shots fired since last compression
1229 * compress is the height of the compressor 1231 * compress is the height of the compressor
@@ -1240,8 +1242,7 @@ struct tile {
1240struct game_context { 1242struct game_context {
1241 unsigned int score; 1243 unsigned int score;
1242 unsigned int level; 1244 unsigned int level;
1243 struct highscore highlevel; 1245 unsigned int highlevel;
1244 struct highscore highscores[NUM_SCORES];
1245 int angle; 1246 int angle;
1246 int shots; 1247 int shots;
1247 int compress; 1248 int compress;
@@ -1252,10 +1253,14 @@ struct game_context {
1252 long elapsedlvl; 1253 long elapsedlvl;
1253 long elapsedshot; 1254 long elapsedshot;
1254 long startedshot; 1255 long startedshot;
1255 bool resume;
1256 struct tile playboard[BB_HEIGHT][BB_WIDTH]; 1256 struct tile playboard[BB_HEIGHT][BB_WIDTH];
1257}; 1257};
1258 1258
1259struct highscore highscores[NUM_SCORES];
1260
1261/* used to denote available resume info */
1262static bool resume = false;
1263
1259static void bubbles_init(struct game_context* bb); 1264static void bubbles_init(struct game_context* bb);
1260static bool bubbles_nextlevel(struct game_context* bb); 1265static bool bubbles_nextlevel(struct game_context* bb);
1261static void bubbles_getonboard(struct game_context* bb); 1266static void bubbles_getonboard(struct game_context* bb);
@@ -1288,8 +1293,9 @@ static void bubbles_init(struct game_context* bb) {
1288 rb->srand(*rb->current_tick); 1293 rb->srand(*rb->current_tick);
1289 1294
1290 /* check for resumed game */ 1295 /* check for resumed game */
1291 if(bb->resume) { 1296 if (resume)
1292 bb->resume = false; 1297 {
1298 resume = false;
1293 return; 1299 return;
1294 } 1300 }
1295 1301
@@ -1304,11 +1310,16 @@ static void bubbles_init(struct game_context* bb) {
1304static bool bubbles_nextlevel(struct game_context* bb) { 1310static bool bubbles_nextlevel(struct game_context* bb) {
1305 int i, j, pos; 1311 int i, j, pos;
1306 1312
1313 /* save highest level */
1314 if (bb->level > bb->highlevel)
1315 bb->highlevel = bb->level;
1316
1307 bb->level++; 1317 bb->level++;
1308 1318
1309 /* check if there are no more levels */ 1319 /* check if there are no more levels */
1310 if(bb->level > NUM_LEVELS) return false; 1320 if(bb->level > NUM_LEVELS) return false;
1311 1321
1322
1312 /* set up the play board */ 1323 /* set up the play board */
1313 rb->memset(bb->playboard, 0, sizeof(bb->playboard)); 1324 rb->memset(bb->playboard, 0, sizeof(bb->playboard));
1314 for(i=0; i<BB_LEVEL_HEIGHT; i++) { 1325 for(i=0; i<BB_LEVEL_HEIGHT; i++) {
@@ -2112,11 +2123,11 @@ static void bubbles_recordscore(struct game_context* bb) {
2112 int position; 2123 int position;
2113 2124
2114 position = highscore_update(bb->score, bb->level, "", 2125 position = highscore_update(bb->score, bb->level, "",
2115 bb->highscores, NUM_SCORES); 2126 highscores, NUM_SCORES);
2116 if (position==0) 2127 if (position==0)
2117 rb->splash(HZ*2, "New High Score"); 2128 rb->splash(HZ*2, "New High Score");
2118 if (position != -1) 2129 if (position != -1)
2119 highscore_show(position, bb->highscores, NUM_SCORES); 2130 highscore_show(position, highscores, NUM_SCORES);
2120} 2131}
2121 2132
2122/***************************************************************************** 2133/*****************************************************************************
@@ -2124,11 +2135,21 @@ static void bubbles_recordscore(struct game_context* bb) {
2124******************************************************************************/ 2135******************************************************************************/
2125static void bubbles_loadscores(struct game_context* bb) { 2136static void bubbles_loadscores(struct game_context* bb) {
2126 2137
2138 int i;
2139 int highlevel = 0;
2127 /* highlevel and highscores */ 2140 /* highlevel and highscores */
2128 highscore_load(SCORE_FILE, &bb->highlevel, NUM_SCORES+1); 2141 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
2142
2143 for (i = 0; i < NUM_SCORES; i++)
2144 {
2145 if (highscores[i].level >= highlevel)
2146 {
2147 highlevel = highscores[i].level+1;
2148 }
2149 }
2129 2150
2130 if( bb->highlevel.level >= NUM_LEVELS ) 2151 if (bb->highlevel < (unsigned)highlevel)
2131 bb->highlevel.level = NUM_LEVELS - 1; 2152 bb->highlevel = highlevel;
2132} 2153}
2133 2154
2134/***************************************************************************** 2155/*****************************************************************************
@@ -2136,8 +2157,9 @@ static void bubbles_loadscores(struct game_context* bb) {
2136******************************************************************************/ 2157******************************************************************************/
2137static void bubbles_savescores(struct game_context* bb) { 2158static void bubbles_savescores(struct game_context* bb) {
2138 2159
2139 /* highlevel and highscores */ 2160 /* highscores */
2140 highscore_save(SCORE_FILE, &bb->highlevel, NUM_SCORES+1); 2161 (void)bb;
2162 highscore_save(SCORE_FILE, highscores, NUM_SCORES+1);
2141} 2163}
2142 2164
2143/***************************************************************************** 2165/*****************************************************************************
@@ -2145,35 +2167,22 @@ static void bubbles_savescores(struct game_context* bb) {
2145******************************************************************************/ 2167******************************************************************************/
2146static bool bubbles_loadgame(struct game_context* bb) { 2168static bool bubbles_loadgame(struct game_context* bb) {
2147 int fd; 2169 int fd;
2148 bool loaded = false;
2149 2170
2171 bool ret = true;
2150 /* open game file */ 2172 /* open game file */
2151 fd = rb->open(SAVE_FILE, O_RDONLY); 2173 fd = rb->open(SAVE_FILE, O_RDONLY);
2152 if(fd < 0) return loaded; 2174 if(fd < 0) return false;
2153 2175
2154 /* read in saved game */ 2176 /* read in saved game */
2155 while(true) { 2177 if(rb->read(fd, bb, sizeof(struct game_context))
2156 if(rb->read(fd, &bb->score, sizeof(bb->score)) <= 0) break; 2178 < (long)sizeof(struct game_context))
2157 if(rb->read(fd, &bb->level, sizeof(bb->level)) <= 0) break; 2179 {
2158 if(rb->read(fd, &bb->angle, sizeof(bb->angle)) <= 0) break; 2180 ret = false;
2159 if(rb->read(fd, &bb->shots, sizeof(bb->shots)) <= 0) break;
2160 if(rb->read(fd, &bb->compress, sizeof(bb->compress)) <= 0) break;
2161 if(rb->read(fd, &bb->onboardcnt, sizeof(bb->onboardcnt)) <= 0) break;
2162 if(rb->read(fd, bb->onboard, sizeof(bb->onboard)) <= 0) break;
2163 if(rb->read(fd, &bb->nextinq, sizeof(bb->nextinq)) <= 0) break;
2164 if(rb->read(fd, bb->queue, sizeof(bb->queue)) <= 0) break;
2165 if(rb->read(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl)) <= 0) break;
2166 if(rb->read(fd, bb->playboard, sizeof(bb->playboard)) <= 0) break;
2167 bb->resume = true;
2168 loaded = true;
2169 break;
2170 } 2181 }
2171 2182
2183 DEBUGF("highlevel: %d\n", bb->highlevel);
2172 rb->close(fd); 2184 rb->close(fd);
2173 2185 return ret;
2174 /* delete saved file */
2175 rb->remove(SAVE_FILE);
2176 return loaded;
2177} 2186}
2178 2187
2179/***************************************************************************** 2188/*****************************************************************************
@@ -2182,22 +2191,22 @@ static bool bubbles_loadgame(struct game_context* bb) {
2182static void bubbles_savegame(struct game_context* bb) { 2191static void bubbles_savegame(struct game_context* bb) {
2183 int fd; 2192 int fd;
2184 2193
2194 if (!resume) /* nothing to save */
2195 return;
2185 /* write out the game state to the save file */ 2196 /* write out the game state to the save file */
2186 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT); 2197 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
2187 rb->write(fd, &bb->score, sizeof(bb->score)); 2198 if (fd < 0)
2188 rb->write(fd, &bb->level, sizeof(bb->level)); 2199 {
2189 rb->write(fd, &bb->angle, sizeof(bb->angle)); 2200 rb->splash(HZ/2, "Failed to save game");
2190 rb->write(fd, &bb->shots, sizeof(bb->shots)); 2201 return;
2191 rb->write(fd, &bb->compress, sizeof(bb->compress)); 2202 }
2192 rb->write(fd, &bb->onboardcnt, sizeof(bb->onboardcnt)); 2203 if (rb->write(fd, bb, sizeof(struct game_context)) <= 0)
2193 rb->write(fd, bb->onboard, sizeof(bb->onboard)); 2204 {
2194 rb->write(fd, &bb->nextinq, sizeof(bb->nextinq)); 2205 rb->splash(HZ/2, "Failed to save game");
2195 rb->write(fd, bb->queue, sizeof(bb->queue)); 2206 }
2196 rb->write(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl)); 2207 DEBUGF("highlevel: %d\n", bb->highlevel);
2197 rb->write(fd, bb->playboard, sizeof(bb->playboard));
2198 rb->close(fd); 2208 rb->close(fd);
2199 2209
2200 bb->resume = true;
2201} 2210}
2202 2211
2203/***************************************************************************** 2212/*****************************************************************************
@@ -2280,14 +2289,12 @@ static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
2280 break; 2289 break;
2281 2290
2282 case BUBBLES_RESUME: /* save and end the game */ 2291 case BUBBLES_RESUME: /* save and end the game */
2292 case BUBBLES_QUIT: /* end the game */
2283 if(!animblock) { 2293 if(!animblock) {
2284 rb->splash(HZ/2, "Saving game..."); 2294 resume = true;
2285 bubbles_savegame(bb);
2286 return BB_END; 2295 return BB_END;
2287 } 2296 }
2288 break; 2297 break;
2289 case BUBBLES_QUIT: /* end the game */
2290 return BB_END;
2291 2298
2292 case ACTION_UNKNOWN: 2299 case ACTION_UNKNOWN:
2293 case ACTION_NONE: /* no button pressed */ 2300 case ACTION_NONE: /* no button pressed */
@@ -2312,44 +2319,51 @@ static int bubbles(struct game_context* bb) {
2312 bool startgame = false; 2319 bool startgame = false;
2313 long timeout; 2320 long timeout;
2314 2321
2315 /* don't resume by default */
2316 bb->resume = false;
2317
2318 /******************** 2322 /********************
2319 * menu * 2323 * menu *
2320 ********************/ 2324 ********************/
2321 MENUITEM_STRINGLIST(menu,"Bubbles Menu",NULL, 2325 MENUITEM_STRINGLIST(menu,"Bubbles Menu",NULL,
2322 "Start New Game", "Resume Game", 2326 "Resume Game", "Start New Game",
2323 "Level", "High Scores", "Playback Control", 2327 "Level", "High Scores", "Playback Control",
2324 "Quit"); 2328 "Quit", "Quit and Save");
2325 while(!startgame){ 2329 while(!startgame){
2326 switch (rb->do_menu(&menu, NULL, NULL, false)) 2330 switch (rb->do_menu(&menu, NULL, NULL, false))
2327 { 2331 {
2328 case 0: /* new game */ 2332 case 0: /* resume game */
2329 bb->level = startlevel; 2333 if (!resume)
2330 startgame = true; 2334 {
2331 break; 2335 rb->splash(HZ/2, "Nothing to resume");
2332 case 1: /* resume game */ 2336 break;
2333 if(!bubbles_loadgame(bb)) { 2337 }
2334 rb->splash(HZ*2, "Nothing to resume"); 2338 else
2335 } else { 2339 {
2340 startlevel = bb->level - 1;
2336 startgame = true; 2341 startgame = true;
2337 } 2342 }
2343 /* delete saved file */
2344 rb->remove(SAVE_FILE);
2345 break;
2346 case 1: /* new game */
2347 bb->level = startlevel;
2348 startgame = true;
2349 resume = false;
2338 break; 2350 break;
2339 case 2: /* choose level */ 2351 case 2: /* choose level */
2340 startlevel++; 2352 startlevel++;
2341 rb->set_int("Choose start level", "", UNIT_INT, &startlevel, 2353 rb->set_int("Choose start level", "", UNIT_INT, &startlevel,
2342 NULL, 1, 1, bb->highlevel.level+1, NULL); 2354 NULL, 1, 1, bb->highlevel+1, NULL);
2343 startlevel--; 2355 startlevel--;
2344 break; 2356 break;
2345 case 3: /* High scores */ 2357 case 3: /* High scores */
2346 highscore_show(NUM_SCORES, bb->highscores, NUM_SCORES); 2358 highscore_show(NUM_SCORES, highscores, NUM_SCORES);
2347 break; 2359 break;
2348 case 4: /* Playback Control */ 2360 case 4: /* Playback Control */
2349 playback_control(NULL); 2361 playback_control(NULL);
2350 break; 2362 break;
2351 case 5: /* quit */ 2363 case 5: /* quit */
2352 return BB_QUIT; 2364 return BB_QUIT;
2365 case 6: /* quit and save */
2366 return BB_QUIT_AND_SAVE;
2353 case MENU_ATTACHED_USB: 2367 case MENU_ATTACHED_USB:
2354 bubbles_callback(bb); 2368 bubbles_callback(bb);
2355 return BB_USB; 2369 return BB_USB;
@@ -2404,14 +2418,16 @@ static int bubbles(struct game_context* bb) {
2404* plugin entry point. 2418* plugin entry point.
2405******************************************************************************/ 2419******************************************************************************/
2406enum plugin_status plugin_start(const void* parameter) { 2420enum plugin_status plugin_start(const void* parameter) {
2407 struct game_context bb; 2421 static struct game_context bb;
2408 bool exit = false; 2422 bool exit = false;
2423 enum plugin_status ret = PLUGIN_OK;
2409 2424
2410 /* plugin init */ 2425 /* plugin init */
2411 (void)parameter; 2426 (void)parameter;
2412 /* end of plugin init */ 2427 /* end of plugin init */
2413 2428
2414 /* load files */ 2429 /* load files */
2430 resume = bubbles_loadgame(&bb);
2415 bubbles_loadscores(&bb); 2431 bubbles_loadscores(&bb);
2416 rb->lcd_clear_display(); 2432 rb->lcd_clear_display();
2417 2433
@@ -2426,35 +2442,34 @@ enum plugin_status plugin_start(const void* parameter) {
2426 case BB_WIN: 2442 case BB_WIN:
2427 rb->splash(HZ*2, "You Win!"); 2443 rb->splash(HZ*2, "You Win!");
2428 /* record high level */ 2444 /* record high level */
2429 if( NUM_LEVELS-1 > bb.highlevel.level) { 2445 if( NUM_LEVELS-1 > bb.highlevel) {
2430 bb.highlevel.level = NUM_LEVELS-1; 2446 bb.highlevel = NUM_LEVELS-1;
2431 } 2447 }
2432 /* record high score */ 2448 /* record high score */
2433 bubbles_recordscore(&bb); 2449 bubbles_recordscore(&bb);
2434 break; 2450 break;
2435 2451
2436 case BB_LOSE: 2452 case BB_LOSE:
2453 resume = false;
2437 rb->splash(HZ*2, "Game Over"); 2454 rb->splash(HZ*2, "Game Over");
2455 /* record high score */
2456 bubbles_recordscore(&bb);
2438 /* fall through to BB_END */ 2457 /* fall through to BB_END */
2439 2458
2440 case BB_END: 2459 case BB_END:
2441 if(!bb.resume) {
2442 /* record high level */
2443 if((int)bb.level-1 > bb.highlevel.level) {
2444 bb.highlevel.score = -1;
2445 highscore_update(0, bb.level-1, "", &bb.highlevel, 1);
2446 }
2447 /* record high score */
2448 bubbles_recordscore(&bb);
2449 }
2450 break; 2460 break;
2451 2461
2452 case BB_USB: 2462 case BB_USB:
2453 rb->lcd_setfont(FONT_UI); 2463 ret = PLUGIN_USB_CONNECTED;
2454 return PLUGIN_USB_CONNECTED; 2464 break;
2455 2465
2456 case BB_QUIT: 2466 case BB_QUIT_AND_SAVE:
2467 rb->splash(HZ/2, "Saving Game and Scors");
2457 bubbles_savescores(&bb); 2468 bubbles_savescores(&bb);
2469 bubbles_savegame(&bb);
2470 /* fall through */
2471
2472 case BB_QUIT:
2458 exit = true; 2473 exit = true;
2459 break; 2474 break;
2460 2475
@@ -2464,7 +2479,7 @@ enum plugin_status plugin_start(const void* parameter) {
2464 } 2479 }
2465 2480
2466 rb->lcd_setfont(FONT_UI); 2481 rb->lcd_setfont(FONT_UI);
2467 return PLUGIN_OK; 2482 return ret;
2468} 2483}
2469 2484
2470#endif 2485#endif