Accept FS#7228 by Dagni McPhee enable pitchscreen on sansa
[Rockbox.git] / apps / plugins / star.c
blob2e27fd280b34bb5f8ea46861dc6be2ca263f46cb
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)
110 #define STAR_QUIT (BUTTON_SELECT | BUTTON_MENU)
111 #define STAR_UP BUTTON_MENU
112 #define STAR_DOWN BUTTON_PLAY
113 #define STAR_TOGGLE_CONTROL_PRE BUTTON_SELECT
114 #define STAR_TOGGLE_CONTROL (BUTTON_SELECT | BUTTON_REL)
115 #define STAR_LEVEL_UP (BUTTON_SELECT | BUTTON_RIGHT)
116 #define STAR_LEVEL_DOWN (BUTTON_SELECT | BUTTON_LEFT)
117 #define STAR_LEVEL_REPEAT (BUTTON_SELECT | BUTTON_PLAY)
118 #define STAR_MENU_RUN BUTTON_RIGHT
119 #define STAR_MENU_RUN2 BUTTON_SELECT
121 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
123 #define STAR_QUIT BUTTON_POWER
124 #define STAR_UP BUTTON_UP
125 #define STAR_DOWN BUTTON_DOWN
126 #define STAR_TOGGLE_CONTROL BUTTON_SELECT
127 #define STAR_LEVEL_UP_PRE BUTTON_REC
128 #define STAR_LEVEL_UP (BUTTON_REC|BUTTON_REL)
129 #define STAR_LEVEL_DOWN_PRE BUTTON_REC
130 #define STAR_LEVEL_DOWN (BUTTON_REC|BUTTON_REPEAT)
131 #define STAR_LEVEL_REPEAT BUTTON_PLAY
132 #define STAR_MENU_RUN BUTTON_RIGHT
133 #define STAR_MENU_RUN2 BUTTON_SELECT
135 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
137 #define STAR_QUIT BUTTON_POWER
138 #define STAR_UP BUTTON_UP
139 #define STAR_DOWN BUTTON_DOWN
140 #define STAR_TOGGLE_CONTROL BUTTON_SELECT
141 #define STAR_LEVEL_UP BUTTON_VOL_UP
142 #define STAR_LEVEL_DOWN BUTTON_VOL_DOWN
143 #define STAR_LEVEL_REPEAT BUTTON_A
144 #define STAR_MENU_RUN BUTTON_SELECT
146 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
148 #define STAR_QUIT BUTTON_POWER
149 #define STAR_UP BUTTON_UP
150 #define STAR_DOWN BUTTON_DOWN
151 #define STAR_TOGGLE_CONTROL BUTTON_SELECT
152 #define STAR_LEVEL_UP (BUTTON_SELECT | BUTTON_RIGHT)
153 #define STAR_LEVEL_DOWN (BUTTON_SELECT | BUTTON_LEFT)
154 #define STAR_LEVEL_REPEAT (BUTTON_SELECT | BUTTON_DOWN)
155 #define STAR_MENU_RUN BUTTON_SELECT
158 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
160 #define STAR_QUIT BUTTON_POWER
161 #define STAR_UP BUTTON_SCROLL_UP
162 #define STAR_DOWN BUTTON_SCROLL_DOWN
163 #define STAR_TOGGLE_CONTROL BUTTON_REW
164 #define STAR_LEVEL_UP (BUTTON_PLAY | BUTTON_SCROLL_UP)
165 #define STAR_LEVEL_DOWN (BUTTON_PLAY | BUTTON_SCROLL_DOWN)
166 #define STAR_LEVEL_REPEAT (BUTTON_PLAY | BUTTON_RIGHT)
167 #define STAR_MENU_RUN BUTTON_FF
169 #endif
171 /* function returns because of USB? */
172 static bool usb_detected = false;
174 /* position of the ball */
175 static int ball_x, ball_y;
177 /* position of the block */
178 static int block_x, block_y;
180 /* number of stars to get to finish the level */
181 static int star_count;
183 /* the object we control : ball or block */
184 static int control;
186 /* the current board */
187 static char board[STAR_HEIGHT][STAR_WIDTH];
189 #include "star_tiles.h"
191 #define TILE_WIDTH BMPWIDTH_star_tiles
192 #define TILE_HEIGHT (BMPHEIGHT_star_tiles/5)
193 #define STAR_OFFSET_X ((LCD_WIDTH - STAR_WIDTH * TILE_WIDTH) / 2)
194 #define STAR_OFFSET_Y ((LCD_HEIGHT - STAR_HEIGHT * TILE_HEIGHT - MAX(TILE_HEIGHT, 8)) / 2)
196 #define WALL 0
197 #define SPACE 1
198 #define BLOCK 2
199 #define STAR 3
200 #define BALL 4
202 #define MENU_START 0
204 /* char font size */
205 static int char_width = -1;
206 static int char_height = -1;
208 static struct plugin_api* rb;
210 /* this arrays contains a group of levels loaded into memory */
211 static unsigned char* levels =
212 "****************\n"
213 "*X**........o*x*\n"
214 "*..........o.***\n"
215 "*.......**o....*\n"
216 "*...**.o......**\n"
217 "**.o..o.....o..*\n"
218 "*.o......o**.o.*\n"
219 "*.....**o.....o*\n"
220 "****************\n"
221 "\n"
222 ".*..*.*.*...*.**\n"
223 "*...o.........X*\n"
224 "...*o..*o...o...\n"
225 "*.*.o.....o..*.*\n"
226 "......*...o...*.\n"
227 "*....*x*..o....*\n"
228 "...*..*.*...*oo*\n"
229 "*.............*.\n"
230 ".*..*........*..\n"
231 "\n"
232 "****************\n"
233 "*...........o*x*\n"
234 "*...**......**X*\n"
235 "*...*o.........*\n"
236 "*.o.....o**...o*\n"
237 "*.*o..o..o*..o**\n"
238 "*.**o.*o..o.o***\n"
239 "*o....**o......*\n"
240 "****************\n"
241 "\n"
242 "****************\n"
243 "*............*x*\n"
244 "*.....*........*\n"
245 "**o*o.o*o*o*o*o*\n"
246 "*.*.*o.o*.*.*.**\n"
247 "**o*o*o.o*o*o*o*\n"
248 "*.....*........*\n"
249 "*...*.......*X.*\n"
250 "****************\n"
251 "\n"
252 ".**************.\n"
253 "*X..*...*..*...*\n"
254 "*..*o.*.o..o.*.*\n"
255 "**......*..*...*\n"
256 "*o.*o*........**\n"
257 "**.....*.o.*...*\n"
258 "*o*..*.*.*...*x*\n"
259 "*...*....o*..*o*\n"
260 ".**************.\n"
261 "\n"
262 "....************\n"
263 "...*...o...*o.o*\n"
264 "..*....o....*.**\n"
265 ".*.....o.......*\n"
266 "*X.....o.......*\n"
267 "**.....o..*...**\n"
268 "*......o....*..*\n"
269 "*x.*...o..**o..*\n"
270 "****************\n"
271 "\n"
272 "****************\n"
273 "*..............*\n"
274 ".**.***..*o.**o*\n"
275 ".*o..*o.*.*.*.*.\n"
276 "..*..*..***.**..\n"
277 ".**..*..*o*.*o**\n"
278 "*..............*\n"
279 "*..X*o....x..*o*\n"
280 "****************\n"
281 "\n"
282 "***************.\n"
283 "*..o**.........*\n"
284 "*..*o..**.o....*\n"
285 "*..o**.*.*o....*\n"
286 "**.....**..*o*.*\n"
287 "**.*.......o*o.*\n"
288 "*oxo*...o..*X*.*\n"
289 "**.............*\n"
290 ".***************\n"
291 "\n"
292 "..*.***********.\n"
293 ".*o*o......*..X*\n"
294 "*o.o*....o....*.\n"
295 ".*.*..o**..o*..*\n"
296 "*..*o.*oxo....o*\n"
297 "*.....o**.....*.\n"
298 "*o*o.........*..\n"
299 "*...........*...\n"
300 ".***********....\n"
301 "\n"
302 "....***********.\n"
303 "*****.o........*\n"
304 "*...x.***o.o*.o*\n"
305 "*.o...*o.*o...*.\n"
306 "*.....*..o..*.o*\n"
307 "*o*o..*.o*..*X*.\n"
308 ".*o...***..***..\n"
309 "*.........*.*.*.\n"
310 ".*********..*..*\n"
311 "\n"
312 "****************\n"
313 "*......*......X*\n"
314 "*..*oo.....oo.**\n"
315 "**...o...**...o*\n"
316 "*o....*o*oo..***\n"
317 "**.**....**....*\n"
318 "*o..o*.o....x.o*\n"
319 "**o***....*...**\n"
320 "***************.\n"
321 "\n"
322 "**.....**..****.\n"
323 "*X*****o.***.o**\n"
324 "*....oo.....o..*\n"
325 "*.**..**o..*o*.*\n"
326 "*.*.o.*.*o.**..*\n"
327 "*.**..**...*x*.*\n"
328 "*.....o........*\n"
329 "*........o.....*\n"
330 "****************\n"
331 "\n"
332 ".**************.\n"
333 "*.X*........o.**\n"
334 "*.*...*o...o**.*\n"
335 "*.......o....*.*\n"
336 "*.o..........*o*\n"
337 "*.*......o.....*\n"
338 "**......o.o..*o*\n"
339 "*x..*....o.*.*.*\n"
340 ".**************.\n"
341 "\n"
342 "****************\n"
343 "*o*o........o*o*\n"
344 "*.o*X......**..*\n"
345 "*.x........o...*\n"
346 "*........o*....*\n"
347 "*......o.......*\n"
348 "*.o*........*..*\n"
349 "*o*o........o*o*\n"
350 "****************\n"
351 "\n"
352 ".******.********\n"
353 "*.....o*.....o.*\n"
354 "*.*.o.*..*...o.*\n"
355 "*..X*...*oo.*o.*\n"
356 ".*.*...*.o..x*.*\n"
357 "*o.......*..*o.*\n"
358 ".*......o.....*.\n"
359 "*o............o*\n"
360 "****************\n"
361 "\n"
362 "****************\n"
363 "**.x*o.o......o*\n"
364 "*o.Xo*o.......**\n"
365 "**.***........**\n"
366 "**.....o*o*....*\n"
367 "*oo.......o*o..*\n"
368 "**.o....****o..*\n"
369 "**o*..*........*\n"
370 "****************\n"
371 "\n"
372 "****************\n"
373 "*.o*........*X.*\n"
374 "*.*..o*oo*o..*.*\n"
375 "*....*o**o*.o..*\n"
376 "*.o*.......o*..*\n"
377 "*..o*o....o*...*\n"
378 "*.*..*.**o*..*.*\n"
379 "*....o.*o...x..*\n"
380 "****************\n"
381 "\n"
382 "****************\n"
383 "*.o....o..x*...*\n"
384 "*..*o*o...*o...*\n"
385 "*...*o*....*o..*\n"
386 "*...o..*...o*o.*\n"
387 "*.*o*...*.o*...*\n"
388 "*.o*o.*.o.*....*\n"
389 "*o*X..*.....*..*\n"
390 "****************\n"
391 "\n"
392 "****************\n"
393 "*o...**.....**o*\n"
394 "*.*..*......*o.*\n"
395 "*.o*...o**..o..*\n"
396 "*.*....*o......*\n"
397 "*....*...o*....*\n"
398 "*.**.o*.**o..*x*\n"
399 "*.o*.*o.....**X*\n"
400 "****************\n"
401 "\n"
402 "****************\n"
403 "*...o*o........*\n"
404 "**o..o*.**o...**\n"
405 "*.*.*.o...*..*.*\n"
406 "*.x.*..**..*.Xo*\n"
407 "*.*..*...o.*.*.*\n"
408 "**...o**.*o..o**\n"
409 "*........o*o...*\n"
410 "****************";
413 * Display text.
415 void star_display_text(char *str, bool waitkey)
417 int chars_by_line;
418 int lines_by_screen;
419 int chars_for_line;
420 int current_line = 0;
421 int first_char_index = 0;
422 char *ptr_char;
423 char *ptr_line;
424 int i;
425 char line[255];
426 int key;
427 bool go_on;
429 rb->lcd_clear_display();
431 chars_by_line = LCD_WIDTH / char_width;
432 lines_by_screen = LCD_HEIGHT / char_height;
436 ptr_char = str + first_char_index;
437 chars_for_line = 0;
438 i = 0;
439 ptr_line = line;
440 while (i < chars_by_line)
442 switch (*ptr_char)
444 case '\t':
445 case ' ':
446 *(ptr_line++) = ' ';
447 case '\n':
448 case '\0':
449 chars_for_line = i;
450 break;
452 default:
453 *(ptr_line++) = *ptr_char;
455 if (*ptr_char == '\n' || *ptr_char == '\0')
456 break;
457 ptr_char++;
458 i++;
461 if (chars_for_line == 0)
462 chars_for_line = i;
464 line[chars_for_line] = '\0';
466 /* test if we have cut a word. If it is the case we don't have to */
467 /* skip the space */
468 if (i == chars_by_line && chars_for_line == chars_by_line)
469 first_char_index += chars_for_line;
470 else
471 first_char_index += chars_for_line + 1;
473 /* print the line on the screen */
474 rb->lcd_putsxy(0, current_line * char_height, line);
476 /* if the number of line showed on the screen is equals to the */
477 /* maximum number of line we can show, we wait for a key pressed to */
478 /* clear and show the remaining text. */
479 current_line++;
480 if (current_line == lines_by_screen || *ptr_char == '\0')
482 current_line = 0;
483 rb->lcd_update();
484 go_on = false;
485 while (waitkey && !go_on)
487 key = rb->button_get(true);
488 switch (key)
490 case STAR_QUIT:
491 case BUTTON_LEFT:
492 case STAR_DOWN:
493 go_on = true;
494 break;
496 default:
497 if (rb->default_event_handler(key) == SYS_USB_CONNECTED)
499 usb_detected = true;
500 go_on = true;
501 break;
505 rb->lcd_clear_display();
507 } while (*ptr_char != '\0');
511 * Do a pretty transition from one level to another.
513 #if !defined(GIGABEAT_F) || defined(SIMULATOR)
514 /* FIXME: this crashes on the Gigabeat but not in the sim */
515 static void star_transition_update(void)
517 int center_x = LCD_WIDTH / 2;
518 int center_y = LCD_HEIGHT / 2;
519 int x = 0;
520 int y = 0;
521 #if LCD_WIDTH >= LCD_HEIGHT
522 int lcd_demi_width = LCD_WIDTH / 2;
523 int var_y = 0;
525 for (; x < lcd_demi_width ; x++)
527 var_y += LCD_HEIGHT;
528 if (var_y > LCD_WIDTH)
530 var_y -= LCD_WIDTH;
531 y++;
533 rb->lcd_update_rect(center_x - x, center_y - y, x * 2, 1);
534 rb->lcd_update_rect(center_x - x, center_y - y, 1, y * 2);
535 rb->lcd_update_rect(center_x + x - 1, center_y - y, 1, y * 2);
536 rb->lcd_update_rect(center_x - x, center_y + y - 1, x * 2, 1);
537 STAR_SLEEP
539 #else
540 int lcd_demi_height = LCD_HEIGHT / 2;
541 int var_x = 0;
543 for (; y < lcd_demi_height ; y++)
545 var_x += LCD_WIDTH;
546 if (var_x > LCD_HEIGHT)
548 var_x -= LCD_HEIGHT;
549 x++;
551 rb->lcd_update_rect(center_x - x, center_y - y, x * 2, 1);
552 rb->lcd_update_rect(center_x - x, center_y - y, 1, y * 2);
553 rb->lcd_update_rect(center_x + x - 1, center_y - y, 1, y * 2);
554 rb->lcd_update_rect(center_x - x, center_y + y - 1, x * 2, 1);
555 STAR_SLEEP
557 #endif
558 rb->lcd_update();
560 #endif
563 * Display information board of the current level.
565 static void star_display_board_info(int current_level)
567 int label_pos_y, tile_pos_y;
568 char str_info[32];
570 if (TILE_HEIGHT > char_height)
572 tile_pos_y = LCD_HEIGHT - TILE_HEIGHT;
573 label_pos_y = tile_pos_y + (TILE_HEIGHT - char_height) / 2;
575 else
577 label_pos_y = LCD_HEIGHT - char_height;
578 tile_pos_y = label_pos_y + (char_height - TILE_HEIGHT) / 2;
581 rb->snprintf(str_info, sizeof(str_info), "L:%02d", current_level + 1);
582 rb->lcd_putsxy(STAR_OFFSET_X, label_pos_y, str_info);
583 rb->snprintf(str_info, sizeof(str_info), "S:%02d", star_count);
584 rb->lcd_putsxy(LCD_WIDTH/2 - 2 * char_width, label_pos_y, str_info);
585 rb->lcd_putsxy(STAR_OFFSET_X + (STAR_WIDTH-1) * TILE_WIDTH - 2 * char_width,
586 label_pos_y, "C:");
588 rb->lcd_bitmap_part(star_tiles, 0, control == STAR_CONTROL_BALL ?
589 BALL*TILE_HEIGHT : BLOCK*TILE_HEIGHT, TILE_WIDTH,
590 STAR_OFFSET_X + (STAR_WIDTH-1) * TILE_WIDTH,
591 tile_pos_y, TILE_WIDTH, TILE_HEIGHT);
593 rb->lcd_update_rect(0, MIN(label_pos_y, tile_pos_y), LCD_WIDTH,
594 MAX(TILE_HEIGHT, char_height));
599 * Load a level into board array.
601 static int star_load_level(int current_level)
603 int x, y;
604 char *ptr_tab;
606 if (current_level < 0)
607 current_level = 0;
608 else if (current_level > STAR_LEVEL_COUNT-1)
609 current_level = STAR_LEVEL_COUNT-1;
612 ptr_tab = levels + current_level * STAR_LEVEL_SIZE;
613 control = STAR_CONTROL_BALL;
614 star_count = 0;
616 rb->lcd_clear_display();
618 for (y = 0 ; y < STAR_HEIGHT ; y++)
620 for (x = 0 ; x < STAR_WIDTH ; x++)
622 board[y][x] = *ptr_tab;
623 switch (*ptr_tab)
625 # define DRAW_TILE( a ) \
626 rb->lcd_bitmap_part( star_tiles, 0, \
627 a*TILE_HEIGHT, TILE_WIDTH, \
628 STAR_OFFSET_X + x * TILE_WIDTH, \
629 STAR_OFFSET_Y + y * TILE_HEIGHT, \
630 TILE_WIDTH, TILE_HEIGHT);
631 case STAR_VOID:
632 DRAW_TILE( SPACE );
633 break;
635 case STAR_WALL:
636 DRAW_TILE( WALL );
637 break;
639 case STAR_STAR:
640 DRAW_TILE( STAR );
641 star_count++;
642 break;
644 case STAR_BALL:
645 ball_x = x;
646 ball_y = y;
647 DRAW_TILE( BALL );
648 break;
651 case STAR_BLOCK:
652 block_x = x;
653 block_y = y;
654 DRAW_TILE( BLOCK );
655 break;
657 ptr_tab++;
659 ptr_tab++;
661 star_display_board_info(current_level);
662 #if !defined(GIGABEAT_F) || defined(SIMULATOR)
663 star_transition_update();
664 #else
665 rb->lcd_update();
666 #endif
667 return 1;
670 static void star_animate_tile(int tile_no, int start_x, int start_y,
671 int delta_x, int delta_y)
673 int i;
675 if (delta_x != 0) /* horizontal */
677 for (i = 1 ; i <= TILE_WIDTH ; i++)
679 STAR_SLEEP
680 rb->lcd_bitmap_part(star_tiles, 0, SPACE * TILE_HEIGHT, TILE_WIDTH,
681 start_x, start_y, TILE_WIDTH, TILE_HEIGHT);
682 rb->lcd_bitmap_part(star_tiles, 0, tile_no * TILE_HEIGHT, TILE_WIDTH,
683 start_x + delta_x * i, start_y, TILE_WIDTH, TILE_HEIGHT);
684 rb->lcd_update_rect(start_x + delta_x * i - (delta_x>0?1:0),
685 start_y, TILE_WIDTH + 1, TILE_HEIGHT);
688 else /* vertical */
690 for (i = 1 ; i <= TILE_HEIGHT ; i++)
692 STAR_SLEEP
693 rb->lcd_bitmap_part(star_tiles, 0, SPACE * TILE_HEIGHT, TILE_WIDTH,
694 start_x, start_y, TILE_WIDTH, TILE_HEIGHT);
695 rb->lcd_bitmap_part(star_tiles, 0, tile_no * TILE_HEIGHT, TILE_WIDTH,
696 start_x, start_y + delta_y * i, TILE_WIDTH, TILE_HEIGHT);
697 rb->lcd_update_rect(start_x, start_y + delta_y * i - (delta_y>0?1:0),
698 TILE_WIDTH, TILE_HEIGHT + 1);
704 * Run the game.
706 static int star_run_game(int current_level)
708 int move_x = 0;
709 int move_y = 0;
710 int key;
711 int lastkey = BUTTON_NONE;
713 int label_offset_y;
715 label_offset_y = LCD_HEIGHT - char_height;
717 if (!star_load_level(current_level))
718 return 0;
720 while (true)
722 move_x = 0;
723 move_y = 0;
725 while ((move_x == 0) && (move_y == 0))
727 key = rb->button_get(true);
728 switch (key)
730 #ifdef STAR_RC_QUIT
731 case STAR_RC_QUIT:
732 #endif
733 case STAR_QUIT:
734 return -1;
736 case BUTTON_LEFT:
737 move_x = -1;
738 break;
740 case BUTTON_RIGHT:
741 move_x = 1;
742 break;
744 case STAR_UP:
745 move_y = -1;
746 break;
748 case STAR_DOWN:
749 move_y = 1;
750 break;
752 case STAR_LEVEL_DOWN:
753 #ifdef STAR_LEVEL_DOWN_PRE
754 if (lastkey != STAR_LEVEL_DOWN_PRE)
755 break;
756 #endif
757 if (current_level > 0)
759 current_level--;
760 star_load_level(current_level);
762 break;
764 case STAR_LEVEL_REPEAT:
765 star_load_level(current_level);
766 break;
768 case STAR_LEVEL_UP:
769 #ifdef STAR_LEVEL_UP_PRE
770 if (lastkey != STAR_LEVEL_UP_PRE)
771 break;
772 #endif
773 if (current_level < STAR_LEVEL_COUNT - 1)
775 current_level++;
776 star_load_level(current_level);
778 break;
780 case STAR_TOGGLE_CONTROL:
781 #ifdef STAR_TOGGLE_CONTROL_PRE
782 if (lastkey != STAR_TOGGLE_CONTROL_PRE)
783 break;
784 #endif
785 #ifdef STAR_TOGGLE_CONTROL2
786 case STAR_TOGGLE_CONTROL2:
787 #endif
788 if (control == STAR_CONTROL_BALL)
789 control = STAR_CONTROL_BLOCK;
790 else
791 control = STAR_CONTROL_BALL;
792 star_display_board_info(current_level);
793 break;
795 default:
796 if (rb->default_event_handler(key) == SYS_USB_CONNECTED)
798 usb_detected = true;
799 return 0;
801 break;
803 if (key != BUTTON_NONE)
804 lastkey = key;
807 if (control == STAR_CONTROL_BALL)
809 board[ball_y][ball_x] = STAR_VOID;
810 while ((board[ball_y + move_y][ball_x + move_x] == STAR_VOID
811 || board[ball_y + move_y][ball_x + move_x] == STAR_STAR))
814 star_animate_tile(BALL, STAR_OFFSET_X + ball_x * TILE_WIDTH,
815 STAR_OFFSET_Y + ball_y * TILE_HEIGHT,
816 move_x, move_y);
817 ball_x += move_x;
818 ball_y += move_y;
820 if (board[ball_y][ball_x] == STAR_STAR)
822 board[ball_y][ball_x] = STAR_VOID;
823 star_count--;
825 star_display_board_info(current_level);
828 board[ball_y][ball_x] = STAR_BALL;
830 else
832 board[block_y][block_x] = STAR_VOID;
833 while (board[block_y + move_y][block_x + move_x] == STAR_VOID)
835 star_animate_tile(BLOCK, STAR_OFFSET_X + block_x * TILE_WIDTH,
836 STAR_OFFSET_Y + block_y * TILE_HEIGHT,
837 move_x, move_y);
838 block_x += move_x;
839 block_y += move_y;
841 board[block_y][block_x] = STAR_BLOCK;
844 if (star_count == 0)
846 current_level++;
847 if (current_level == STAR_LEVEL_COUNT)
849 rb->lcd_clear_display();
850 star_display_text("Congratulations!", true);
851 rb->lcd_update();
853 /* There is no such level as STAR_LEVEL_COUNT so it can't be the
854 * current_level */
855 current_level--;
856 return 1;
858 star_load_level(current_level);
864 * Display the choice menu.
866 static int star_menu(void)
868 int selection, level=1;
869 bool menu_quit = false;
871 /* get the size of char */
872 rb->lcd_getstringsize("a", &char_width, &char_height);
874 MENUITEM_STRINGLIST(menu,"Star Menu",NULL,"Play","Choose Level",
875 "Information","Keys","Quit");
877 while(!menu_quit)
879 switch(rb->do_menu(&menu, &selection))
881 case 0:
882 menu_quit = true;
883 break;
884 case 1:
885 rb->set_int("Level", "", UNIT_INT, &level,
886 NULL, 1, 1, STAR_LEVEL_COUNT, NULL );
887 break;
888 case 2:
889 star_display_text(
890 "INFO\n\n"
891 "Take all the stars to go to the next level. "
892 "You can toggle control with the block to "
893 "use it as a mobile wall. The block cannot "
894 "take stars.", true);
895 break;
896 case 3:
897 #if CONFIG_KEYPAD == RECORDER_PAD
898 star_display_text("KEYS\n\n"
899 "[ON] Toggle Ctl.\n"
900 "[OFF] Exit\n"
901 "[F1] Prev. level\n"
902 "[F2] Reset level\n"
903 "[F3] Next level", true);
904 #elif CONFIG_KEYPAD == ONDIO_PAD
905 star_display_text("KEYS\n\n"
906 "[MODE] Toggle Ctl\n"
907 "[OFF] Exit\n"
908 "[M <] Prev. level\n"
909 "[M ^] Reset level\n"
910 "[M >] Next level", true);
911 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
912 star_display_text("KEYS\n\n"
913 "[MODE/NAVI] Toggle Ctrl\n"
914 "[OFF] Exit\n"
915 "[ON + LEFT] Prev. level\n"
916 "[ON + NAVI] Reset level\n"
917 "[ON + RIGHT] Next level", true);
918 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD)
919 star_display_text("KEYS\n\n"
920 "[SELECT] Toggle Ctl\n"
921 "[S + MENU] Exit\n"
922 "[S <] Prev. level\n"
923 "[S + PLAY] Reset level\n"
924 "[S >] Next level", true);
925 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
926 star_display_text("KEYS\n\n"
927 "[SELECT] Toggle Ctl\n"
928 "[POWER] Exit\n"
929 "[REC..] Prev. level\n"
930 "[PLAY] Reset level\n"
931 "[REC] Next level", true);
932 #elif CONFIG_KEYPAD == GIGABEAT_PAD
933 star_display_text("KEYS\n\n"
934 "[MENU] Toggle Control\n"
935 "[A] Exit\n"
936 "[PWR+DOWN] Prev. level\n"
937 "[PWR+RIGHT] Reset level\n"
938 "[PWR+UP] Next level", true);
939 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
940 star_display_text("KEYS\n\n"
941 "[REW] Toggle Ctl\n"
942 "[POWER] Exit\n"
943 "[PLAY+DOWN] Prev. level\n"
944 "[PLAY+RIGHT] Reset level\n"
945 "[PLAY+UP] Next level", true);
946 #endif
947 break;
948 default:
949 menu_quit = true;
950 break;
954 if (selection == MENU_START)
956 rb->lcd_setfont(FONT_SYSFIXED);
957 rb->lcd_getstringsize("a", &char_width, &char_height);
958 level--;
959 star_run_game(level);
962 return PLUGIN_OK;
966 * Main entry point
968 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
970 (void)parameter;
971 rb = api;
973 #if LCD_DEPTH > 1
974 rb->lcd_set_backdrop(NULL);
975 rb->lcd_set_background( LCD_BLACK );
976 rb->lcd_set_foreground( LCD_WHITE );
977 #endif
979 /* display choice menu */
980 return star_menu();
983 #endif