diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/CATEGORIES | 1 | ||||
-rw-r--r-- | apps/plugins/SOURCES | 1 | ||||
-rw-r--r-- | apps/plugins/dart_scorer.c | 601 |
3 files changed, 603 insertions, 0 deletions
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES index 49016fef13..5320015772 100644 --- a/apps/plugins/CATEGORIES +++ b/apps/plugins/CATEGORIES | |||
@@ -22,6 +22,7 @@ clock,apps | |||
22 | codebuster,games | 22 | codebuster,games |
23 | credits,viewers | 23 | credits,viewers |
24 | cube,demos | 24 | cube,demos |
25 | dart_scorer,apps | ||
25 | db_commit,apps | 26 | db_commit,apps |
26 | db_folder_select,viewers | 27 | db_folder_select,viewers |
27 | demystify,demos | 28 | demystify,demos |
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index b857f26ba5..bf36d50a40 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES | |||
@@ -9,6 +9,7 @@ tagcache/tagcache.c | |||
9 | chessclock.c | 9 | chessclock.c |
10 | credits.c | 10 | credits.c |
11 | cube.c | 11 | cube.c |
12 | dart_scorer.c | ||
12 | dict.c | 13 | dict.c |
13 | jackpot.c | 14 | jackpot.c |
14 | keybox.c | 15 | keybox.c |
diff --git a/apps/plugins/dart_scorer.c b/apps/plugins/dart_scorer.c new file mode 100644 index 0000000000..1e8dd8f37b --- /dev/null +++ b/apps/plugins/dart_scorer.c | |||
@@ -0,0 +1,601 @@ | |||
1 | #include "plugin.h" | ||
2 | #include "lib/display_text.h" | ||
3 | #include "lib/helper.h" | ||
4 | #include "lib/playback_control.h" | ||
5 | #include "lib/pluginlib_exit.h" | ||
6 | #include "lib/pluginlib_actions.h" | ||
7 | |||
8 | #define BUTTON_ROWS 6 | ||
9 | #define BUTTON_COLS 5 | ||
10 | |||
11 | #define REC_HEIGHT (int)(LCD_HEIGHT / (BUTTON_ROWS + 1)) | ||
12 | #define REC_WIDTH (int)(LCD_WIDTH / BUTTON_COLS) | ||
13 | |||
14 | #define Y_7_POS (LCD_HEIGHT) /* Leave room for the border */ | ||
15 | #define Y_6_POS (Y_7_POS - REC_HEIGHT) /* y6 = 63 */ | ||
16 | #define Y_5_POS (Y_6_POS - REC_HEIGHT) /* y5 = 53 */ | ||
17 | #define Y_4_POS (Y_5_POS - REC_HEIGHT) /* y4 = 43 */ | ||
18 | #define Y_3_POS (Y_4_POS - REC_HEIGHT) /* y3 = 33 */ | ||
19 | #define Y_2_POS (Y_3_POS - REC_HEIGHT) /* y2 = 23 */ | ||
20 | #define Y_1_POS (Y_2_POS - REC_HEIGHT) /* y1 = 13 */ | ||
21 | #define Y_0_POS 0 /* y0 = 0 */ | ||
22 | |||
23 | #define X_0_POS 0 /* x0 = 0 */ | ||
24 | #define X_1_POS (X_0_POS + REC_WIDTH) /* x1 = 22 */ | ||
25 | #define X_2_POS (X_1_POS + REC_WIDTH) /* x2 = 44 */ | ||
26 | #define X_3_POS (X_2_POS + REC_WIDTH) /* x3 = 66 */ | ||
27 | #define X_4_POS (X_3_POS + REC_WIDTH) /* x4 = 88 */ | ||
28 | #define X_5_POS (X_4_POS + REC_WIDTH) /* x5 = 110, column 111 left blank */ | ||
29 | |||
30 | #if (CONFIG_KEYPAD == IPOD_1G2G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) | ||
31 | #define DARTS_QUIT PLA_SELECT_REPEAT | ||
32 | #else | ||
33 | #define DARTS_QUIT PLA_CANCEL | ||
34 | #endif | ||
35 | #define DARTS_SELECT PLA_SELECT | ||
36 | #define DARTS_RIGHT PLA_RIGHT | ||
37 | #define DARTS_LEFT PLA_LEFT | ||
38 | #define DARTS_UP PLA_UP | ||
39 | #define DARTS_DOWN PLA_DOWN | ||
40 | #define DARTS_RRIGHT PLA_RIGHT_REPEAT | ||
41 | #define DARTS_RLEFT PLA_LEFT_REPEAT | ||
42 | #define DARTS_RUP PLA_UP_REPEAT | ||
43 | #define DARTS_RDOWN PLA_DOWN_REPEAT | ||
44 | |||
45 | #define RESUME_FILE PLUGIN_GAMES_DATA_DIR "/dart_scorer.save" | ||
46 | /* leave first line blank on bitmap display, for pause icon */ | ||
47 | #define FIRST_LINE 1 | ||
48 | |||
49 | #define NUM_PLAYERS 2 | ||
50 | #define MAX_UNDO 100 | ||
51 | |||
52 | static const struct button_mapping *plugin_contexts[] = {pla_main_ctx}; | ||
53 | |||
54 | /* game data structures */ | ||
55 | enum game_mode | ||
56 | { | ||
57 | five, | ||
58 | three | ||
59 | }; | ||
60 | static struct settings_struct | ||
61 | { | ||
62 | enum game_mode mode; | ||
63 | int scores[2]; | ||
64 | bool turn; | ||
65 | int throws; | ||
66 | int history[MAX_UNDO]; | ||
67 | int history_ptr; | ||
68 | } settings; | ||
69 | |||
70 | /* temporary data */ | ||
71 | static bool loaded = false; /* has a save been loaded? */ | ||
72 | int btn_row, btn_col; /* current position index for button */ | ||
73 | int prev_btn_row, prev_btn_col; /* previous cursor position */ | ||
74 | unsigned char *buttonChar[6][5] = { | ||
75 | {"", "Single", "Double", "Triple", ""}, | ||
76 | {"1", "2", "3", "4", "5"}, | ||
77 | {"6", "7", "8", "9", "10"}, | ||
78 | {"11", "12", "13", "14", "15"}, | ||
79 | {"16", "17", "18", "19", "20"}, | ||
80 | {"", "Missed", "Bull", "Undo", ""}}; | ||
81 | int modifier; | ||
82 | |||
83 | static int do_dart_scorer_pause_menu(void); | ||
84 | static void drawButtons(void); | ||
85 | |||
86 | /* First, increases *dimen1 by dimen1_delta modulo dimen1_modulo. | ||
87 | If dimen1 wraps, increases *dimen2 by dimen2_delta modulo dimen2_modulo. | ||
88 | */ | ||
89 | static void move_with_wrap_and_shift( | ||
90 | int *dimen1, int dimen1_delta, int dimen1_modulo, | ||
91 | int *dimen2, int dimen2_delta, int dimen2_modulo) | ||
92 | { | ||
93 | bool wrapped = false; | ||
94 | |||
95 | *dimen1 += dimen1_delta; | ||
96 | if (*dimen1 < 0) | ||
97 | { | ||
98 | *dimen1 = dimen1_modulo - 1; | ||
99 | wrapped = true; | ||
100 | } | ||
101 | else if (*dimen1 >= dimen1_modulo) | ||
102 | { | ||
103 | *dimen1 = 0; | ||
104 | wrapped = true; | ||
105 | } | ||
106 | |||
107 | if (wrapped) | ||
108 | { | ||
109 | /* Make the dividend always positive to be sure about the result. | ||
110 | Adding dimen2_modulo does not change it since we do it modulo. */ | ||
111 | *dimen2 = (*dimen2 + dimen2_modulo + dimen2_delta) % dimen2_modulo; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | static void drawButtons() | ||
116 | { | ||
117 | int i, j, w, h; | ||
118 | for (i = 0; i <= 5; i++) | ||
119 | { | ||
120 | for (j = 0; j <= 4; j++) | ||
121 | { | ||
122 | unsigned char button_text[16]; | ||
123 | char *selected_prefix = (i == 0 && modifier > 0 && j == modifier) ? "*" : ""; | ||
124 | rb->snprintf(button_text, sizeof(button_text), "%s%s", selected_prefix, buttonChar[i][j]); | ||
125 | rb->lcd_getstringsize(button_text, &w, &h); | ||
126 | if (i == btn_row && j == btn_col) /* selected item */ | ||
127 | rb->lcd_set_drawmode(DRMODE_SOLID); | ||
128 | else | ||
129 | rb->lcd_set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); | ||
130 | rb->lcd_fillrect(X_0_POS + j * REC_WIDTH, | ||
131 | Y_1_POS + i * REC_HEIGHT, | ||
132 | REC_WIDTH, REC_HEIGHT + 1); | ||
133 | if (i == btn_row && j == btn_col) /* selected item */ | ||
134 | rb->lcd_set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); | ||
135 | else | ||
136 | rb->lcd_set_drawmode(DRMODE_SOLID); | ||
137 | rb->lcd_putsxy(X_0_POS + j * REC_WIDTH + (REC_WIDTH - w) / 2, | ||
138 | Y_1_POS + i * REC_HEIGHT + (REC_HEIGHT - h) / 2 + 1, | ||
139 | button_text); | ||
140 | } | ||
141 | } | ||
142 | rb->lcd_set_drawmode(DRMODE_SOLID); | ||
143 | } | ||
144 | |||
145 | static void draw(void) | ||
146 | { | ||
147 | rb->lcd_clear_display(); | ||
148 | |||
149 | char buf[32]; | ||
150 | |||
151 | int x = 5; | ||
152 | int y = 10; | ||
153 | for (int i = 0; i < NUM_PLAYERS; ++i, x = x + 95) | ||
154 | { | ||
155 | char *turn_marker = (i == settings.turn) ? "*" : ""; | ||
156 | rb->snprintf(buf, sizeof(buf), "%sPlayer %d: %d", turn_marker, i + 1, settings.scores[i]); | ||
157 | rb->lcd_putsxy(x, y, buf); | ||
158 | } | ||
159 | int throws_x = (LCD_WIDTH / 2) - 10; | ||
160 | char throws_buf[3]; | ||
161 | for (int i = 0; i < settings.throws; ++i, throws_x += 5) | ||
162 | { | ||
163 | rb->strcat(throws_buf, "1"); | ||
164 | rb->lcd_putsxy(throws_x, y, "|"); | ||
165 | } | ||
166 | |||
167 | drawButtons(); | ||
168 | |||
169 | rb->lcd_update(); | ||
170 | } | ||
171 | |||
172 | /***************************************************************************** | ||
173 | * save_game() saves the current game state. | ||
174 | ******************************************************************************/ | ||
175 | static void save_game(void) | ||
176 | { | ||
177 | int fd = rb->open(RESUME_FILE, O_WRONLY | O_CREAT, 0666); | ||
178 | if (fd < 0) | ||
179 | return; | ||
180 | |||
181 | rb->write(fd, &settings, sizeof(struct settings_struct)); | ||
182 | |||
183 | rb->close(fd); | ||
184 | rb->lcd_update(); | ||
185 | } | ||
186 | |||
187 | /* load_game() loads the saved game and returns load success.*/ | ||
188 | static bool load_game(void) | ||
189 | { | ||
190 | signed int fd; | ||
191 | bool loaded = false; | ||
192 | |||
193 | /* open game file */ | ||
194 | fd = rb->open(RESUME_FILE, O_RDONLY); | ||
195 | if (fd < 0) | ||
196 | return false; | ||
197 | |||
198 | /* read in saved game */ | ||
199 | if (rb->read(fd, &settings, sizeof(struct settings_struct)) == (long)sizeof(struct settings_struct)) | ||
200 | { | ||
201 | loaded = true; | ||
202 | } | ||
203 | |||
204 | rb->close(fd); | ||
205 | |||
206 | return loaded; | ||
207 | return false; | ||
208 | } | ||
209 | |||
210 | /* asks the user if they wish to quit */ | ||
211 | static bool confirm_quit(void) | ||
212 | { | ||
213 | const struct text_message prompt = {(const char *[]){"Are you sure?", "This will clear your current game."}, 2}; | ||
214 | enum yesno_res response = rb->gui_syncyesno_run(&prompt, NULL, NULL); | ||
215 | if (response == YESNO_NO) | ||
216 | return false; | ||
217 | else | ||
218 | return true; | ||
219 | } | ||
220 | |||
221 | /* displays the help text */ | ||
222 | static bool do_help(void) | ||
223 | { | ||
224 | |||
225 | #ifdef HAVE_LCD_COLOR | ||
226 | rb->lcd_set_foreground(LCD_WHITE); | ||
227 | rb->lcd_set_background(LCD_BLACK); | ||
228 | #endif | ||
229 | |||
230 | rb->lcd_setfont(FONT_UI); | ||
231 | |||
232 | static char *help_text[] = {"Dart Scorer", "", "", "Keep score of your darts game."}; | ||
233 | |||
234 | struct style_text style[] = { | ||
235 | {0, TEXT_CENTER | TEXT_UNDERLINE}, | ||
236 | }; | ||
237 | |||
238 | return display_text(ARRAYLEN(help_text), help_text, style, NULL, true); | ||
239 | } | ||
240 | |||
241 | static void undo(void) | ||
242 | { | ||
243 | if (!settings.history_ptr) | ||
244 | { | ||
245 | rb->splash(HZ * 2, "Out of undos!"); | ||
246 | return; | ||
247 | } | ||
248 | |||
249 | /* jumping back to previous player? */ | ||
250 | int turn = settings.throws == 3 ? !settings.turn : settings.turn; | ||
251 | if (turn != settings.turn) | ||
252 | { | ||
253 | settings.throws = 0; | ||
254 | settings.turn ^= true; | ||
255 | } | ||
256 | |||
257 | if (settings.history[settings.history_ptr - 1] >= 0) | ||
258 | { | ||
259 | settings.scores[turn] += settings.history[--settings.history_ptr]; | ||
260 | ++settings.throws; | ||
261 | } | ||
262 | else | ||
263 | { | ||
264 | /* | ||
265 | negative history means we bust. negative filled for all skipped throws | ||
266 | from being bust so consume back until no more | ||
267 | */ | ||
268 | for (; settings.throws < 3 && settings.history[settings.history_ptr - 1] < 0; --settings.history_ptr, ++settings.throws) | ||
269 | { | ||
270 | } | ||
271 | } | ||
272 | } | ||
273 | |||
274 | static void init_game(bool newgame) | ||
275 | { | ||
276 | if (newgame) | ||
277 | { | ||
278 | /* initialize the game context */ | ||
279 | modifier = 1; | ||
280 | btn_row = 1; | ||
281 | btn_col = 0; | ||
282 | |||
283 | int game_mode = -1; | ||
284 | MENUITEM_STRINGLIST(menu, "Game Mode", NULL, "501", "301"); | ||
285 | while (game_mode < 0) | ||
286 | { | ||
287 | switch (rb->do_menu(&menu, &game_mode, NULL, false)) | ||
288 | { | ||
289 | case 0: | ||
290 | { | ||
291 | settings.mode = five; | ||
292 | break; | ||
293 | } | ||
294 | case 1: | ||
295 | { | ||
296 | settings.mode = three; | ||
297 | break; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | for (int i = 0; i < NUM_PLAYERS; ++i) | ||
302 | { | ||
303 | settings.scores[i] = (settings.mode == five) ? 501 : 301; | ||
304 | } | ||
305 | settings.turn = false; | ||
306 | settings.throws = 3; | ||
307 | settings.history_ptr = 0; | ||
308 | rb->lcd_clear_display(); | ||
309 | } | ||
310 | } | ||
311 | } | ||
312 | |||
313 | /* main game loop */ | ||
314 | static enum plugin_status do_game(bool newgame) | ||
315 | { | ||
316 | init_game(newgame); | ||
317 | draw(); | ||
318 | |||
319 | while (1) | ||
320 | { | ||
321 | /* wait for button press */ | ||
322 | int button = pluginlib_getaction(-1, plugin_contexts, ARRAYLEN(plugin_contexts)); | ||
323 | unsigned char *selected = buttonChar[btn_row][btn_col]; | ||
324 | switch (button) | ||
325 | { | ||
326 | case DARTS_SELECT: | ||
327 | if ((!rb->strcmp(selected, "")) || (!rb->strcmp(selected, "Single"))) | ||
328 | modifier = 1; | ||
329 | else if (!rb->strcmp(selected, "Double")) | ||
330 | modifier = 2; | ||
331 | else if (!rb->strcmp(selected, "Triple")) | ||
332 | modifier = 3; | ||
333 | else if (!rb->strcmp(selected, "Undo")) | ||
334 | { | ||
335 | undo(); | ||
336 | continue; | ||
337 | } | ||
338 | else | ||
339 | { | ||
340 | /* main logic of score keeping */ | ||
341 | if (modifier == 0) | ||
342 | modifier = 1; | ||
343 | int hit = (!rb->strcmp(selected, "Bull")) ? 25 : rb->atoi(selected); | ||
344 | if (hit == 25 && modifier == 3) | ||
345 | { | ||
346 | /* no triple bullseye! */ | ||
347 | rb->splash(HZ * 2, "Triple Bull... Don't be silly!"); | ||
348 | continue; | ||
349 | } | ||
350 | hit *= modifier; | ||
351 | if (hit > settings.scores[settings.turn]) | ||
352 | { | ||
353 | rb->splash(HZ * 2, "Bust! End of turn."); | ||
354 | for (int i = 0; i < settings.throws; ++i) | ||
355 | settings.history[settings.history_ptr++] = -1; | ||
356 | settings.throws = 0; | ||
357 | } | ||
358 | else if (hit == settings.scores[settings.turn] - 1) | ||
359 | { | ||
360 | rb->splash(HZ * 2, "1 left! Must checkout with a double. End of turn."); | ||
361 | for (int i = 0; i < settings.throws; ++i) | ||
362 | settings.history[settings.history_ptr++] = -1; | ||
363 | settings.throws = 0; | ||
364 | } | ||
365 | else if (hit == settings.scores[settings.turn] && modifier != 2) | ||
366 | { | ||
367 | rb->splash(HZ * 2, "Must checkout with a double! End of turn."); | ||
368 | for (int i = 0; i < settings.throws; ++i) | ||
369 | settings.history[settings.history_ptr++] = -1; | ||
370 | settings.throws = 0; | ||
371 | } | ||
372 | else | ||
373 | { | ||
374 | settings.scores[settings.turn] -= hit; | ||
375 | --settings.throws; | ||
376 | settings.history[settings.history_ptr++] = hit; | ||
377 | modifier = 1; | ||
378 | if (!settings.scores[settings.turn]) | ||
379 | goto GAMEOVER; | ||
380 | } | ||
381 | |||
382 | if (!settings.throws) | ||
383 | { | ||
384 | settings.throws = 3; | ||
385 | settings.turn ^= true; | ||
386 | } | ||
387 | } | ||
388 | break; | ||
389 | case DARTS_LEFT: | ||
390 | case DARTS_RLEFT: | ||
391 | move_with_wrap_and_shift( | ||
392 | &btn_col, -1, BUTTON_COLS, | ||
393 | &btn_row, 0, BUTTON_ROWS); | ||
394 | break; | ||
395 | case DARTS_RIGHT: | ||
396 | case DARTS_RRIGHT: | ||
397 | move_with_wrap_and_shift( | ||
398 | &btn_col, 1, BUTTON_COLS, | ||
399 | &btn_row, 0, BUTTON_ROWS); | ||
400 | break; | ||
401 | #ifdef DARTS_UP | ||
402 | case DARTS_UP: | ||
403 | case DARTS_RUP: | ||
404 | #ifdef HAVE_SCROLLWHEEL | ||
405 | case PLA_SCROLL_BACK: | ||
406 | case PLA_SCROLL_BACK_REPEAT: | ||
407 | #endif | ||
408 | move_with_wrap_and_shift( | ||
409 | &btn_row, -1, BUTTON_ROWS, | ||
410 | &btn_col, 0, BUTTON_COLS); | ||
411 | break; | ||
412 | #endif | ||
413 | #ifdef DARTS_DOWN | ||
414 | case DARTS_DOWN: | ||
415 | case DARTS_RDOWN: | ||
416 | #ifdef HAVE_SCROLLWHEEL | ||
417 | case PLA_SCROLL_FWD: | ||
418 | case PLA_SCROLL_FWD_REPEAT: | ||
419 | #endif | ||
420 | move_with_wrap_and_shift( | ||
421 | &btn_row, 1, BUTTON_ROWS, | ||
422 | &btn_col, 0, BUTTON_COLS); | ||
423 | break; | ||
424 | #endif | ||
425 | case DARTS_QUIT: | ||
426 | switch (do_dart_scorer_pause_menu()) | ||
427 | { | ||
428 | case 0: /* resume */ | ||
429 | break; | ||
430 | case 1: | ||
431 | init_game(true); | ||
432 | continue; | ||
433 | case 2: /* quit w/o saving */ | ||
434 | rb->remove(RESUME_FILE); | ||
435 | return PLUGIN_ERROR; | ||
436 | case 3: /* save & quit */ | ||
437 | save_game(); | ||
438 | return PLUGIN_ERROR; | ||
439 | break; | ||
440 | } | ||
441 | break; | ||
442 | default: | ||
443 | { | ||
444 | exit_on_usb(button); /* handle poweroff and USB */ | ||
445 | break; | ||
446 | } | ||
447 | } | ||
448 | draw(); | ||
449 | } | ||
450 | |||
451 | GAMEOVER: | ||
452 | rb->splashf(HZ * 3, "Gameover. Player %d wins!", settings.turn + 1); | ||
453 | |||
454 | return PLUGIN_OK; | ||
455 | } | ||
456 | |||
457 | /* decide if this_item should be shown in the main menu */ | ||
458 | /* used to hide resume option when there is no save */ | ||
459 | static int mainmenu_cb(int action, | ||
460 | const struct menu_item_ex *this_item, | ||
461 | struct gui_synclist *this_list) | ||
462 | { | ||
463 | (void)this_list; | ||
464 | int idx = ((intptr_t)this_item); | ||
465 | if (action == ACTION_REQUEST_MENUITEM && !loaded && (idx == 0 || idx == 5)) | ||
466 | return ACTION_EXIT_MENUITEM; | ||
467 | return action; | ||
468 | } | ||
469 | |||
470 | /* show the pause menu */ | ||
471 | static int do_dart_scorer_pause_menu(void) | ||
472 | { | ||
473 | int sel = 0; | ||
474 | MENUITEM_STRINGLIST(menu, "Dart Scorer", NULL, | ||
475 | "Resume Game", | ||
476 | "Start New Game", | ||
477 | "Playback Control", | ||
478 | "Help", | ||
479 | "Quit without Saving", | ||
480 | "Quit"); | ||
481 | while (1) | ||
482 | { | ||
483 | switch (rb->do_menu(&menu, &sel, NULL, false)) | ||
484 | { | ||
485 | case 0: | ||
486 | { | ||
487 | rb->splash(HZ * 2, "Resume"); | ||
488 | return 0; | ||
489 | } | ||
490 | case 1: | ||
491 | { | ||
492 | if (!confirm_quit()) | ||
493 | break; | ||
494 | else | ||
495 | { | ||
496 | rb->splash(HZ * 2, "New Game"); | ||
497 | return 1; | ||
498 | } | ||
499 | } | ||
500 | case 2: | ||
501 | playback_control(NULL); | ||
502 | break; | ||
503 | case 3: | ||
504 | do_help(); | ||
505 | break; | ||
506 | case 4: /* quit w/o saving */ | ||
507 | { | ||
508 | if (!confirm_quit()) | ||
509 | break; | ||
510 | else | ||
511 | { | ||
512 | return 2; | ||
513 | } | ||
514 | } | ||
515 | case 5: | ||
516 | return 3; | ||
517 | default: | ||
518 | break; | ||
519 | } | ||
520 | } | ||
521 | } | ||
522 | |||
523 | /* show the main menu */ | ||
524 | static enum plugin_status do_dart_scorer_menu(void) | ||
525 | { | ||
526 | int sel = 0; | ||
527 | loaded = load_game(); | ||
528 | MENUITEM_STRINGLIST(menu, | ||
529 | "Dart Scorer Menu", | ||
530 | mainmenu_cb, | ||
531 | "Resume Game", | ||
532 | "Start New Game", | ||
533 | "Playback Control", | ||
534 | "Help", | ||
535 | "Quit without Saving", | ||
536 | "Quit"); | ||
537 | while (true) | ||
538 | { | ||
539 | switch (rb->do_menu(&menu, &sel, NULL, false)) | ||
540 | { | ||
541 | case 0: /* Start new game or resume a game */ | ||
542 | case 1: | ||
543 | { | ||
544 | if (sel == 1 && loaded) | ||
545 | { | ||
546 | if (!confirm_quit()) | ||
547 | break; | ||
548 | } | ||
549 | enum plugin_status ret = do_game(sel == 1); | ||
550 | switch (ret) | ||
551 | { | ||
552 | case PLUGIN_OK: | ||
553 | { | ||
554 | loaded = false; | ||
555 | rb->remove(RESUME_FILE); | ||
556 | break; | ||
557 | } | ||
558 | case PLUGIN_USB_CONNECTED: | ||
559 | save_game(); | ||
560 | return ret; | ||
561 | case PLUGIN_ERROR: /* exit without menu */ | ||
562 | return PLUGIN_OK; | ||
563 | default: | ||
564 | break; | ||
565 | } | ||
566 | break; | ||
567 | } | ||
568 | case 2: | ||
569 | playback_control(NULL); | ||
570 | break; | ||
571 | case 3: | ||
572 | do_help(); | ||
573 | break; | ||
574 | case 4: | ||
575 | if (confirm_quit()) | ||
576 | return PLUGIN_OK; | ||
577 | break; | ||
578 | case 5: | ||
579 | if (loaded) | ||
580 | save_game(); | ||
581 | return PLUGIN_OK; | ||
582 | default: | ||
583 | break; | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
588 | /* prepares for exit */ | ||
589 | static void cleanup(void) | ||
590 | { | ||
591 | backlight_use_settings(); | ||
592 | } | ||
593 | |||
594 | enum plugin_status plugin_start(const void *parameter) | ||
595 | { | ||
596 | (void)parameter; | ||
597 | /* now start the game menu */ | ||
598 | enum plugin_status ret = do_dart_scorer_menu(); | ||
599 | cleanup(); | ||
600 | return ret; | ||
601 | } | ||