when changing settings from the Talk and Voice window also update the main widgets...
[Rockbox.git] / apps / plugins / star.c
blob56fe89c4d390da9365ec94a1695802073c7f56fa
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Frederic Dang Ngoc
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include "plugin.h"
20 #ifdef HAVE_LCD_BITMAP
22 PLUGIN_HEADER
24 /* size of a level in file */
25 #define STAR_LEVEL_SIZE ((STAR_WIDTH + 1) * STAR_HEIGHT + 1)
27 /* size of the game board */
28 #define STAR_WIDTH 16
29 #define STAR_HEIGHT 9
31 /* number of level */
32 #define STAR_LEVEL_COUNT 20
34 /* values of object in the board */
35 #define STAR_VOID '.'
36 #define STAR_WALL '*'
37 #define STAR_STAR 'o'
38 #define STAR_BALL 'X'
39 #define STAR_BLOCK 'x'
41 /* sleep time between two frames */
42 #if (LCD_HEIGHT * LCD_WIDTH >= 70000) && defined(IPOD_ARCH)
43 /* iPod 5G LCD is *slow* */
44 #define STAR_SLEEP rb->yield();
45 #elif (LCD_HEIGHT * LCD_WIDTH >= 30000)
46 #define STAR_SLEEP rb->sleep(0);
47 #else
48 #define STAR_SLEEP rb->sleep(1);
49 #endif
51 /* value of ball and block control */
52 #define STAR_CONTROL_BALL 0
53 #define STAR_CONTROL_BLOCK 1
55 /* variable button definitions */
56 #if CONFIG_KEYPAD == RECORDER_PAD
57 #define STAR_QUIT BUTTON_OFF
58 #define STAR_UP BUTTON_UP
59 #define STAR_DOWN BUTTON_DOWN
60 #define STAR_TOGGLE_CONTROL BUTTON_ON
61 #define STAR_TOGGLE_CONTROL2 BUTTON_PLAY
62 #define STAR_LEVEL_UP BUTTON_F3
63 #define STAR_LEVEL_DOWN BUTTON_F1
64 #define STAR_LEVEL_REPEAT BUTTON_F2
65 #define STAR_MENU_RUN BUTTON_PLAY
66 #define STAR_MENU_RUN2 BUTTON_RIGHT
67 #define STAR_MENU_RUN3 BUTTON_ON
69 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
70 #define STAR_QUIT BUTTON_OFF
71 #define STAR_UP BUTTON_UP
72 #define STAR_DOWN BUTTON_DOWN
73 #define STAR_TOGGLE_CONTROL BUTTON_ON
74 #define STAR_TOGGLE_CONTROL2 BUTTON_SELECT
75 #define STAR_LEVEL_UP BUTTON_F3
76 #define STAR_LEVEL_DOWN BUTTON_F1
77 #define STAR_LEVEL_REPEAT BUTTON_F2
78 #define STAR_MENU_RUN BUTTON_SELECT
79 #define STAR_MENU_RUN2 BUTTON_RIGHT
80 #define STAR_MENU_RUN3 BUTTON_ON
82 #elif CONFIG_KEYPAD == ONDIO_PAD
83 #define STAR_QUIT BUTTON_OFF
84 #define STAR_UP BUTTON_UP
85 #define STAR_DOWN BUTTON_DOWN
86 #define STAR_TOGGLE_CONTROL_PRE BUTTON_MENU
87 #define STAR_TOGGLE_CONTROL (BUTTON_MENU | BUTTON_REL)
88 #define STAR_LEVEL_UP (BUTTON_MENU | BUTTON_RIGHT)
89 #define STAR_LEVEL_DOWN (BUTTON_MENU | BUTTON_LEFT)
90 #define STAR_LEVEL_REPEAT (BUTTON_MENU | BUTTON_UP)
91 #define STAR_MENU_RUN BUTTON_RIGHT
93 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
94 (CONFIG_KEYPAD == IRIVER_H300_PAD)
95 #define STAR_QUIT BUTTON_OFF
96 #define STAR_UP BUTTON_UP
97 #define STAR_DOWN BUTTON_DOWN
98 #define STAR_TOGGLE_CONTROL BUTTON_MODE
99 #define STAR_TOGGLE_CONTROL2 BUTTON_SELECT
100 #define STAR_LEVEL_UP (BUTTON_ON | BUTTON_RIGHT)
101 #define STAR_LEVEL_DOWN (BUTTON_ON | BUTTON_LEFT)
102 #define STAR_LEVEL_REPEAT (BUTTON_ON | BUTTON_SELECT)
103 #define STAR_MENU_RUN BUTTON_RIGHT
104 #define STAR_MENU_RUN2 BUTTON_SELECT
106 #define STAR_RC_QUIT BUTTON_RC_STOP
107 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
108 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
109 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
111 #define STAR_QUIT (BUTTON_SELECT | BUTTON_MENU)
112 #define STAR_UP BUTTON_MENU
113 #define STAR_DOWN BUTTON_PLAY
114 #define STAR_TOGGLE_CONTROL_PRE BUTTON_SELECT
115 #define STAR_TOGGLE_CONTROL (BUTTON_SELECT | BUTTON_REL)
116 #define STAR_LEVEL_UP (BUTTON_SELECT | BUTTON_RIGHT)
117 #define STAR_LEVEL_DOWN (BUTTON_SELECT | BUTTON_LEFT)
118 #define STAR_LEVEL_REPEAT (BUTTON_SELECT | BUTTON_PLAY)
119 #define STAR_MENU_RUN BUTTON_RIGHT
120 #define STAR_MENU_RUN2 BUTTON_SELECT
122 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
124 #define STAR_QUIT BUTTON_POWER
125 #define STAR_UP BUTTON_UP
126 #define STAR_DOWN BUTTON_DOWN
127 #define STAR_TOGGLE_CONTROL BUTTON_SELECT
128 #define STAR_LEVEL_UP_PRE BUTTON_REC
129 #define STAR_LEVEL_UP (BUTTON_REC|BUTTON_REL)
130 #define STAR_LEVEL_DOWN_PRE BUTTON_REC
131 #define STAR_LEVEL_DOWN (BUTTON_REC|BUTTON_REPEAT)
132 #define STAR_LEVEL_REPEAT BUTTON_PLAY
133 #define STAR_MENU_RUN BUTTON_RIGHT
134 #define STAR_MENU_RUN2 BUTTON_SELECT
136 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
138 #define STAR_QUIT BUTTON_POWER
139 #define STAR_UP BUTTON_UP
140 #define STAR_DOWN BUTTON_DOWN
141 #define STAR_TOGGLE_CONTROL BUTTON_SELECT
142 #define STAR_LEVEL_UP BUTTON_VOL_UP
143 #define STAR_LEVEL_DOWN BUTTON_VOL_DOWN
144 #define STAR_LEVEL_REPEAT BUTTON_A
145 #define STAR_MENU_RUN BUTTON_SELECT
147 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
148 (CONFIG_KEYPAD == SANSA_C200_PAD)
150 #define STAR_QUIT BUTTON_POWER
151 #define STAR_UP BUTTON_UP
152 #define STAR_DOWN BUTTON_DOWN
153 #define STAR_TOGGLE_CONTROL BUTTON_SELECT
154 #define STAR_LEVEL_UP (BUTTON_SELECT | BUTTON_RIGHT)
155 #define STAR_LEVEL_DOWN (BUTTON_SELECT | BUTTON_LEFT)
156 #define STAR_LEVEL_REPEAT (BUTTON_SELECT | BUTTON_DOWN)
157 #define STAR_MENU_RUN BUTTON_SELECT
160 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
162 #define STAR_QUIT BUTTON_POWER
163 #define STAR_UP BUTTON_SCROLL_UP
164 #define STAR_DOWN BUTTON_SCROLL_DOWN
165 #define STAR_TOGGLE_CONTROL BUTTON_REW
166 #define STAR_LEVEL_UP (BUTTON_PLAY | BUTTON_SCROLL_UP)
167 #define STAR_LEVEL_DOWN (BUTTON_PLAY | BUTTON_SCROLL_DOWN)
168 #define STAR_LEVEL_REPEAT (BUTTON_PLAY | BUTTON_RIGHT)
169 #define STAR_MENU_RUN BUTTON_FF
171 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
173 #define STAR_QUIT BUTTON_BACK
174 #define STAR_UP BUTTON_UP
175 #define STAR_DOWN BUTTON_DOWN
176 #define STAR_TOGGLE_CONTROL BUTTON_SELECT
177 #define STAR_LEVEL_UP BUTTON_VOL_UP
178 #define STAR_LEVEL_DOWN BUTTON_VOL_DOWN
179 #define STAR_LEVEL_REPEAT BUTTON_MENU
180 #define STAR_MENU_RUN BUTTON_SELECT
182 #elif (CONFIG_KEYPAD == MROBE100_PAD)
184 #define STAR_QUIT BUTTON_POWER
185 #define STAR_UP BUTTON_UP
186 #define STAR_DOWN BUTTON_DOWN
187 #define STAR_TOGGLE_CONTROL BUTTON_SELECT
188 #define STAR_LEVEL_UP BUTTON_PLAY
189 #define STAR_LEVEL_DOWN BUTTON_MENU
190 #define STAR_LEVEL_REPEAT BUTTON_DISPLAY
191 #define STAR_MENU_RUN BUTTON_SELECT
193 #else
194 #error No keymap defined!
195 #endif
197 /* function returns because of USB? */
198 static bool usb_detected = false;
200 /* position of the ball */
201 static int ball_x, ball_y;
203 /* position of the block */
204 static int block_x, block_y;
206 /* number of stars to get to finish the level */
207 static int star_count;
209 /* the object we control : ball or block */
210 static int control;
212 /* the current board */
213 static char board[STAR_HEIGHT][STAR_WIDTH];
215 #include "star_tiles.h"
217 #define TILE_WIDTH BMPWIDTH_star_tiles
218 #define TILE_HEIGHT (BMPHEIGHT_star_tiles/5)
219 #define STAR_OFFSET_X ((LCD_WIDTH - STAR_WIDTH * TILE_WIDTH) / 2)
220 #define STAR_OFFSET_Y ((LCD_HEIGHT - STAR_HEIGHT * TILE_HEIGHT - MAX(TILE_HEIGHT, 8)) / 2)
222 #define WALL 0
223 #define SPACE 1
224 #define BLOCK 2
225 #define STAR 3
226 #define BALL 4
228 #define MENU_START 0
230 /* char font size */
231 static int char_width = -1;
232 static int char_height = -1;
234 static struct plugin_api* rb;
236 /* this arrays contains a group of levels loaded into memory */
237 static unsigned char* levels =
238 "****************\n"
239 "*X**........o*x*\n"
240 "*..........o.***\n"
241 "*.......**o....*\n"
242 "*...**.o......**\n"
243 "**.o..o.....o..*\n"
244 "*.o......o**.o.*\n"
245 "*.....**o.....o*\n"
246 "****************\n"
247 "\n"
248 ".*..*.*.*...*.**\n"
249 "*...o.........X*\n"
250 "...*o..*o...o...\n"
251 "*.*.o.....o..*.*\n"
252 "......*...o...*.\n"
253 "*....*x*..o....*\n"
254 "...*..*.*...*oo*\n"
255 "*.............*.\n"
256 ".*..*........*..\n"
257 "\n"
258 "****************\n"
259 "*...........o*x*\n"
260 "*...**......**X*\n"
261 "*...*o.........*\n"
262 "*.o.....o**...o*\n"
263 "*.*o..o..o*..o**\n"
264 "*.**o.*o..o.o***\n"
265 "*o....**o......*\n"
266 "****************\n"
267 "\n"
268 "****************\n"
269 "*............*x*\n"
270 "*.....*........*\n"
271 "**o*o.o*o*o*o*o*\n"
272 "*.*.*o.o*.*.*.**\n"
273 "**o*o*o.o*o*o*o*\n"
274 "*.....*........*\n"
275 "*...*.......*X.*\n"
276 "****************\n"
277 "\n"
278 ".**************.\n"
279 "*X..*...*..*...*\n"
280 "*..*o.*.o..o.*.*\n"
281 "**......*..*...*\n"
282 "*o.*o*........**\n"
283 "**.....*.o.*...*\n"
284 "*o*..*.*.*...*x*\n"
285 "*...*....o*..*o*\n"
286 ".**************.\n"
287 "\n"
288 "....************\n"
289 "...*...o...*o.o*\n"
290 "..*....o....*.**\n"
291 ".*.....o.......*\n"
292 "*X.....o.......*\n"
293 "**.....o..*...**\n"
294 "*......o....*..*\n"
295 "*x.*...o..**o..*\n"
296 "****************\n"
297 "\n"
298 "****************\n"
299 "*..............*\n"
300 ".**.***..*o.**o*\n"
301 ".*o..*o.*.*.*.*.\n"
302 "..*..*..***.**..\n"
303 ".**..*..*o*.*o**\n"
304 "*..............*\n"
305 "*..X*o....x..*o*\n"
306 "****************\n"
307 "\n"
308 "***************.\n"
309 "*..o**.........*\n"
310 "*..*o..**.o....*\n"
311 "*..o**.*.*o....*\n"
312 "**.....**..*o*.*\n"
313 "**.*.......o*o.*\n"
314 "*oxo*...o..*X*.*\n"
315 "**.............*\n"
316 ".***************\n"
317 "\n"
318 "..*.***********.\n"
319 ".*o*o......*..X*\n"
320 "*o.o*....o....*.\n"
321 ".*.*..o**..o*..*\n"
322 "*..*o.*oxo....o*\n"
323 "*.....o**.....*.\n"
324 "*o*o.........*..\n"
325 "*...........*...\n"
326 ".***********....\n"
327 "\n"
328 "....***********.\n"
329 "*****.o........*\n"
330 "*...x.***o.o*.o*\n"
331 "*.o...*o.*o...*.\n"
332 "*.....*..o..*.o*\n"
333 "*o*o..*.o*..*X*.\n"
334 ".*o...***..***..\n"
335 "*.........*.*.*.\n"
336 ".*********..*..*\n"
337 "\n"
338 "****************\n"
339 "*......*......X*\n"
340 "*..*oo.....oo.**\n"
341 "**...o...**...o*\n"
342 "*o....*o*oo..***\n"
343 "**.**....**....*\n"
344 "*o..o*.o....x.o*\n"
345 "**o***....*...**\n"
346 "***************.\n"
347 "\n"
348 "**.....**..****.\n"
349 "*X*****o.***.o**\n"
350 "*....oo.....o..*\n"
351 "*.**..**o..*o*.*\n"
352 "*.*.o.*.*o.**..*\n"
353 "*.**..**...*x*.*\n"
354 "*.....o........*\n"
355 "*........o.....*\n"
356 "****************\n"
357 "\n"
358 ".**************.\n"
359 "*.X*........o.**\n"
360 "*.*...*o...o**.*\n"
361 "*.......o....*.*\n"
362 "*.o..........*o*\n"
363 "*.*......o.....*\n"
364 "**......o.o..*o*\n"
365 "*x..*....o.*.*.*\n"
366 ".**************.\n"
367 "\n"
368 "****************\n"
369 "*o*o........o*o*\n"
370 "*.o*X......**..*\n"
371 "*.x........o...*\n"
372 "*........o*....*\n"
373 "*......o.......*\n"
374 "*.o*........*..*\n"
375 "*o*o........o*o*\n"
376 "****************\n"
377 "\n"
378 ".******.********\n"
379 "*.....o*.....o.*\n"
380 "*.*.o.*..*...o.*\n"
381 "*..X*...*oo.*o.*\n"
382 ".*.*...*.o..x*.*\n"
383 "*o.......*..*o.*\n"
384 ".*......o.....*.\n"
385 "*o............o*\n"
386 "****************\n"
387 "\n"
388 "****************\n"
389 "**.x*o.o......o*\n"
390 "*o.Xo*o.......**\n"
391 "**.***........**\n"
392 "**.....o*o*....*\n"
393 "*oo.......o*o..*\n"
394 "**.o....****o..*\n"
395 "**o*..*........*\n"
396 "****************\n"
397 "\n"
398 "****************\n"
399 "*.o*........*X.*\n"
400 "*.*..o*oo*o..*.*\n"
401 "*....*o**o*.o..*\n"
402 "*.o*.......o*..*\n"
403 "*..o*o....o*...*\n"
404 "*.*..*.**o*..*.*\n"
405 "*....o.*o...x..*\n"
406 "****************\n"
407 "\n"
408 "****************\n"
409 "*.o....o..x*...*\n"
410 "*..*o*o...*o...*\n"
411 "*...*o*....*o..*\n"
412 "*...o..*...o*o.*\n"
413 "*.*o*...*.o*...*\n"
414 "*.o*o.*.o.*....*\n"
415 "*o*X..*.....*..*\n"
416 "****************\n"
417 "\n"
418 "****************\n"
419 "*o...**.....**o*\n"
420 "*.*..*......*o.*\n"
421 "*.o*...o**..o..*\n"
422 "*.*....*o......*\n"
423 "*....*...o*....*\n"
424 "*.**.o*.**o..*x*\n"
425 "*.o*.*o.....**X*\n"
426 "****************\n"
427 "\n"
428 "****************\n"
429 "*...o*o........*\n"
430 "**o..o*.**o...**\n"
431 "*.*.*.o...*..*.*\n"
432 "*.x.*..**..*.Xo*\n"
433 "*.*..*...o.*.*.*\n"
434 "**...o**.*o..o**\n"
435 "*........o*o...*\n"
436 "****************";
439 * Display text.
441 void star_display_text(char *str, bool waitkey)
443 int chars_by_line;
444 int lines_by_screen;
445 int chars_for_line;
446 int current_line = 0;
447 int first_char_index = 0;
448 char *ptr_char;
449 char *ptr_line;
450 int i;
451 char line[255];
452 int key;
453 bool go_on;
455 rb->lcd_clear_display();
457 chars_by_line = LCD_WIDTH / char_width;
458 lines_by_screen = LCD_HEIGHT / char_height;
462 ptr_char = str + first_char_index;
463 chars_for_line = 0;
464 i = 0;
465 ptr_line = line;
466 while (i < chars_by_line)
468 switch (*ptr_char)
470 case '\t':
471 case ' ':
472 *(ptr_line++) = ' ';
473 case '\n':
474 case '\0':
475 chars_for_line = i;
476 break;
478 default:
479 *(ptr_line++) = *ptr_char;
481 if (*ptr_char == '\n' || *ptr_char == '\0')
482 break;
483 ptr_char++;
484 i++;
487 if (chars_for_line == 0)
488 chars_for_line = i;
490 line[chars_for_line] = '\0';
492 /* test if we have cut a word. If it is the case we don't have to */
493 /* skip the space */
494 if (i == chars_by_line && chars_for_line == chars_by_line)
495 first_char_index += chars_for_line;
496 else
497 first_char_index += chars_for_line + 1;
499 /* print the line on the screen */
500 rb->lcd_putsxy(0, current_line * char_height, line);
502 /* if the number of line showed on the screen is equals to the */
503 /* maximum number of line we can show, we wait for a key pressed to */
504 /* clear and show the remaining text. */
505 current_line++;
506 if (current_line == lines_by_screen || *ptr_char == '\0')
508 current_line = 0;
509 rb->lcd_update();
510 go_on = false;
511 while (waitkey && !go_on)
513 key = rb->button_get(true);
514 switch (key)
516 case STAR_QUIT:
517 case BUTTON_LEFT:
518 case STAR_DOWN:
519 go_on = true;
520 break;
522 default:
523 if (rb->default_event_handler(key) == SYS_USB_CONNECTED)
525 usb_detected = true;
526 go_on = true;
527 break;
531 rb->lcd_clear_display();
533 } while (*ptr_char != '\0');
537 * Do a pretty transition from one level to another.
539 static void star_transition_update(void)
541 const int center_x = LCD_WIDTH / 2;
542 const int center_y = LCD_HEIGHT / 2;
543 int x = 0;
544 int y = 0;
545 #if LCD_WIDTH >= LCD_HEIGHT
546 #if defined(IPOD_VIDEO)
547 const int step = 4;
548 #else
549 const int step = 1;
550 #endif
551 const int lcd_demi_width = LCD_WIDTH / 2;
552 int var_y = 0;
554 for (; x < lcd_demi_width ; x+=step)
556 var_y += LCD_HEIGHT;
557 if (var_y > LCD_WIDTH)
559 var_y -= LCD_WIDTH;
560 y+=step;
562 if( x )
564 rb->lcd_update_rect(center_x - x, center_y - y, x*2, step);
565 rb->lcd_update_rect(center_x - x, center_y + y - step, x*2, step);
567 if( y )
569 rb->lcd_update_rect(center_x - x, center_y - y, step, y*2);
570 rb->lcd_update_rect(center_x + x - step, center_y - y, step, y*2);
572 STAR_SLEEP
574 #else
575 int lcd_demi_height = LCD_HEIGHT / 2;
576 int var_x = 0;
578 for (; y < lcd_demi_height ; y++)
580 var_x += LCD_WIDTH;
581 if (var_x > LCD_HEIGHT)
583 var_x -= LCD_HEIGHT;
584 x++;
586 if( x )
588 rb->lcd_update_rect(center_x - x, center_y - y, x * 2, 1);
589 rb->lcd_update_rect(center_x - x, center_y + y - 1, x * 2, 1);
591 if( y )
593 rb->lcd_update_rect(center_x - x, center_y - y, 1, y * 2);
594 rb->lcd_update_rect(center_x + x - 1, center_y - y, 1, y * 2);
596 STAR_SLEEP
598 #endif
599 rb->lcd_update();
603 * Display information board of the current level.
605 static void star_display_board_info(int current_level)
607 int label_pos_y, tile_pos_y;
608 char str_info[32];
610 if (TILE_HEIGHT > char_height)
612 tile_pos_y = LCD_HEIGHT - TILE_HEIGHT;
613 label_pos_y = tile_pos_y + (TILE_HEIGHT - char_height) / 2;
615 else
617 label_pos_y = LCD_HEIGHT - char_height;
618 tile_pos_y = label_pos_y + (char_height - TILE_HEIGHT) / 2;
621 rb->snprintf(str_info, sizeof(str_info), "L:%02d", current_level + 1);
622 rb->lcd_putsxy(STAR_OFFSET_X, label_pos_y, str_info);
623 rb->snprintf(str_info, sizeof(str_info), "S:%02d", star_count);
624 rb->lcd_putsxy(LCD_WIDTH/2 - 2 * char_width, label_pos_y, str_info);
625 rb->lcd_putsxy(STAR_OFFSET_X + (STAR_WIDTH-1) * TILE_WIDTH - 2 * char_width,
626 label_pos_y, "C:");
628 rb->lcd_bitmap_part(star_tiles, 0, control == STAR_CONTROL_BALL ?
629 BALL*TILE_HEIGHT : BLOCK*TILE_HEIGHT, TILE_WIDTH,
630 STAR_OFFSET_X + (STAR_WIDTH-1) * TILE_WIDTH,
631 tile_pos_y, TILE_WIDTH, TILE_HEIGHT);
633 rb->lcd_update_rect(0, MIN(label_pos_y, tile_pos_y), LCD_WIDTH,
634 MAX(TILE_HEIGHT, char_height));
639 * Load a level into board array.
641 static int star_load_level(int current_level)
643 int x, y;
644 char *ptr_tab;
646 if (current_level < 0)
647 current_level = 0;
648 else if (current_level > STAR_LEVEL_COUNT-1)
649 current_level = STAR_LEVEL_COUNT-1;
652 ptr_tab = levels + current_level * STAR_LEVEL_SIZE;
653 control = STAR_CONTROL_BALL;
654 star_count = 0;
656 rb->lcd_clear_display();
658 for (y = 0 ; y < STAR_HEIGHT ; y++)
660 for (x = 0 ; x < STAR_WIDTH ; x++)
662 board[y][x] = *ptr_tab;
663 switch (*ptr_tab)
665 # define DRAW_TILE( a ) \
666 rb->lcd_bitmap_part( star_tiles, 0, \
667 a*TILE_HEIGHT, TILE_WIDTH, \
668 STAR_OFFSET_X + x * TILE_WIDTH, \
669 STAR_OFFSET_Y + y * TILE_HEIGHT, \
670 TILE_WIDTH, TILE_HEIGHT);
671 case STAR_VOID:
672 DRAW_TILE( SPACE );
673 break;
675 case STAR_WALL:
676 DRAW_TILE( WALL );
677 break;
679 case STAR_STAR:
680 DRAW_TILE( STAR );
681 star_count++;
682 break;
684 case STAR_BALL:
685 ball_x = x;
686 ball_y = y;
687 DRAW_TILE( BALL );
688 break;
691 case STAR_BLOCK:
692 block_x = x;
693 block_y = y;
694 DRAW_TILE( BLOCK );
695 break;
697 ptr_tab++;
699 ptr_tab++;
701 star_display_board_info(current_level);
702 star_transition_update();
703 return 1;
706 static void star_animate_tile(int tile_no, int start_x, int start_y,
707 int delta_x, int delta_y)
709 int i;
711 if (delta_x != 0) /* horizontal */
713 for (i = 1 ; i <= TILE_WIDTH ; i++)
715 STAR_SLEEP
716 rb->lcd_bitmap_part(star_tiles, 0, SPACE * TILE_HEIGHT, TILE_WIDTH,
717 start_x, start_y, TILE_WIDTH, TILE_HEIGHT);
718 rb->lcd_bitmap_part(star_tiles, 0, tile_no * TILE_HEIGHT, TILE_WIDTH,
719 start_x + delta_x * i, start_y, TILE_WIDTH, TILE_HEIGHT);
720 rb->lcd_update_rect(start_x + delta_x * i - (delta_x>0?1:0),
721 start_y, TILE_WIDTH + 1, TILE_HEIGHT);
724 else /* vertical */
726 for (i = 1 ; i <= TILE_HEIGHT ; i++)
728 STAR_SLEEP
729 rb->lcd_bitmap_part(star_tiles, 0, SPACE * TILE_HEIGHT, TILE_WIDTH,
730 start_x, start_y, TILE_WIDTH, TILE_HEIGHT);
731 rb->lcd_bitmap_part(star_tiles, 0, tile_no * TILE_HEIGHT, TILE_WIDTH,
732 start_x, start_y + delta_y * i, TILE_WIDTH, TILE_HEIGHT);
733 rb->lcd_update_rect(start_x, start_y + delta_y * i - (delta_y>0?1:0),
734 TILE_WIDTH, TILE_HEIGHT + 1);
740 * Run the game.
742 static int star_run_game(int current_level)
744 int move_x = 0;
745 int move_y = 0;
746 int key;
747 int lastkey = BUTTON_NONE;
749 int label_offset_y;
751 label_offset_y = LCD_HEIGHT - char_height;
753 if (!star_load_level(current_level))
754 return 0;
756 while (true)
758 move_x = 0;
759 move_y = 0;
761 while ((move_x == 0) && (move_y == 0))
763 key = rb->button_get(true);
764 switch (key)
766 #ifdef STAR_RC_QUIT
767 case STAR_RC_QUIT:
768 #endif
769 case STAR_QUIT:
770 return -1;
772 case BUTTON_LEFT:
773 move_x = -1;
774 break;
776 case BUTTON_RIGHT:
777 move_x = 1;
778 break;
780 case STAR_UP:
781 move_y = -1;
782 break;
784 case STAR_DOWN:
785 move_y = 1;
786 break;
788 case STAR_LEVEL_DOWN:
789 #ifdef STAR_LEVEL_DOWN_PRE
790 if (lastkey != STAR_LEVEL_DOWN_PRE)
791 break;
792 #endif
793 if (current_level > 0)
795 current_level--;
796 star_load_level(current_level);
798 break;
800 case STAR_LEVEL_REPEAT:
801 star_load_level(current_level);
802 break;
804 case STAR_LEVEL_UP:
805 #ifdef STAR_LEVEL_UP_PRE
806 if (lastkey != STAR_LEVEL_UP_PRE)
807 break;
808 #endif
809 if (current_level < STAR_LEVEL_COUNT - 1)
811 current_level++;
812 star_load_level(current_level);
814 break;
816 case STAR_TOGGLE_CONTROL:
817 #ifdef STAR_TOGGLE_CONTROL_PRE
818 if (lastkey != STAR_TOGGLE_CONTROL_PRE)
819 break;
820 #endif
821 #ifdef STAR_TOGGLE_CONTROL2
822 case STAR_TOGGLE_CONTROL2:
823 #endif
824 if (control == STAR_CONTROL_BALL)
825 control = STAR_CONTROL_BLOCK;
826 else
827 control = STAR_CONTROL_BALL;
828 star_display_board_info(current_level);
829 break;
831 default:
832 if (rb->default_event_handler(key) == SYS_USB_CONNECTED)
834 usb_detected = true;
835 return 0;
837 break;
839 if (key != BUTTON_NONE)
840 lastkey = key;
843 if (control == STAR_CONTROL_BALL)
845 board[ball_y][ball_x] = STAR_VOID;
846 while ((board[ball_y + move_y][ball_x + move_x] == STAR_VOID
847 || board[ball_y + move_y][ball_x + move_x] == STAR_STAR))
850 star_animate_tile(BALL, STAR_OFFSET_X + ball_x * TILE_WIDTH,
851 STAR_OFFSET_Y + ball_y * TILE_HEIGHT,
852 move_x, move_y);
853 ball_x += move_x;
854 ball_y += move_y;
856 if (board[ball_y][ball_x] == STAR_STAR)
858 board[ball_y][ball_x] = STAR_VOID;
859 star_count--;
861 star_display_board_info(current_level);
864 board[ball_y][ball_x] = STAR_BALL;
866 else
868 board[block_y][block_x] = STAR_VOID;
869 while (board[block_y + move_y][block_x + move_x] == STAR_VOID)
871 star_animate_tile(BLOCK, STAR_OFFSET_X + block_x * TILE_WIDTH,
872 STAR_OFFSET_Y + block_y * TILE_HEIGHT,
873 move_x, move_y);
874 block_x += move_x;
875 block_y += move_y;
877 board[block_y][block_x] = STAR_BLOCK;
880 if (star_count == 0)
882 current_level++;
883 if (current_level == STAR_LEVEL_COUNT)
885 rb->lcd_clear_display();
886 star_display_text("Congratulations!", true);
887 rb->lcd_update();
889 /* There is no such level as STAR_LEVEL_COUNT so it can't be the
890 * current_level */
891 current_level--;
892 return 1;
894 star_load_level(current_level);
900 * Display the choice menu.
902 static int star_menu(void)
904 int selection, level=1;
905 bool menu_quit = false;
907 /* get the size of char */
908 rb->lcd_getstringsize("a", &char_width, &char_height);
910 MENUITEM_STRINGLIST(menu,"Star Menu",NULL,"Play","Choose Level",
911 "Information","Keys","Quit");
913 while(!menu_quit)
915 switch(rb->do_menu(&menu, &selection))
917 case 0:
918 menu_quit = true;
919 break;
920 case 1:
921 rb->set_int("Level", "", UNIT_INT, &level,
922 NULL, 1, 1, STAR_LEVEL_COUNT, NULL );
923 break;
924 case 2:
925 star_display_text(
926 "INFO\n\n"
927 "Take all the stars to go to the next level. "
928 "You can toggle control with the block to "
929 "use it as a mobile wall. The block cannot "
930 "take stars.", true);
931 break;
932 case 3:
933 #if CONFIG_KEYPAD == RECORDER_PAD
934 star_display_text("KEYS\n\n"
935 "[ON] Toggle Ctl.\n"
936 "[OFF] Exit\n"
937 "[F1] Prev. level\n"
938 "[F2] Reset level\n"
939 "[F3] Next level", true);
940 #elif CONFIG_KEYPAD == ONDIO_PAD
941 star_display_text("KEYS\n\n"
942 "[MODE] Toggle Ctl\n"
943 "[OFF] Exit\n"
944 "[M <] Prev. level\n"
945 "[M ^] Reset level\n"
946 "[M >] Next level", true);
947 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
948 star_display_text("KEYS\n\n"
949 "[MODE/NAVI] Toggle Ctrl\n"
950 "[OFF] Exit\n"
951 "[ON + LEFT] Prev. level\n"
952 "[ON + NAVI] Reset level\n"
953 "[ON + RIGHT] Next level", true);
954 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
955 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
956 star_display_text("KEYS\n\n"
957 "[SELECT] Toggle Ctl\n"
958 "[S + MENU] Exit\n"
959 "[S <] Prev. level\n"
960 "[S + PLAY] Reset level\n"
961 "[S >] Next level", true);
962 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
963 star_display_text("KEYS\n\n"
964 "[SELECT] Toggle Ctl\n"
965 "[POWER] Exit\n"
966 "[REC..] Prev. level\n"
967 "[PLAY] Reset level\n"
968 "[REC] Next level", true);
969 #elif CONFIG_KEYPAD == GIGABEAT_PAD
970 star_display_text("KEYS\n\n"
971 "[MENU] Toggle Control\n"
972 "[A] Exit\n"
973 "[PWR+DOWN] Prev. level\n"
974 "[PWR+RIGHT] Reset level\n"
975 "[PWR+UP] Next level", true);
976 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
977 star_display_text("KEYS\n\n"
978 "[REW] Toggle Ctl\n"
979 "[POWER] Exit\n"
980 "[PLAY+DOWN] Prev. level\n"
981 "[PLAY+RIGHT] Reset level\n"
982 "[PLAY+UP] Next level", true);
983 #endif
984 break;
985 default:
986 menu_quit = true;
987 break;
991 if (selection == MENU_START)
993 rb->lcd_setfont(FONT_SYSFIXED);
994 rb->lcd_getstringsize("a", &char_width, &char_height);
995 level--;
996 star_run_game(level);
999 return PLUGIN_OK;
1003 * Main entry point
1005 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
1007 (void)parameter;
1008 rb = api;
1010 #if LCD_DEPTH > 1
1011 rb->lcd_set_backdrop(NULL);
1012 rb->lcd_set_background( LCD_BLACK );
1013 rb->lcd_set_foreground( LCD_WHITE );
1014 #endif
1016 /* display choice menu */
1017 return star_menu();
1020 #endif