1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Vicentini Martin
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 /* variable button definitions */
24 #if CONFIG_KEYPAD == RECORDER_PAD
25 #define PUZZLE_QUIT BUTTON_OFF
26 #define PUZZLE_LEFT BUTTON_LEFT
27 #define PUZZLE_RIGHT BUTTON_RIGHT
28 #define PUZZLE_UP BUTTON_UP
29 #define PUZZLE_DOWN BUTTON_DOWN
30 #define PUZZLE_SHUFFLE BUTTON_F1
31 #define PUZZLE_PICTURE BUTTON_F2
33 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
34 #define PUZZLE_QUIT BUTTON_OFF
35 #define PUZZLE_LEFT BUTTON_LEFT
36 #define PUZZLE_RIGHT BUTTON_RIGHT
37 #define PUZZLE_UP BUTTON_UP
38 #define PUZZLE_DOWN BUTTON_DOWN
39 #define PUZZLE_SHUFFLE BUTTON_F1
40 #define PUZZLE_PICTURE BUTTON_F2
42 #elif CONFIG_KEYPAD == ONDIO_PAD
43 #define PUZZLE_QUIT BUTTON_OFF
44 #define PUZZLE_LEFT BUTTON_LEFT
45 #define PUZZLE_RIGHT BUTTON_RIGHT
46 #define PUZZLE_UP BUTTON_UP
47 #define PUZZLE_DOWN BUTTON_DOWN
48 #define PUZZLE_SHUFFLE_PICTURE_PRE BUTTON_MENU
49 #define PUZZLE_SHUFFLE (BUTTON_MENU | BUTTON_REPEAT)
50 #define PUZZLE_PICTURE (BUTTON_MENU | BUTTON_REL)
52 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
53 (CONFIG_KEYPAD == IRIVER_H300_PAD)
54 #define PUZZLE_QUIT BUTTON_OFF
55 #define PUZZLE_LEFT BUTTON_LEFT
56 #define PUZZLE_RIGHT BUTTON_RIGHT
57 #define PUZZLE_UP BUTTON_UP
58 #define PUZZLE_DOWN BUTTON_DOWN
59 #define PUZZLE_SHUFFLE BUTTON_SELECT
60 #define PUZZLE_PICTURE BUTTON_ON
62 #define PUZZLE_RC_QUIT BUTTON_RC_STOP
64 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
65 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
66 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
67 #define PUZZLE_QUIT (BUTTON_SELECT | BUTTON_MENU)
68 #define PUZZLE_LEFT BUTTON_LEFT
69 #define PUZZLE_RIGHT BUTTON_RIGHT
70 #define PUZZLE_UP BUTTON_MENU
71 #define PUZZLE_DOWN BUTTON_PLAY
72 #define PUZZLE_SHUFFLE (BUTTON_SELECT | BUTTON_LEFT)
73 #define PUZZLE_PICTURE (BUTTON_SELECT | BUTTON_RIGHT)
75 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
76 #define PUZZLE_QUIT BUTTON_POWER
77 #define PUZZLE_LEFT BUTTON_LEFT
78 #define PUZZLE_RIGHT BUTTON_RIGHT
79 #define PUZZLE_UP BUTTON_UP
80 #define PUZZLE_DOWN BUTTON_DOWN
81 #define PUZZLE_SHUFFLE BUTTON_REC
82 #define PUZZLE_PICTURE BUTTON_PLAY
84 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
85 #define PUZZLE_QUIT BUTTON_POWER
86 #define PUZZLE_LEFT BUTTON_LEFT
87 #define PUZZLE_RIGHT BUTTON_RIGHT
88 #define PUZZLE_UP BUTTON_UP
89 #define PUZZLE_DOWN BUTTON_DOWN
90 #define PUZZLE_SHUFFLE BUTTON_SELECT
91 #define PUZZLE_PICTURE BUTTON_A
93 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
94 (CONFIG_KEYPAD == SANSA_C200_PAD)
95 #define PUZZLE_QUIT BUTTON_POWER
96 #define PUZZLE_LEFT BUTTON_LEFT
97 #define PUZZLE_RIGHT BUTTON_RIGHT
98 #define PUZZLE_UP BUTTON_UP
99 #define PUZZLE_DOWN BUTTON_DOWN
100 #define PUZZLE_SHUFFLE BUTTON_REC
101 #define PUZZLE_PICTURE BUTTON_SELECT
103 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
104 #define PUZZLE_QUIT (BUTTON_HOME|BUTTON_REPEAT)
105 #define PUZZLE_LEFT BUTTON_LEFT
106 #define PUZZLE_RIGHT BUTTON_RIGHT
107 #define PUZZLE_UP BUTTON_UP
108 #define PUZZLE_DOWN BUTTON_DOWN
109 #define PUZZLE_SHUFFLE BUTTON_SELECT|BUTTON_DOWN
110 #define PUZZLE_PICTURE BUTTON_SELECT
112 #elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
113 #define PUZZLE_QUIT BUTTON_POWER
114 #define PUZZLE_LEFT BUTTON_LEFT
115 #define PUZZLE_RIGHT BUTTON_RIGHT
116 #define PUZZLE_UP BUTTON_UP
117 #define PUZZLE_DOWN BUTTON_DOWN
118 #define PUZZLE_SHUFFLE BUTTON_HOME
119 #define PUZZLE_PICTURE BUTTON_SELECT
121 #elif (CONFIG_KEYPAD == SANSA_M200_PAD)
122 #define PUZZLE_QUIT BUTTON_POWER
123 #define PUZZLE_LEFT BUTTON_LEFT
124 #define PUZZLE_RIGHT BUTTON_RIGHT
125 #define PUZZLE_UP BUTTON_UP
126 #define PUZZLE_DOWN BUTTON_DOWN
127 #define PUZZLE_SHUFFLE (BUTTON_SELECT | BUTTON_UP)
128 #define PUZZLE_PICTURE (BUTTON_SELECT | BUTTON_REL)
130 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
131 #define PUZZLE_QUIT BUTTON_POWER
132 #define PUZZLE_LEFT BUTTON_LEFT
133 #define PUZZLE_RIGHT BUTTON_RIGHT
134 #define PUZZLE_UP BUTTON_SCROLL_UP
135 #define PUZZLE_DOWN BUTTON_SCROLL_DOWN
136 #define PUZZLE_SHUFFLE BUTTON_REW
137 #define PUZZLE_PICTURE BUTTON_PLAY
139 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \
140 (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)
141 #define PUZZLE_QUIT BUTTON_BACK
142 #define PUZZLE_LEFT BUTTON_LEFT
143 #define PUZZLE_RIGHT BUTTON_RIGHT
144 #define PUZZLE_UP BUTTON_UP
145 #define PUZZLE_DOWN BUTTON_DOWN
146 #define PUZZLE_SHUFFLE BUTTON_SELECT
147 #define PUZZLE_PICTURE BUTTON_MENU
149 #elif (CONFIG_KEYPAD == MROBE100_PAD)
150 #define PUZZLE_QUIT BUTTON_POWER
151 #define PUZZLE_LEFT BUTTON_LEFT
152 #define PUZZLE_RIGHT BUTTON_RIGHT
153 #define PUZZLE_UP BUTTON_UP
154 #define PUZZLE_DOWN BUTTON_DOWN
155 #define PUZZLE_SHUFFLE BUTTON_SELECT
156 #define PUZZLE_PICTURE BUTTON_DISPLAY
158 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
159 #define PUZZLE_QUIT BUTTON_RC_REC
160 #define PUZZLE_LEFT BUTTON_RC_REW
161 #define PUZZLE_RIGHT BUTTON_RC_FF
162 #define PUZZLE_UP BUTTON_RC_VOL_UP
163 #define PUZZLE_DOWN BUTTON_RC_VOL_DOWN
164 #define PUZZLE_SHUFFLE BUTTON_RC_MODE
165 #define PUZZLE_PICTURE BUTTON_RC_MENU
167 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
168 #define PUZZLE_QUIT BUTTON_POWER
169 #define PUZZLE_QUIT_TEXT "[POWER]"
171 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
172 #define PUZZLE_QUIT BUTTON_BACK
173 #define PUZZLE_LEFT BUTTON_LEFT
174 #define PUZZLE_RIGHT BUTTON_RIGHT
175 #define PUZZLE_UP BUTTON_UP
176 #define PUZZLE_DOWN BUTTON_DOWN
177 #define PUZZLE_SHUFFLE BUTTON_PLAY
178 #define PUZZLE_PICTURE BUTTON_MENU
180 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
181 #define PUZZLE_QUIT BUTTON_POWER
182 #define PUZZLE_LEFT BUTTON_LEFT
183 #define PUZZLE_RIGHT BUTTON_RIGHT
184 #define PUZZLE_UP BUTTON_UP
185 #define PUZZLE_DOWN BUTTON_DOWN
186 #define PUZZLE_SHUFFLE BUTTON_VIEW
187 #define PUZZLE_PICTURE BUTTON_MENU
189 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
190 #define PUZZLE_QUIT BUTTON_POWER
191 #define PUZZLE_LEFT BUTTON_LEFT
192 #define PUZZLE_RIGHT BUTTON_RIGHT
193 #define PUZZLE_UP BUTTON_UP
194 #define PUZZLE_DOWN BUTTON_DOWN
195 #define PUZZLE_SHUFFLE BUTTON_NEXT
196 #define PUZZLE_PICTURE BUTTON_MENU
198 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
199 #define PUZZLE_QUIT BUTTON_POWER
200 #define PUZZLE_LEFT BUTTON_PREV
201 #define PUZZLE_RIGHT BUTTON_NEXT
202 #define PUZZLE_UP BUTTON_UP
203 #define PUZZLE_DOWN BUTTON_DOWN
204 #define PUZZLE_SHUFFLE BUTTON_RIGHT
205 #define PUZZLE_PICTURE BUTTON_MENU
207 #elif CONFIG_KEYPAD == ONDAVX747_PAD || \
208 CONFIG_KEYPAD == ONDAVX777_PAD || \
209 CONFIG_KEYPAD == MROBE500_PAD
210 #define PUZZLE_QUIT BUTTON_POWER
211 #define PUZZLE_QUIT_TEXT "[POWER]"
213 #elif (CONFIG_KEYPAD == SAMSUNG_YH_PAD)
214 #define PUZZLE_QUIT BUTTON_REC
215 #define PUZZLE_LEFT BUTTON_LEFT
216 #define PUZZLE_RIGHT BUTTON_RIGHT
217 #define PUZZLE_UP BUTTON_UP
218 #define PUZZLE_DOWN BUTTON_DOWN
219 #define PUZZLE_SHUFFLE BUTTON_REW
220 #define PUZZLE_PICTURE BUTTON_PLAY
222 #elif (CONFIG_KEYPAD == PBELL_VIBE500_PAD)
223 #define PUZZLE_QUIT BUTTON_REC
224 #define PUZZLE_LEFT BUTTON_PREV
225 #define PUZZLE_RIGHT BUTTON_NEXT
226 #define PUZZLE_UP BUTTON_UP
227 #define PUZZLE_DOWN BUTTON_DOWN
228 #define PUZZLE_SHUFFLE BUTTON_CANCEL
229 #define PUZZLE_PICTURE BUTTON_MENU
231 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
232 #define PUZZLE_QUIT (BUTTON_REC | BUTTON_PLAY)
233 #define PUZZLE_LEFT BUTTON_VOL_DOWN
234 #define PUZZLE_RIGHT BUTTON_VOL_UP
235 #define PUZZLE_UP BUTTON_REW
236 #define PUZZLE_DOWN BUTTON_FF
237 #define PUZZLE_SHUFFLE BUTTON_REC
238 #define PUZZLE_PICTURE BUTTON_PLAY
240 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
241 #define PUZZLE_QUIT (BUTTON_REC | BUTTON_REPEAT)
242 #define PUZZLE_LEFT BUTTON_REW
243 #define PUZZLE_RIGHT BUTTON_FF
244 #define PUZZLE_UP BUTTON_UP
245 #define PUZZLE_DOWN BUTTON_DOWN
246 #define PUZZLE_SHUFFLE BUTTON_ENTER
247 #define PUZZLE_PICTURE BUTTON_PLAY
249 #elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
250 #define PUZZLE_QUIT BUTTON_POWER
251 #define PUZZLE_LEFT BUTTON_LEFT
252 #define PUZZLE_RIGHT BUTTON_RIGHT
253 #define PUZZLE_UP BUTTON_UP
254 #define PUZZLE_DOWN BUTTON_DOWN
255 #define PUZZLE_SHUFFLE BUTTON_PLAYPAUSE
256 #define PUZZLE_PICTURE BUTTON_SELECT
258 #elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
259 #define PUZZLE_QUIT BUTTON_POWER
260 #define PUZZLE_LEFT BUTTON_LEFT
261 #define PUZZLE_RIGHT BUTTON_RIGHT
262 #define PUZZLE_UP BUTTON_UP
263 #define PUZZLE_DOWN BUTTON_DOWN
264 #define PUZZLE_SHUFFLE BUTTON_VOL_DOWN
265 #define PUZZLE_PICTURE BUTTON_SELECT
268 #error No keymap defined!
271 #ifdef HAVE_TOUCHSCREEN
273 #define PUZZLE_QUIT BUTTON_TOPLEFT
276 #define PUZZLE_LEFT BUTTON_MIDLEFT
279 #define PUZZLE_RIGHT BUTTON_MIDRIGHT
282 #define PUZZLE_UP BUTTON_TOPMIDDLE
285 #define PUZZLE_DOWN BUTTON_BOTTOMMIDDLE
287 #ifndef PUZZLE_SHUFFLE
288 #define PUZZLE_SHUFFLE BUTTON_BOTTOMLEFT
290 #ifndef PUZZLE_PICTURE
291 #define PUZZLE_PICTURE BUTTON_CENTER
293 #ifndef PUZZLE_QUIT_TEXT
294 #define PUZZLE_QUIT_TEXT "[TOPLEFT]"
296 #ifndef PUZZLE_SHUFFLE_TEXT
297 #define PUZZLE_SHUFFLE_TEXT "[BOTTOMLEFT]"
299 #ifndef PUZZLE_PICTURE_TEXT
300 #define PUZZLE_PICTURE_TEXT "[CENTER]"
305 #include "lib/read_image.h"
306 #define READ_IMAGE read_image_file
308 #define READ_IMAGE rb->read_bmp_file
311 #include "pluginbitmaps/sliding_puzzle.h"
312 #define IMAGE_WIDTH BMPWIDTH_sliding_puzzle
313 #define IMAGE_HEIGHT BMPHEIGHT_sliding_puzzle
314 #define IMAGE_SIZE IMAGE_WIDTH
316 /* use a square image, (the default Archos bitmap looks square on its display)
317 Puzzle image dimension is min(lcd_height,lcd_width)
318 4x4 is more convenient for square puzzles
319 Note: sliding_puzzle.bmp should be evenly divisible by SPOTS_X
320 and SPOTS_Y, otherwise lcd_bitmap_part stride won't be correct */
323 #define SPOTS_WIDTH (IMAGE_WIDTH / SPOTS_X)
324 #define SPOTS_HEIGHT (IMAGE_HEIGHT / SPOTS_Y)
325 #define NUM_SPOTS (SPOTS_X*SPOTS_Y)
326 #define HOLE_ID (NUM_SPOTS)
327 #define INITIAL_HOLE (HOLE_ID-1)
331 PICMODE_NUMERALS
= 0,
332 PICMODE_INITIAL_PICTURE
,
333 PICMODE_DEFAULT_PICTURE
,
338 PICMODE_LAST_XXX
/* placeholder */
341 static const char* const picmode_descriptions
[] = {
348 "Shouldn't Get Here",
351 static int spots
[NUM_SPOTS
];
352 static int hole
= INITIAL_HOLE
, moves
;
353 static unsigned char s
[32];
354 static enum picmodes picmode
= PICMODE_INITIAL_PICTURE
;
355 static int num_font
= FONT_UI
;
356 static int moves_font
= FONT_UI
;
357 static int moves_y
= 0;
359 static unsigned char *img_buf
;
360 static size_t img_buf_len
;
362 static char albumart_path
[MAX_PATH
+1];
364 static char img_buf_path
[MAX_PATH
+1];
366 static const fb_data
* puzzle_bmp_ptr
;
367 /* initial_bmp_path points to selected bitmap if this game is launched
368 as a viewer for a .bmp file, or NULL if game is launched regular way */
369 static const char * initial_bmp_path
=NULL
;
372 static const char * get_albumart_bmp_path(void)
374 struct mp3entry
* track
= rb
->audio_current_track();
376 if (!track
|| !track
->path
|| track
->path
[0] == '\0')
379 if (!rb
->search_albumart_files(track
, "", albumart_path
, MAX_PATH
) )
382 albumart_path
[ MAX_PATH
] = '\0';
383 return albumart_path
;
388 static const char * get_random_bmp_path(void)
390 return(initial_bmp_path
);
394 static bool load_resize_bitmap(void)
397 const char * filename
= NULL
;
399 /* initially assume using the built-in default */
400 puzzle_bmp_ptr
= sliding_puzzle
;
403 /* some modes don't even need to touch disk and trivially succeed */
404 case PICMODE_NUMERALS
:
405 case PICMODE_DEFAULT_PICTURE
:
410 case PICMODE_ALBUM_ART
:
411 filename
= get_albumart_bmp_path();
416 if(NULL == (filename=get_random_bmp_path()) )
417 filename = initial_bmp_path;
420 case PICMODE_INITIAL_PICTURE
:
421 filename
= initial_bmp_path
;
425 if( filename
!= NULL
)
427 /* if we already loaded image before, don't touch disk */
428 if( 0 == rb
->strcmp( filename
, img_buf_path
) )
430 puzzle_bmp_ptr
= (const fb_data
*)img_buf
;
434 struct bitmap main_bitmap
;
435 rb
->memset(&main_bitmap
,0,sizeof(struct bitmap
));
436 main_bitmap
.data
= img_buf
;
438 main_bitmap
.width
= IMAGE_WIDTH
;
439 main_bitmap
.height
= IMAGE_HEIGHT
;
441 rc
= READ_IMAGE( filename
, &main_bitmap
,
443 FORMAT_NATIVE
|FORMAT_RESIZE
|FORMAT_DITHER
,
447 puzzle_bmp_ptr
= (const fb_data
*)img_buf
;
448 rb
->strcpy( img_buf_path
, filename
);
453 /* something must have failed. get_albumart_bmp_path could return
454 NULL if albumart doesn't exist or couldn't be loaded, or
455 read_bmp_file could have failed. return false and caller should
456 try the next mode (PICMODE_DEFAULT_PICTURE and PICMODE_NUMERALS will
461 /* draws a spot at the coordinates (x,y), range of p is 1-20 */
462 static void draw_spot(int p
, int x
, int y
)
469 /* the bottom-right cell of the default sliding_puzzle image is
470 an appropriate hole graphic */
471 rb
->lcd_bitmap_part(sliding_puzzle
, ((p
-1)%SPOTS_X
)*SPOTS_WIDTH
,
472 ((p
-1)/SPOTS_X
)*SPOTS_HEIGHT
,
474 BMPWIDTH_sliding_puzzle
, BMPHEIGHT_sliding_puzzle
),
475 x
, y
, SPOTS_WIDTH
, SPOTS_HEIGHT
);
477 /* just draw a black rectangle */
478 int old_fg
= rb
->lcd_get_foreground();
479 rb
->lcd_set_foreground(LCD_BLACK
);
480 rb
->lcd_fillrect(x
,y
,SPOTS_WIDTH
,SPOTS_HEIGHT
);
481 rb
->lcd_set_foreground(LCD_WHITE
);
482 rb
->lcd_drawrect(x
,y
,SPOTS_WIDTH
,SPOTS_HEIGHT
);
483 rb
->lcd_set_foreground(old_fg
);
486 else if (picmode
!= PICMODE_NUMERALS
)
488 rb
->lcd_bitmap_part( puzzle_bmp_ptr
, ((p
-1)%SPOTS_X
)*SPOTS_WIDTH
,
489 ((p
-1)/SPOTS_X
)*SPOTS_HEIGHT
,
491 BMPWIDTH_sliding_puzzle
, BMPHEIGHT_sliding_puzzle
),
492 x
, y
, SPOTS_WIDTH
, SPOTS_HEIGHT
);
494 rb
->lcd_drawrect(x
, y
, SPOTS_WIDTH
, SPOTS_HEIGHT
);
495 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
496 rb
->lcd_fillrect(x
+1, y
+1, SPOTS_WIDTH
-2, SPOTS_HEIGHT
-2);
497 rb
->lcd_set_drawmode(DRMODE_SOLID
);
498 rb
->snprintf(s
, sizeof(s
), "%d", p
);
499 rb
->lcd_setfont(num_font
);
500 rb
->lcd_getstringsize(s
, &w
, &h
);
501 rb
->lcd_putsxy(x
+ (SPOTS_WIDTH
/2) - w
/ 2,
502 y
+ (SPOTS_HEIGHT
/2) - h
/ 2, s
);
506 /* check if the puzzle is solved */
507 static bool puzzle_finished(void)
510 for (i
=0; i
<NUM_SPOTS
; i
++)
511 if (spots
[i
] != (i
+1))
516 /* move a piece in any direction */
517 static void move_spot(int x
, int y
)
520 spots
[hole
] = spots
[hole
-x
-SPOTS_X
*y
];
521 hole
-= (x
+SPOTS_X
*y
);
523 rb
->lcd_setfont(moves_font
);
524 #if LCD_WIDTH > LCD_HEIGHT
525 rb
->snprintf(s
, sizeof(s
), "%d", moves
);
526 w
= rb
->lcd_getstringsize(s
, NULL
, NULL
);
527 rb
->lcd_putsxy((IMAGE_WIDTH
+1+(LCD_WIDTH
-IMAGE_WIDTH
-1)/2) - w
/ 2,
531 rb
->lcd_putsxyf(3, moves_y
, "Moves: %d", moves
);
536 (hole
%SPOTS_X
)*SPOTS_WIDTH
,
537 (hole
/SPOTS_X
)*SPOTS_HEIGHT
);
538 draw_spot(spots
[hole
],
539 (hole
%SPOTS_X
)*SPOTS_WIDTH
+ (i
*x
*SPOTS_WIDTH
)/5,
540 (hole
/SPOTS_X
)*SPOTS_HEIGHT
+ (i
*y
*SPOTS_HEIGHT
)/5);
545 (hole
%SPOTS_X
)*SPOTS_WIDTH
,
546 (hole
/SPOTS_X
)*SPOTS_HEIGHT
);
547 draw_spot(spots
[hole
],
548 ((hole
%SPOTS_X
)+x
)*SPOTS_WIDTH
,
549 ((hole
/SPOTS_X
)+y
)*SPOTS_HEIGHT
);
552 spots
[hole
] = HOLE_ID
;
555 static void draw_playfield(void)
559 rb
->lcd_clear_display();
560 rb
->lcd_setfont(moves_font
);
561 #if LCD_WIDTH > LCD_HEIGHT
562 rb
->lcd_vline(IMAGE_WIDTH
, 0, LCD_HEIGHT
-1);
563 w
= rb
->lcd_getstringsize("Moves", NULL
, NULL
);
564 rb
->lcd_putsxy((IMAGE_WIDTH
+1+(LCD_WIDTH
-IMAGE_WIDTH
-1)/2) - w
/ 2,
566 rb
->snprintf(s
, sizeof(s
), "%d", moves
);
567 w
= rb
->lcd_getstringsize(s
, NULL
, NULL
);
568 rb
->lcd_putsxy((IMAGE_WIDTH
+1+(LCD_WIDTH
-IMAGE_WIDTH
-1)/2) - w
/ 2,
572 rb
->lcd_hline(0, LCD_WIDTH
-1, IMAGE_HEIGHT
);
573 rb
->lcd_putsxyf(3, moves_y
, "Moves: %d", moves
);
576 /* draw spots to the lcd */
577 for (i
=0; i
<NUM_SPOTS
; i
++)
578 draw_spot(spots
[i
], (i
%SPOTS_X
)*SPOTS_WIDTH
, (i
/SPOTS_X
)*SPOTS_HEIGHT
);
583 /* initializes the puzzle */
584 static void puzzle_init(void)
586 int i
, r
, temp
, tsp
[NUM_SPOTS
];
591 for (i
=NUM_SPOTS
-1; i
>=0; i
--) {
592 r
= (rb
->rand() % (i
+1));
598 if (spots
[i
]==HOLE_ID
)
602 /* test if the puzzle is solvable */
603 for (i
=0; i
<NUM_SPOTS
; i
++)
607 /* First, check if the problem has even or odd parity,
608 depending on where the empty square is */
609 if ((((SPOTS_X
-1)-hole
%SPOTS_X
) + ((SPOTS_Y
-1)-hole
/SPOTS_X
))%2 == 1)
612 /* Now check how many swaps we need to solve it */
613 for (i
=0; i
<NUM_SPOTS
-1; i
++) {
614 while (tsp
[i
] != (i
+1)) {
616 tsp
[i
] = tsp
[temp
-1];
622 /* if the random puzzle isn't solvable just change two spots */
624 if (spots
[0]!=HOLE_ID
&& spots
[1]!=HOLE_ID
) {
638 /* the main game loop */
639 static int puzzle_loop(void)
642 #if defined(PUZZLE_SHUFFLE_PICTURE_PRE)
643 int lastbutton
= BUTTON_NONE
;
649 button
= rb
->button_get(true);
651 #ifdef PUZZLE_RC_QUIT
655 /* get out of here */
659 #ifdef PUZZLE_SHUFFLE_PICTURE_PRE
660 if (lastbutton
!= PUZZLE_SHUFFLE_PICTURE_PRE
)
663 /* mix up the pieces */
668 #ifdef PUZZLE_SHUFFLE_PICTURE_PRE
669 if (lastbutton
!= PUZZLE_SHUFFLE_PICTURE_PRE
)
673 picmode
= (picmode
+1)%PICMODE_LAST_XXX
;
675 /* if load_resize_bitmap fails to load bitmap, try next picmode
679 load_success
= load_resize_bitmap();
681 picmode
= (picmode
+1)%PICMODE_LAST_XXX
;
683 while( !load_success
);
685 /* tell the user what mode we picked in the end! */
686 rb
->splash(HZ
,picmode_descriptions
[ picmode
] );
691 if ((hole
%SPOTS_X
)<(SPOTS_X
-1) && !puzzle_finished())
696 if ((hole
%SPOTS_X
)>0 && !puzzle_finished())
701 if ((hole
/SPOTS_X
)<(SPOTS_Y
-1) && !puzzle_finished())
706 if ((hole
/SPOTS_X
)>0 && !puzzle_finished())
711 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
712 return PLUGIN_USB_CONNECTED
;
715 #if defined(PUZZLE_SHUFFLE_PICTURE_PRE)
716 if (button
!= BUTTON_NONE
)
722 enum plugin_status
plugin_start(
723 const void* parameter
)
727 initial_bmp_path
=(const char *)parameter
;
728 img_buf
= rb
->plugin_get_buffer(&img_buf_len
);
729 picmode
= PICMODE_INITIAL_PICTURE
;
730 img_buf_path
[0] = '\0';
732 /* If launched as a viewer, just go straight to the game without
733 bothering with the splash or instructions page */
736 /* if not launched as a viewer, use default puzzle, and show help */
737 picmode
= PICMODE_DEFAULT_PICTURE
;
740 rb
->lcd_getstringsize((unsigned char *)"Sliding Puzzle", &w
, &h
);
743 rb
->lcd_clear_display();
744 rb
->lcd_putsxy(LCD_WIDTH
/2-w
, (LCD_HEIGHT
/2)-h
,
745 (unsigned char *)"Sliding Puzzle");
749 /* print instructions */
750 rb
->lcd_clear_display();
751 rb
->lcd_setfont(FONT_SYSFIXED
);
752 #if CONFIG_KEYPAD == RECORDER_PAD || CONFIG_KEYPAD == ARCHOS_AV300_PAD
753 rb
->lcd_putsxy(3, 18, "[OFF] to stop");
754 rb
->lcd_putsxy(3, 28, "[F1] shuffle");
755 rb
->lcd_putsxy(3, 38, "[F2] change pic");
756 #elif CONFIG_KEYPAD == ONDIO_PAD
757 rb
->lcd_putsxy(0, 18, "[OFF] to stop");
758 rb
->lcd_putsxy(0, 28, "[MODE..] shuffle");
759 rb
->lcd_putsxy(0, 38, "[MODE] change pic");
760 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
761 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
762 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
763 rb
->lcd_putsxy(0, 18, "[S-MENU] to stop");
764 rb
->lcd_putsxy(0, 28, "[S-LEFT] shuffle");
765 rb
->lcd_putsxy(0, 38, "[S-RIGHT] change pic");
766 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
767 (CONFIG_KEYPAD == IRIVER_H300_PAD)
768 rb
->lcd_putsxy(0, 18, "[STOP] to stop");
769 rb
->lcd_putsxy(0, 28, "[SELECT] shuffle");
770 rb
->lcd_putsxy(0, 38, "[PLAY] change pic");
771 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
772 rb
->lcd_putsxy(0, 18, "[OFF] to stop");
773 rb
->lcd_putsxy(0, 28, "[REC] shuffle");
774 rb
->lcd_putsxy(0, 38, "[PLAY] change pic");
775 #elif CONFIG_KEYPAD == GIGABEAT_PAD
776 rb
->lcd_putsxy(0, 18, "[POWER] to stop");
777 rb
->lcd_putsxy(0, 28, "[SELECT] shuffle");
778 rb
->lcd_putsxy(0, 38, "[A] change pic");
779 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
780 (CONFIG_KEYPAD == SANSA_C200_PAD)
781 rb
->lcd_putsxy(0, 18, "[OFF] to stop");
782 rb
->lcd_putsxy(0, 28, "[REC] shuffle");
783 rb
->lcd_putsxy(0, 38, "[SELECT] change pic");
784 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
785 rb
->lcd_putsxy(0, 18, "[OFF] to stop");
786 rb
->lcd_putsxy(0, 28, "[REW] shuffle");
787 rb
->lcd_putsxy(0, 38, "[PLAY] change pic");
788 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD || \
789 CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
790 rb
->lcd_putsxy(0, 18, "[BACK] to stop");
791 rb
->lcd_putsxy(0, 28, "[SELECT] shuffle");
792 rb
->lcd_putsxy(0, 38, "[MENU] change pic");
793 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
794 rb
->lcd_putsxy(0, 18, "[REC] to stop");
795 rb
->lcd_putsxy(0, 28, "[MODE] shuffle");
796 rb
->lcd_putsxy(0, 38, "[MENU] change pic");
798 #ifdef HAVE_TOUCHSCREEN
799 rb
->lcd_putsxy(0, 18, PUZZLE_QUIT_TEXT
" to stop");
800 rb
->lcd_putsxy(0, 28, PUZZLE_SHUFFLE_TEXT
" shuffle");
801 rb
->lcd_putsxy(0, 38, PUZZLE_PICTURE_TEXT
" change pic");
804 rb
->lcd_putsxy(0,48," pic->albumart->num");
806 rb
->lcd_putsxy(0,48," pic<->num");
809 rb
->button_get_w_tmo(HZ
*2);
814 if( !load_resize_bitmap() )
816 rb
->lcd_clear_display();
817 rb
->splash(HZ
*2,"Failed to load bitmap!");
821 /* Calculate possible font sizes and text positions */
822 rb
->lcd_setfont(FONT_UI
);
823 rb
->lcd_getstringsize("15", &w
, &h
);
824 if ((w
> (SPOTS_WIDTH
-2)) || (h
> (SPOTS_HEIGHT
-2)))
825 num_font
= FONT_SYSFIXED
;
827 #if LCD_WIDTH > LCD_HEIGHT
828 rb
->lcd_getstringsize("Moves", &w
, &h
);
829 if (w
> (LCD_WIDTH
-IMAGE_WIDTH
-1))
830 moves_font
= FONT_SYSFIXED
;
831 rb
->lcd_setfont(moves_font
);
832 rb
->lcd_getstringsize("Moves", &w
, &h
);
835 rb
->lcd_getstringsize("Moves: 999", &w
, &h
);
836 if ((w
> LCD_WIDTH
) || (h
> (LCD_HEIGHT
-IMAGE_HEIGHT
-1)))
837 moves_font
= FONT_SYSFIXED
;
838 rb
->lcd_setfont(moves_font
);
839 rb
->lcd_getstringsize("Moves: 999", &w
, &h
);
840 moves_y
= (IMAGE_HEIGHT
+1+(LCD_HEIGHT
-IMAGE_HEIGHT
-1)/2) - h
/ 2;
842 for (i
=0; i
<NUM_SPOTS
; i
++)
845 #ifdef HAVE_LCD_COLOR
846 rb
->lcd_set_background(LCD_BLACK
);
847 rb
->lcd_set_foreground(LCD_WHITE
);
848 rb
->lcd_set_backdrop(NULL
);
850 rb
->lcd_set_background(LCD_WHITE
);
851 rb
->lcd_set_foreground(LCD_BLACK
);
852 rb
->lcd_set_backdrop(NULL
);
858 return puzzle_loop();