Fix some quotation marks. Thanks to Alexander Levin for pointing it out.
[Rockbox.git] / apps / plugins / sliding_puzzle.c
blob2c6e249a00a55f512304626c0ce291e0979e1c01
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Vicentini Martin
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 #include "bmp.h"
22 #ifdef HAVE_LCD_BITMAP
23 PLUGIN_HEADER
25 /* variable button definitions */
26 #if CONFIG_KEYPAD == RECORDER_PAD
27 #define PUZZLE_QUIT BUTTON_OFF
28 #define PUZZLE_LEFT BUTTON_LEFT
29 #define PUZZLE_RIGHT BUTTON_RIGHT
30 #define PUZZLE_UP BUTTON_UP
31 #define PUZZLE_DOWN BUTTON_DOWN
32 #define PUZZLE_SHUFFLE BUTTON_F1
33 #define PUZZLE_PICTURE BUTTON_F2
35 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
36 #define PUZZLE_QUIT BUTTON_OFF
37 #define PUZZLE_LEFT BUTTON_LEFT
38 #define PUZZLE_RIGHT BUTTON_RIGHT
39 #define PUZZLE_UP BUTTON_UP
40 #define PUZZLE_DOWN BUTTON_DOWN
41 #define PUZZLE_SHUFFLE BUTTON_F1
42 #define PUZZLE_PICTURE BUTTON_F2
44 #elif CONFIG_KEYPAD == ONDIO_PAD
45 #define PUZZLE_QUIT BUTTON_OFF
46 #define PUZZLE_LEFT BUTTON_LEFT
47 #define PUZZLE_RIGHT BUTTON_RIGHT
48 #define PUZZLE_UP BUTTON_UP
49 #define PUZZLE_DOWN BUTTON_DOWN
50 #define PUZZLE_SHUFFLE_PICTURE_PRE BUTTON_MENU
51 #define PUZZLE_SHUFFLE (BUTTON_MENU | BUTTON_REPEAT)
52 #define PUZZLE_PICTURE (BUTTON_MENU | BUTTON_REL)
54 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
55 (CONFIG_KEYPAD == IRIVER_H300_PAD)
56 #define PUZZLE_QUIT BUTTON_OFF
57 #define PUZZLE_LEFT BUTTON_LEFT
58 #define PUZZLE_RIGHT BUTTON_RIGHT
59 #define PUZZLE_UP BUTTON_UP
60 #define PUZZLE_DOWN BUTTON_DOWN
61 #define PUZZLE_SHUFFLE BUTTON_SELECT
62 #define PUZZLE_PICTURE BUTTON_ON
64 #define PUZZLE_RC_QUIT BUTTON_RC_STOP
66 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
67 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
68 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
69 #define PUZZLE_QUIT (BUTTON_SELECT | BUTTON_MENU)
70 #define PUZZLE_LEFT BUTTON_LEFT
71 #define PUZZLE_RIGHT BUTTON_RIGHT
72 #define PUZZLE_UP BUTTON_MENU
73 #define PUZZLE_DOWN BUTTON_PLAY
74 #define PUZZLE_SHUFFLE (BUTTON_SELECT | BUTTON_LEFT)
75 #define PUZZLE_PICTURE (BUTTON_SELECT | BUTTON_RIGHT)
77 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
78 #define PUZZLE_QUIT BUTTON_POWER
79 #define PUZZLE_LEFT BUTTON_LEFT
80 #define PUZZLE_RIGHT BUTTON_RIGHT
81 #define PUZZLE_UP BUTTON_UP
82 #define PUZZLE_DOWN BUTTON_DOWN
83 #define PUZZLE_SHUFFLE BUTTON_REC
84 #define PUZZLE_PICTURE BUTTON_PLAY
86 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
87 #define PUZZLE_QUIT BUTTON_POWER
88 #define PUZZLE_LEFT BUTTON_LEFT
89 #define PUZZLE_RIGHT BUTTON_RIGHT
90 #define PUZZLE_UP BUTTON_UP
91 #define PUZZLE_DOWN BUTTON_DOWN
92 #define PUZZLE_SHUFFLE BUTTON_SELECT
93 #define PUZZLE_PICTURE BUTTON_A
95 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
96 (CONFIG_KEYPAD == SANSA_C200_PAD)
97 #define PUZZLE_QUIT BUTTON_POWER
98 #define PUZZLE_LEFT BUTTON_LEFT
99 #define PUZZLE_RIGHT BUTTON_RIGHT
100 #define PUZZLE_UP BUTTON_UP
101 #define PUZZLE_DOWN BUTTON_DOWN
102 #define PUZZLE_SHUFFLE BUTTON_REC
103 #define PUZZLE_PICTURE BUTTON_SELECT
105 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
106 #define PUZZLE_QUIT BUTTON_POWER
107 #define PUZZLE_LEFT BUTTON_LEFT
108 #define PUZZLE_RIGHT BUTTON_RIGHT
109 #define PUZZLE_UP BUTTON_SCROLL_UP
110 #define PUZZLE_DOWN BUTTON_SCROLL_DOWN
111 #define PUZZLE_SHUFFLE BUTTON_REW
112 #define PUZZLE_PICTURE BUTTON_PLAY
114 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
115 #define PUZZLE_QUIT BUTTON_BACK
116 #define PUZZLE_LEFT BUTTON_LEFT
117 #define PUZZLE_RIGHT BUTTON_RIGHT
118 #define PUZZLE_UP BUTTON_UP
119 #define PUZZLE_DOWN BUTTON_DOWN
120 #define PUZZLE_SHUFFLE BUTTON_SELECT
121 #define PUZZLE_PICTURE BUTTON_MENU
123 #elif (CONFIG_KEYPAD == MROBE100_PAD)
124 #define PUZZLE_QUIT BUTTON_POWER
125 #define PUZZLE_LEFT BUTTON_LEFT
126 #define PUZZLE_RIGHT BUTTON_RIGHT
127 #define PUZZLE_UP BUTTON_UP
128 #define PUZZLE_DOWN BUTTON_DOWN
129 #define PUZZLE_SHUFFLE BUTTON_SELECT
130 #define PUZZLE_PICTURE BUTTON_DISPLAY
132 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
133 #define PUZZLE_QUIT BUTTON_RC_REC
134 #define PUZZLE_LEFT BUTTON_RC_REW
135 #define PUZZLE_RIGHT BUTTON_RC_FF
136 #define PUZZLE_UP BUTTON_RC_VOL_UP
137 #define PUZZLE_DOWN BUTTON_RC_VOL_DOWN
138 #define PUZZLE_SHUFFLE BUTTON_RC_MODE
139 #define PUZZLE_PICTURE BUTTON_RC_MENU
141 #elif (CONFIG_KEYPAD == COWOND2_PAD)
142 #define PUZZLE_QUIT BUTTON_POWER
143 #define PUZZLE_LEFT BUTTON_LEFT
144 #define PUZZLE_RIGHT BUTTON_RIGHT
145 #define PUZZLE_UP BUTTON_UP
146 #define PUZZLE_DOWN BUTTON_DOWN
147 #define PUZZLE_SHUFFLE BUTTON_MENU
148 #define PUZZLE_PICTURE BUTTON_SELECT
150 #else
151 #error No keymap defined!
152 #endif
155 #include "sliding_puzzle.h"
156 #define IMAGE_WIDTH BMPWIDTH_sliding_puzzle
157 #define IMAGE_HEIGHT BMPHEIGHT_sliding_puzzle
158 #define IMAGE_SIZE IMAGE_WIDTH
160 static struct plugin_api* rb;
162 /* use a square image, (the default Archos bitmap looks square on its display)
163 Puzzle image dimension is min(lcd_height,lcd_width)
164 4x4 is more convenient for square puzzles
165 Note: sliding_puzzle.bmp should be evenly divisible by SPOTS_X
166 and SPOTS_Y, otherwise lcd_bitmap_part stride won't be correct */
167 #define SPOTS_X 4
168 #define SPOTS_Y 4
169 #define SPOTS_WIDTH (IMAGE_WIDTH / SPOTS_X)
170 #define SPOTS_HEIGHT (IMAGE_HEIGHT / SPOTS_Y)
171 #define NUM_SPOTS (SPOTS_X*SPOTS_Y)
172 #define HOLE_ID (NUM_SPOTS)
173 #define INITIAL_HOLE (HOLE_ID-1)
175 enum picmodes
177 PICMODE_NUMERALS = 0,
178 PICMODE_INITIAL_PICTURE,
179 PICMODE_DEFAULT_PICTURE,
180 #ifdef HAVE_ALBUMART
181 PICMODE_ALBUM_ART,
182 #endif
183 // PICMODE_RANDOM,
184 PICMODE_LAST_XXX /* placeholder */
187 static const char* const picmode_descriptions[] = {
188 "Numerals",
189 "Viewer Picture",
190 "Default Picture",
191 #ifdef HAVE_ALBUMART
192 "Album Art",
193 #endif
194 "Shouldn't Get Here",
197 static int spots[NUM_SPOTS];
198 static int hole = INITIAL_HOLE, moves;
199 static unsigned char s[32];
200 static enum picmodes picmode = PICMODE_INITIAL_PICTURE;
201 static int num_font = FONT_UI;
202 static int moves_font = FONT_UI;
203 static int moves_y = 0;
205 static unsigned char img_buf[IMAGE_WIDTH*IMAGE_HEIGHT*sizeof(fb_data)]
206 __attribute__ ((aligned(16)));
207 #if LCD_DEPTH>1
208 static unsigned char temp_img_buf[LCD_WIDTH*LCD_HEIGHT*sizeof(fb_data)]
209 __attribute__ ((aligned(16)));
210 #endif
211 #ifdef HAVE_ALBUMART
212 static char albumart_path[MAX_PATH+1];
213 #endif
214 static char img_buf_path[MAX_PATH+1];
216 static const fb_data * puzzle_bmp_ptr;
217 /* initial_bmp_path points to selected bitmap if this game is launched
218 as a viewer for a .bmp file, or NULL if game is launched regular way */
219 static const char * initial_bmp_path=NULL;
221 #ifdef HAVE_ALBUMART
222 const char * get_albumart_bmp_path(void)
224 struct mp3entry* track = rb->audio_current_track();
226 if (!track || !track->path || track->path[0] == '\0')
227 return NULL;
229 if (!rb->search_albumart_files(track, "", albumart_path, MAX_PATH ) )
230 return NULL;
232 albumart_path[ MAX_PATH ] = '\0';
233 return albumart_path;
235 #endif
237 const char * get_random_bmp_path(void)
239 return(initial_bmp_path);
242 static bool load_resize_bitmap(void)
244 int rc;
245 const char * filename = NULL;
247 /* initially assume using the built-in default */
248 puzzle_bmp_ptr = sliding_puzzle;
250 switch( picmode ){
251 /* some modes don't even need to touch disk and trivially succeed */
252 case PICMODE_NUMERALS:
253 case PICMODE_DEFAULT_PICTURE:
254 default:
255 return(true);
257 #ifdef HAVE_ALBUMART
258 case PICMODE_ALBUM_ART:
259 filename = get_albumart_bmp_path();
260 break;
261 #endif
263 case PICMODE_RANDOM:
264 if(NULL == (filename=get_random_bmp_path()) )
265 filename = initial_bmp_path;
266 break;
268 case PICMODE_INITIAL_PICTURE:
269 filename = initial_bmp_path;
270 break;
273 if( filename != NULL )
275 /* if we already loaded image before, don't touch disk */
276 if( 0 == rb->strcmp( filename, img_buf_path ) )
278 puzzle_bmp_ptr = (const fb_data *)img_buf;
279 return true;
282 struct bitmap main_bitmap;
283 rb->memset(&main_bitmap,0,sizeof(struct bitmap));
284 main_bitmap.data = img_buf;
286 #if LCD_DEPTH>1
287 struct bitmap temp_bitmap;
288 rb->memset(&temp_bitmap,0,sizeof(struct bitmap));
289 temp_bitmap.data = temp_img_buf;
291 main_bitmap.width = IMAGE_WIDTH;
292 main_bitmap.height = IMAGE_HEIGHT;
294 rc = rb->read_bmp_file( filename, &temp_bitmap, sizeof(temp_img_buf),
295 FORMAT_NATIVE );
296 if( rc > 0 )
298 simple_resize_bitmap( &temp_bitmap, &main_bitmap );
299 puzzle_bmp_ptr = (const fb_data *)img_buf;
300 rb->strcpy( img_buf_path, filename );
301 return true;
303 #else
304 rc = rb->read_bmp_file( filename, &main_bitmap, sizeof(img_buf),
305 FORMAT_NATIVE );
306 if( rc > 0 )
308 puzzle_bmp_ptr = (const fb_data *)img_buf;
309 rb->strcpy( img_buf_path, filename );
310 return true;
312 #endif
315 /* something must have failed. get_albumart_bmp_path could return
316 NULL if albumart doesn't exist or couldn't be loaded, or
317 read_bmp_file could have failed. return false and caller should
318 try the next mode (PICMODE_DEFAULT_PICTURE and PICMODE_NUMERALS will
319 always succeed) */
320 return false;
323 /* draws a spot at the coordinates (x,y), range of p is 1-20 */
324 static void draw_spot(int p, int x, int y)
326 int w, h;
328 if (p == HOLE_ID)
330 #if LCD_DEPTH==1
331 /* the bottom-right cell of the default sliding_puzzle image is
332 an appropriate hole graphic */
333 rb->lcd_bitmap_part(sliding_puzzle, ((p-1)%SPOTS_X)*SPOTS_WIDTH,
334 ((p-1)/SPOTS_X)*SPOTS_HEIGHT,
335 IMAGE_WIDTH, x, y, SPOTS_WIDTH, SPOTS_HEIGHT);
336 #else
337 /* just draw a black rectangle */
338 int old_fg = rb->lcd_get_foreground();
339 rb->lcd_set_foreground(LCD_BLACK);
340 rb->lcd_fillrect(x,y,SPOTS_WIDTH,SPOTS_HEIGHT);
341 rb->lcd_set_foreground(old_fg);
342 #endif
344 else if (picmode != PICMODE_NUMERALS)
346 rb->lcd_bitmap_part( puzzle_bmp_ptr, ((p-1)%SPOTS_X)*SPOTS_WIDTH,
347 ((p-1)/SPOTS_X)*SPOTS_HEIGHT,
348 IMAGE_WIDTH, x, y, SPOTS_WIDTH, SPOTS_HEIGHT);
349 } else {
350 rb->lcd_drawrect(x, y, SPOTS_WIDTH, SPOTS_HEIGHT);
351 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
352 rb->lcd_fillrect(x+1, y+1, SPOTS_WIDTH-2, SPOTS_HEIGHT-2);
353 rb->lcd_set_drawmode(DRMODE_SOLID);
354 rb->snprintf(s, sizeof(s), "%d", p);
355 rb->lcd_setfont(num_font);
356 rb->lcd_getstringsize(s, &w, &h);
357 rb->lcd_putsxy(x + (SPOTS_WIDTH/2) - w / 2,
358 y + (SPOTS_HEIGHT/2) - h / 2, s);
362 /* check if the puzzle is solved */
363 static bool puzzle_finished(void)
365 int i;
366 for (i=0; i<NUM_SPOTS; i++)
367 if (spots[i] != (i+1))
368 return false;
369 return true;
372 /* move a piece in any direction */
373 static void move_spot(int x, int y)
375 int i, w;
376 spots[hole] = spots[hole-x-SPOTS_X*y];
377 hole -= (x+SPOTS_X*y);
378 moves++;
379 rb->lcd_setfont(moves_font);
380 #if LCD_WIDTH > LCD_HEIGHT
381 rb->snprintf(s, sizeof(s), "%d", moves);
382 w = rb->lcd_getstringsize(s, NULL, NULL);
383 rb->lcd_putsxy((IMAGE_WIDTH+1+(LCD_WIDTH-IMAGE_WIDTH-1)/2) - w / 2,
384 moves_y, s);
385 #else
386 (void)w;
387 rb->snprintf(s, sizeof(s), "Moves: %d", moves);
388 rb->lcd_putsxy(3, moves_y, s);
389 #endif
390 for(i=1;i<=4;i++)
392 draw_spot(HOLE_ID,
393 (hole%SPOTS_X)*SPOTS_WIDTH,
394 (hole/SPOTS_X)*SPOTS_HEIGHT);
395 draw_spot(spots[hole],
396 (hole%SPOTS_X)*SPOTS_WIDTH + (i*x*SPOTS_WIDTH)/5,
397 (hole/SPOTS_X)*SPOTS_HEIGHT + (i*y*SPOTS_HEIGHT)/5);
398 rb->lcd_update();
399 rb->sleep(HZ/50);
401 draw_spot(HOLE_ID,
402 (hole%SPOTS_X)*SPOTS_WIDTH,
403 (hole/SPOTS_X)*SPOTS_HEIGHT);
404 draw_spot(spots[hole],
405 ((hole%SPOTS_X)+x)*SPOTS_WIDTH,
406 ((hole/SPOTS_X)+y)*SPOTS_HEIGHT);
407 rb->lcd_update();
409 spots[hole] = HOLE_ID;
412 static void draw_playfield(void)
414 int i, w;
416 rb->lcd_clear_display();
417 rb->lcd_setfont(moves_font);
418 #if LCD_WIDTH > LCD_HEIGHT
419 rb->lcd_vline(IMAGE_WIDTH, 0, LCD_HEIGHT-1);
420 w = rb->lcd_getstringsize("Moves", NULL, NULL);
421 rb->lcd_putsxy((IMAGE_WIDTH+1+(LCD_WIDTH-IMAGE_WIDTH-1)/2) - w / 2,
422 10, "Moves");
423 rb->snprintf(s, sizeof(s), "%d", moves);
424 w = rb->lcd_getstringsize(s, NULL, NULL);
425 rb->lcd_putsxy((IMAGE_WIDTH+1+(LCD_WIDTH-IMAGE_WIDTH-1)/2) - w / 2,
426 moves_y, s);
427 #else
428 (void)w;
429 rb->lcd_hline(0, LCD_WIDTH-1, IMAGE_HEIGHT);
430 rb->snprintf(s, sizeof(s), "Moves: %d", moves);
431 rb->lcd_putsxy(3, moves_y, s);
432 #endif
434 /* draw spots to the lcd */
435 for (i=0; i<NUM_SPOTS; i++)
436 draw_spot(spots[i], (i%SPOTS_X)*SPOTS_WIDTH, (i/SPOTS_X)*SPOTS_HEIGHT);
438 rb->lcd_update();
441 /* initializes the puzzle */
442 static void puzzle_init(void)
444 int i, r, temp, tsp[NUM_SPOTS];
446 moves = 0;
448 /* shuffle spots */
449 for (i=NUM_SPOTS-1; i>=0; i--) {
450 r = (rb->rand() % (i+1));
452 temp = spots[r];
453 spots[r] = spots[i];
454 spots[i] = temp;
456 if (spots[i]==HOLE_ID)
457 hole = i;
460 /* test if the puzzle is solvable */
461 for (i=0; i<NUM_SPOTS; i++)
462 tsp[i] = spots[i];
463 r=0;
465 /* First, check if the problem has even or odd parity,
466 depending on where the empty square is */
467 if ((((SPOTS_X-1)-hole%SPOTS_X) + ((SPOTS_Y-1)-hole/SPOTS_X))%2 == 1)
468 ++r;
470 /* Now check how many swaps we need to solve it */
471 for (i=0; i<NUM_SPOTS-1; i++) {
472 while (tsp[i] != (i+1)) {
473 temp = tsp[i];
474 tsp[i] = tsp[temp-1];
475 tsp[temp-1] = temp;
476 ++r;
480 /* if the random puzzle isn't solvable just change two spots */
481 if (r%2 == 1) {
482 if (spots[0]!=HOLE_ID && spots[1]!=HOLE_ID) {
483 temp = spots[0];
484 spots[0] = spots[1];
485 spots[1] = temp;
486 } else {
487 temp = spots[2];
488 spots[2] = spots[3];
489 spots[3] = temp;
493 draw_playfield();
496 /* the main game loop */
497 static int puzzle_loop(void)
499 int button;
500 int lastbutton = BUTTON_NONE;
501 bool load_success;
503 puzzle_init();
504 while(true) {
505 button = rb->button_get(true);
506 switch (button) {
507 #ifdef PUZZLE_RC_QUIT
508 case PUZZLE_RC_QUIT:
509 #endif
510 case PUZZLE_QUIT:
511 /* get out of here */
512 return PLUGIN_OK;
514 case PUZZLE_SHUFFLE:
515 #ifdef PUZZLE_SHUFFLE_PICTURE_PRE
516 if (lastbutton != PUZZLE_SHUFFLE_PICTURE_PRE)
517 break;
518 #endif
519 /* mix up the pieces */
520 puzzle_init();
521 break;
523 case PUZZLE_PICTURE:
524 #ifdef PUZZLE_SHUFFLE_PICTURE_PRE
525 if (lastbutton != PUZZLE_SHUFFLE_PICTURE_PRE)
526 break;
527 #endif
528 /* change picture */
529 picmode = (picmode+1)%PICMODE_LAST_XXX;
531 /* if load_resize_bitmap fails to load bitmap, try next picmode */
534 load_success = load_resize_bitmap();
535 if( !load_success )
536 picmode = (picmode+1)%PICMODE_LAST_XXX;
538 while( !load_success );
540 /* tell the user what mode we picked in the end! */
541 rb->splash(HZ,picmode_descriptions[ picmode ] );
542 draw_playfield();
543 break;
545 case PUZZLE_LEFT:
546 if ((hole%SPOTS_X)<(SPOTS_X-1) && !puzzle_finished())
547 move_spot(-1, 0);
548 break;
550 case PUZZLE_RIGHT:
551 if ((hole%SPOTS_X)>0 && !puzzle_finished())
552 move_spot(1, 0);
553 break;
555 case PUZZLE_UP:
556 if ((hole/SPOTS_X)<(SPOTS_Y-1) && !puzzle_finished())
557 move_spot(0, -1);
558 break;
560 case PUZZLE_DOWN:
561 if ((hole/SPOTS_X)>0 && !puzzle_finished())
562 move_spot(0, 1);
563 break;
565 default:
566 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
567 return PLUGIN_USB_CONNECTED;
568 break;
570 if (button != BUTTON_NONE)
571 lastbutton = button;
575 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
577 int i, w, h;
579 rb = api;
581 initial_bmp_path=(const char *)parameter;
582 picmode = PICMODE_INITIAL_PICTURE;
583 img_buf_path[0] = '\0';
585 /* If launched as a viewer, just go straight to the game without
586 bothering with the splash or instructions page */
587 if(parameter==NULL)
589 /* if not launched as a viewer, use default puzzle, and show help */
590 picmode = PICMODE_DEFAULT_PICTURE;
592 /* print title */
593 rb->lcd_getstringsize((unsigned char *)"Sliding Puzzle", &w, &h);
594 w = (w+1)/2;
595 h = (h+1)/2;
596 rb->lcd_clear_display();
597 rb->lcd_putsxy(LCD_WIDTH/2-w, (LCD_HEIGHT/2)-h,
598 (unsigned char *)"Sliding Puzzle");
599 rb->lcd_update();
600 rb->sleep(HZ);
602 /* print instructions */
603 rb->lcd_clear_display();
604 rb->lcd_setfont(FONT_SYSFIXED);
605 #if CONFIG_KEYPAD == RECORDER_PAD || CONFIG_KEYPAD == ARCHOS_AV300_PAD
606 rb->lcd_putsxy(3, 18, "[OFF] to stop");
607 rb->lcd_putsxy(3, 28, "[F1] shuffle");
608 rb->lcd_putsxy(3, 38, "[F2] change pic");
609 #elif CONFIG_KEYPAD == ONDIO_PAD
610 rb->lcd_putsxy(0, 18, "[OFF] to stop");
611 rb->lcd_putsxy(0, 28, "[MODE..] shuffle");
612 rb->lcd_putsxy(0, 38, "[MODE] change pic");
613 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
614 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
615 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
616 rb->lcd_putsxy(0, 18, "[S-MENU] to stop");
617 rb->lcd_putsxy(0, 28, "[S-LEFT] shuffle");
618 rb->lcd_putsxy(0, 38, "[S-RIGHT] change pic");
619 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
620 (CONFIG_KEYPAD == IRIVER_H300_PAD)
621 rb->lcd_putsxy(0, 18, "[STOP] to stop");
622 rb->lcd_putsxy(0, 28, "[SELECT] shuffle");
623 rb->lcd_putsxy(0, 38, "[PLAY] change pic");
624 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
625 rb->lcd_putsxy(0, 18, "[OFF] to stop");
626 rb->lcd_putsxy(0, 28, "[REC] shuffle");
627 rb->lcd_putsxy(0, 38, "[PLAY] change pic");
628 #elif CONFIG_KEYPAD == GIGABEAT_PAD
629 rb->lcd_putsxy(0, 18, "[OFF] to stop");
630 rb->lcd_putsxy(0, 28, "[SELECT] shuffle");
631 rb->lcd_putsxy(0, 38, "[A] change pic");
632 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
633 (CONFIG_KEYPAD == SANSA_C200_PAD)
634 rb->lcd_putsxy(0, 18, "[OFF] to stop");
635 rb->lcd_putsxy(0, 28, "[REC] shuffle");
636 rb->lcd_putsxy(0, 38, "[SELECT] change pic");
637 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
638 rb->lcd_putsxy(0, 18, "[OFF] to stop");
639 rb->lcd_putsxy(0, 28, "[REW] shuffle");
640 rb->lcd_putsxy(0, 38, "[PLAY] change pic");
641 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
642 rb->lcd_putsxy(0, 18, "[REC] to stop");
643 rb->lcd_putsxy(0, 28, "[MODE] shuffle");
644 rb->lcd_putsxy(0, 38, "[MENU] change pic");
645 #endif
646 #ifdef HAVE_ALBUMART
647 rb->lcd_putsxy(0,48," pic->albumart->num");
648 #else
649 rb->lcd_putsxy(0,48," pic<->num");
650 #endif
651 rb->lcd_update();
652 rb->button_get_w_tmo(HZ*2);
655 hole = INITIAL_HOLE;
657 if( !load_resize_bitmap() )
659 rb->lcd_clear_display();
660 rb->splash(HZ*2,"Failed to load bitmap!");
661 return PLUGIN_OK;
664 /* Calculate possible font sizes and text positions */
665 rb->lcd_setfont(FONT_UI);
666 rb->lcd_getstringsize("15", &w, &h);
667 if ((w > (SPOTS_WIDTH-2)) || (h > (SPOTS_HEIGHT-2)))
668 num_font = FONT_SYSFIXED;
670 #if LCD_WIDTH > LCD_HEIGHT
671 rb->lcd_getstringsize("Moves", &w, &h);
672 if (w > (LCD_WIDTH-IMAGE_WIDTH-1))
673 moves_font = FONT_SYSFIXED;
674 rb->lcd_setfont(moves_font);
675 rb->lcd_getstringsize("Moves", &w, &h);
676 moves_y = 10 + h;
677 #else
678 rb->lcd_getstringsize("Moves: 999", &w, &h);
679 if ((w > LCD_WIDTH) || (h > (LCD_HEIGHT-IMAGE_HEIGHT-1)))
680 moves_font = FONT_SYSFIXED;
681 rb->lcd_setfont(moves_font);
682 rb->lcd_getstringsize("Moves: 999", &w, &h);
683 moves_y = (IMAGE_HEIGHT+1+(LCD_HEIGHT-IMAGE_HEIGHT-1)/2) - h / 2;
684 #endif
685 for (i=0; i<NUM_SPOTS; i++)
686 spots[i]=(i+1);
688 #ifdef HAVE_LCD_COLOR
689 rb->lcd_set_background(LCD_BLACK);
690 rb->lcd_set_foreground(LCD_WHITE);
691 rb->lcd_set_backdrop(NULL);
692 #elif LCD_DEPTH > 1
693 rb->lcd_set_background(LCD_WHITE);
694 rb->lcd_set_foreground(LCD_BLACK);
695 rb->lcd_set_backdrop(NULL);
696 #endif
698 draw_playfield();
699 rb->sleep(HZ*2);
701 return puzzle_loop();
704 #endif