1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Adam Boot
12 * Color graphics from Gweled (http://sebdelestaing.free.fr/gweled/)
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
25 #include "lib/playback_control.h"
27 #ifdef HAVE_LCD_BITMAP
31 /* button definitions */
32 #if CONFIG_KEYPAD == RECORDER_PAD
33 #define JEWELS_UP BUTTON_UP
34 #define JEWELS_DOWN BUTTON_DOWN
35 #define JEWELS_LEFT BUTTON_LEFT
36 #define JEWELS_RIGHT BUTTON_RIGHT
37 #define JEWELS_SELECT BUTTON_PLAY
38 #define JEWELS_CANCEL BUTTON_OFF
40 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
41 #define JEWELS_UP BUTTON_UP
42 #define JEWELS_DOWN BUTTON_DOWN
43 #define JEWELS_LEFT BUTTON_LEFT
44 #define JEWELS_RIGHT BUTTON_RIGHT
45 #define JEWELS_SELECT BUTTON_SELECT
46 #define JEWELS_CANCEL BUTTON_OFF
48 #elif CONFIG_KEYPAD == ONDIO_PAD
49 #define JEWELS_UP BUTTON_UP
50 #define JEWELS_DOWN BUTTON_DOWN
51 #define JEWELS_LEFT BUTTON_LEFT
52 #define JEWELS_RIGHT BUTTON_RIGHT
53 #define JEWELS_SELECT BUTTON_MENU
54 #define JEWELS_CANCEL BUTTON_OFF
56 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
57 #define JEWELS_UP BUTTON_UP
58 #define JEWELS_DOWN BUTTON_DOWN
59 #define JEWELS_LEFT BUTTON_LEFT
60 #define JEWELS_RIGHT BUTTON_RIGHT
61 #define JEWELS_SELECT BUTTON_SELECT
62 #define JEWELS_MENU BUTTON_MODE
63 #define JEWELS_CANCEL BUTTON_OFF
64 #define JEWELS_RC_CANCEL BUTTON_RC_STOP
66 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
67 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
68 #define JEWELS_SCROLLWHEEL
69 #define JEWELS_UP BUTTON_MENU
70 #define JEWELS_DOWN BUTTON_PLAY
71 #define JEWELS_LEFT BUTTON_LEFT
72 #define JEWELS_RIGHT BUTTON_RIGHT
73 #define JEWELS_PREV BUTTON_SCROLL_BACK
74 #define JEWELS_NEXT BUTTON_SCROLL_FWD
75 #define JEWELS_SELECT BUTTON_SELECT
77 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
78 #define JEWELS_UP BUTTON_UP
79 #define JEWELS_DOWN BUTTON_DOWN
80 #define JEWELS_LEFT BUTTON_LEFT
81 #define JEWELS_RIGHT BUTTON_RIGHT
82 #define JEWELS_SELECT BUTTON_SELECT
83 #define JEWELS_CANCEL BUTTON_PLAY
85 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
86 #define JEWELS_UP BUTTON_UP
87 #define JEWELS_DOWN BUTTON_DOWN
88 #define JEWELS_LEFT BUTTON_LEFT
89 #define JEWELS_RIGHT BUTTON_RIGHT
90 #define JEWELS_SELECT BUTTON_SELECT
91 #define JEWELS_CANCEL BUTTON_POWER
93 #elif CONFIG_KEYPAD == GIGABEAT_PAD
94 #define JEWELS_UP BUTTON_UP
95 #define JEWELS_DOWN BUTTON_DOWN
96 #define JEWELS_LEFT BUTTON_LEFT
97 #define JEWELS_RIGHT BUTTON_RIGHT
98 #define JEWELS_SELECT BUTTON_SELECT
99 #define JEWELS_CANCEL BUTTON_POWER
101 #elif CONFIG_KEYPAD == SANSA_E200_PAD
102 #define JEWELS_SCROLLWHEEL
103 #define JEWELS_UP BUTTON_UP
104 #define JEWELS_DOWN BUTTON_DOWN
105 #define JEWELS_LEFT BUTTON_LEFT
106 #define JEWELS_RIGHT BUTTON_RIGHT
107 #define JEWELS_PREV BUTTON_SCROLL_BACK
108 #define JEWELS_NEXT BUTTON_SCROLL_FWD
109 #define JEWELS_SELECT BUTTON_SELECT
110 #define JEWELS_CANCEL BUTTON_POWER
112 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
113 #define JEWELS_SCROLLWHEEL
114 #define JEWELS_UP BUTTON_UP
115 #define JEWELS_DOWN BUTTON_DOWN
116 #define JEWELS_LEFT BUTTON_LEFT
117 #define JEWELS_RIGHT BUTTON_RIGHT
118 #define JEWELS_PREV BUTTON_SCROLL_BACK
119 #define JEWELS_NEXT BUTTON_SCROLL_FWD
120 #define JEWELS_SELECT BUTTON_SELECT
121 #define JEWELS_CANCEL (BUTTON_HOME|BUTTON_REPEAT)
123 #elif CONFIG_KEYPAD == SANSA_C200_PAD || \
124 CONFIG_KEYPAD == SANSA_CLIP_PAD || \
125 CONFIG_KEYPAD == SANSA_M200_PAD
126 #define JEWELS_UP BUTTON_UP
127 #define JEWELS_DOWN BUTTON_DOWN
128 #define JEWELS_LEFT BUTTON_LEFT
129 #define JEWELS_RIGHT BUTTON_RIGHT
130 #define JEWELS_SELECT BUTTON_SELECT
131 #define JEWELS_CANCEL BUTTON_POWER
133 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
134 #define JEWELS_UP BUTTON_SCROLL_UP
135 #define JEWELS_DOWN BUTTON_SCROLL_DOWN
136 #define JEWELS_LEFT BUTTON_LEFT
137 #define JEWELS_RIGHT BUTTON_RIGHT
138 #define JEWELS_SELECT BUTTON_PLAY
139 #define JEWELS_CANCEL BUTTON_POWER
141 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
142 #define JEWELS_UP BUTTON_UP
143 #define JEWELS_DOWN BUTTON_DOWN
144 #define JEWELS_LEFT BUTTON_LEFT
145 #define JEWELS_RIGHT BUTTON_RIGHT
146 #define JEWELS_SELECT BUTTON_SELECT
147 #define JEWELS_MENU BUTTON_MENU
148 #define JEWELS_CANCEL BUTTON_BACK
150 #elif CONFIG_KEYPAD == MROBE100_PAD
151 #define JEWELS_UP BUTTON_UP
152 #define JEWELS_DOWN BUTTON_DOWN
153 #define JEWELS_LEFT BUTTON_LEFT
154 #define JEWELS_RIGHT BUTTON_RIGHT
155 #define JEWELS_SELECT BUTTON_SELECT
156 #define JEWELS_CANCEL BUTTON_POWER
158 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
159 #define JEWELS_UP BUTTON_RC_VOL_UP
160 #define JEWELS_DOWN BUTTON_RC_VOL_DOWN
161 #define JEWELS_LEFT BUTTON_RC_REW
162 #define JEWELS_RIGHT BUTTON_RC_FF
163 #define JEWELS_SELECT BUTTON_RC_PLAY
164 #define JEWELS_CANCEL BUTTON_RC_REC
166 #define JEWELS_RC_CANCEL BUTTON_REC
168 #elif CONFIG_KEYPAD == COWOND2_PAD
169 #define JEWELS_CANCEL BUTTON_POWER
171 #elif CONFIG_KEYPAD == IAUDIO67_PAD
172 #define JEWELS_UP BUTTON_STOP
173 #define JEWELS_DOWN BUTTON_PLAY
174 #define JEWELS_LEFT BUTTON_LEFT
175 #define JEWELS_RIGHT BUTTON_RIGHT
176 #define JEWELS_SELECT BUTTON_MENU
177 #define JEWELS_CANCEL BUTTON_POWER
179 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
180 #define JEWELS_UP BUTTON_UP
181 #define JEWELS_DOWN BUTTON_DOWN
182 #define JEWELS_LEFT BUTTON_LEFT
183 #define JEWELS_RIGHT BUTTON_RIGHT
184 #define JEWELS_SELECT BUTTON_SELECT
185 #define JEWELS_CANCEL BUTTON_BACK
187 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
188 #define JEWELS_UP BUTTON_UP
189 #define JEWELS_DOWN BUTTON_DOWN
190 #define JEWELS_LEFT BUTTON_LEFT
191 #define JEWELS_RIGHT BUTTON_RIGHT
192 #define JEWELS_SELECT BUTTON_SELECT
193 #define JEWELS_CANCEL BUTTON_POWER
195 #elif CONFIG_KEYPAD == ONDAVX747_PAD || CONFIG_KEYPAD == MROBE500_PAD
196 #define JEWELS_CANCEL BUTTON_POWER
199 #error No keymap defined!
202 #ifdef HAVE_TOUCHSCREEN
204 #define JEWELS_UP BUTTON_TOPMIDDLE
207 #define JEWELS_DOWN BUTTON_BOTTOMMIDDLE
210 #define JEWELS_LEFT BUTTON_MIDLEFT
213 #define JEWELS_RIGHT BUTTON_MIDRIGHT
215 #ifndef JEWELS_SELECT
216 #define JEWELS_SELECT BUTTON_CENTER
218 #ifndef JEWELS_CANCEL
219 #define JEWELS_CANCEL BUTTON_TOPLEFT
223 /* use 30x30 tiles (iPod Video, Gigabeat, Onda VX747) */
224 #if (LCD_HEIGHT == 240) && (LCD_WIDTH == 320) || \
225 ((LCD_HEIGHT == 320) && (LCD_WIDTH == 240)) || \
226 ((LCD_HEIGHT == 400) && (LCD_WIDTH == 240))
227 #define TILE_WIDTH 30
228 #define TILE_HEIGHT 30
230 #define NUM_SCORES 10
232 /* use 22x22 tiles (H300, iPod Color) */
233 #elif ((LCD_HEIGHT == 176) && (LCD_WIDTH == 220)) || \
234 ((LCD_HEIGHT == 220) && (LCD_WIDTH == 176))
235 #define TILE_WIDTH 22
236 #define TILE_HEIGHT 22
238 #define NUM_SCORES 10
240 /* use 16x16 tiles (iPod Nano) */
241 #elif (LCD_HEIGHT == 132) && (LCD_WIDTH == 176)
242 #define TILE_WIDTH 16
243 #define TILE_HEIGHT 16
245 #define NUM_SCORES 10
247 /* use 16x16 tiles (H100, iAudio X5, iPod 3G, iPod 4G grayscale) */
248 #elif (LCD_HEIGHT == 128) && (LCD_WIDTH == 160)
249 #define TILE_WIDTH 16
250 #define TILE_HEIGHT 16
252 #define NUM_SCORES 10
254 /* use 14x14 tiles (H10 5/6 GB) */
255 #elif (LCD_HEIGHT == 128) && (LCD_WIDTH == 128)
256 #define TILE_WIDTH 14
257 #define TILE_HEIGHT 14
259 #define NUM_SCORES 10
261 /* use 13x13 tiles (iPod Mini) */
262 #elif (LCD_HEIGHT == 110) && (LCD_WIDTH == 138)
263 #define TILE_WIDTH 13
264 #define TILE_HEIGHT 13
266 #define NUM_SCORES 10
268 /* use 12x12 tiles (iAudio M3) */
269 #elif (LCD_HEIGHT == 96) && (LCD_WIDTH == 128)
270 #define TILE_WIDTH 12
271 #define TILE_HEIGHT 12
275 /* use 10x10 tiles (Sansa c200) */
276 #elif (LCD_HEIGHT == 80) && (LCD_WIDTH == 132)
277 #define TILE_WIDTH 10
278 #define TILE_HEIGHT 10
282 /* use 10x8 tiles (iFP 700) */
283 #elif (LCD_HEIGHT == 64) && (LCD_WIDTH == 128)
284 #define TILE_WIDTH 10
285 #define TILE_HEIGHT 8
289 /* use 10x8 tiles (Recorder, Ondio) */
290 #elif (LCD_HEIGHT == 64) && (LCD_WIDTH == 112)
291 #define TILE_WIDTH 10
292 #define TILE_HEIGHT 8
297 #error JEWELS: Unsupported LCD
301 #define SCORE_FILE PLUGIN_GAMES_DIR "/jewels.score"
302 #define SAVE_FILE PLUGIN_GAMES_DIR "/jewels.save"
304 /* final game return status */
305 #define BJ_QUIT_FROM_GAME 4
311 /* swap directions */
317 /* play board dimension */
321 /* next level threshold */
322 #define LEVEL_PTS 100
324 /* animation frame rate */
334 #define FONT_HEIGHT 8
336 #define MENU_WIDTH 100
366 struct jewels_menuitem
{
368 enum menu_result res
;
371 {"Jewels", false, 0, 6,
372 {{"New Game", MRES_NEW
},
373 {"Puzzle", MRES_PUZZLE
},
374 {"Resume Saved Game", MRES_RESUME
},
375 {"High Scores", MRES_SCORES
},
377 {"Quit", MRES_QUIT
}}},
379 {{"Audio Playback", MRES_PLAYBACK
},
380 {"Resume Game", MRES_RESUME
},
381 {"Save Game", MRES_SAVE
},
382 {"End Game", MRES_QUIT
},
383 {"Exit Jewels", MRES_EXIT
}}}
386 /* external bitmaps */
387 extern const fb_data jewels
[];
389 /* tile background colors */
390 #ifdef HAVE_LCD_COLOR
391 static const unsigned jewels_bkgd
[2] = {
392 LCD_RGBPACK(104, 63, 63),
393 LCD_RGBPACK(83, 44, 44)
398 * type is the jewel number 0-7
399 * falling if the jewel is falling
400 * delete marks the jewel for deletion
408 /* the game context struct
409 * score is the current level score
410 * segments is the number of cleared segments in the current run
411 * level is the current level
412 * type is the game type (normal or puzzle)
413 * highscores is the list of high scores
414 * resume denotes whether to resume the currently loaded game
415 * dirty denotes whether the high scores are out of sync with the saved file
416 * playboard is the game playing board (first row is hidden)
417 * num_jewels is the number of different jewels to use
419 struct game_context
{
421 unsigned int segments
;
424 unsigned int highscores
[NUM_SCORES
];
427 struct tile playboard
[BJ_HEIGHT
][BJ_WIDTH
];
428 unsigned int num_jewels
;
431 #define MAX_NUM_JEWELS 7
433 #define MAX_PUZZLE_TILES 4
434 #define NUM_PUZZLE_LEVELS 10
442 struct puzzle_level
{
443 unsigned int num_jewels
;
444 unsigned int num_tiles
;
445 struct puzzle_tile tiles
[MAX_PUZZLE_TILES
];
448 #define PUZZLE_TILE_UP 1
449 #define PUZZLE_TILE_DOWN 2
450 #define PUZZLE_TILE_LEFT 4
451 #define PUZZLE_TILE_RIGHT 8
453 struct puzzle_level puzzle_levels
[NUM_PUZZLE_LEVELS
] = {
454 { 5, 2, { {3, 3, PUZZLE_TILE_RIGHT
},
455 {4, 2, PUZZLE_TILE_LEFT
} } },
456 { 5, 2, { {3, 2, PUZZLE_TILE_DOWN
},
457 {3, 4, PUZZLE_TILE_UP
} } },
458 { 6, 3, { {3, 2, PUZZLE_TILE_DOWN
},
459 {3, 4, PUZZLE_TILE_UP
|PUZZLE_TILE_DOWN
},
460 {3, 6, PUZZLE_TILE_UP
} } },
461 { 6, 3, { {3, 2, PUZZLE_TILE_RIGHT
},
462 {4, 3, PUZZLE_TILE_LEFT
|PUZZLE_TILE_RIGHT
},
463 {5, 4, PUZZLE_TILE_LEFT
} } },
464 { 6, 2, { {3, 4, PUZZLE_TILE_RIGHT
},
465 {4, 2, PUZZLE_TILE_LEFT
} } },
466 { 6, 2, { {3, 2, PUZZLE_TILE_DOWN
},
467 {4, 4, PUZZLE_TILE_UP
} } },
468 { 7, 4, { {3, 2, PUZZLE_TILE_RIGHT
|PUZZLE_TILE_DOWN
},
469 {4, 3, PUZZLE_TILE_LEFT
|PUZZLE_TILE_DOWN
},
470 {3, 4, PUZZLE_TILE_RIGHT
|PUZZLE_TILE_UP
},
471 {4, 4, PUZZLE_TILE_LEFT
|PUZZLE_TILE_UP
} } },
472 { 6, 3, { {3, 2, PUZZLE_TILE_DOWN
},
473 {4, 4, PUZZLE_TILE_UP
|PUZZLE_TILE_DOWN
},
474 {3, 6, PUZZLE_TILE_UP
} } },
475 { 7, 3, { {2, 2, PUZZLE_TILE_RIGHT
},
476 {4, 1, PUZZLE_TILE_LEFT
|PUZZLE_TILE_RIGHT
},
477 {5, 4, PUZZLE_TILE_LEFT
} } },
478 { 7, 4, { {3, 0, PUZZLE_TILE_RIGHT
|PUZZLE_TILE_DOWN
},
479 {5, 0, PUZZLE_TILE_LEFT
|PUZZLE_TILE_DOWN
},
480 {2, 7, PUZZLE_TILE_RIGHT
|PUZZLE_TILE_UP
},
481 {4, 7, PUZZLE_TILE_LEFT
|PUZZLE_TILE_UP
} } },
484 /*****************************************************************************
485 * jewels_init() initializes jewels data structures.
486 ******************************************************************************/
487 static void jewels_init(struct game_context
* bj
) {
488 /* seed the rand generator */
489 rb
->srand(*rb
->current_tick
);
491 /* check for resumed game */
502 /* clear playing board */
503 rb
->memset(bj
->playboard
, 0, sizeof(bj
->playboard
));
506 /*****************************************************************************
507 * jewels_setcolors() set the foreground and background colors.
508 ******************************************************************************/
509 static inline void jewels_setcolors(void) {
510 #ifdef HAVE_LCD_COLOR
511 rb
->lcd_set_background(LCD_RGBPACK(49, 26, 26));
512 rb
->lcd_set_foreground(LCD_RGBPACK(210, 181, 181));
516 /*****************************************************************************
517 * jewels_drawboard() redraws the entire game board.
518 ******************************************************************************/
519 static void jewels_drawboard(struct game_context
* bj
) {
522 unsigned int tempscore
;
523 char *title
= "Level";
526 tempscore
= (bj
->score
>LEVEL_PTS
? LEVEL_PTS
: bj
->score
);
529 rb
->lcd_clear_display();
531 /* dispay playing board */
532 for(i
=0; i
<BJ_HEIGHT
-1; i
++){
533 for(j
=0; j
<BJ_WIDTH
; j
++){
534 #ifdef HAVE_LCD_COLOR
535 rb
->lcd_set_foreground(jewels_bkgd
[(i
+j
)%2]);
536 rb
->lcd_fillrect(j
*TILE_WIDTH
, i
*TILE_HEIGHT
+YOFS
,
537 TILE_WIDTH
, TILE_HEIGHT
);
538 rb
->lcd_bitmap_transparent_part(jewels
,
539 0, TILE_HEIGHT
*(bj
->playboard
[i
+1][j
].type
),
540 TILE_WIDTH
, j
*TILE_WIDTH
, i
*TILE_HEIGHT
+YOFS
,
541 TILE_WIDTH
, TILE_HEIGHT
);
543 rb
->lcd_bitmap_part(jewels
,
544 0, TILE_HEIGHT
*(bj
->playboard
[i
+1][j
].type
),
545 TILE_WIDTH
, j
*TILE_WIDTH
, i
*TILE_HEIGHT
+YOFS
,
546 TILE_WIDTH
, TILE_HEIGHT
);
551 #if LCD_WIDTH > LCD_HEIGHT /* horizontal layout */
553 /* draw separator lines */
555 rb
->lcd_vline(BJ_WIDTH
*TILE_WIDTH
, 0, LCD_HEIGHT
-1);
556 rb
->lcd_hline(BJ_WIDTH
*TILE_WIDTH
, LCD_WIDTH
-1, 18);
557 rb
->lcd_hline(BJ_WIDTH
*TILE_WIDTH
, LCD_WIDTH
-1, LCD_HEIGHT
-10);
559 /* draw progress bar */
560 #ifdef HAVE_LCD_COLOR
561 rb
->lcd_set_foreground(LCD_RGBPACK(104, 63, 63));
563 rb
->lcd_fillrect(BJ_WIDTH
*TILE_WIDTH
+(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/4,
564 (LCD_HEIGHT
-10)-(((LCD_HEIGHT
-10)-18)*
565 tempscore
/LEVEL_PTS
),
566 (LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2,
567 ((LCD_HEIGHT
-10)-18)*tempscore
/LEVEL_PTS
);
568 #ifdef HAVE_LCD_COLOR
569 rb
->lcd_set_foreground(LCD_RGBPACK(83, 44, 44));
570 rb
->lcd_drawrect(BJ_WIDTH
*TILE_WIDTH
+(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/4+1,
571 (LCD_HEIGHT
-10)-(((LCD_HEIGHT
-10)-18)*
572 tempscore
/LEVEL_PTS
)+1,
573 (LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2-2,
574 ((LCD_HEIGHT
-10)-18)*tempscore
/LEVEL_PTS
-1);
576 rb
->lcd_drawrect(BJ_WIDTH
*TILE_WIDTH
+(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/4,
577 (LCD_HEIGHT
-10)-(((LCD_HEIGHT
-10)-18)*
578 tempscore
/LEVEL_PTS
),
579 (LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2,
580 ((LCD_HEIGHT
-10)-18)*tempscore
/LEVEL_PTS
+1);
584 rb
->lcd_getstringsize(title
, &w
, &h
);
585 rb
->lcd_putsxy(LCD_WIDTH
-(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2-w
/2, 1, title
);
587 rb
->snprintf(str
, 4, "%d", bj
->level
);
588 rb
->lcd_getstringsize(str
, &w
, &h
);
589 rb
->lcd_putsxy(LCD_WIDTH
-(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2-w
/2, 10, str
);
591 rb
->snprintf(str
, 6, "%d", (bj
->level
-1)*LEVEL_PTS
+bj
->score
);
592 rb
->lcd_getstringsize(str
, &w
, &h
);
593 rb
->lcd_putsxy(LCD_WIDTH
-(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2-w
/2,
596 #elif LCD_WIDTH < LCD_HEIGHT /* vertical layout */
598 /* draw separator lines */
600 rb
->lcd_hline(0, LCD_WIDTH
-1, 8*TILE_HEIGHT
+YOFS
);
601 rb
->lcd_hline(0, LCD_WIDTH
-1, LCD_HEIGHT
-14);
602 rb
->lcd_vline(LCD_WIDTH
/2, LCD_HEIGHT
-14, LCD_HEIGHT
-1);
604 /* draw progress bar */
605 #ifdef HAVE_LCD_COLOR
606 rb
->lcd_set_foreground(LCD_RGBPACK(104, 63, 63));
608 rb
->lcd_fillrect(0, (8*TILE_HEIGHT
+YOFS
)
609 +(LCD_HEIGHT
-14-(8*TILE_HEIGHT
+YOFS
))/4,
610 LCD_WIDTH
*tempscore
/LEVEL_PTS
,
611 (LCD_HEIGHT
-14-(8*TILE_HEIGHT
+YOFS
))/2);
612 #ifdef HAVE_LCD_COLOR
613 rb
->lcd_set_foreground(LCD_RGBPACK(83, 44, 44));
614 rb
->lcd_drawrect(1, (8*TILE_HEIGHT
+YOFS
)
615 +(LCD_HEIGHT
-14-(8*TILE_HEIGHT
+YOFS
))/4+1,
616 LCD_WIDTH
*tempscore
/LEVEL_PTS
-1,
617 (LCD_HEIGHT
-14-(8*TILE_HEIGHT
+YOFS
))/2-2);
619 rb
->lcd_drawrect(0, (8*TILE_HEIGHT
+YOFS
)
620 +(LCD_HEIGHT
-14-(8*TILE_HEIGHT
+YOFS
))/4,
621 LCD_WIDTH
*tempscore
/LEVEL_PTS
+1,
622 (LCD_HEIGHT
-14-(8*TILE_HEIGHT
+YOFS
))/2);
626 rb
->snprintf(str
, 10, "%s %d", title
, bj
->level
);
627 rb
->lcd_putsxy(1, LCD_HEIGHT
-10, str
);
629 rb
->snprintf(str
, 6, "%d", (bj
->level
-1)*LEVEL_PTS
+bj
->score
);
630 rb
->lcd_getstringsize(str
, &w
, &h
);
631 rb
->lcd_putsxy((LCD_WIDTH
-2)-w
, LCD_HEIGHT
-10, str
);
633 #else /* square layout */
635 /* draw separator lines */
637 rb
->lcd_hline(0, LCD_WIDTH
-1, 8*TILE_HEIGHT
+YOFS
);
638 rb
->lcd_vline(BJ_WIDTH
*TILE_WIDTH
, 0, 8*TILE_HEIGHT
+YOFS
);
639 rb
->lcd_vline(LCD_WIDTH
/2, 8*TILE_HEIGHT
+YOFS
, LCD_HEIGHT
-1);
641 /* draw progress bar */
642 #ifdef HAVE_LCD_COLOR
643 rb
->lcd_set_foreground(LCD_RGBPACK(104, 63, 63));
645 rb
->lcd_fillrect(BJ_WIDTH
*TILE_WIDTH
+(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/4,
646 (8*TILE_HEIGHT
+YOFS
)-(8*TILE_HEIGHT
+YOFS
)
647 *tempscore
/LEVEL_PTS
,
648 (LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2,
649 (8*TILE_HEIGHT
+YOFS
)*tempscore
/LEVEL_PTS
);
650 #ifdef HAVE_LCD_COLOR
651 rb
->lcd_set_foreground(LCD_RGBPACK(83, 44, 44));
652 rb
->lcd_drawrect(BJ_WIDTH
*TILE_WIDTH
+(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/4+1,
653 (8*TILE_HEIGHT
+YOFS
)-(8*TILE_HEIGHT
+YOFS
)
654 *tempscore
/LEVEL_PTS
+1,
655 (LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2-2,
656 (8*TILE_HEIGHT
+YOFS
)*tempscore
/LEVEL_PTS
-1);
658 rb
->lcd_drawrect(BJ_WIDTH
*TILE_WIDTH
+(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/4,
659 (8*TILE_HEIGHT
+YOFS
)-(8*TILE_HEIGHT
+YOFS
)
660 *tempscore
/LEVEL_PTS
,
661 (LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2,
662 (8*TILE_HEIGHT
+YOFS
)*tempscore
/LEVEL_PTS
+1);
666 rb
->snprintf(str
, 10, "%s %d", title
, bj
->level
);
667 rb
->lcd_putsxy(1, LCD_HEIGHT
-(LCD_HEIGHT
-(8*TILE_HEIGHT
+YOFS
))/2-3, str
);
669 rb
->snprintf(str
, 6, "%d", (bj
->level
-1)*LEVEL_PTS
+bj
->score
);
670 rb
->lcd_getstringsize(str
, &w
, &h
);
671 rb
->lcd_putsxy((LCD_WIDTH
-2)-w
,
672 LCD_HEIGHT
-(LCD_HEIGHT
-(8*TILE_HEIGHT
+YOFS
))/2-3, str
);
679 /*****************************************************************************
680 * jewels_showmenu() displays the chosen menu after performing the chosen
682 ******************************************************************************/
683 static enum menu_result
jewels_showmenu(struct jewels_menu
* menu
,
689 int extraline
= LCD_HEIGHT
<= ((menu
->itemcnt
+2)*FONT_HEIGHT
) ? 0 : 1;
691 /* handle menu command */
694 menu
->selected
= (menu
->selected
+1)%menu
->itemcnt
;
698 menu
->selected
= (menu
->selected
-1+menu
->itemcnt
)%menu
->itemcnt
;
702 return menu
->items
[menu
->selected
].res
;
708 /* clear menu area */
709 firstline
= (LCD_HEIGHT
/FONT_HEIGHT
-(menu
->itemcnt
+3))/2;
711 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
712 rb
->lcd_fillrect((LCD_WIDTH
-MENU_WIDTH
)/2, firstline
*FONT_HEIGHT
,
713 MENU_WIDTH
, (menu
->itemcnt
+3)*FONT_HEIGHT
);
714 rb
->lcd_set_drawmode(DRMODE_SOLID
);
717 rb
->lcd_drawrect((LCD_WIDTH
-MENU_WIDTH
)/2-1, firstline
*FONT_HEIGHT
-1,
718 MENU_WIDTH
+2, (menu
->itemcnt
+3)*FONT_HEIGHT
+2);
719 rb
->lcd_hline((LCD_WIDTH
-MENU_WIDTH
)/2-1,
720 (LCD_WIDTH
-MENU_WIDTH
)/2-1+MENU_WIDTH
+2,
721 (firstline
+1)*FONT_HEIGHT
);
724 /* draw menu items */
725 rb
->lcd_getstringsize(menu
->title
, &w
, &h
);
726 rb
->lcd_putsxy((LCD_WIDTH
-w
)/2, firstline
*FONT_HEIGHT
, menu
->title
);
728 for(i
=0; i
<menu
->itemcnt
; i
++) {
729 if(i
== menu
->selected
) {
730 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
732 rb
->lcd_putsxy((LCD_WIDTH
-MENU_WIDTH
)/2,
733 (firstline
+i
+1+extraline
)*FONT_HEIGHT
,
734 menu
->items
[i
].text
);
735 if(i
== menu
->selected
) {
736 rb
->lcd_set_drawmode(DRMODE_SOLID
);
740 adj
= (firstline
== 0 ? 0 : 1);
741 rb
->lcd_update_rect((LCD_WIDTH
-MENU_WIDTH
)/2-1, firstline
*FONT_HEIGHT
-adj
,
742 MENU_WIDTH
+2, (menu
->itemcnt
+3)*FONT_HEIGHT
+2*adj
);
746 /*****************************************************************************
747 * jewels_putjewels() makes the jewels fall to fill empty spots and adds
748 * new random jewels at the empty spots at the top of each row.
749 ******************************************************************************/
750 static void jewels_putjewels(struct game_context
* bj
){
753 long lasttick
, currenttick
;
755 /* loop to make all the jewels fall */
757 /* mark falling jewels and add new jewels to hidden top row*/
760 for(j
=0; j
<BJ_WIDTH
; j
++) {
761 if(bj
->playboard
[1][j
].type
== 0) {
762 bj
->playboard
[0][j
].type
= rb
->rand()%bj
->num_jewels
+1;
764 for(i
=BJ_HEIGHT
-2; i
>=0; i
--) {
765 if(!mark
&& bj
->playboard
[i
+1][j
].type
== 0) {
769 if(mark
) bj
->playboard
[i
][j
].falling
= true;
771 /*if(bj->playboard[1][j].falling) {
772 bj->playboard[0][j].type = rb->rand()%bj->num_jewels+1;
773 bj->playboard[0][j].falling = true;
778 /* break if there are no falling jewels */
781 /* animate falling jewels */
782 lasttick
= *rb
->current_tick
;
784 for(k
=1; k
<=8; k
++) {
785 for(i
=BJ_HEIGHT
-2; i
>=0; i
--) {
786 for(j
=0; j
<BJ_WIDTH
; j
++) {
787 if(bj
->playboard
[i
][j
].falling
&&
788 bj
->playboard
[i
][j
].type
!= 0) {
789 /* clear old position */
790 #ifdef HAVE_LCD_COLOR
792 rb
->lcd_set_foreground(rb
->lcd_get_background());
794 rb
->lcd_set_foreground(jewels_bkgd
[(i
-1+j
)%2]);
796 rb
->lcd_fillrect(j
*TILE_WIDTH
, (i
-1)*TILE_HEIGHT
+YOFS
,
797 TILE_WIDTH
, TILE_HEIGHT
);
798 if(bj
->playboard
[i
+1][j
].type
== 0) {
799 rb
->lcd_set_foreground(jewels_bkgd
[(i
+j
)%2]);
800 rb
->lcd_fillrect(j
*TILE_WIDTH
, i
*TILE_HEIGHT
+YOFS
,
801 TILE_WIDTH
, TILE_HEIGHT
);
804 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
805 rb
->lcd_fillrect(j
*TILE_WIDTH
, (i
-1)*TILE_HEIGHT
+YOFS
,
806 TILE_WIDTH
, TILE_HEIGHT
);
807 if(bj
->playboard
[i
+1][j
].type
== 0) {
808 rb
->lcd_fillrect(j
*TILE_WIDTH
, i
*TILE_HEIGHT
+YOFS
,
809 TILE_WIDTH
, TILE_HEIGHT
);
811 rb
->lcd_set_drawmode(DRMODE_SOLID
);
814 /* draw new position */
815 #ifdef HAVE_LCD_COLOR
816 rb
->lcd_bitmap_transparent_part(jewels
, 0,
817 TILE_HEIGHT
*(bj
->playboard
[i
][j
].type
),
818 TILE_WIDTH
, j
*TILE_WIDTH
,
819 (i
-1)*TILE_HEIGHT
+YOFS
+
820 ((((TILE_HEIGHT
<<10)*k
)/8)>>10),
821 TILE_WIDTH
, TILE_HEIGHT
);
823 rb
->lcd_bitmap_part(jewels
, 0,
824 TILE_HEIGHT
*(bj
->playboard
[i
][j
].type
),
825 TILE_WIDTH
, j
*TILE_WIDTH
,
826 (i
-1)*TILE_HEIGHT
+YOFS
+
827 ((((TILE_HEIGHT
<<10)*k
)/8)>>10),
828 TILE_WIDTH
, TILE_HEIGHT
);
834 rb
->lcd_update_rect(0, 0, TILE_WIDTH
*8, LCD_HEIGHT
);
837 /* framerate limiting */
838 currenttick
= *rb
->current_tick
;
839 if(currenttick
-lasttick
< HZ
/MAX_FPS
) {
840 rb
->sleep((HZ
/MAX_FPS
)-(currenttick
-lasttick
));
844 lasttick
= currenttick
;
847 /* shift jewels down */
848 for(j
=0; j
<BJ_WIDTH
; j
++) {
849 for(i
=BJ_HEIGHT
-1; i
>=1; i
--) {
850 if(bj
->playboard
[i
-1][j
].falling
) {
851 bj
->playboard
[i
][j
].type
= bj
->playboard
[i
-1][j
].type
;
856 /* clear out top row */
857 for(j
=0; j
<BJ_WIDTH
; j
++) {
858 bj
->playboard
[0][j
].type
= 0;
861 /* mark everything not falling */
862 for(i
=0; i
<BJ_HEIGHT
; i
++) {
863 for(j
=0; j
<BJ_WIDTH
; j
++) {
864 bj
->playboard
[i
][j
].falling
= false;
870 /*****************************************************************************
871 * jewels_clearjewels() finds all the connected rows and columns and
872 * calculates and returns the points earned.
873 ******************************************************************************/
874 static unsigned int jewels_clearjewels(struct game_context
* bj
) {
877 unsigned int points
= 0;
879 /* check for connected rows */
880 for(i
=1; i
<BJ_HEIGHT
; i
++) {
883 for(j
=0; j
<BJ_WIDTH
; j
++) {
884 if(bj
->playboard
[i
][j
].type
== last
&&
885 bj
->playboard
[i
][j
].type
!= 0 &&
886 bj
->playboard
[i
][j
].type
<= MAX_NUM_JEWELS
) {
891 points
+= bj
->segments
;
892 bj
->playboard
[i
][j
].delete = true;
893 bj
->playboard
[i
][j
-1].delete = true;
894 bj
->playboard
[i
][j
-2].delete = true;
897 bj
->playboard
[i
][j
].delete = true;
901 last
= bj
->playboard
[i
][j
].type
;
906 /* check for connected columns */
907 for(j
=0; j
<BJ_WIDTH
; j
++) {
910 for(i
=1; i
<BJ_HEIGHT
; i
++) {
911 if(bj
->playboard
[i
][j
].type
!= 0 &&
912 bj
->playboard
[i
][j
].type
== last
&&
913 bj
->playboard
[i
][j
].type
<= MAX_NUM_JEWELS
) {
918 points
+= bj
->segments
;
919 bj
->playboard
[i
][j
].delete = true;
920 bj
->playboard
[i
-1][j
].delete = true;
921 bj
->playboard
[i
-2][j
].delete = true;
924 bj
->playboard
[i
][j
].delete = true;
928 last
= bj
->playboard
[i
][j
].type
;
933 /* clear deleted jewels */
934 for(i
=1; i
<BJ_HEIGHT
; i
++) {
935 for(j
=0; j
<BJ_WIDTH
; j
++) {
936 if(bj
->playboard
[i
][j
].delete) {
937 bj
->playboard
[i
][j
].delete = false;
938 bj
->playboard
[i
][j
].type
= 0;
946 /*****************************************************************************
947 * jewels_runboard() runs the board until it settles in a fixed state and
948 * returns points earned.
949 ******************************************************************************/
950 static unsigned int jewels_runboard(struct game_context
* bj
) {
951 unsigned int points
= 0;
956 while((ret
= jewels_clearjewels(bj
)) > 0) {
958 jewels_drawboard(bj
);
959 jewels_putjewels(bj
);
965 /*****************************************************************************
966 * jewels_swapjewels() swaps two jewels as long as it results in points and
967 * returns points earned.
968 ******************************************************************************/
969 static unsigned int jewels_swapjewels(struct game_context
* bj
,
970 int x
, int y
, int direc
) {
972 int horzmod
, vertmod
;
975 unsigned int points
= 0;
976 long lasttick
, currenttick
;
978 /* check for invalid parameters */
979 if(x
< 0 || x
>= BJ_WIDTH
|| y
< 0 || y
>= BJ_HEIGHT
-1 ||
980 direc
< SWAP_UP
|| direc
> SWAP_LEFT
) {
984 /* check for invalid directions */
985 if((x
== 0 && direc
== SWAP_LEFT
) ||
986 (x
== BJ_WIDTH
-1 && direc
== SWAP_RIGHT
) ||
987 (y
== 0 && direc
== SWAP_UP
) ||
988 (y
== BJ_HEIGHT
-2 && direc
== SWAP_DOWN
)) {
992 /* set direction variables */
998 movelen
= TILE_HEIGHT
;
1002 movelen
= TILE_WIDTH
;
1006 movelen
= TILE_HEIGHT
;
1010 movelen
= TILE_WIDTH
;
1015 lasttick
= *rb
->current_tick
;
1017 /* animate swapping jewels */
1018 for(k
=0; k
<=8; k
++) {
1019 /* clear old position */
1020 #ifdef HAVE_LCD_COLOR
1021 rb
->lcd_set_foreground(jewels_bkgd
[(x
+y
)%2]);
1022 rb
->lcd_fillrect(x
*TILE_WIDTH
,
1024 TILE_WIDTH
, TILE_HEIGHT
);
1025 rb
->lcd_set_foreground(jewels_bkgd
[(x
+horzmod
+y
+vertmod
)%2]);
1026 rb
->lcd_fillrect((x
+horzmod
)*TILE_WIDTH
,
1027 (y
+vertmod
)*TILE_HEIGHT
+YOFS
,
1028 TILE_WIDTH
, TILE_HEIGHT
);
1030 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
1031 rb
->lcd_fillrect(x
*TILE_WIDTH
,
1033 TILE_WIDTH
, TILE_HEIGHT
);
1034 rb
->lcd_fillrect((x
+horzmod
)*TILE_WIDTH
,
1035 (y
+vertmod
)*TILE_HEIGHT
+YOFS
,
1036 TILE_WIDTH
, TILE_HEIGHT
);
1037 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1039 /* draw new position */
1040 #ifdef HAVE_LCD_COLOR
1041 rb
->lcd_bitmap_transparent_part(jewels
,
1042 0, TILE_HEIGHT
*(bj
->playboard
1043 [y
+1+vertmod
][x
+horzmod
].type
), TILE_WIDTH
,
1044 (x
+horzmod
)*TILE_WIDTH
-horzmod
*
1045 ((((movelen
<<10)*k
)/8)>>10),
1046 (y
+vertmod
)*TILE_HEIGHT
-vertmod
*
1047 ((((movelen
<<10)*k
)/8)>>10)+YOFS
,
1048 TILE_WIDTH
, TILE_HEIGHT
);
1049 rb
->lcd_bitmap_transparent_part(jewels
,
1050 0, TILE_HEIGHT
*(bj
->playboard
[y
+1][x
].type
),
1051 TILE_WIDTH
, x
*TILE_WIDTH
+horzmod
*
1052 ((((movelen
<<10)*k
)/8)>>10),
1053 y
*TILE_HEIGHT
+vertmod
*
1054 ((((movelen
<<10)*k
)/8)>>10)+YOFS
,
1055 TILE_WIDTH
, TILE_HEIGHT
);
1057 rb
->lcd_bitmap_part(jewels
,
1058 0, TILE_HEIGHT
*(bj
->playboard
1059 [y
+1+vertmod
][x
+horzmod
].type
), TILE_WIDTH
,
1060 (x
+horzmod
)*TILE_WIDTH
-horzmod
*
1061 ((((movelen
<<10)*k
)/8)>>10),
1062 (y
+vertmod
)*TILE_HEIGHT
-vertmod
*
1063 ((((movelen
<<10)*k
)/8)>>10)+YOFS
,
1064 TILE_WIDTH
, TILE_HEIGHT
);
1065 rb
->lcd_set_drawmode(DRMODE_FG
);
1066 rb
->lcd_bitmap_part(jewels
,
1067 0, TILE_HEIGHT
*(bj
->playboard
[y
+1][x
].type
),
1068 TILE_WIDTH
, x
*TILE_WIDTH
+horzmod
*
1069 ((((movelen
<<10)*k
)/8)>>10),
1070 y
*TILE_HEIGHT
+vertmod
*
1071 ((((movelen
<<10)*k
)/8)>>10)+YOFS
,
1072 TILE_WIDTH
, TILE_HEIGHT
);
1073 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1076 rb
->lcd_update_rect(0, 0, TILE_WIDTH
*8, LCD_HEIGHT
);
1079 /* framerate limiting */
1080 currenttick
= *rb
->current_tick
;
1081 if(currenttick
-lasttick
< HZ
/MAX_FPS
) {
1082 rb
->sleep((HZ
/MAX_FPS
)-(currenttick
-lasttick
));
1086 lasttick
= currenttick
;
1090 int temp
= bj
->playboard
[y
+1][x
].type
;
1091 bj
->playboard
[y
+1][x
].type
=
1092 bj
->playboard
[y
+1+vertmod
][x
+horzmod
].type
;
1093 bj
->playboard
[y
+1+vertmod
][x
+horzmod
].type
= temp
;
1097 points
= jewels_runboard(bj
);
1108 /*****************************************************************************
1109 * jewels_movesavail() uses pattern matching to see if there are any
1110 * available move left.
1111 ******************************************************************************/
1112 static bool jewels_movesavail(struct game_context
* bj
) {
1117 for(i
=1; i
<BJ_HEIGHT
; i
++) {
1118 for(j
=0; j
<BJ_WIDTH
; j
++) {
1119 mytype
= bj
->playboard
[i
][j
].type
;
1120 if(mytype
== 0 || mytype
> MAX_NUM_JEWELS
) continue;
1122 /* check horizontal patterns */
1123 if(j
<= BJ_WIDTH
-3) {
1125 if(bj
->playboard
[i
-1][j
+1].type
== mytype
) {
1126 if(bj
->playboard
[i
-1][j
+2].type
== mytype
)
1127 {moves
= true; break;}
1128 if(bj
->playboard
[i
][j
+2].type
== mytype
)
1129 {moves
= true; break;}
1131 if(bj
->playboard
[i
][j
+1].type
== mytype
) {
1132 if(bj
->playboard
[i
-1][j
+2].type
== mytype
)
1133 {moves
= true; break;}
1137 if(j
<= BJ_WIDTH
-4) {
1138 if(bj
->playboard
[i
][j
+3].type
== mytype
) {
1139 if(bj
->playboard
[i
][j
+1].type
== mytype
)
1140 {moves
= true; break;}
1141 if(bj
->playboard
[i
][j
+2].type
== mytype
)
1142 {moves
= true; break;}
1146 if(i
< BJ_HEIGHT
-1) {
1147 if(bj
->playboard
[i
][j
+1].type
== mytype
) {
1148 if(bj
->playboard
[i
+1][j
+2].type
== mytype
)
1149 {moves
= true; break;}
1151 if(bj
->playboard
[i
+1][j
+1].type
== mytype
) {
1152 if(bj
->playboard
[i
][j
+2].type
== mytype
)
1153 {moves
= true; break;}
1154 if(bj
->playboard
[i
+1][j
+2].type
== mytype
)
1155 {moves
= true; break;}
1160 /* check vertical patterns */
1161 if(i
<= BJ_HEIGHT
-3) {
1163 if(bj
->playboard
[i
+1][j
-1].type
== mytype
) {
1164 if(bj
->playboard
[i
+2][j
-1].type
== mytype
)
1165 {moves
= true; break;}
1166 if(bj
->playboard
[i
+2][j
].type
== mytype
)
1167 {moves
= true; break;}
1169 if(bj
->playboard
[i
+1][j
].type
== mytype
) {
1170 if(bj
->playboard
[i
+2][j
-1].type
== mytype
)
1171 {moves
= true; break;}
1175 if(i
<= BJ_HEIGHT
-4) {
1176 if(bj
->playboard
[i
+3][j
].type
== mytype
) {
1177 if(bj
->playboard
[i
+1][j
].type
== mytype
)
1178 {moves
= true; break;}
1179 if(bj
->playboard
[i
+2][j
].type
== mytype
)
1180 {moves
= true; break;}
1184 if(j
< BJ_WIDTH
-1) {
1185 if(bj
->playboard
[i
+1][j
].type
== mytype
) {
1186 if(bj
->playboard
[i
+2][j
+1].type
== mytype
)
1187 {moves
= true; break;}
1189 if(bj
->playboard
[i
+1][j
+1].type
== mytype
) {
1190 if(bj
->playboard
[i
+2][j
].type
== mytype
)
1191 {moves
= true; break;}
1192 if (bj
->playboard
[i
+2][j
+1].type
== mytype
)
1193 {moves
= true; break;}
1205 /*****************************************************************************
1206 * jewels_puzzle_is_finished(bj) checks if the puzzle is finished.
1207 ******************************************************************************/
1208 static int jewels_puzzle_is_finished(struct game_context
* bj
) {
1210 for(i
=0; i
<BJ_HEIGHT
; i
++) {
1211 for(j
=0; j
<BJ_WIDTH
; j
++) {
1212 int mytype
= bj
->playboard
[i
][j
].type
;
1213 if(mytype
>MAX_NUM_JEWELS
) {
1214 mytype
-= MAX_NUM_JEWELS
;
1215 if(mytype
&PUZZLE_TILE_UP
) {
1216 if(i
==0 || bj
->playboard
[i
-1][j
].type
<=MAX_NUM_JEWELS
||
1217 !((bj
->playboard
[i
-1][j
].type
-MAX_NUM_JEWELS
)
1221 if(mytype
&PUZZLE_TILE_DOWN
) {
1222 if(i
==BJ_HEIGHT
-1 ||
1223 bj
->playboard
[i
+1][j
].type
<=MAX_NUM_JEWELS
||
1224 !((bj
->playboard
[i
+1][j
].type
-MAX_NUM_JEWELS
)
1228 if(mytype
&PUZZLE_TILE_LEFT
) {
1229 if(j
==0 || bj
->playboard
[i
][j
-1].type
<=MAX_NUM_JEWELS
||
1230 !((bj
->playboard
[i
][j
-1].type
-MAX_NUM_JEWELS
)
1231 &PUZZLE_TILE_RIGHT
))
1234 if(mytype
&PUZZLE_TILE_RIGHT
) {
1236 bj
->playboard
[i
][j
+1].type
<=MAX_NUM_JEWELS
||
1237 !((bj
->playboard
[i
][j
+1].type
-MAX_NUM_JEWELS
)
1247 /*****************************************************************************
1248 * jewels_initlevel() initialises a level.
1249 ******************************************************************************/
1250 static unsigned int jewels_initlevel(struct game_context
* bj
) {
1251 unsigned int points
= 0;
1254 case GAME_TYPE_NORMAL
:
1255 bj
->num_jewels
= MAX_NUM_JEWELS
;
1258 case GAME_TYPE_PUZZLE
:
1261 struct puzzle_tile
*tile
;
1263 bj
->num_jewels
= puzzle_levels
[bj
->level
-1].num_jewels
;
1265 for(i
=0; i
<BJ_HEIGHT
; i
++) {
1266 for(j
=0; j
<BJ_WIDTH
; j
++) {
1267 bj
->playboard
[i
][j
].type
= (rb
->rand()%bj
->num_jewels
)+1;
1268 bj
->playboard
[i
][j
].falling
= false;
1269 bj
->playboard
[i
][j
].delete = false;
1272 jewels_runboard(bj
);
1273 tile
= puzzle_levels
[bj
->level
-1].tiles
;
1274 for(i
=0; i
<puzzle_levels
[bj
->level
-1].num_tiles
; i
++, tile
++) {
1275 bj
->playboard
[tile
->y
+1][tile
->x
].type
= MAX_NUM_JEWELS
1282 jewels_drawboard(bj
);
1284 /* run the play board */
1285 jewels_putjewels(bj
);
1286 points
+= jewels_runboard(bj
);
1290 /*****************************************************************************
1291 * jewels_nextlevel() advances the game to the next level and returns
1293 ******************************************************************************/
1294 static void jewels_nextlevel(struct game_context
* bj
) {
1296 unsigned int points
= 0;
1299 case GAME_TYPE_NORMAL
:
1300 /* roll over score, change and display level */
1301 while(bj
->score
>= LEVEL_PTS
) {
1302 bj
->score
-= LEVEL_PTS
;
1304 rb
->splashf(HZ
*2, "Level %d", bj
->level
);
1305 jewels_drawboard(bj
);
1308 /* randomly clear some jewels */
1309 for(i
=0; i
<16; i
++) {
1313 if(bj
->playboard
[y
][x
].type
!= 0) {
1315 bj
->playboard
[y
][x
].type
= 0;
1320 case GAME_TYPE_PUZZLE
:
1322 if(bj
->level
>NUM_PUZZLE_LEVELS
) {
1323 rb
->splash(HZ
*2, "You win!");
1326 rb
->splashf(HZ
*2, "Level %d", bj
->level
);
1331 points
+= jewels_initlevel(bj
);
1332 bj
->score
+= points
;
1335 /*****************************************************************************
1336 * jewels_recordscore() inserts a high score into the high scores list and
1337 * returns the high score position.
1338 ******************************************************************************/
1339 static int jewels_recordscore(struct game_context
* bj
) {
1342 unsigned int current
, temp
;
1344 /* calculate total score */
1345 current
= (bj
->level
-1)*LEVEL_PTS
+bj
->score
;
1346 if(current
<= 0) return 0;
1348 /* insert the current score into the high scores */
1349 for(i
=0; i
<NUM_SCORES
; i
++) {
1350 if(current
>= bj
->highscores
[i
]) {
1355 temp
= bj
->highscores
[i
];
1356 bj
->highscores
[i
] = current
;
1364 /*****************************************************************************
1365 * jewels_loadscores() loads the high scores saved file.
1366 ******************************************************************************/
1367 static void jewels_loadscores(struct game_context
* bj
) {
1372 /* clear high scores */
1373 rb
->memset(bj
->highscores
, 0, sizeof(bj
->highscores
));
1375 /* open scores file */
1376 fd
= rb
->open(SCORE_FILE
, O_RDONLY
);
1379 /* read in high scores */
1380 if(rb
->read(fd
, bj
->highscores
, sizeof(bj
->highscores
)) <= 0) {
1381 /* scores are bad, reset */
1382 rb
->memset(bj
->highscores
, 0, sizeof(bj
->highscores
));
1388 /*****************************************************************************
1389 * jewels_savescores() saves the high scores saved file.
1390 ******************************************************************************/
1391 static void jewels_savescores(struct game_context
* bj
) {
1394 /* write out the high scores to the save file */
1395 fd
= rb
->open(SCORE_FILE
, O_WRONLY
|O_CREAT
);
1396 rb
->write(fd
, bj
->highscores
, sizeof(bj
->highscores
));
1401 /*****************************************************************************
1402 * jewels_loadgame() loads the saved game and returns load success.
1403 ******************************************************************************/
1404 static bool jewels_loadgame(struct game_context
* bj
) {
1406 bool loaded
= false;
1408 /* open game file */
1409 fd
= rb
->open(SAVE_FILE
, O_RDONLY
);
1410 if(fd
< 0) return loaded
;
1412 /* read in saved game */
1414 if(rb
->read(fd
, &bj
->score
, sizeof(bj
->score
)) <= 0) break;
1415 if(rb
->read(fd
, &bj
->level
, sizeof(bj
->level
)) <= 0) break;
1416 if(rb
->read(fd
, &bj
->type
, sizeof(bj
->type
)) <= 0) break;
1417 if(rb
->read(fd
, bj
->playboard
, sizeof(bj
->playboard
)) <= 0) break;
1425 /* delete saved file */
1426 rb
->remove(SAVE_FILE
);
1430 /*****************************************************************************
1431 * jewels_savegame() saves the current game state.
1432 ******************************************************************************/
1433 static void jewels_savegame(struct game_context
* bj
) {
1436 /* write out the game state to the save file */
1437 fd
= rb
->open(SAVE_FILE
, O_WRONLY
|O_CREAT
);
1438 rb
->write(fd
, &bj
->score
, sizeof(bj
->score
));
1439 rb
->write(fd
, &bj
->level
, sizeof(bj
->level
));
1440 rb
->write(fd
, &bj
->type
, sizeof(bj
->type
));
1441 rb
->write(fd
, bj
->playboard
, sizeof(bj
->playboard
));
1447 /*****************************************************************************
1448 * jewels_callback() is the default event handler callback which is called
1449 * on usb connect and shutdown.
1450 ******************************************************************************/
1451 static void jewels_callback(void* param
) {
1452 struct game_context
* bj
= (struct game_context
*) param
;
1454 rb
->splash(HZ
, "Saving high scores...");
1455 jewels_savescores(bj
);
1459 /*****************************************************************************
1460 * jewels_main() is the main game subroutine, it returns the final game status.
1461 ******************************************************************************/
1462 static int jewels_main(struct game_context
* bj
) {
1467 bool startgame
= false;
1468 bool inmenu
= false;
1469 bool selected
= false;
1470 enum menu_cmd cmd
= MCMD_NONE
;
1471 enum menu_result res
;
1473 /* the cursor coordinates */
1476 /* don't resume by default */
1479 /********************
1481 ********************/
1482 rb
->lcd_clear_display();
1485 res
= jewels_showmenu(&bjmenu
[0], cmd
);
1488 rb
->snprintf(str
, 18, "High Score: %d", bj
->highscores
[0]);
1489 rb
->lcd_getstringsize(str
, &w
, &h
);
1490 rb
->lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
-8, str
);
1498 bj
->type
= GAME_TYPE_NORMAL
;
1503 bj
->type
= GAME_TYPE_PUZZLE
;
1507 if(!jewels_loadgame(bj
)) {
1508 rb
->splash(HZ
*2, "Nothing to resume");
1509 rb
->lcd_clear_display();
1516 rb
->lcd_clear_display();
1518 /* room for a title? */
1520 if(LCD_HEIGHT
-NUM_SCORES
*8 >= 8) {
1521 rb
->snprintf(str
, 12, "%s", "High Scores");
1522 rb
->lcd_getstringsize(str
, &w
, &h
);
1523 rb
->lcd_putsxy((LCD_WIDTH
-w
)/2, 0, str
);
1527 /* print high scores */
1528 for(i
=0; i
<NUM_SCORES
; i
++) {
1529 rb
->snprintf(str
, 11, "#%02d: %d", i
+1, bj
->highscores
[i
]);
1530 rb
->lcd_puts(0, i
+j
, str
);
1535 button
= rb
->button_get(true);
1536 if(button
!= BUTTON_NONE
&& !(button
&BUTTON_REL
)) break;
1539 rb
->lcd_clear_display();
1543 /* welcome screen to display key bindings */
1544 rb
->lcd_clear_display();
1545 rb
->snprintf(str
, 5, "%s", "Help");
1546 rb
->lcd_getstringsize(str
, &w
, &h
);
1547 rb
->lcd_putsxy((LCD_WIDTH
-w
)/2, 0, str
);
1548 #if CONFIG_KEYPAD == RECORDER_PAD
1549 rb
->lcd_puts(0, 2, "Controls:");
1550 rb
->lcd_puts(0, 3, "Directions = move");
1551 rb
->lcd_puts(0, 4, "PLAY = select");
1552 rb
->lcd_puts(0, 5, "Long PLAY = menu");
1553 rb
->lcd_puts(0, 6, "OFF = cancel");
1554 #elif CONFIG_KEYPAD == ONDIO_PAD
1555 rb
->lcd_puts(0, 2, "Controls:");
1556 rb
->lcd_puts(0, 3, "Directions = move");
1557 rb
->lcd_puts(0, 4, "MENU = select");
1558 rb
->lcd_puts(0, 5, "Long MENU = menu");
1559 rb
->lcd_puts(0, 6, "OFF = cancel");
1560 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
1561 rb
->lcd_puts(0, 2, "Controls:");
1562 rb
->lcd_puts(0, 3, "Directions = move");
1563 rb
->lcd_puts(0, 4, "SELECT = select");
1564 rb
->lcd_puts(0, 5, "Long SELECT = menu");
1565 rb
->lcd_puts(0, 6, "PLAY = cancel");
1566 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
1567 rb
->lcd_puts(0, 2, "Swap pairs of jewels to");
1568 rb
->lcd_puts(0, 3, "form connected segments");
1569 rb
->lcd_puts(0, 4, "of three or more of the");
1570 rb
->lcd_puts(0, 5, "same type.");
1571 rb
->lcd_puts(0, 7, "Controls:");
1572 rb
->lcd_puts(0, 8, "Directions to move");
1573 rb
->lcd_puts(0, 9, "SELECT to select");
1574 rb
->lcd_puts(0, 10, "Long SELECT to show menu");
1575 rb
->lcd_puts(0, 11, "OFF to cancel");
1576 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
1577 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
1578 rb
->lcd_puts(0, 2, "Swap pairs of jewels to");
1579 rb
->lcd_puts(0, 3, "form connected segments");
1580 rb
->lcd_puts(0, 4, "of three or more of the");
1581 rb
->lcd_puts(0, 5, "same type.");
1582 rb
->lcd_puts(0, 7, "Controls:");
1583 rb
->lcd_puts(0, 8, "Directions or scroll to move");
1584 rb
->lcd_puts(0, 9, "SELECT to select");
1585 rb
->lcd_puts(0, 10, "Long SELECT to show menu");
1586 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
1587 rb
->lcd_puts(0, 2, "Swap pairs of jewels to");
1588 rb
->lcd_puts(0, 3, "form connected segments");
1589 rb
->lcd_puts(0, 4, "of three or more of the");
1590 rb
->lcd_puts(0, 5, "same type.");
1591 rb
->lcd_puts(0, 7, "Controls:");
1592 rb
->lcd_puts(0, 8, "Directions to move");
1593 rb
->lcd_puts(0, 9, "SELECT to select");
1594 rb
->lcd_puts(0, 10, "Long SELECT to show menu");
1595 rb
->lcd_puts(0, 11, "PLAY to cancel");
1596 #elif CONFIG_KEYPAD == GIGABEAT_PAD \
1597 || CONFIG_KEYPAD == MROBE100_PAD
1598 rb
->lcd_puts(0, 2, "Swap pairs of jewels to");
1599 rb
->lcd_puts(0, 3, "form connected segments");
1600 rb
->lcd_puts(0, 4, "of three or more of the");
1601 rb
->lcd_puts(0, 5, "same type.");
1602 rb
->lcd_puts(0, 7, "Controls:");
1603 rb
->lcd_puts(0, 8, "Directions to move");
1604 rb
->lcd_puts(0, 9, "SELECT to select");
1605 rb
->lcd_puts(0, 10, "Long SELECT to show menu");
1606 rb
->lcd_puts(0, 11, "POWER to cancel");
1607 #elif CONFIG_KEYPAD == SANSA_E200_PAD \
1608 || CONFIG_KEYPAD == SANSA_C200_PAD \
1609 || CONFIG_KEYPAD == SANSA_CLIP_PAD \
1610 || CONFIG_KEYPAD == SANSA_FUZE_PAD \
1611 || CONFIG_KEYPAD == SANSA_M200_PAD
1612 rb
->lcd_puts(0, 2, "Swap pairs of jewels to");
1613 rb
->lcd_puts(0, 3, "form connected segments");
1614 rb
->lcd_puts(0, 4, "of three or more of the");
1615 rb
->lcd_puts(0, 5, "same type.");
1616 rb
->lcd_puts(0, 7, "Controls:");
1617 rb
->lcd_puts(0, 8, "Directions to move");
1618 rb
->lcd_puts(0, 9, "SELECT to select");
1619 rb
->lcd_puts(0, 10, "Long SELECT to show menu");
1620 rb
->lcd_puts(0, 11, "POWER to cancel");
1621 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
1622 rb
->lcd_puts(0, 2, "Swap pairs of jewels");
1623 rb
->lcd_puts(0, 3, "to form connected");
1624 rb
->lcd_puts(0, 4, "segments of three or ");
1625 rb
->lcd_puts(0, 5, "more of the");
1626 rb
->lcd_puts(0, 6, "same type.");
1627 rb
->lcd_puts(0, 8, "Controls:");
1628 rb
->lcd_puts(0, 9, "Directions or scroll to move");
1629 rb
->lcd_puts(0, 10, "PLAY to select");
1630 rb
->lcd_puts(0, 11, "Long PLAY for menu");
1631 rb
->lcd_puts(0, 12, "POWER to cancel");
1632 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
1633 rb
->lcd_puts(0, 2, "Swap pairs of jewels");
1634 rb
->lcd_puts(0, 3, "to form connected");
1635 rb
->lcd_puts(0, 4, "segments of three or ");
1636 rb
->lcd_puts(0, 5, "more of the");
1637 rb
->lcd_puts(0, 6, "same type.");
1638 rb
->lcd_puts(0, 8, "Controls:");
1639 rb
->lcd_puts(0, 9, "Directions or scroll to move");
1640 rb
->lcd_puts(0, 10, "PLAY to select");
1641 rb
->lcd_puts(0, 11, "Long PLAY for menu");
1642 rb
->lcd_puts(0, 12, "REC to cancel");
1643 #elif CONFIG_KEYPAD == COWOND2_PAD
1644 rb
->lcd_puts(0, 11, "POWER to cancel");
1645 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
1646 rb
->lcd_puts(0, 2, "Swap pairs of jewels to");
1647 rb
->lcd_puts(0, 3, "form connected segments");
1648 rb
->lcd_puts(0, 4, "of three or more of the");
1649 rb
->lcd_puts(0, 5, "same type.");
1650 rb
->lcd_puts(0, 7, "Controls:");
1651 rb
->lcd_puts(0, 8, "Directions to move");
1652 rb
->lcd_puts(0, 9, "SELECT to select");
1653 rb
->lcd_puts(0, 10, "Long SELECT to show menu");
1654 rb
->lcd_puts(0, 11, "BACK to cancel");
1655 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
1656 rb
->lcd_puts(0, 2, "Swap pairs of jewels to");
1657 rb
->lcd_puts(0, 3, "form connected segments");
1658 rb
->lcd_puts(0, 4, "of three or more of the");
1659 rb
->lcd_puts(0, 5, "same type.");
1660 rb
->lcd_puts(0, 7, "Controls:");
1661 rb
->lcd_puts(0, 8, "Directions to move");
1662 rb
->lcd_puts(0, 9, "MIDDLE to select");
1663 rb
->lcd_puts(0, 10, "Long MIDDLE to show menu");
1664 rb
->lcd_puts(0, 11, "BACK to cancel");
1665 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
1666 rb
->lcd_puts(0, 2, "Swap pairs of jewels to");
1667 rb
->lcd_puts(0, 3, "form connected segments");
1668 rb
->lcd_puts(0, 4, "of three or more of the");
1669 rb
->lcd_puts(0, 5, "same type.");
1670 rb
->lcd_puts(0, 7, "Controls:");
1671 rb
->lcd_puts(0, 8, "Directions to move");
1672 rb
->lcd_puts(0, 9, "SELECT/PLAY to select");
1673 rb
->lcd_puts(0, 10, "Long SELECT to show menu");
1674 rb
->lcd_puts(0, 11, "POWER to cancel");
1675 #elif CONFIG_KEYPAD == ONDAVX747_PAD || CONFIG_KEYPAD == MROBE500_PAD
1676 rb
->lcd_puts(0, 11, "POWER to cancel");
1678 #warning: missing help text.
1681 #ifdef HAVE_TOUCHSCREEN
1682 rb
->lcd_puts(0, 2, "Swap pairs of jewels to");
1683 rb
->lcd_puts(0, 3, "form connected segments");
1684 rb
->lcd_puts(0, 4, "of three or more of the");
1685 rb
->lcd_puts(0, 5, "same type.");
1686 rb
->lcd_puts(0, 7, "Controls:");
1687 rb
->lcd_puts(0, 8, "Directions to move");
1688 rb
->lcd_puts(0, 9, "CENTER to select");
1689 rb
->lcd_puts(0, 10, "Long CENTER to show menu");
1693 button
= rb
->button_get(true);
1694 if(button
!= BUTTON_NONE
&& !(button
&BUTTON_REL
)) break;
1696 rb
->lcd_clear_display();
1706 /* handle menu button presses */
1707 button
= rb
->button_get(true);
1709 #ifdef JEWELS_SCROLLWHEEL
1711 case (JEWELS_PREV
|BUTTON_REPEAT
):
1714 case (JEWELS_UP
|BUTTON_REPEAT
):
1718 #ifdef JEWELS_SCROLLWHEEL
1720 case (JEWELS_NEXT
|BUTTON_REPEAT
):
1723 case (JEWELS_DOWN
|BUTTON_REPEAT
):
1732 #ifdef JEWELS_CANCEL
1733 #ifdef JEWELS_RC_CANCEL
1734 case JEWELS_RC_CANCEL
:
1741 if(rb
->default_event_handler_ex(button
, jewels_callback
,
1742 (void*) bj
) == SYS_USB_CONNECTED
)
1748 /********************
1750 ********************/
1753 /********************
1755 ********************/
1756 bj
->score
+= jewels_initlevel(bj
);
1757 if (!jewels_movesavail(bj
)) {
1759 case GAME_TYPE_NORMAL
:
1762 case GAME_TYPE_PUZZLE
:
1764 rb
->splash(2*HZ
, "No more moves!");
1765 bj
->score
+= jewels_initlevel(bj
);
1766 } while(!jewels_movesavail(bj
));
1771 /**********************
1773 **********************/
1775 int no_movesavail
= false;
1778 /* refresh the board */
1779 jewels_drawboard(bj
);
1781 /* display the cursor */
1783 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
1784 rb
->lcd_fillrect(x
*TILE_WIDTH
, y
*TILE_HEIGHT
+YOFS
,
1785 TILE_WIDTH
, TILE_HEIGHT
);
1786 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1788 rb
->lcd_drawrect(x
*TILE_WIDTH
, y
*TILE_HEIGHT
+YOFS
,
1789 TILE_WIDTH
, TILE_HEIGHT
);
1791 rb
->lcd_update_rect(x
*TILE_WIDTH
, y
*TILE_HEIGHT
+YOFS
,
1792 TILE_WIDTH
, TILE_HEIGHT
);
1794 res
= jewels_showmenu(&bjmenu
[1], cmd
);
1803 playback_control(NULL
);
1804 rb
->lcd_setfont(FONT_SYSFIXED
);
1810 rb
->splash(HZ
, "Saving game...");
1811 jewels_savegame(bj
);
1818 return BJ_QUIT_FROM_GAME
;
1825 /* handle game button presses */
1827 button
= rb
->button_get(true);
1829 case JEWELS_LEFT
: /* move cursor left */
1830 case (JEWELS_LEFT
|BUTTON_REPEAT
):
1833 bj
->score
+= jewels_swapjewels(bj
, x
, y
, SWAP_LEFT
);
1835 if (!jewels_movesavail(bj
)) no_movesavail
= true;
1837 x
= (x
+BJ_WIDTH
-1)%BJ_WIDTH
;
1842 case JEWELS_RIGHT
: /* move cursor right */
1843 case (JEWELS_RIGHT
|BUTTON_REPEAT
):
1846 bj
->score
+= jewels_swapjewels(bj
, x
, y
, SWAP_RIGHT
);
1848 if (!jewels_movesavail(bj
)) no_movesavail
= true;
1857 case JEWELS_DOWN
: /* move cursor down */
1858 case (JEWELS_DOWN
|BUTTON_REPEAT
):
1861 bj
->score
+= jewels_swapjewels(bj
, x
, y
, SWAP_DOWN
);
1863 if (!jewels_movesavail(bj
)) no_movesavail
= true;
1865 y
= (y
+1)%(BJ_HEIGHT
-1);
1872 case JEWELS_UP
: /* move cursor up */
1873 case (JEWELS_UP
|BUTTON_REPEAT
):
1876 bj
->score
+= jewels_swapjewels(bj
, x
, y
, SWAP_UP
);
1878 if (!jewels_movesavail(bj
)) no_movesavail
= true;
1880 y
= (y
+(BJ_HEIGHT
-1)-1)%(BJ_HEIGHT
-1);
1887 #ifdef JEWELS_SCROLLWHEEL
1888 case JEWELS_PREV
: /* scroll backwards */
1889 case (JEWELS_PREV
|BUTTON_REPEAT
):
1893 y
= (y
+(BJ_HEIGHT
-1)-1)%(BJ_HEIGHT
-1);
1895 x
= (x
+BJ_WIDTH
-1)%BJ_WIDTH
;
1902 case JEWELS_NEXT
: /* scroll forwards */
1903 case (JEWELS_NEXT
|BUTTON_REPEAT
):
1906 if(x
== BJ_WIDTH
-1) {
1907 y
= (y
+1)%(BJ_HEIGHT
-1);
1917 case JEWELS_SELECT
: /* toggle selected */
1919 selected
= !selected
;
1928 case (JEWELS_SELECT
|BUTTON_REPEAT
): /* show menu */
1929 if(!inmenu
) inmenu
= true;
1932 #ifdef JEWELS_CANCEL
1933 #ifdef JEWELS_RC_CANCEL
1934 case JEWELS_RC_CANCEL
:
1936 case JEWELS_CANCEL
: /* end game */
1942 if(rb
->default_event_handler_ex(button
, jewels_callback
,
1943 (void*) bj
) == SYS_USB_CONNECTED
)
1948 if (no_movesavail
) {
1950 case GAME_TYPE_NORMAL
:
1953 case GAME_TYPE_PUZZLE
:
1955 rb
->splash(2*HZ
, "No more moves!");
1956 bj
->score
+= jewels_initlevel(bj
);
1957 } while(!jewels_movesavail(bj
));
1963 case GAME_TYPE_NORMAL
:
1964 if(bj
->score
>= LEVEL_PTS
)
1965 jewels_nextlevel(bj
);
1968 case GAME_TYPE_PUZZLE
:
1969 if(jewels_puzzle_is_finished(bj
))
1970 jewels_nextlevel(bj
);
1976 /*****************************************************************************
1977 * plugin entry point.
1978 ******************************************************************************/
1979 enum plugin_status
plugin_start(const void* parameter
) {
1980 struct game_context bj
;
1987 /* end of plugin init */
1989 /* load high scores */
1990 jewels_loadscores(&bj
);
1992 rb
->lcd_setfont(FONT_SYSFIXED
);
1994 rb
->lcd_set_backdrop(NULL
);
1999 switch(jewels_main(&bj
)){
2001 rb
->splash(HZ
*2, "No more moves!");
2002 /* fall through to BJ_END */
2006 if((position
= jewels_recordscore(&bj
))) {
2007 rb
->snprintf(str
, 19, "New high score #%d!", position
);
2008 rb
->splash(HZ
*2, str
);
2014 rb
->lcd_setfont(FONT_UI
);
2015 return PLUGIN_USB_CONNECTED
;
2019 rb
->splash(HZ
, "Saving high scores...");
2020 jewels_savescores(&bj
);
2025 case BJ_QUIT_FROM_GAME
:
2027 if((position
= jewels_recordscore(&bj
))) {
2028 rb
->snprintf(str
, 19, "New high score #%d!", position
);
2029 rb
->splash(HZ
*2, str
);
2033 rb
->splash(HZ
, "Saving high scores...");
2034 jewels_savescores(&bj
);
2044 rb
->lcd_setfont(FONT_UI
);
2048 #endif /* HAVE_LCD_BITMAP */