Fix the pitch detector plugin for iaudioM3
[kugel-rb.git] / apps / plugins / clix.c
blob9c53bdab70f07d0249620317e407e61435934634
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008-2009 Rene Peinthor
11 * Contribution from Johannes Schwarz (new menu system, use of highscore lib)
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
20 #include "plugin.h"
21 #include "lib/highscore.h"
22 #include "lib/playback_control.h"
23 #include "lib/display_text.h"
25 PLUGIN_HEADER
27 #if (CONFIG_KEYPAD == SANSA_E200_PAD)
28 #define CLIX_BUTTON_QUIT BUTTON_POWER
29 #define CLIX_BUTTON_UP BUTTON_UP
30 #define CLIX_BUTTON_DOWN BUTTON_DOWN
31 #define CLIX_BUTTON_SCROLL_FWD BUTTON_SCROLL_FWD
32 #define CLIX_BUTTON_SCROLL_BACK BUTTON_SCROLL_BACK
33 #define CLIX_BUTTON_LEFT BUTTON_LEFT
34 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
35 #define CLIX_BUTTON_CLICK BUTTON_SELECT
37 #elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
38 #define CLIX_BUTTON_QUIT BUTTON_POWER
39 #define CLIX_BUTTON_UP BUTTON_UP
40 #define CLIX_BUTTON_DOWN BUTTON_DOWN
41 #define CLIX_BUTTON_LEFT BUTTON_LEFT
42 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
43 #define CLIX_BUTTON_CLICK BUTTON_SELECT
45 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
46 #define CLIX_BUTTON_QUIT BUTTON_HOME
47 #define CLIX_BUTTON_UP BUTTON_UP
48 #define CLIX_BUTTON_DOWN BUTTON_DOWN
49 #define CLIX_BUTTON_SCROLL_FWD BUTTON_SCROLL_FWD
50 #define CLIX_BUTTON_SCROLL_BACK BUTTON_SCROLL_BACK
51 #define CLIX_BUTTON_LEFT BUTTON_LEFT
52 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
53 #define CLIX_BUTTON_CLICK BUTTON_SELECT
55 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
56 #define CLIX_BUTTON_QUIT BUTTON_POWER
57 #define CLIX_BUTTON_UP BUTTON_UP
58 #define CLIX_BUTTON_DOWN BUTTON_DOWN
59 #define CLIX_BUTTON_SCROLL_FWD BUTTON_VOL_UP
60 #define CLIX_BUTTON_SCROLL_BACK BUTTON_VOL_DOWN
61 #define CLIX_BUTTON_LEFT BUTTON_LEFT
62 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
63 #define CLIX_BUTTON_CLICK BUTTON_SELECT
65 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
66 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
67 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
68 #define CLIX_BUTTON_QUIT (BUTTON_SELECT | BUTTON_MENU)
69 #define CLIX_BUTTON_UP BUTTON_MENU
70 #define CLIX_BUTTON_DOWN BUTTON_PLAY
71 #define CLIX_BUTTON_SCROLL_FWD BUTTON_SCROLL_FWD
72 #define CLIX_BUTTON_SCROLL_BACK BUTTON_SCROLL_BACK
73 #define CLIX_BUTTON_CLICK BUTTON_SELECT
74 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
75 #define CLIX_BUTTON_LEFT BUTTON_LEFT
77 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
78 #define CLIX_BUTTON_QUIT BUTTON_POWER
79 #define CLIX_BUTTON_LEFT BUTTON_LEFT
80 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
81 #define CLIX_BUTTON_CLICK BUTTON_SELECT
82 #define CLIX_BUTTON_UP BUTTON_UP
83 #define CLIX_BUTTON_DOWN BUTTON_DOWN
85 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
86 #define CLIX_BUTTON_QUIT BUTTON_BACK
87 #define CLIX_BUTTON_LEFT BUTTON_LEFT
88 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
89 #define CLIX_BUTTON_CLICK BUTTON_SELECT
90 #define CLIX_BUTTON_UP BUTTON_UP
91 #define CLIX_BUTTON_DOWN BUTTON_DOWN
93 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
94 #define CLIX_BUTTON_QUIT BUTTON_POWER
95 #define CLIX_BUTTON_LEFT BUTTON_LEFT
96 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
97 #define CLIX_BUTTON_CLICK BUTTON_PLAY
98 #define CLIX_BUTTON_UP BUTTON_SCROLL_UP
99 #define CLIX_BUTTON_DOWN BUTTON_SCROLL_DOWN
101 #elif CONFIG_KEYPAD == IAUDIO67_PAD
102 #define CLIX_BUTTON_QUIT BUTTON_POWER
103 #define CLIX_BUTTON_LEFT BUTTON_LEFT
104 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
105 #define CLIX_BUTTON_CLICK BUTTON_PLAY
106 #define CLIX_BUTTON_UP BUTTON_STOP
107 #define CLIX_BUTTON_DOWN BUTTON_PLAY
109 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
110 #define CLIX_BUTTON_QUIT BUTTON_POWER
111 #define CLIX_BUTTON_LEFT BUTTON_LEFT
112 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
113 #define CLIX_BUTTON_CLICK BUTTON_SELECT
114 #define CLIX_BUTTON_UP BUTTON_UP
115 #define CLIX_BUTTON_DOWN BUTTON_DOWN
117 #elif (CONFIG_KEYPAD == IRIVER_H300_PAD)
118 #define CLIX_BUTTON_QUIT BUTTON_OFF
119 #define CLIX_BUTTON_LEFT BUTTON_LEFT
120 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
121 #define CLIX_BUTTON_CLICK BUTTON_SELECT
122 #define CLIX_BUTTON_UP BUTTON_UP
123 #define CLIX_BUTTON_DOWN BUTTON_DOWN
125 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
126 #define CLIX_BUTTON_QUIT BUTTON_BACK
127 #define CLIX_BUTTON_LEFT BUTTON_LEFT
128 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
129 #define CLIX_BUTTON_CLICK BUTTON_SELECT
130 #define CLIX_BUTTON_UP BUTTON_UP
131 #define CLIX_BUTTON_DOWN BUTTON_DOWN
133 #elif (CONFIG_KEYPAD == PHILIPS_HDD1630_PAD)
134 #define CLIX_BUTTON_QUIT BUTTON_POWER
135 #define CLIX_BUTTON_LEFT BUTTON_LEFT
136 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
137 #define CLIX_BUTTON_CLICK BUTTON_SELECT
138 #define CLIX_BUTTON_UP BUTTON_UP
139 #define CLIX_BUTTON_DOWN BUTTON_DOWN
141 #elif CONFIG_KEYPAD == COWOND2_PAD
142 #define CLIX_BUTTON_QUIT BUTTON_POWER
144 #elif (CONFIG_KEYPAD == ONDAVX747_PAD)
145 #define CLIX_BUTTON_QUIT BUTTON_POWER
146 #define CLIX_BUTTON_CLICK BUTTON_MENU
147 #elif (CONFIG_KEYPAD == ONDAVX777_PAD)
148 #define CLIX_BUTTON_QUIT BUTTON_POWER
150 #elif (CONFIG_KEYPAD == MROBE500_PAD)
151 #define CLIX_BUTTON_QUIT BUTTON_POWER
153 #elif (CONFIG_KEYPAD == SAMSUNG_YH_PAD)
154 #define CLIX_BUTTON_QUIT BUTTON_REC
155 #define CLIX_BUTTON_LEFT BUTTON_LEFT
156 #define CLIX_BUTTON_RIGHT BUTTON_RIGHT
157 #define CLIX_BUTTON_CLICK BUTTON_PLAY
158 #define CLIX_BUTTON_UP BUTTON_UP
159 #define CLIX_BUTTON_DOWN BUTTON_DOWN
161 #else
162 #error "no keymap"
163 #endif
165 #ifndef CLIX_BUTTON_CLICK
166 #define CLIX_BUTTON_CLICK BUTTON_CENTER
167 #endif
169 #define HIGHSCORE_FILE PLUGIN_GAMES_DIR "/clix.score"
170 #define NUM_SCORES 5
171 struct highscore highest[NUM_SCORES];
173 #define NUM_LEVELS 9
174 #define BLINK_TICKCOUNT 25
175 #define MARGIN 5
177 #if (LCD_WIDTH >= LCD_HEIGHT)
178 #define BOARD_WIDTH 18
179 #define BOARD_HEIGHT 12
180 #else
181 #define BOARD_WIDTH 12
182 #define BOARD_HEIGHT 18
183 #endif
185 #if (LCD_WIDTH>=480)
186 #if (LCD_WIDTH/BOARD_WIDTH) > (LCD_HEIGHT/BOARD_HEIGHT)
187 #define CELL_SIZE (LCD_HEIGHT/BOARD_HEIGHT)
188 #else
189 #define CELL_SIZE (LCD_WIDTH/BOARD_WIDTH)
190 #endif
192 #elif (LCD_WIDTH >= 306 && LCD_HEIGHT>= 204)
193 #define CELL_SIZE 16
195 #elif (LCD_WIDTH >= 270 && LCD_HEIGHT>= 180)
196 #define CELL_SIZE 14
198 #elif (LCD_WIDTH >= 234 && LCD_HEIGHT>= 156)
199 #define CELL_SIZE 12
201 #elif (LCD_WIDTH >= 198 && LCD_HEIGHT>= 132)
202 #define CELL_SIZE 10
204 #elif (LCD_WIDTH >= 162 && LCD_HEIGHT>= 108)
205 #define CELL_SIZE 8
207 #elif (LCD_WIDTH >= 126 && LCD_HEIGHT>= 84)
208 #define CELL_SIZE 6
210 #elif (LCD_WIDTH >= 60)
211 #define CELL_SIZE 4
212 #endif
214 #define XYPOS(x,y) ((y) * BOARD_WIDTH + x)
215 #define XOFS LCD_WIDTH/2-(BOARD_WIDTH * (CELL_SIZE + 1)/2)
216 #define YOFS (LCD_HEIGHT+10)/2-(BOARD_HEIGHT * (CELL_SIZE + 1)/2)
219 struct clix_game_state_t {
220 int level; /* current level */
221 int score; /* current game score */
222 int x,y; /* current positions of the cursor */
223 int board[BOARD_WIDTH * BOARD_HEIGHT]; /* play board*/
224 /* state of selected fields,maybe we can store this in the play board too */
225 bool board_selected[ BOARD_WIDTH * BOARD_HEIGHT];
226 int selected_count;
227 int status;
228 bool blink; /* true if selected CELLS are currently white */
231 /* game state enum */
232 enum {
233 CLIX_GAMEOVER = -1,
234 CLIX_CONTINUE,
235 CLIX_CLEARED
238 /* cell color enum */
239 enum {
240 CC_BLACK = -1,
241 CC_BLUE,
242 CC_GREEN,
243 CC_RED,
244 CC_YELLOW,
245 CC_ORANGE,
246 CC_CYAN,
247 CC_BROWN,
248 CC_PINK,
249 CC_DARK_BLUE,
250 CC_DARK_GREEN
253 /* recursive function to check if a neighbour cell is of the same color
254 if so call the function with the neighbours position
256 static void clix_set_selected(struct clix_game_state_t* state,
257 const int x, const int y)
259 state->selected_count++;
260 state->board_selected[ XYPOS( x, y)] = true;
261 int current_color = state->board[ XYPOS( x, y)];
263 if( (x - 1) >= 0 &&
264 state->board[ XYPOS( x - 1, y)] == current_color &&
265 state->board_selected[ XYPOS(x - 1, y)] == false)
266 clix_set_selected( state, x - 1, y);
268 if( (y + 1) < BOARD_HEIGHT &&
269 state->board[ XYPOS( x, y + 1)] == current_color &&
270 state->board_selected[ XYPOS(x, y + 1)] == false)
271 clix_set_selected( state, x, y + 1);
273 if( (x + 1) < BOARD_WIDTH &&
274 state->board[ XYPOS( x + 1, y)] == current_color &&
275 state->board_selected[ XYPOS(x + 1, y)] == false)
276 clix_set_selected( state, x + 1, y);
278 if( (y - 1) >= 0 &&
279 state->board[ XYPOS( x, y - 1)] == current_color &&
280 state->board_selected[ XYPOS(x, y - 1)] == false)
281 clix_set_selected( state, x, y - 1);
284 /* updates "blinking" cells by finding out which one is a valid neighbours */
285 static void clix_update_selected(struct clix_game_state_t* state)
287 int i;
289 for( i = 0; i < BOARD_WIDTH * BOARD_HEIGHT; ++i)
291 state->board_selected[i] = false;
293 state->selected_count = 0;
295 /* recursion starts here */
296 clix_set_selected( state, state->x, state->y);
299 /* inits the board with new random colors according to the level */
300 static void clix_init_new_level(struct clix_game_state_t* state)
302 int i;
303 int r;
305 state->y = BOARD_HEIGHT / 2;
306 state->x = BOARD_WIDTH / 2;
308 rb->srand( *rb->current_tick);
309 /* create a random colored board, according to the current level */
310 for(i = 0; i < BOARD_HEIGHT * BOARD_WIDTH; ++i)
312 r = rb->rand() % (state->level + 1);
313 state->board[i] = r;
317 /* this inits the game state structure */
318 static void clix_init(struct clix_game_state_t* state)
320 state->level = 1;
321 state->score = 0;
322 state->blink = false;
323 state->status = CLIX_CONTINUE;
325 clix_init_new_level(state);
327 clix_update_selected(state);
330 /* Function for drawing a cell */
331 static void clix_draw_cell(struct clix_game_state_t* state, const int x, const int y)
333 int realx = XOFS;
334 int realy = YOFS;
336 realx += x * (CELL_SIZE + 1);
337 realy += y * (CELL_SIZE + 1);
339 if (state->blink && state->board_selected[ XYPOS( x, y)]) {
340 rb->lcd_set_foreground(LCD_WHITE);
341 } else {
342 switch (state->board[ XYPOS( x, y)])
344 case CC_BLUE:
345 rb->lcd_set_foreground( LCD_RGBPACK( 25, 25, 255));
346 break;
347 case CC_GREEN:
348 rb->lcd_set_foreground( LCD_RGBPACK( 25, 255, 25));
349 break;
350 case CC_RED:
351 rb->lcd_set_foreground( LCD_RGBPACK( 255, 25, 25));
352 break;
353 case CC_YELLOW:
354 rb->lcd_set_foreground( LCD_RGBPACK( 225, 225, 25));
355 break;
356 case CC_ORANGE:
357 rb->lcd_set_foreground( LCD_RGBPACK( 230, 140, 15));
358 break;
359 case CC_CYAN:
360 rb->lcd_set_foreground( LCD_RGBPACK( 25, 245, 230));
361 break;
362 case CC_BROWN:
363 rb->lcd_set_foreground( LCD_RGBPACK(139, 69, 19));
364 break;
365 case CC_PINK:
366 rb->lcd_set_foreground( LCD_RGBPACK(255, 105, 180));
367 break;
368 case CC_DARK_GREEN:
369 rb->lcd_set_foreground( LCD_RGBPACK( 0, 100, 0));
370 break;
371 case CC_DARK_BLUE:
372 rb->lcd_set_foreground( LCD_RGBPACK( 280, 32, 144));
373 break;
374 default:
375 rb->lcd_set_foreground( LCD_BLACK);
376 break;
380 rb->lcd_fillrect( realx, realy, CELL_SIZE, CELL_SIZE);
382 /* draw cursor */
383 if ( x == state->x && y == state->y) {
384 rb->lcd_set_foreground( LCD_WHITE);
385 rb->lcd_drawrect( realx - 1, realy - 1, CELL_SIZE + 2, CELL_SIZE + 2);
389 /* main function of drawing the whole board and score... */
390 static void clix_draw(struct clix_game_state_t* state)
392 int i,j;
393 char str[30];
395 /* Clear screen */
396 rb->lcd_clear_display();
397 rb->lcd_set_foreground( LCD_WHITE);
399 rb->lcd_putsxy( MARGIN, MARGIN, "Score:");
400 rb->snprintf( str, sizeof(str), "%d", state->score);
401 rb->lcd_putsxy( 43, MARGIN, str);
402 #if LCD_WIDTH <= 100
403 rb->lcd_putsxy( 75, MARGIN, "L:");
404 rb->snprintf( str, sizeof(str), "%d", state->level);
405 rb->lcd_putsxy( 90, MARGIN, str);
406 #else
407 rb->lcd_putsxy( 75, MARGIN, "Level:");
408 rb->snprintf( str, sizeof(str), "%d", state->level);
409 rb->lcd_putsxy( 113, MARGIN, str);
410 #endif
411 for( i = 0; i < BOARD_WIDTH; ++i)
413 for( j = 0; j < BOARD_HEIGHT; ++j)
415 clix_draw_cell( state, i, j);
419 rb->lcd_update();
422 static void clix_move_cursor(struct clix_game_state_t* state, const bool left)
424 int x, y;
426 x = state->x;
429 y = state->y;
430 while(state->board[ XYPOS( x, y)] == CC_BLACK && y < BOARD_HEIGHT) y++;
431 if (y < BOARD_HEIGHT) {
432 state->y = y;
433 state->x = x;
435 else
437 if (left) {
438 if( x >= 0)
439 x--;
440 else
441 y = state->y;
443 else
445 if( x < BOARD_WIDTH - 1)
446 x++;
447 else
448 x = 0;
451 } while ( y != state->y);
455 /* returns the color of the given position, if out of bounds return CC_BLACK */
456 static int clix_get_color(struct clix_game_state_t* state, const int x, const int y)
458 if( x >= 0 && x < BOARD_WIDTH && y >= 0 && y < BOARD_HEIGHT)
459 return state->board[XYPOS( x, y)];
460 else
461 return CC_BLACK;
464 static int clix_clear_selected(struct clix_game_state_t* state)
466 int i, j, x, y;
468 state->status = CLIX_CLEARED;
470 /* clear the selected blocks */
471 for( i = 0; i < BOARD_WIDTH; ++i)
473 for( j = 0; j < BOARD_HEIGHT; ++j)
475 if( state->board_selected[ XYPOS( i, j)] )
477 state->board_selected[ XYPOS( i, j)] = false;
478 state->board[ XYPOS( i, j)] = CC_BLACK;
483 /* count score */
484 state->score += state->selected_count * state->level;
485 state->selected_count = 0;
487 /* let blocks falling down */
488 for( i = BOARD_WIDTH - 1; i >= 0; --i)
490 for( j = BOARD_HEIGHT - 1; j >= 0; --j)
492 y = j;
493 while( (y + 1) < BOARD_HEIGHT &&
494 state->board[ XYPOS( i, y + 1)] == CC_BLACK
496 y++;
498 if (y != j) {
499 state->board[ XYPOS( i, y)] = state->board[ XYPOS( i, j)];
500 state->board[ XYPOS( i, j)] = CC_BLACK;
505 /* move columns to left side */
506 for( i = 0; i < BOARD_WIDTH; ++i)
508 x = i;
509 while( (x - 1) >= 0 &&
510 state->board[ XYPOS( x - 1, BOARD_HEIGHT - 1)] == CC_BLACK
512 x--;
513 if (x != i)
515 for( j = 0; j < BOARD_HEIGHT; ++j)
517 state->board[ XYPOS( x, j)] = state->board[ XYPOS( i, j)];
518 state->board[ XYPOS( i, j)] = CC_BLACK;
523 if(state->board[ XYPOS( 0, BOARD_HEIGHT - 1)] != CC_BLACK)
524 state->status = CLIX_CONTINUE;
526 if (state->status != CLIX_CLEARED) {
527 /* check if a move is still possible, otherwise the game is over.
528 tart from the left bottom, because there are the last fields
529 at the end of the game.
531 for( i = 0; i < BOARD_WIDTH; ++i)
533 for( j = BOARD_HEIGHT - 1; j >= 0; --j)
535 int color = state->board[ XYPOS( i, j)];
536 if (color != CC_BLACK) {
537 if (color == clix_get_color( state, i - 1, j) ||
538 color == clix_get_color( state, i + 1, j) ||
539 color == clix_get_color( state, i, j - 1) ||
540 color == clix_get_color( state, i, j + 1)
543 /* end the loop, but in a diffrent way than usually*/
544 i = BOARD_WIDTH + 1;
545 j = -2;
550 /* if the loops ended without a possible move, the game is over */
551 if( i == BOARD_WIDTH && j == -1)
552 state->status = CLIX_GAMEOVER;
554 /* set cursor to the right position */
555 if (state->status == CLIX_CONTINUE) {
556 clix_move_cursor( state, true);
557 clix_update_selected( state);
561 return state->status;
564 static bool clix_help(void)
566 #define WORDS (sizeof help_text / sizeof (char*))
567 static char *help_text[] = {
568 "Clix", "", "Aim", "",
569 "Remove", "all", "blocks", "from", "the", "board", "to", "achieve",
570 "the", "next", "level.", "You", "can", "only", "remove", "blocks,",
571 "if", "at", "least", "two", "blocks", "with", "the", "same", "color",
572 "have", "a", "direct", "connection.", "The", "more", "blocks", "you",
573 "remove", "per", "turn,", "the", "more", "points", "you", "get."
575 static struct style_text formation[]={
576 { 0, TEXT_CENTER|TEXT_UNDERLINE },
577 { 2, C_RED },
578 { -1, 0 }
580 int button;
582 rb->lcd_setfont(FONT_UI);
583 rb->lcd_set_foreground(LCD_WHITE);
584 if (display_text(WORDS, help_text, formation, NULL))
585 return true;
586 do {
587 button = rb->button_get(true);
588 if ( rb->default_event_handler( button ) == SYS_USB_CONNECTED )
589 return true;
590 } while( ( button == BUTTON_NONE )
591 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
592 rb->lcd_setfont(FONT_SYSFIXED);
593 return 0;
596 static bool _ingame;
597 static int clix_menu_cb(int action, const struct menu_item_ex *this_item)
599 if(action == ACTION_REQUEST_MENUITEM
600 && !_ingame && ((intptr_t)this_item)==0)
601 return ACTION_EXIT_MENUITEM;
602 return action;
605 static int clix_menu(struct clix_game_state_t* state, bool ingame)
607 rb->button_clear_queue();
608 int choice = 0;
609 bool leave_menu=false;
610 int ret=0;
612 _ingame = ingame;
614 MENUITEM_STRINGLIST (main_menu, "Clix Menu", clix_menu_cb,
615 "Resume Game",
616 "Start New Game",
617 "Help",
618 "High Scores",
619 "Playback Control",
620 "Quit");
622 #ifdef HAVE_TOUCHSCREEN
623 /* Entering Menu, set the touchscreen to the global setting */
624 rb->touchscreen_set_mode(rb->global_settings->touch_mode);
625 #endif
627 while (!leave_menu) {
629 switch (rb->do_menu(&main_menu, &choice, NULL, false)) {
630 case 0:
631 leave_menu=true;
632 ret = 0;
633 break;
634 case 1:
635 clix_init(state);
636 leave_menu=true;
637 ret = 0;
638 break;
639 case 2:
640 if (clix_help()) {
641 leave_menu=true;
642 ret = 1;
644 break;
645 case 3:
646 highscore_show(NUM_SCORES, highest, NUM_SCORES, true);
647 break;
648 case 4:
649 playback_control(NULL);
650 break;
651 case 5:
652 case MENU_ATTACHED_USB:
653 leave_menu=true;
654 ret = 1;
655 break;
656 default:
657 break;
661 #ifdef HAVE_TOUCHSCREEN
662 /* Leaving the menu, set back to pointer mode */
663 rb->touchscreen_set_mode(TOUCHSCREEN_POINT);
664 #endif
666 return ret;
669 static int clix_handle_game(struct clix_game_state_t* state)
671 if (clix_menu(state, 0))
672 return 1;
674 int button;
675 int blink_tick = *rb->current_tick + BLINK_TICKCOUNT;
676 int position;
678 int time;
679 int start;
680 int end;
681 int oldx, oldy;
683 int lastbutton = BUTTON_NONE;
685 while(true)
687 if (blink_tick < *rb->current_tick) {
688 state->blink = state->blink ? false : true;
689 blink_tick = *rb->current_tick + BLINK_TICKCOUNT;
692 time = 6; /* number of ticks this function will loop reading keys */
693 start = *rb->current_tick;
694 end = start + time;
695 while(end > *rb->current_tick)
697 oldx = state->x;
698 oldy = state->y;
700 button = rb->button_get_w_tmo(end - *rb->current_tick);
701 #ifdef HAVE_TOUCHSCREEN
702 if(button & BUTTON_TOUCHSCREEN)
704 int x = rb->button_get_data() >> 16;
705 int y = rb->button_get_data() & 0xffff;
707 x -= XOFS;
708 y -= YOFS;
709 if(x >= 0 && y >= 0)
711 x /= CELL_SIZE + 1;
712 y /= CELL_SIZE + 1;
714 if(x < BOARD_WIDTH && y < BOARD_HEIGHT
715 && state->board[XYPOS(x, y)] != CC_BLACK)
717 if(state->x == x && state->y == y)
718 button = CLIX_BUTTON_CLICK;
719 else
721 state->x = x;
722 state->y = y;
727 #endif
728 switch( button)
730 #ifndef HAVE_TOUCHSCREEN
731 #ifdef CLIX_BUTTON_SCROLL_BACK
732 case CLIX_BUTTON_SCROLL_BACK:
733 case CLIX_BUTTON_SCROLL_BACK|BUTTON_REPEAT:
734 #endif
735 case CLIX_BUTTON_UP:
736 if( state->y == 0 ||
737 state->board[ XYPOS( state->x, state->y - 1)] ==
738 CC_BLACK
740 state->y = BOARD_HEIGHT - 1;
741 else
742 state->y--;
744 clix_move_cursor(state, true);
745 break;
746 case CLIX_BUTTON_RIGHT:
747 if( state->x == (BOARD_WIDTH - 1))
748 state->x = 0;
749 else
750 state->x++;
752 clix_move_cursor(state, false);
753 break;
754 #ifdef CLIX_BUTTON_SCROLL_FWD
755 case CLIX_BUTTON_SCROLL_FWD:
756 case CLIX_BUTTON_SCROLL_FWD|BUTTON_REPEAT:
757 #endif
758 case CLIX_BUTTON_DOWN:
759 if( state->y == (BOARD_HEIGHT - 1))
760 state->y = 0;
761 else
762 state->y++;
764 clix_move_cursor( state, true);
765 break;
766 case CLIX_BUTTON_LEFT:
767 if( state->x == 0)
768 state->x = BOARD_WIDTH - 1;
769 else
770 state->x--;
772 clix_move_cursor(state, true);
774 break;
775 #endif
776 case CLIX_BUTTON_CLICK:
778 if (state->selected_count > 1) {
779 switch( clix_clear_selected( state))
781 case CLIX_CLEARED:
782 state->score += state->level * 100;
783 clix_draw( state);
784 if (state->level < NUM_LEVELS) {
785 rb->splash(HZ*2, "Great! Next Level!");
786 state->level++;
787 clix_init_new_level( state);
788 clix_update_selected( state);
790 else {
791 rb->splash(HZ*2, "Congratulation!!!");
792 rb->lcd_clear_display();
793 rb->splash(HZ*2, "You have finished the game.");
794 if (clix_menu(state, 0))
795 return 1;
797 break;
798 case CLIX_GAMEOVER:
799 clix_draw( state);
800 rb->splash(HZ*2, "Game Over!");
801 rb->lcd_clear_display();
802 position=highscore_update(state->score,
803 state->level, "",
804 highest,NUM_SCORES);
805 if (position == 0)
806 rb->splash(HZ*2, "New High Score");
807 if (position != -1)
808 highscore_show(position, highest,
809 NUM_SCORES, true);
810 if (clix_menu(state, 0))
811 return 1;
812 break;
813 default:
814 rb->sleep(10); /* prevent repeating clicks */
815 break;
819 break;
820 case CLIX_BUTTON_QUIT:
821 if (clix_menu(state, 1) != 0) {
822 rb->button_clear_queue();
823 return 1;
825 break;
826 default:
828 break;
831 if(button != BUTTON_NONE)
832 lastbutton = button;
834 if( (oldx != state->x || oldy != state->y) &&
835 state->board_selected[ XYPOS( oldx, oldy)] !=
836 state->board_selected[ XYPOS( state->x, state->y)]
839 clix_update_selected(state);
841 clix_draw(state);
842 rb->sleep(time);
847 /* this is the plugin entry point */
848 enum plugin_status plugin_start(const void* parameter)
850 (void)parameter;
852 rb->lcd_set_backdrop(NULL);
853 rb->lcd_set_foreground(LCD_WHITE);
854 rb->lcd_set_background(LCD_BLACK);
855 rb->lcd_setfont(FONT_SYSFIXED);
856 #ifdef HAVE_TOUCHSCREEN
857 rb->touchscreen_set_mode(TOUCHSCREEN_POINT);
858 #endif
860 highscore_load(HIGHSCORE_FILE, highest, NUM_SCORES);
862 struct clix_game_state_t state;
863 clix_handle_game( &state);
865 highscore_save(HIGHSCORE_FILE, highest, NUM_SCORES);
867 return PLUGIN_OK;