1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Eli Sherer
12 * Heavily modified for embedded use by Björn Stenberg (bjorn@haxx.se)
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 ****************************************************************************/
24 #include "lib/highscore.h"
25 #include "lib/playergfx.h"
26 #include "lib/helper.h"
30 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
31 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
32 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
34 #define ROCKBLOX_OFF (BUTTON_MENU | BUTTON_SELECT)
35 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_BACK
36 #define ROCKBLOX_ROTATE_RIGHT2 (BUTTON_MENU | BUTTON_REL)
37 #define ROCKBLOX_ROTATE_LEFT BUTTON_SCROLL_FWD
38 #define ROCKBLOX_LEFT BUTTON_LEFT
39 #define ROCKBLOX_RIGHT BUTTON_RIGHT
40 #define ROCKBLOX_DOWN BUTTON_PLAY
41 #define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_PLAY)
42 #define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
44 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
45 (CONFIG_KEYPAD == IRIVER_H300_PAD)
47 #define ROCKBLOX_OFF BUTTON_OFF
48 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
49 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
50 #define ROCKBLOX_DOWN BUTTON_DOWN
51 #define ROCKBLOX_LEFT BUTTON_LEFT
52 #define ROCKBLOX_RIGHT BUTTON_RIGHT
53 #define ROCKBLOX_DROP BUTTON_MODE
54 #define ROCKBLOX_RESTART BUTTON_ON
56 #define ROCKBLOX_RC_OFF BUTTON_RC_STOP
58 #elif CONFIG_KEYPAD == RECORDER_PAD
60 #define ROCKBLOX_OFF BUTTON_OFF
61 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
62 #define ROCKBLOX_ROTATE_LEFT BUTTON_PLAY
63 #define ROCKBLOX_DOWN BUTTON_DOWN
64 #define ROCKBLOX_LEFT BUTTON_LEFT
65 #define ROCKBLOX_RIGHT BUTTON_RIGHT
66 #define ROCKBLOX_DROP BUTTON_ON
67 #define ROCKBLOX_RESTART BUTTON_F1
69 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
71 #define ROCKBLOX_OFF BUTTON_OFF
72 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
73 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
74 #define ROCKBLOX_DOWN BUTTON_DOWN
75 #define ROCKBLOX_LEFT BUTTON_LEFT
76 #define ROCKBLOX_RIGHT BUTTON_RIGHT
77 #define ROCKBLOX_DROP BUTTON_ON
78 #define ROCKBLOX_RESTART BUTTON_F1
80 #elif CONFIG_KEYPAD == PLAYER_PAD
82 #define ROCKBLOX_OFF BUTTON_STOP
83 #define ROCKBLOX_ROTATE_RIGHT BUTTON_PLAY
84 #define ROCKBLOX_ROTATE_LEFT (BUTTON_ON|BUTTON_PLAY)
85 #define ROCKBLOX_DOWN BUTTON_MENU
86 #define ROCKBLOX_LEFT BUTTON_LEFT
87 #define ROCKBLOX_RIGHT BUTTON_RIGHT
88 #define ROCKBLOX_DROP_PRE BUTTON_ON
89 #define ROCKBLOX_DROP (BUTTON_ON|BUTTON_REL)
91 #elif CONFIG_KEYPAD == ONDIO_PAD
93 #define ROCKBLOX_OFF BUTTON_OFF
94 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
95 #define ROCKBLOX_ROTATE_LEFT (BUTTON_MENU|BUTTON_UP)
96 #define ROCKBLOX_DOWN BUTTON_DOWN
97 #define ROCKBLOX_LEFT BUTTON_LEFT
98 #define ROCKBLOX_RIGHT BUTTON_RIGHT
99 #define ROCKBLOX_DROP_PRE BUTTON_MENU
100 #define ROCKBLOX_DROP (BUTTON_MENU|BUTTON_REL)
102 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
104 #define ROCKBLOX_OFF BUTTON_POWER
105 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
106 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
107 #define ROCKBLOX_DOWN BUTTON_DOWN
108 #define ROCKBLOX_LEFT BUTTON_LEFT
109 #define ROCKBLOX_RIGHT BUTTON_RIGHT
110 #define ROCKBLOX_DROP BUTTON_REC
111 #define ROCKBLOX_RESTART BUTTON_PLAY
113 #elif CONFIG_KEYPAD == SANSA_E200_PAD
115 #define ROCKBLOX_OFF BUTTON_POWER
116 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_BACK
117 #define ROCKBLOX_ROTATE_RIGHT2 BUTTON_UP
118 #define ROCKBLOX_ROTATE_LEFT BUTTON_SCROLL_FWD
119 #define ROCKBLOX_DOWN BUTTON_DOWN
120 #define ROCKBLOX_LEFT BUTTON_LEFT
121 #define ROCKBLOX_RIGHT BUTTON_RIGHT
122 #define ROCKBLOX_DROP BUTTON_SELECT
123 #define ROCKBLOX_RESTART BUTTON_REC
125 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
127 #define ROCKBLOX_OFF BUTTON_POWER
128 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_BACK
129 #define ROCKBLOX_ROTATE_RIGHT2 BUTTON_UP
130 #define ROCKBLOX_ROTATE_LEFT BUTTON_SCROLL_FWD
131 #define ROCKBLOX_DOWN BUTTON_DOWN
132 #define ROCKBLOX_LEFT BUTTON_LEFT
133 #define ROCKBLOX_RIGHT BUTTON_RIGHT
134 #define ROCKBLOX_DROP BUTTON_SELECT
135 #define ROCKBLOX_RESTART BUTTON_HOME
138 #elif CONFIG_KEYPAD == SANSA_C200_PAD
140 #define ROCKBLOX_OFF BUTTON_POWER
141 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
142 #define ROCKBLOX_ROTATE_RIGHT2 BUTTON_VOL_DOWN
143 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
144 #define ROCKBLOX_DOWN BUTTON_DOWN
145 #define ROCKBLOX_LEFT BUTTON_LEFT
146 #define ROCKBLOX_RIGHT BUTTON_RIGHT
147 #define ROCKBLOX_DROP BUTTON_SELECT
148 #define ROCKBLOX_RESTART BUTTON_REC
150 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
152 #define ROCKBLOX_OFF BUTTON_POWER
153 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
154 #define ROCKBLOX_ROTATE_RIGHT2 BUTTON_VOL_DOWN
155 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
156 #define ROCKBLOX_DOWN BUTTON_DOWN
157 #define ROCKBLOX_LEFT BUTTON_LEFT
158 #define ROCKBLOX_RIGHT BUTTON_RIGHT
159 #define ROCKBLOX_DROP BUTTON_SELECT
160 #define ROCKBLOX_RESTART BUTTON_HOME
162 #elif CONFIG_KEYPAD == SANSA_M200_PAD
164 #define ROCKBLOX_OFF BUTTON_POWER
165 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
166 #define ROCKBLOX_ROTATE_RIGHT2 BUTTON_VOL_DOWN
167 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
168 #define ROCKBLOX_DOWN BUTTON_DOWN
169 #define ROCKBLOX_LEFT BUTTON_LEFT
170 #define ROCKBLOX_RIGHT BUTTON_RIGHT
171 #define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_UP)
172 #define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
174 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
176 #define ROCKBLOX_OFF BUTTON_POWER
177 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_UP
178 #define ROCKBLOX_ROTATE_LEFT BUTTON_REW
179 #define ROCKBLOX_DOWN BUTTON_SCROLL_DOWN
180 #define ROCKBLOX_LEFT BUTTON_LEFT
181 #define ROCKBLOX_RIGHT BUTTON_RIGHT
182 #define ROCKBLOX_DROP BUTTON_FF
183 #define ROCKBLOX_RESTART BUTTON_PLAY
185 #elif CONFIG_KEYPAD == GIGABEAT_PAD
187 #define ROCKBLOX_OFF BUTTON_POWER
188 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
189 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
190 #define ROCKBLOX_ROTATE BUTTON_UP
191 #define ROCKBLOX_DOWN BUTTON_DOWN
192 #define ROCKBLOX_LEFT BUTTON_LEFT
193 #define ROCKBLOX_RIGHT BUTTON_RIGHT
194 #define ROCKBLOX_DROP BUTTON_SELECT
195 #define ROCKBLOX_RESTART BUTTON_A
197 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
199 #define ROCKBLOX_OFF BUTTON_PLAY
200 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
201 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
202 #define ROCKBLOX_DOWN BUTTON_DOWN
203 #define ROCKBLOX_LEFT BUTTON_LEFT
204 #define ROCKBLOX_RIGHT BUTTON_RIGHT
205 #define ROCKBLOX_DROP BUTTON_MODE
206 #define ROCKBLOX_RESTART BUTTON_EQ
208 #elif CONFIG_KEYPAD == MROBE500_PAD
209 #define ROCKBLOX_OFF BUTTON_POWER
210 #define ROCKBLOX_ROTATE_RIGHT BUTTON_RC_VOL_UP
211 #define ROCKBLOX_ROTATE_LEFT BUTTON_RC_VOL_DOWN
212 #define ROCKBLOX_DOWN BUTTON_RC_DOWN
213 #define ROCKBLOX_LEFT BUTTON_LEFT
214 #define ROCKBLOX_RIGHT BUTTON_RIGHT
215 #define ROCKBLOX_DROP BUTTON_RC_HEART
216 #define ROCKBLOX_RESTART BUTTON_RC_MODE
218 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
219 #define ROCKBLOX_OFF BUTTON_BACK
220 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
221 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
222 #define ROCKBLOX_ROTATE BUTTON_UP
223 #define ROCKBLOX_DOWN BUTTON_DOWN
224 #define ROCKBLOX_LEFT BUTTON_LEFT
225 #define ROCKBLOX_RIGHT BUTTON_RIGHT
226 #define ROCKBLOX_DROP BUTTON_SELECT
227 #define ROCKBLOX_RESTART BUTTON_PLAY
229 #elif CONFIG_KEYPAD == MROBE100_PAD
231 #define ROCKBLOX_OFF BUTTON_POWER
232 #define ROCKBLOX_ROTATE_RIGHT BUTTON_MENU
233 #define ROCKBLOX_ROTATE_LEFT BUTTON_PLAY
234 #define ROCKBLOX_ROTATE BUTTON_UP
235 #define ROCKBLOX_DOWN BUTTON_DOWN
236 #define ROCKBLOX_LEFT BUTTON_LEFT
237 #define ROCKBLOX_RIGHT BUTTON_RIGHT
238 #define ROCKBLOX_DROP BUTTON_SELECT
239 #define ROCKBLOX_RESTART BUTTON_DISPLAY
241 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
243 #define ROCKBLOX_OFF BUTTON_RC_REC
244 #define ROCKBLOX_ROTATE_RIGHT BUTTON_RC_VOL_DOWN
245 #define ROCKBLOX_ROTATE_LEFT BUTTON_RC_VOL_UP
246 #define ROCKBLOX_DOWN BUTTON_RC_MENU
247 #define ROCKBLOX_LEFT BUTTON_RC_REW
248 #define ROCKBLOX_RIGHT BUTTON_RC_FF
249 #define ROCKBLOX_DROP BUTTON_RC_PLAY
250 #define ROCKBLOX_RESTART BUTTON_RC_MODE
252 #elif CONFIG_KEYPAD == COWOND2_PAD
253 #define ROCKBLOX_OFF BUTTON_POWER
254 #define ROCKBLOX_RESTART BUTTON_MENU
256 #elif CONFIG_KEYPAD == IAUDIO67_PAD
258 #define ROCKBLOX_OFF BUTTON_POWER
259 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOLDOWN
260 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOLUP
261 #define ROCKBLOX_DOWN BUTTON_STOP
262 #define ROCKBLOX_LEFT BUTTON_LEFT
263 #define ROCKBLOX_RIGHT BUTTON_RIGHT
264 #define ROCKBLOX_DROP BUTTON_PLAY
265 #define ROCKBLOX_RESTART BUTTON_MENU
267 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
268 #define ROCKBLOX_OFF BUTTON_BACK
269 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
270 #define ROCKBLOX_ROTATE_LEFT BUTTON_PLAY
271 #define ROCKBLOX_DOWN BUTTON_DOWN
272 #define ROCKBLOX_LEFT BUTTON_LEFT
273 #define ROCKBLOX_RIGHT BUTTON_RIGHT
274 #define ROCKBLOX_DROP BUTTON_SELECT
275 #define ROCKBLOX_RESTART BUTTON_CUSTOM
277 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
279 #define ROCKBLOX_OFF BUTTON_POWER
280 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
281 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
282 #define ROCKBLOX_ROTATE BUTTON_UP
283 #define ROCKBLOX_DOWN BUTTON_DOWN
284 #define ROCKBLOX_LEFT BUTTON_LEFT
285 #define ROCKBLOX_RIGHT BUTTON_RIGHT
286 #define ROCKBLOX_DROP BUTTON_SELECT
287 #define ROCKBLOX_RESTART BUTTON_MENU
290 #error No keymap defined!
293 #ifdef HAVE_TOUCHSCREEN
295 #define ROCKBLOX_OFF BUTTON_TOPLEFT
297 #ifndef ROCKBLOX_ROTATE_RIGHT
298 #define ROCKBLOX_ROTATE_RIGHT BUTTON_BOTTOMRIGHT
300 #ifndef ROCKBLOX_ROTATE_LEFT
301 #define ROCKBLOX_ROTATE_LEFT BUTTON_BOTTOMLEFT
303 #ifndef ROCKBLOX_DOWN
304 #define ROCKBLOX_DOWN BUTTON_BOTTOMMIDDLE
306 #ifndef ROCKBLOX_LEFT
307 #define ROCKBLOX_LEFT BUTTON_MIDLEFT
309 #ifndef ROCKBLOX_RIGHT
310 #define ROCKBLOX_RIGHT BUTTON_MIDRIGHT
312 #ifndef ROCKBLOX_DROP
313 #define ROCKBLOX_DROP BUTTON_CENTER
315 #ifndef ROCKBLOX_RESTART
316 #define ROCKBLOX_RESTART BUTTON_TOPRIGHT
321 #define EMPTY_BLOCK 7
323 #define BOARD_WIDTH 10
325 #ifdef HAVE_LCD_BITMAP
327 #define BOARD_HEIGHT 20
329 #if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
331 #define BLOCK_WIDTH 30
332 #define BLOCK_HEIGHT 30
335 #define PREVIEW_X 342
336 #define PREVIEW_Y 482
341 #define HIGH_LABEL_X 344
342 #define HIGH_SCORE_Y 326
343 #define HIGH_LEVEL_Y 344
345 #elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640)
347 #define BLOCK_WIDTH 30
348 #define BLOCK_HEIGHT 30
351 #define PREVIEW_X 342
352 #define PREVIEW_Y 482
357 #define HIGH_LABEL_X 344
358 #define HIGH_SCORE_Y 326
359 #define HIGH_LEVEL_Y 344
361 #elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
363 #define BLOCK_WIDTH 12
364 #define BLOCK_HEIGHT 12
374 #elif (LCD_WIDTH == 240) && (LCD_HEIGHT == 320)
376 #define BLOCK_WIDTH 15
377 #define BLOCK_HEIGHT 15
380 #define PREVIEW_X 171
381 #define PREVIEW_Y 241
386 #define HIGH_LABEL_X 172
387 #define HIGH_SCORE_Y 163
388 #define HIGH_LEVEL_Y 172
390 #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176)
392 #define BLOCK_WIDTH 8
393 #define BLOCK_HEIGHT 8
396 #define PREVIEW_X 158
397 #define PREVIEW_Y 130
403 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132)
405 #define BLOCK_WIDTH 6
406 #define BLOCK_HEIGHT 6
409 #define PREVIEW_X 126
410 #define PREVIEW_Y 102
416 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220)
418 #define BLOCK_WIDTH 10
419 #define BLOCK_HEIGHT 10
422 #define PREVIEW_X 124
423 #define PREVIEW_Y 167
428 #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128)
430 #define BLOCK_WIDTH 6
431 #define BLOCK_HEIGHT 6
434 #define PREVIEW_X 114
435 #define PREVIEW_Y 100
441 #elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110)
443 #define BLOCK_WIDTH 5
444 #define BLOCK_HEIGHT 5
454 #elif (LCD_WIDTH == 132) && (LCD_HEIGHT == 80)
456 #define BLOCK_WIDTH 4
457 #define BLOCK_HEIGHT 4
467 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 128)
469 #define BLOCK_WIDTH 6
470 #define BLOCK_HEIGHT 6
474 #define PREVIEW_Y 100
480 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 96)
482 #define BLOCK_WIDTH 4
483 #define BLOCK_HEIGHT 4
493 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64)
495 #define BLOCK_WIDTH 3
496 #define BLOCK_HEIGHT 3
506 #elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
508 #define BLOCK_WIDTH 4
509 #define BLOCK_HEIGHT 3
523 #define LEVEL_X LABEL_X
527 #define LINES_X LABEL_X
530 #define MYLCD(fn) rb->lcd_ ## fn
532 extern const fb_data rockblox_background
[];
534 #else /* HAVE_LCD_CHARCELLS */
536 #define BOARD_HEIGHT 14
538 #define BLOCK_WIDTH 1
539 #define BLOCK_HEIGHT 1
545 #define MYLCD(fn) pgfx_ ## fn
549 /* <<Explanation on Rockblox shapes>>
552 %% - O has 1 orientation
555 %% %% - Z has 2 orientations
559 %% %% - S has 2 orientations
563 % %%%% - I has 2 orientations
567 % % % %%% - L has 4 orientations
571 % % % %%% - J has 4 orientations
575 %% % %% % - T has 4 orientations
580 static bool gameover
= false;
581 /* c=current f=figure o=orientation n=next */
582 static int lines
= 0, level
= 0, score
= 0, cx
, cy
, cf
, co
, nf
;
583 static short board
[BOARD_HEIGHT
][BOARD_WIDTH
]; /* 20 rows of 10 blocks */
585 #ifdef HAVE_SCROLLWHEEL
586 int wheel_events
= 0, last_wheel_event
= 0;
587 bool wheel_enabled
= false;
590 static const short scoring
[4] = { /* scoring for each number of lines */
591 #if BOARD_HEIGHT == 20
592 40 /* single */ , 100 /* double */ , 300 /* triple */ , 1200 /* rockblox */
593 #elif BOARD_HEIGHT == 14 /* Player special values */
594 60 /* single */ , 150 /* double */ , 500 /* triple */ , 2000 /* rockblox */
601 unsigned short color
[3]; /* color of figure (light,middle,shadow) */
603 unsigned short max_or
; /* max orientations */
604 signed short shapeX
[4], shapeY
[4]; /* implementation of figures */
607 /* array of figures */
608 figures
[BLOCKS_NUM
] = {
612 {LCD_RGBPACK (153, 255, 255), LCD_RGBPACK(0, 255, 255),
613 LCD_RGBPACK(0,153,153)},
615 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
624 {LCD_RGBPACK (255, 153, 128), LCD_RGBPACK (255, 0, 0),
625 LCD_RGBPACK (153, 0, 0)},
627 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
636 {LCD_RGBPACK (153, 255, 153), LCD_RGBPACK (0, 255, 0),
637 LCD_RGBPACK (0, 153, 0)},
639 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
648 {LCD_RGBPACK (153, 153, 255), LCD_RGBPACK (0, 0, 255),
649 LCD_RGBPACK (0, 0, 153)},
651 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
660 {LCD_RGBPACK (255, 255, 153), LCD_RGBPACK (255, 255, 0),
661 LCD_RGBPACK (153, 153, 0)},
663 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
672 {LCD_RGBPACK (255, 153, 255), LCD_RGBPACK (255, 0, 255),
673 LCD_RGBPACK (153, 0, 153)},
675 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
684 {LCD_RGBPACK (204, 204, 204), LCD_RGBPACK (153, 153, 153),
685 LCD_RGBPACK (85, 85, 85)},
687 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
695 /* Rockbox File System only supports full filenames inc dir */
696 #define HIGH_SCORE PLUGIN_GAMES_DIR "/rockblox.score"
697 #define MAX_HIGH_SCORES 5
698 /* Default High Scores... */
699 struct highscore Highest
[MAX_HIGH_SCORES
];
701 /* get random number from (0) to (range-1) */
702 static int t_rand (int range
)
704 return rb
->rand () % range
;
707 /* init the board array to have no blocks */
708 static void init_board (void)
711 for (i
= 0; i
< BOARD_WIDTH
; i
++)
712 for (j
= 0; j
< BOARD_HEIGHT
; j
++)
713 board
[j
][i
] = EMPTY_BLOCK
;
716 /* show the score, level and lines */
717 static void show_details (void)
719 char str
[25]; /* for strings */
721 #ifdef HAVE_LCD_BITMAP
723 rb
->lcd_set_foreground (LCD_BLACK
);
724 rb
->lcd_set_background (LCD_WHITE
);
726 rb
->snprintf (str
, sizeof (str
), "%d", score
);
727 rb
->lcd_putsxy (LABEL_X
, SCORE_Y
, str
);
728 rb
->snprintf (str
, sizeof (str
), "%d", level
);
729 rb
->lcd_putsxy (LEVEL_X
, LEVEL_Y
, str
);
730 rb
->snprintf (str
, sizeof (str
), "%d", lines
);
731 rb
->lcd_putsxy (LINES_X
, LINES_Y
, str
);
732 #else /* HAVE_LCD_CHARCELLS */
733 rb
->snprintf (str
, sizeof (str
), "L%d/%d", level
, lines
);
734 rb
->lcd_puts (5, 0, str
);
735 rb
->snprintf (str
, sizeof (str
), "S%d", score
);
736 rb
->lcd_puts (5, 1, str
);
741 static void show_highscores (void)
744 char str
[25]; /* for strings */
746 for (i
= MAX_HIGH_SCORES
-1; i
>=0; i
--)
748 rb
->snprintf (str
, sizeof (str
), "%06d L%1d", Highest
[i
].score
, Highest
[i
].level
);
749 rb
->lcd_putsxy (HIGH_LABEL_X
, HIGH_SCORE_Y
+ (10 * ((MAX_HIGH_SCORES
-1) - i
)), str
);
754 static void init_rockblox (void)
756 highscore_update(score
, level
, Highest
, MAX_HIGH_SCORES
);
762 nf
= t_rand (BLOCKS_NUM
);
764 #ifdef HAVE_LCD_BITMAP
765 rb
->lcd_bitmap (rockblox_background
, 0, 0, LCD_WIDTH
, LCD_HEIGHT
);
766 #else /* HAVE_LCD_CHARCELLS */
768 pgfx_display_block (3, 0, 3, 1);
769 pgfx_display_block (4, 0, 3, 0);
770 pgfx_clear_display();
771 pgfx_fillrect (3, 0, 2, 14);
772 pgfx_fillrect (15, 7, 2, 7);
781 static inline int level_speed(int level
)
783 #if BOARD_HEIGHT == 20
784 return (5*HZ
) / (level
+ 9);
785 #elif BOARD_HEIGHT == 14
786 return (7*HZ
) / (level
+ 9);
790 static int getRelativeX (int figure
, int square
, int orientation
)
792 switch (orientation
) {
794 return figures
[figure
].shapeX
[square
];
796 return figures
[figure
].shapeY
[square
];
798 return -figures
[figure
].shapeX
[square
];
800 return -figures
[figure
].shapeY
[square
];
806 static int getRelativeY (int figure
, int square
, int orientation
)
808 switch (orientation
) {
810 return figures
[figure
].shapeY
[square
];
812 return -figures
[figure
].shapeX
[square
];
814 return -figures
[figure
].shapeY
[square
];
816 return figures
[figure
].shapeX
[square
];
822 /* redraw the while board on the screen */
823 static void refresh_board (void)
825 int i
, j
, x
, y
, block
;
828 rb
->lcd_set_foreground (LCD_BLACK
);
830 MYLCD(set_drawmode
) (DRMODE_SOLID
| DRMODE_INVERSEVID
);
833 MYLCD(fillrect
) (BOARD_X
, BOARD_Y
, BOARD_WIDTH
* BLOCK_WIDTH
,
834 BOARD_HEIGHT
* BLOCK_HEIGHT
);
837 MYLCD(set_drawmode
) (DRMODE_SOLID
);
840 for (i
= 0; i
< BOARD_WIDTH
; i
++)
841 for (j
= 0; j
< BOARD_HEIGHT
; j
++) {
843 if (block
!= EMPTY_BLOCK
) {
844 #ifdef HAVE_LCD_BITMAP
847 rb
->lcd_set_foreground (figures
[block
].color
[1]);
849 rb
->lcd_fillrect (BOARD_X
+ i
* BLOCK_WIDTH
,
850 BOARD_Y
+ j
* BLOCK_HEIGHT
,
851 BLOCK_WIDTH
, BLOCK_HEIGHT
);
854 rb
->lcd_set_foreground (figures
[block
].color
[0]);
856 rb
->lcd_vline (BOARD_X
+ i
* BLOCK_WIDTH
,
857 BOARD_Y
+ j
* BLOCK_HEIGHT
,
858 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 2);
859 rb
->lcd_hline (BOARD_X
+ i
* BLOCK_WIDTH
,
860 BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 2,
861 BOARD_Y
+ j
* BLOCK_HEIGHT
);
864 rb
->lcd_set_foreground (figures
[block
].color
[2]);
866 rb
->lcd_vline (BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 1,
867 BOARD_Y
+ j
* BLOCK_HEIGHT
+ 1,
868 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 1);
869 rb
->lcd_hline (BOARD_X
+ i
* BLOCK_WIDTH
+ 1,
870 BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 1,
871 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 1);
872 #else /* HAVE_LCD_CHARCELLS */
873 pgfx_drawpixel (BOARD_X
+ i
, BOARD_Y
+ j
);
878 for (i
= 0; i
< 4; i
++) {
879 x
= getRelativeX (cf
, i
, co
) + cx
;
880 y
= getRelativeY (cf
, i
, co
) + cy
;
881 #ifdef HAVE_LCD_BITMAP
883 rb
->lcd_set_foreground (figures
[cf
].color
[1]); /* middle drawing */
885 rb
->lcd_fillrect (BOARD_X
+ x
* BLOCK_WIDTH
,
886 BOARD_Y
+ y
* BLOCK_HEIGHT
,
887 BLOCK_WIDTH
, BLOCK_HEIGHT
);
889 rb
->lcd_set_foreground (figures
[cf
].color
[0]); /* light drawing */
891 rb
->lcd_vline (BOARD_X
+ x
* BLOCK_WIDTH
, BOARD_Y
+ y
* BLOCK_HEIGHT
,
892 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 2);
893 rb
->lcd_hline (BOARD_X
+ x
* BLOCK_WIDTH
,
894 BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 2,
895 BOARD_Y
+ y
* BLOCK_HEIGHT
);
897 rb
->lcd_set_foreground (figures
[cf
].color
[2]); /* shadow drawing */
899 rb
->lcd_vline (BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 1,
900 BOARD_Y
+ y
* BLOCK_HEIGHT
+ 1,
901 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 1);
902 rb
->lcd_hline (BOARD_X
+ x
* BLOCK_WIDTH
+ 1,
903 BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 1,
904 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 1);
905 #else /* HAVE_LCD_CHARCELLS */
906 pgfx_drawpixel (BOARD_X
+ x
, BOARD_Y
+ y
);
912 static bool canMoveTo (int x
, int y
, int newOrientation
)
915 for (i
= 0; i
< 4; i
++) {
916 ry
= getRelativeY (cf
, i
, newOrientation
) + y
;
917 rx
= getRelativeX (cf
, i
, newOrientation
) + x
;
918 if ((rx
< 0 || rx
>= BOARD_WIDTH
) ||
919 (ry
< 0 || ry
>= BOARD_HEIGHT
) || (board
[ry
][rx
] != EMPTY_BLOCK
))
925 /* draws the preview of next block in the preview window */
926 static void draw_next_block (void)
929 /* clear preview window first */
931 rb
->lcd_set_foreground (LCD_BLACK
);
933 MYLCD(set_drawmode
) (DRMODE_SOLID
| DRMODE_INVERSEVID
);
937 MYLCD(fillrect
) (PREVIEW_X
, PREVIEW_Y
, BLOCK_WIDTH
* 4, BLOCK_HEIGHT
* 4);
940 MYLCD(set_drawmode
) (DRMODE_SOLID
);
943 /* draw the lightgray rectangles */
945 rb
->lcd_set_foreground (LCD_RGBPACK (40, 40, 40));
947 rb
->lcd_set_foreground (LCD_DARKGRAY
);
951 for (rx
= 0; rx
< 4; rx
++)
952 for (ry
= 0; ry
< 4; ry
++)
953 rb
->lcd_drawrect (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
954 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
, BLOCK_WIDTH
,
958 /* draw the figure */
959 for (i
= 0; i
< 4; i
++) {
960 rx
= getRelativeX (nf
, i
, 0) + 2;
961 ry
= getRelativeY (nf
, i
, 0) + 2;
962 #ifdef HAVE_LCD_BITMAP
964 rb
->lcd_set_foreground (figures
[nf
].color
[1]); /* middle drawing */
966 rb
->lcd_fillrect (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
967 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
,
968 BLOCK_WIDTH
, BLOCK_HEIGHT
);
970 rb
->lcd_set_foreground (figures
[nf
].color
[0]); /* light drawing */
972 rb
->lcd_vline (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
973 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
,
974 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 2);
975 rb
->lcd_hline (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
976 PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 2,
977 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
);
979 rb
->lcd_set_foreground (figures
[nf
].color
[2]); /* shadow drawing */
981 rb
->lcd_vline (PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 1,
982 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
+ 1,
983 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 1);
984 rb
->lcd_hline (PREVIEW_X
+ rx
* BLOCK_WIDTH
+ 1,
985 PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 1,
986 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 1);
987 #else /* HAVE_LCD_CHARCELLS */
988 pgfx_drawpixel (PREVIEW_X
+ rx
, PREVIEW_Y
+ ry
);
994 /* move the block to a relative location */
995 static void move_block (int x
, int y
, int o
)
997 if (canMoveTo (cx
+ x
, cy
+ y
, o
)) {
1004 /* try to add a new block to play with (return true if gameover) */
1005 static void new_block (void)
1010 co
= 0; /* start at the same orientation all time */
1011 nf
= t_rand (BLOCKS_NUM
);
1012 gameover
= !canMoveTo (cx
, cy
, co
);
1018 /* check for filled lines and do what necessary */
1019 static int check_lines (void)
1024 for (j
= 0; j
< BOARD_HEIGHT
; j
++) {
1025 for (i
= 0; ((i
< BOARD_WIDTH
) && (board
[j
][i
] != EMPTY_BLOCK
)); i
++);
1026 if (i
== BOARD_WIDTH
) { /* woo hoo, we have a line */
1028 for (y
= j
; y
> 0; y
--)
1029 for (i
= 0; i
< BOARD_WIDTH
; i
++)
1030 board
[y
][i
] = board
[y
- 1][i
]; /* fall line */
1037 /* moves down the figure and returns true if gameover */
1038 static void move_down (void)
1042 if (!canMoveTo (cx
, cy
+ 1, co
)) {
1043 /* save figure to board */
1044 for (i
= 0; i
< 4; i
++) {
1045 rx
= getRelativeX (cf
, i
, co
) + cx
;
1046 ry
= getRelativeY (cf
, i
, co
) + cy
;
1049 /* check if formed some lines */
1052 /* the original scoring from "http://en.wikipedia.org/wiki/Rockblox" */
1053 score
+= scoring
[l
- 1] * level
;
1055 level
= (int) lines
/ 10 + 1;
1061 /* generate a new figure */
1064 move_block (0, 1, co
);
1067 static int rockblox_loop (void)
1070 int lastbutton
= BUTTON_NONE
;
1071 long next_down_tick
= *rb
->current_tick
+ level_speed(level
);
1076 #ifdef HAS_BUTTON_HOLD
1077 if (rb
->button_hold ()) {
1078 /* Turn on backlight timeout (revert to settings) */
1079 backlight_use_settings(); /* backlight control in lib/helper.c */
1080 rb
->splash(0, "Paused");
1081 while (rb
->button_hold ())
1084 /* Turn off backlight timeout */
1085 backlight_force_on(); /* backlight control in lib/helper.c */
1087 /* get rid of the splash text */
1088 rb
->lcd_bitmap (rockblox_background
, 0, 0, LCD_WIDTH
, LCD_HEIGHT
);
1098 button
= rb
->button_get_w_tmo (MAX(next_down_tick
- *rb
->current_tick
, 1));
1100 #ifdef ROCKBLOX_RC_OFF
1101 case ROCKBLOX_RC_OFF
:
1106 #if defined(ROCKBLOX_ROTATE)
1107 case ROCKBLOX_ROTATE
:
1109 case ROCKBLOX_ROTATE_RIGHT
:
1110 case ROCKBLOX_ROTATE_RIGHT
| BUTTON_REPEAT
:
1111 #ifdef HAVE_SCROLLWHEEL
1112 /* if the wheel is disabled, add an event to the stack. */
1113 if(wheel_enabled
== false)
1116 /* if it's enabled, go ahead and rotate.. */
1119 move_block (0, 0, (co
+ 1) % figures
[cf
].max_or
);
1122 case ROCKBLOX_ROTATE_LEFT
:
1123 case ROCKBLOX_ROTATE_LEFT
| BUTTON_REPEAT
:
1124 #ifdef HAVE_SCROLLWHEEL
1125 if(wheel_enabled
== false)
1131 (co
+ figures
[cf
].max_or
-
1132 1) % figures
[cf
].max_or
);
1135 #ifdef ROCKBLOX_ROTATE_RIGHT2
1136 case ROCKBLOX_ROTATE_RIGHT2
:
1137 move_block (0, 0, (co
+ 1) % figures
[cf
].max_or
);
1142 case ROCKBLOX_DOWN
| BUTTON_REPEAT
:
1143 move_block (0, 1, co
);
1146 case ROCKBLOX_RIGHT
:
1147 case ROCKBLOX_RIGHT
| BUTTON_REPEAT
:
1148 move_block (1, 0, co
);
1152 case ROCKBLOX_LEFT
| BUTTON_REPEAT
:
1153 move_block (-1, 0, co
);
1157 #ifdef ROCKBLOX_DROP_PRE
1158 if (lastbutton
!= ROCKBLOX_DROP_PRE
)
1161 while (canMoveTo (cx
, cy
+ 1, co
))
1162 move_block (0, 1, co
);
1164 #ifdef ROCKBLOX_RESTART
1165 case ROCKBLOX_RESTART
:
1166 rb
->splash (HZ
* 1, "Restarting...");
1173 if (rb
->default_event_handler (button
) == SYS_USB_CONNECTED
)
1174 return PLUGIN_USB_CONNECTED
;
1177 if (button
!= BUTTON_NONE
)
1178 lastbutton
= button
;
1180 #ifdef HAVE_SCROLLWHEEL
1181 /* check if we should enable the scroll wheel, if events
1182 * begin to stack up... */
1183 if(wheel_enabled
== false)
1185 /* stopped rotating the wheel, reset the count */
1186 if(wheel_events
== last_wheel_event
)
1188 last_wheel_event
= 0;
1191 /* rotated the wheel a while constantly, enable it. */
1192 else if(wheel_events
> 3)
1194 wheel_enabled
= true;
1197 /* this evens out the last event and the "current" event.
1198 * if we get an event next time through button reading, it will
1199 * remain ahead of last_event. if we don't, they'll end up equaling
1200 * each other.. thus, the scroll count will be reset. */
1201 if(wheel_enabled
== false && wheel_events
> last_wheel_event
)
1206 if (TIME_AFTER(*rb
->current_tick
, next_down_tick
)) {
1208 next_down_tick
+= level_speed(level
);
1209 if (TIME_AFTER(*rb
->current_tick
, next_down_tick
))
1210 /* restart time "raster" when we had to wait longer than usual
1211 * (pause, game restart etc) */
1212 next_down_tick
= *rb
->current_tick
+ level_speed(level
);
1217 rb
->lcd_set_foreground (LCD_BLACK
);
1219 rb
->splash (HZ
* 2, "Game Over");
1230 enum plugin_status
plugin_start (const void *parameter
)
1236 rb
->srand (*rb
->current_tick
);
1238 /* Load HighScore if any */
1239 highscore_load(HIGH_SCORE
,Highest
,MAX_HIGH_SCORES
);
1242 rb
->lcd_set_backdrop(NULL
);
1245 #ifdef HAVE_LCD_BITMAP
1246 rb
->lcd_setfont (FONT_SYSFIXED
);
1248 if (!pgfx_init(4, 2))
1250 rb
->splash(HZ
*2, "Old LCD :(");
1254 /* Turn off backlight timeout */
1255 backlight_force_on(); /* backlight control in lib/helper.c */
1258 ret
= rockblox_loop ();
1260 #ifdef HAVE_LCD_BITMAP
1261 rb
->lcd_setfont (FONT_UI
);
1265 /* Save user's HighScore */
1266 highscore_save(HIGH_SCORE
,Highest
,MAX_HIGH_SCORES
);
1267 backlight_use_settings(); /* backlight control in lib/helper.c */