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 "highscore.h"
25 #include "playergfx.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)
46 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
47 (CONFIG_KEYPAD == IRIVER_H300_PAD)
49 #define ROCKBLOX_OFF BUTTON_OFF
50 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
51 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
52 #define ROCKBLOX_DOWN BUTTON_DOWN
53 #define ROCKBLOX_LEFT BUTTON_LEFT
54 #define ROCKBLOX_RIGHT BUTTON_RIGHT
55 #define ROCKBLOX_DROP BUTTON_MODE
56 #define ROCKBLOX_RESTART BUTTON_ON
58 #define ROCKBLOX_RC_OFF BUTTON_RC_STOP
60 #elif CONFIG_KEYPAD == RECORDER_PAD
62 #define ROCKBLOX_OFF BUTTON_OFF
63 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
64 #define ROCKBLOX_ROTATE_LEFT BUTTON_PLAY
65 #define ROCKBLOX_DOWN BUTTON_DOWN
66 #define ROCKBLOX_LEFT BUTTON_LEFT
67 #define ROCKBLOX_RIGHT BUTTON_RIGHT
68 #define ROCKBLOX_DROP BUTTON_ON
69 #define ROCKBLOX_RESTART BUTTON_F1
71 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
73 #define ROCKBLOX_OFF BUTTON_OFF
74 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
75 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
76 #define ROCKBLOX_DOWN BUTTON_DOWN
77 #define ROCKBLOX_LEFT BUTTON_LEFT
78 #define ROCKBLOX_RIGHT BUTTON_RIGHT
79 #define ROCKBLOX_DROP BUTTON_ON
80 #define ROCKBLOX_RESTART BUTTON_F1
82 #elif CONFIG_KEYPAD == PLAYER_PAD
84 #define ROCKBLOX_OFF BUTTON_STOP
85 #define ROCKBLOX_ROTATE_RIGHT BUTTON_PLAY
86 #define ROCKBLOX_ROTATE_LEFT (BUTTON_ON|BUTTON_PLAY)
87 #define ROCKBLOX_DOWN BUTTON_MENU
88 #define ROCKBLOX_LEFT BUTTON_LEFT
89 #define ROCKBLOX_RIGHT BUTTON_RIGHT
90 #define ROCKBLOX_DROP_PRE BUTTON_ON
91 #define ROCKBLOX_DROP (BUTTON_ON|BUTTON_REL)
93 #elif CONFIG_KEYPAD == ONDIO_PAD
95 #define ROCKBLOX_OFF BUTTON_OFF
96 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
97 #define ROCKBLOX_ROTATE_LEFT (BUTTON_MENU|BUTTON_UP)
98 #define ROCKBLOX_DOWN BUTTON_DOWN
99 #define ROCKBLOX_LEFT BUTTON_LEFT
100 #define ROCKBLOX_RIGHT BUTTON_RIGHT
101 #define ROCKBLOX_DROP_PRE BUTTON_MENU
102 #define ROCKBLOX_DROP (BUTTON_MENU|BUTTON_REL)
104 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
106 #define ROCKBLOX_OFF BUTTON_POWER
107 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
108 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
109 #define ROCKBLOX_DOWN BUTTON_DOWN
110 #define ROCKBLOX_LEFT BUTTON_LEFT
111 #define ROCKBLOX_RIGHT BUTTON_RIGHT
112 #define ROCKBLOX_DROP BUTTON_REC
113 #define ROCKBLOX_RESTART BUTTON_PLAY
115 #elif CONFIG_KEYPAD == SANSA_E200_PAD
117 #define ROCKBLOX_OFF BUTTON_POWER
118 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_BACK
119 #define ROCKBLOX_ROTATE_LEFT BUTTON_SCROLL_FWD
120 #define ROCKBLOX_DOWN BUTTON_DOWN
121 #define ROCKBLOX_LEFT BUTTON_LEFT
122 #define ROCKBLOX_RIGHT BUTTON_RIGHT
123 #define ROCKBLOX_DROP BUTTON_SELECT
124 #define ROCKBLOX_RESTART BUTTON_REC
126 #elif CONFIG_KEYPAD == SANSA_C200_PAD
128 #define ROCKBLOX_OFF BUTTON_POWER
129 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
130 #define ROCKBLOX_ROTATE_RIGHT2 BUTTON_VOL_DOWN
131 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
132 #define ROCKBLOX_DOWN BUTTON_DOWN
133 #define ROCKBLOX_LEFT BUTTON_LEFT
134 #define ROCKBLOX_RIGHT BUTTON_RIGHT
135 #define ROCKBLOX_DROP BUTTON_SELECT
136 #define ROCKBLOX_RESTART BUTTON_REC
138 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
140 #define ROCKBLOX_OFF BUTTON_POWER
141 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_UP
142 #define ROCKBLOX_ROTATE_LEFT BUTTON_REW
143 #define ROCKBLOX_DOWN BUTTON_SCROLL_DOWN
144 #define ROCKBLOX_LEFT BUTTON_LEFT
145 #define ROCKBLOX_RIGHT BUTTON_RIGHT
146 #define ROCKBLOX_DROP BUTTON_FF
147 #define ROCKBLOX_RESTART BUTTON_PLAY
149 #elif CONFIG_KEYPAD == GIGABEAT_PAD
151 #define ROCKBLOX_OFF BUTTON_POWER
152 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
153 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
154 #define ROCKBLOX_ROTATE BUTTON_UP
155 #define ROCKBLOX_DOWN BUTTON_DOWN
156 #define ROCKBLOX_LEFT BUTTON_LEFT
157 #define ROCKBLOX_RIGHT BUTTON_RIGHT
158 #define ROCKBLOX_DROP BUTTON_SELECT
159 #define ROCKBLOX_RESTART BUTTON_A
161 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
163 #define ROCKBLOX_OFF BUTTON_PLAY
164 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
165 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
166 #define ROCKBLOX_DOWN BUTTON_DOWN
167 #define ROCKBLOX_LEFT BUTTON_LEFT
168 #define ROCKBLOX_RIGHT BUTTON_RIGHT
169 #define ROCKBLOX_DROP BUTTON_MODE
170 #define ROCKBLOX_RESTART BUTTON_EQ
172 #elif CONFIG_KEYPAD == MROBE500_PAD
173 #define ROCKBLOX_OFF BUTTON_POWER
174 #define ROCKBLOX_ROTATE_RIGHT BUTTON_RC_VOL_UP
175 #define ROCKBLOX_ROTATE_LEFT BUTTON_RC_VOL_DOWN
176 #define ROCKBLOX_DOWN BUTTON_RC_DOWN
177 #define ROCKBLOX_LEFT BUTTON_LEFT
178 #define ROCKBLOX_RIGHT BUTTON_RIGHT
179 #define ROCKBLOX_DROP BUTTON_RC_HEART
180 #define ROCKBLOX_RESTART BUTTON_RC_MODE
182 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
183 #define ROCKBLOX_OFF BUTTON_BACK
184 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
185 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
186 #define ROCKBLOX_ROTATE BUTTON_UP
187 #define ROCKBLOX_DOWN BUTTON_DOWN
188 #define ROCKBLOX_LEFT BUTTON_LEFT
189 #define ROCKBLOX_RIGHT BUTTON_RIGHT
190 #define ROCKBLOX_DROP BUTTON_SELECT
191 #define ROCKBLOX_RESTART BUTTON_PLAY
193 #elif CONFIG_KEYPAD == MROBE100_PAD
195 #define ROCKBLOX_OFF BUTTON_POWER
196 #define ROCKBLOX_ROTATE_RIGHT BUTTON_MENU
197 #define ROCKBLOX_ROTATE_LEFT BUTTON_PLAY
198 #define ROCKBLOX_ROTATE BUTTON_UP
199 #define ROCKBLOX_DOWN BUTTON_DOWN
200 #define ROCKBLOX_LEFT BUTTON_LEFT
201 #define ROCKBLOX_RIGHT BUTTON_RIGHT
202 #define ROCKBLOX_DROP BUTTON_SELECT
203 #define ROCKBLOX_RESTART BUTTON_DISPLAY
205 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
207 #define ROCKBLOX_OFF BUTTON_RC_REC
208 #define ROCKBLOX_ROTATE_RIGHT BUTTON_RC_VOL_DOWN
209 #define ROCKBLOX_ROTATE_LEFT BUTTON_RC_VOL_UP
210 #define ROCKBLOX_DOWN BUTTON_RC_MENU
211 #define ROCKBLOX_LEFT BUTTON_RC_REW
212 #define ROCKBLOX_RIGHT BUTTON_RC_FF
213 #define ROCKBLOX_DROP BUTTON_RC_PLAY
214 #define ROCKBLOX_RESTART BUTTON_RC_MODE
216 #elif CONFIG_KEYPAD == COWOND2_PAD
217 #define ROCKBLOX_OFF BUTTON_POWER
218 #define ROCKBLOX_RESTART BUTTON_MENU
220 #elif CONFIG_KEYPAD == IAUDIO67_PAD
222 #define ROCKBLOX_OFF BUTTON_POWER
223 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOLDOWN
224 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOLUP
225 #define ROCKBLOX_DOWN BUTTON_STOP
226 #define ROCKBLOX_LEFT BUTTON_LEFT
227 #define ROCKBLOX_RIGHT BUTTON_RIGHT
228 #define ROCKBLOX_DROP BUTTON_PLAY
229 #define ROCKBLOX_RESTART BUTTON_MENU
232 #error No keymap defined!
235 #ifdef HAVE_TOUCHSCREEN
237 #define ROCKBLOX_OFF BUTTON_TOPLEFT
239 #ifndef ROCKBLOX_ROTATE_RIGHT
240 #define ROCKBLOX_ROTATE_RIGHT BUTTON_BOTTOMRIGHT
242 #ifndef ROCKBLOX_ROTATE_LEFT
243 #define ROCKBLOX_ROTATE_LEFT BUTTON_BOTTOMLEFT
245 #ifndef ROCKBLOX_DOWN
246 #define ROCKBLOX_DOWN BUTTON_BOTTOMMIDDLE
248 #ifndef ROCKBLOX_LEFT
249 #define ROCKBLOX_LEFT BUTTON_MIDLEFT
251 #ifndef ROCKBLOX_RIGHT
252 #define ROCKBLOX_RIGHT BUTTON_MIDRIGHT
254 #ifndef ROCKBLOX_DROP
255 #define ROCKBLOX_DROP BUTTON_CENTER
257 #ifndef ROCKBLOX_RESTART
258 #define ROCKBLOX_RESTART BUTTON_TOPRIGHT
263 #define EMPTY_BLOCK 7
265 #define BOARD_WIDTH 10
267 #ifdef HAVE_LCD_BITMAP
269 #define BOARD_HEIGHT 20
271 #if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
273 #define BLOCK_WIDTH 30
274 #define BLOCK_HEIGHT 30
277 #define PREVIEW_X 342
278 #define PREVIEW_Y 482
283 #define HIGH_LABEL_X 344
284 #define HIGH_SCORE_Y 326
285 #define HIGH_LEVEL_Y 344
287 #elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640)
289 #define BLOCK_WIDTH 30
290 #define BLOCK_HEIGHT 30
293 #define PREVIEW_X 342
294 #define PREVIEW_Y 482
299 #define HIGH_LABEL_X 344
300 #define HIGH_SCORE_Y 326
301 #define HIGH_LEVEL_Y 344
303 #elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
305 #define BLOCK_WIDTH 12
306 #define BLOCK_HEIGHT 12
316 #elif (LCD_WIDTH == 240) && (LCD_HEIGHT == 320)
318 #define BLOCK_WIDTH 15
319 #define BLOCK_HEIGHT 15
322 #define PREVIEW_X 171
323 #define PREVIEW_Y 241
328 #define HIGH_LABEL_X 172
329 #define HIGH_SCORE_Y 163
330 #define HIGH_LEVEL_Y 172
332 #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176)
334 #define BLOCK_WIDTH 8
335 #define BLOCK_HEIGHT 8
338 #define PREVIEW_X 158
339 #define PREVIEW_Y 130
345 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132)
347 #define BLOCK_WIDTH 6
348 #define BLOCK_HEIGHT 6
351 #define PREVIEW_X 126
352 #define PREVIEW_Y 102
358 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220)
360 #define BLOCK_WIDTH 10
361 #define BLOCK_HEIGHT 10
364 #define PREVIEW_X 124
365 #define PREVIEW_Y 167
370 #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128)
372 #define BLOCK_WIDTH 6
373 #define BLOCK_HEIGHT 6
376 #define PREVIEW_X 114
377 #define PREVIEW_Y 100
383 #elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110)
385 #define BLOCK_WIDTH 5
386 #define BLOCK_HEIGHT 5
396 #elif (LCD_WIDTH == 132) && (LCD_HEIGHT == 80)
398 #define BLOCK_WIDTH 4
399 #define BLOCK_HEIGHT 4
409 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 128)
411 #define BLOCK_WIDTH 6
412 #define BLOCK_HEIGHT 6
416 #define PREVIEW_Y 100
422 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 96)
424 #define BLOCK_WIDTH 4
425 #define BLOCK_HEIGHT 4
435 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64)
437 #define BLOCK_WIDTH 3
438 #define BLOCK_HEIGHT 3
448 #elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
450 #define BLOCK_WIDTH 4
451 #define BLOCK_HEIGHT 3
465 #define LEVEL_X LABEL_X
469 #define LINES_X LABEL_X
472 #define MYLCD(fn) rb->lcd_ ## fn
474 extern const fb_data rockblox_background
[];
476 #else /* HAVE_LCD_CHARCELLS */
478 #define BOARD_HEIGHT 14
480 #define BLOCK_WIDTH 1
481 #define BLOCK_HEIGHT 1
487 #define MYLCD(fn) pgfx_ ## fn
491 /* <<Explanation on Rockblox shapes>>
494 %% - O has 1 orientation
497 %% %% - Z has 2 orientations
501 %% %% - S has 2 orientations
505 % %%%% - I has 2 orientations
509 % % % %%% - L has 4 orientations
513 % % % %%% - J has 4 orientations
517 %% % %% % - T has 4 orientations
522 /* must have variable */
523 static const struct plugin_api
*rb
;
525 static bool gameover
= false;
526 /* c=current f=figure o=orientation n=next */
527 static int lines
= 0, level
= 0, score
= 0, cx
, cy
, cf
, co
, nf
;
528 static short board
[BOARD_HEIGHT
][BOARD_WIDTH
]; /* 20 rows of 10 blocks */
531 int wheel_events
= 0, last_wheel_event
= 0;
532 bool wheel_enabled
= false;
535 static const short scoring
[4] = { /* scoring for each number of lines */
536 #if BOARD_HEIGHT == 20
537 40 /* single */ , 100 /* double */ , 300 /* triple */ , 1200 /* rockblox */
538 #elif BOARD_HEIGHT == 14 /* Player special values */
539 60 /* single */ , 150 /* double */ , 500 /* triple */ , 2000 /* rockblox */
546 unsigned short color
[3]; /* color of figure (light,middle,shadow) */
548 unsigned short max_or
; /* max orientations */
549 signed short shapeX
[4], shapeY
[4]; /* implementation of figures */
552 /* array of figures */
553 figures
[BLOCKS_NUM
] = {
557 {LCD_RGBPACK (153, 255, 255), LCD_RGBPACK(0, 255, 255),
558 LCD_RGBPACK(0,153,153)},
560 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
569 {LCD_RGBPACK (255, 153, 128), LCD_RGBPACK (255, 0, 0),
570 LCD_RGBPACK (153, 0, 0)},
572 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
581 {LCD_RGBPACK (153, 255, 153), LCD_RGBPACK (0, 255, 0),
582 LCD_RGBPACK (0, 153, 0)},
584 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
593 {LCD_RGBPACK (153, 153, 255), LCD_RGBPACK (0, 0, 255),
594 LCD_RGBPACK (0, 0, 153)},
596 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
605 {LCD_RGBPACK (255, 255, 153), LCD_RGBPACK (255, 255, 0),
606 LCD_RGBPACK (153, 153, 0)},
608 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
617 {LCD_RGBPACK (255, 153, 255), LCD_RGBPACK (255, 0, 255),
618 LCD_RGBPACK (153, 0, 153)},
620 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
629 {LCD_RGBPACK (204, 204, 204), LCD_RGBPACK (153, 153, 153),
630 LCD_RGBPACK (85, 85, 85)},
632 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
640 /* Rockbox File System only supports full filenames inc dir */
641 #define HIGH_SCORE PLUGIN_GAMES_DIR "/rockblox.score"
642 #define MAX_HIGH_SCORES 5
643 /* Default High Scores... */
644 struct highscore Highest
[MAX_HIGH_SCORES
];
646 /* get random number from (0) to (range-1) */
647 static int t_rand (int range
)
649 return rb
->rand () % range
;
652 /* init the board array to have no blocks */
653 static void init_board (void)
656 for (i
= 0; i
< BOARD_WIDTH
; i
++)
657 for (j
= 0; j
< BOARD_HEIGHT
; j
++)
658 board
[j
][i
] = EMPTY_BLOCK
;
661 /* show the score, level and lines */
662 static void show_details (void)
664 char str
[25]; /* for strings */
666 #ifdef HAVE_LCD_BITMAP
668 rb
->lcd_set_foreground (LCD_BLACK
);
669 rb
->lcd_set_background (LCD_WHITE
);
671 rb
->snprintf (str
, sizeof (str
), "%d", score
);
672 rb
->lcd_putsxy (LABEL_X
, SCORE_Y
, str
);
673 rb
->snprintf (str
, sizeof (str
), "%d", level
);
674 rb
->lcd_putsxy (LEVEL_X
, LEVEL_Y
, str
);
675 rb
->snprintf (str
, sizeof (str
), "%d", lines
);
676 rb
->lcd_putsxy (LINES_X
, LINES_Y
, str
);
677 #else /* HAVE_LCD_CHARCELLS */
678 rb
->snprintf (str
, sizeof (str
), "L%d/%d", level
, lines
);
679 rb
->lcd_puts (5, 0, str
);
680 rb
->snprintf (str
, sizeof (str
), "S%d", score
);
681 rb
->lcd_puts (5, 1, str
);
686 static void show_highscores (void)
689 char str
[25]; /* for strings */
691 for (i
= MAX_HIGH_SCORES
-1; i
>=0; i
--)
693 rb
->snprintf (str
, sizeof (str
), "%06d L%1d", Highest
[i
].score
, Highest
[i
].level
);
694 rb
->lcd_putsxy (HIGH_LABEL_X
, HIGH_SCORE_Y
+ (10 * ((MAX_HIGH_SCORES
-1) - i
)), str
);
699 static void init_rockblox (void)
701 highscore_update(score
, level
, Highest
, MAX_HIGH_SCORES
);
707 nf
= t_rand (BLOCKS_NUM
);
709 #ifdef HAVE_LCD_BITMAP
710 rb
->lcd_bitmap (rockblox_background
, 0, 0, LCD_WIDTH
, LCD_HEIGHT
);
711 #else /* HAVE_LCD_CHARCELLS */
713 pgfx_display_block (3, 0, 3, 1);
714 pgfx_display_block (4, 0, 3, 0);
715 pgfx_clear_display();
716 pgfx_fillrect (3, 0, 2, 14);
717 pgfx_fillrect (15, 7, 2, 7);
726 static inline int level_speed(int level
)
728 #if BOARD_HEIGHT == 20
729 return (5*HZ
) / (level
+ 9);
730 #elif BOARD_HEIGHT == 14
731 return (7*HZ
) / (level
+ 9);
735 static int getRelativeX (int figure
, int square
, int orientation
)
737 switch (orientation
) {
739 return figures
[figure
].shapeX
[square
];
741 return figures
[figure
].shapeY
[square
];
743 return -figures
[figure
].shapeX
[square
];
745 return -figures
[figure
].shapeY
[square
];
751 static int getRelativeY (int figure
, int square
, int orientation
)
753 switch (orientation
) {
755 return figures
[figure
].shapeY
[square
];
757 return -figures
[figure
].shapeX
[square
];
759 return -figures
[figure
].shapeY
[square
];
761 return figures
[figure
].shapeX
[square
];
767 /* redraw the while board on the screen */
768 static void refresh_board (void)
770 int i
, j
, x
, y
, block
;
773 rb
->lcd_set_foreground (LCD_BLACK
);
775 MYLCD(set_drawmode
) (DRMODE_SOLID
| DRMODE_INVERSEVID
);
778 MYLCD(fillrect
) (BOARD_X
, BOARD_Y
, BOARD_WIDTH
* BLOCK_WIDTH
,
779 BOARD_HEIGHT
* BLOCK_HEIGHT
);
782 MYLCD(set_drawmode
) (DRMODE_SOLID
);
785 for (i
= 0; i
< BOARD_WIDTH
; i
++)
786 for (j
= 0; j
< BOARD_HEIGHT
; j
++) {
788 if (block
!= EMPTY_BLOCK
) {
789 #ifdef HAVE_LCD_BITMAP
792 rb
->lcd_set_foreground (figures
[block
].color
[1]);
794 rb
->lcd_fillrect (BOARD_X
+ i
* BLOCK_WIDTH
,
795 BOARD_Y
+ j
* BLOCK_HEIGHT
,
796 BLOCK_WIDTH
, BLOCK_HEIGHT
);
799 rb
->lcd_set_foreground (figures
[block
].color
[0]);
801 rb
->lcd_vline (BOARD_X
+ i
* BLOCK_WIDTH
,
802 BOARD_Y
+ j
* BLOCK_HEIGHT
,
803 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 2);
804 rb
->lcd_hline (BOARD_X
+ i
* BLOCK_WIDTH
,
805 BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 2,
806 BOARD_Y
+ j
* BLOCK_HEIGHT
);
809 rb
->lcd_set_foreground (figures
[block
].color
[2]);
811 rb
->lcd_vline (BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 1,
812 BOARD_Y
+ j
* BLOCK_HEIGHT
+ 1,
813 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 1);
814 rb
->lcd_hline (BOARD_X
+ i
* BLOCK_WIDTH
+ 1,
815 BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 1,
816 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 1);
817 #else /* HAVE_LCD_CHARCELLS */
818 pgfx_drawpixel (BOARD_X
+ i
, BOARD_Y
+ j
);
823 for (i
= 0; i
< 4; i
++) {
824 x
= getRelativeX (cf
, i
, co
) + cx
;
825 y
= getRelativeY (cf
, i
, co
) + cy
;
826 #ifdef HAVE_LCD_BITMAP
828 rb
->lcd_set_foreground (figures
[cf
].color
[1]); /* middle drawing */
830 rb
->lcd_fillrect (BOARD_X
+ x
* BLOCK_WIDTH
,
831 BOARD_Y
+ y
* BLOCK_HEIGHT
,
832 BLOCK_WIDTH
, BLOCK_HEIGHT
);
834 rb
->lcd_set_foreground (figures
[cf
].color
[0]); /* light drawing */
836 rb
->lcd_vline (BOARD_X
+ x
* BLOCK_WIDTH
, BOARD_Y
+ y
* BLOCK_HEIGHT
,
837 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 2);
838 rb
->lcd_hline (BOARD_X
+ x
* BLOCK_WIDTH
,
839 BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 2,
840 BOARD_Y
+ y
* BLOCK_HEIGHT
);
842 rb
->lcd_set_foreground (figures
[cf
].color
[2]); /* shadow drawing */
844 rb
->lcd_vline (BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 1,
845 BOARD_Y
+ y
* BLOCK_HEIGHT
+ 1,
846 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 1);
847 rb
->lcd_hline (BOARD_X
+ x
* BLOCK_WIDTH
+ 1,
848 BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 1,
849 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 1);
850 #else /* HAVE_LCD_CHARCELLS */
851 pgfx_drawpixel (BOARD_X
+ x
, BOARD_Y
+ y
);
857 static bool canMoveTo (int x
, int y
, int newOrientation
)
860 for (i
= 0; i
< 4; i
++) {
861 ry
= getRelativeY (cf
, i
, newOrientation
) + y
;
862 rx
= getRelativeX (cf
, i
, newOrientation
) + x
;
863 if ((rx
< 0 || rx
>= BOARD_WIDTH
) ||
864 (ry
< 0 || ry
>= BOARD_HEIGHT
) || (board
[ry
][rx
] != EMPTY_BLOCK
))
870 /* draws the preview of next block in the preview window */
871 static void draw_next_block (void)
874 /* clear preview window first */
876 rb
->lcd_set_foreground (LCD_BLACK
);
878 MYLCD(set_drawmode
) (DRMODE_SOLID
| DRMODE_INVERSEVID
);
882 MYLCD(fillrect
) (PREVIEW_X
, PREVIEW_Y
, BLOCK_WIDTH
* 4, BLOCK_HEIGHT
* 4);
885 MYLCD(set_drawmode
) (DRMODE_SOLID
);
888 /* draw the lightgray rectangles */
890 rb
->lcd_set_foreground (LCD_RGBPACK (40, 40, 40));
892 rb
->lcd_set_foreground (LCD_DARKGRAY
);
896 for (rx
= 0; rx
< 4; rx
++)
897 for (ry
= 0; ry
< 4; ry
++)
898 rb
->lcd_drawrect (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
899 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
, BLOCK_WIDTH
,
903 /* draw the figure */
904 for (i
= 0; i
< 4; i
++) {
905 rx
= getRelativeX (nf
, i
, 0) + 2;
906 ry
= getRelativeY (nf
, i
, 0) + 2;
907 #ifdef HAVE_LCD_BITMAP
909 rb
->lcd_set_foreground (figures
[nf
].color
[1]); /* middle drawing */
911 rb
->lcd_fillrect (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
912 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
,
913 BLOCK_WIDTH
, BLOCK_HEIGHT
);
915 rb
->lcd_set_foreground (figures
[nf
].color
[0]); /* light drawing */
917 rb
->lcd_vline (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
918 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
,
919 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 2);
920 rb
->lcd_hline (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
921 PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 2,
922 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
);
924 rb
->lcd_set_foreground (figures
[nf
].color
[2]); /* shadow drawing */
926 rb
->lcd_vline (PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 1,
927 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
+ 1,
928 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 1);
929 rb
->lcd_hline (PREVIEW_X
+ rx
* BLOCK_WIDTH
+ 1,
930 PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 1,
931 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 1);
932 #else /* HAVE_LCD_CHARCELLS */
933 pgfx_drawpixel (PREVIEW_X
+ rx
, PREVIEW_Y
+ ry
);
939 /* move the block to a relative location */
940 static void move_block (int x
, int y
, int o
)
942 if (canMoveTo (cx
+ x
, cy
+ y
, o
)) {
949 /* try to add a new block to play with (return true if gameover) */
950 static void new_block (void)
955 co
= 0; /* start at the same orientation all time */
956 nf
= t_rand (BLOCKS_NUM
);
957 gameover
= !canMoveTo (cx
, cy
, co
);
963 /* check for filled lines and do what necessary */
964 static int check_lines (void)
969 for (j
= 0; j
< BOARD_HEIGHT
; j
++) {
970 for (i
= 0; ((i
< BOARD_WIDTH
) && (board
[j
][i
] != EMPTY_BLOCK
)); i
++);
971 if (i
== BOARD_WIDTH
) { /* woo hoo, we have a line */
973 for (y
= j
; y
> 0; y
--)
974 for (i
= 0; i
< BOARD_WIDTH
; i
++)
975 board
[y
][i
] = board
[y
- 1][i
]; /* fall line */
982 /* moves down the figure and returns true if gameover */
983 static void move_down (void)
987 if (!canMoveTo (cx
, cy
+ 1, co
)) {
988 /* save figure to board */
989 for (i
= 0; i
< 4; i
++) {
990 rx
= getRelativeX (cf
, i
, co
) + cx
;
991 ry
= getRelativeY (cf
, i
, co
) + cy
;
994 /* check if formed some lines */
997 /* the original scoring from "http://en.wikipedia.org/wiki/Rockblox" */
998 score
+= scoring
[l
- 1] * level
;
1000 level
= (int) lines
/ 10 + 1;
1006 /* generate a new figure */
1009 move_block (0, 1, co
);
1012 static int rockblox_loop (void)
1015 int lastbutton
= BUTTON_NONE
;
1016 long next_down_tick
= *rb
->current_tick
+ level_speed(level
);
1021 #ifdef HAS_BUTTON_HOLD
1022 if (rb
->button_hold ()) {
1023 /* Turn on backlight timeout (revert to settings) */
1024 backlight_use_settings(rb
); /* backlight control in lib/helper.c */
1025 rb
->splash(0, "Paused");
1026 while (rb
->button_hold ())
1029 /* Turn off backlight timeout */
1030 backlight_force_on(rb
); /* backlight control in lib/helper.c */
1032 /* get rid of the splash text */
1033 rb
->lcd_bitmap (rockblox_background
, 0, 0, LCD_WIDTH
, LCD_HEIGHT
);
1043 button
= rb
->button_get_w_tmo (MAX(next_down_tick
- *rb
->current_tick
, 1));
1045 #ifdef ROCKBLOX_RC_OFF
1046 case ROCKBLOX_RC_OFF
:
1051 #if defined(ROCKBLOX_ROTATE)
1052 case ROCKBLOX_ROTATE
:
1054 case ROCKBLOX_ROTATE_RIGHT
:
1055 case ROCKBLOX_ROTATE_RIGHT
| BUTTON_REPEAT
:
1057 /* if the wheel is disabled, add an event to the stack. */
1058 if(wheel_enabled
== false)
1061 /* if it's enabled, go ahead and rotate.. */
1064 move_block (0, 0, (co
+ 1) % figures
[cf
].max_or
);
1067 case ROCKBLOX_ROTATE_LEFT
:
1068 case ROCKBLOX_ROTATE_LEFT
| BUTTON_REPEAT
:
1070 if(wheel_enabled
== false)
1076 (co
+ figures
[cf
].max_or
-
1077 1) % figures
[cf
].max_or
);
1080 #ifdef ROCKBLOX_ROTATE_RIGHT2
1081 case ROCKBLOX_ROTATE_RIGHT2
:
1082 move_block (0, 0, (co
+ 1) % figures
[cf
].max_or
);
1087 case ROCKBLOX_DOWN
| BUTTON_REPEAT
:
1088 move_block (0, 1, co
);
1091 case ROCKBLOX_RIGHT
:
1092 case ROCKBLOX_RIGHT
| BUTTON_REPEAT
:
1093 move_block (1, 0, co
);
1097 case ROCKBLOX_LEFT
| BUTTON_REPEAT
:
1098 move_block (-1, 0, co
);
1102 #ifdef ROCKBLOX_DROP_PRE
1103 if (lastbutton
!= ROCKBLOX_DROP_PRE
)
1106 while (canMoveTo (cx
, cy
+ 1, co
))
1107 move_block (0, 1, co
);
1109 #ifdef ROCKBLOX_RESTART
1110 case ROCKBLOX_RESTART
:
1111 rb
->splash (HZ
* 1, "Restarting...");
1118 if (rb
->default_event_handler (button
) == SYS_USB_CONNECTED
)
1119 return PLUGIN_USB_CONNECTED
;
1122 if (button
!= BUTTON_NONE
)
1123 lastbutton
= button
;
1126 /* check if we should enable the scroll wheel, if events
1127 * begin to stack up... */
1128 if(wheel_enabled
== false)
1130 /* stopped rotating the wheel, reset the count */
1131 if(wheel_events
== last_wheel_event
)
1133 last_wheel_event
= 0;
1136 /* rotated the wheel a while constantly, enable it. */
1137 else if(wheel_events
> 3)
1139 wheel_enabled
= true;
1142 /* this evens out the last event and the "current" event.
1143 * if we get an event next time through button reading, it will
1144 * remain ahead of last_event. if we don't, they'll end up equaling
1145 * each other.. thus, the scroll count will be reset. */
1146 if(wheel_enabled
== false && wheel_events
> last_wheel_event
)
1151 if (TIME_AFTER(*rb
->current_tick
, next_down_tick
)) {
1153 next_down_tick
+= level_speed(level
);
1154 if (TIME_AFTER(*rb
->current_tick
, next_down_tick
))
1155 /* restart time "raster" when we had to wait longer than usual
1156 * (pause, game restart etc) */
1157 next_down_tick
= *rb
->current_tick
+ level_speed(level
);
1162 rb
->lcd_set_foreground (LCD_BLACK
);
1164 rb
->splash (HZ
* 2, "Game Over");
1175 enum plugin_status
plugin_start (const struct plugin_api
*api
, const void *parameter
)
1182 rb
->srand (*rb
->current_tick
);
1184 /* Load HighScore if any */
1186 highscore_load(HIGH_SCORE
,Highest
,MAX_HIGH_SCORES
);
1189 rb
->lcd_set_backdrop(NULL
);
1192 #ifdef HAVE_LCD_BITMAP
1193 rb
->lcd_setfont (FONT_SYSFIXED
);
1195 if (!pgfx_init(rb
, 4, 2))
1197 rb
->splash(HZ
*2, "Old LCD :(");
1201 /* Turn off backlight timeout */
1202 backlight_force_on(rb
); /* backlight control in lib/helper.c */
1205 ret
= rockblox_loop ();
1207 #ifdef HAVE_LCD_BITMAP
1208 rb
->lcd_setfont (FONT_UI
);
1212 /* Save user's HighScore */
1213 highscore_save(HIGH_SCORE
,Highest
,MAX_HIGH_SCORES
);
1214 backlight_use_settings(rb
); /* backlight control in lib/helper.c */