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 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "highscore.h"
23 #include "playergfx.h"
28 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
29 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
30 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
32 #define ROCKBLOX_OFF (BUTTON_MENU | BUTTON_SELECT)
33 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_BACK
34 #define ROCKBLOX_ROTATE_RIGHT2 (BUTTON_MENU | BUTTON_REL)
35 #define ROCKBLOX_ROTATE_LEFT BUTTON_SCROLL_FWD
36 #define ROCKBLOX_LEFT BUTTON_LEFT
37 #define ROCKBLOX_RIGHT BUTTON_RIGHT
38 #define ROCKBLOX_DOWN BUTTON_PLAY
39 #define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_PLAY)
40 #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_LEFT BUTTON_SCROLL_FWD
118 #define ROCKBLOX_DOWN BUTTON_DOWN
119 #define ROCKBLOX_LEFT BUTTON_LEFT
120 #define ROCKBLOX_RIGHT BUTTON_RIGHT
121 #define ROCKBLOX_DROP BUTTON_SELECT
122 #define ROCKBLOX_RESTART BUTTON_REC
124 #elif CONFIG_KEYPAD == SANSA_C200_PAD
126 #define ROCKBLOX_OFF BUTTON_POWER
127 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
128 #define ROCKBLOX_ROTATE_RIGHT2 BUTTON_VOL_DOWN
129 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
130 #define ROCKBLOX_DOWN BUTTON_DOWN
131 #define ROCKBLOX_LEFT BUTTON_LEFT
132 #define ROCKBLOX_RIGHT BUTTON_RIGHT
133 #define ROCKBLOX_DROP BUTTON_SELECT
134 #define ROCKBLOX_RESTART BUTTON_REC
136 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
138 #define ROCKBLOX_OFF BUTTON_POWER
139 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_UP
140 #define ROCKBLOX_ROTATE_LEFT BUTTON_REW
141 #define ROCKBLOX_DOWN BUTTON_SCROLL_DOWN
142 #define ROCKBLOX_LEFT BUTTON_LEFT
143 #define ROCKBLOX_RIGHT BUTTON_RIGHT
144 #define ROCKBLOX_DROP BUTTON_FF
145 #define ROCKBLOX_RESTART BUTTON_PLAY
147 #elif CONFIG_KEYPAD == GIGABEAT_PAD
149 #define ROCKBLOX_OFF BUTTON_POWER
150 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
151 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
152 #define ROCKBLOX_ROTATE BUTTON_UP
153 #define ROCKBLOX_DOWN BUTTON_DOWN
154 #define ROCKBLOX_LEFT BUTTON_LEFT
155 #define ROCKBLOX_RIGHT BUTTON_RIGHT
156 #define ROCKBLOX_DROP BUTTON_SELECT
157 #define ROCKBLOX_RESTART BUTTON_A
159 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
161 #define ROCKBLOX_OFF BUTTON_PLAY
162 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
163 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
164 #define ROCKBLOX_DOWN BUTTON_DOWN
165 #define ROCKBLOX_LEFT BUTTON_LEFT
166 #define ROCKBLOX_RIGHT BUTTON_RIGHT
167 #define ROCKBLOX_DROP BUTTON_MODE
168 #define ROCKBLOX_RESTART BUTTON_EQ
170 #elif CONFIG_KEYPAD == MROBE500_PAD
171 #define ROCKBLOX_OFF BUTTON_POWER
172 #define ROCKBLOX_ROTATE_RIGHT BUTTON_RC_VOL_UP
173 #define ROCKBLOX_ROTATE_LEFT BUTTON_RC_VOL_DOWN
174 #define ROCKBLOX_DOWN BUTTON_RC_DOWN
175 #define ROCKBLOX_LEFT BUTTON_LEFT
176 #define ROCKBLOX_RIGHT BUTTON_RIGHT
177 #define ROCKBLOX_DROP BUTTON_RC_HEART
178 #define ROCKBLOX_RESTART BUTTON_RC_MODE
180 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
181 #define ROCKBLOX_OFF BUTTON_BACK
182 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
183 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
184 #define ROCKBLOX_ROTATE BUTTON_UP
185 #define ROCKBLOX_DOWN BUTTON_DOWN
186 #define ROCKBLOX_LEFT BUTTON_LEFT
187 #define ROCKBLOX_RIGHT BUTTON_RIGHT
188 #define ROCKBLOX_DROP BUTTON_SELECT
189 #define ROCKBLOX_RESTART BUTTON_PLAY
194 #define EMPTY_BLOCK 7
196 #define BOARD_WIDTH 10
198 #ifdef HAVE_LCD_BITMAP
200 #define BOARD_HEIGHT 20
202 #if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
204 #define BLOCK_WIDTH 30
205 #define BLOCK_HEIGHT 30
208 #define PREVIEW_X 342
209 #define PREVIEW_Y 482
214 #define HIGH_LABEL_X 344
215 #define HIGH_SCORE_Y 326
216 #define HIGH_LEVEL_Y 344
218 #elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640)
220 #define BLOCK_WIDTH 30
221 #define BLOCK_HEIGHT 30
224 #define PREVIEW_X 342
225 #define PREVIEW_Y 482
230 #define HIGH_LABEL_X 344
231 #define HIGH_SCORE_Y 326
232 #define HIGH_LEVEL_Y 344
234 #elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
236 #define BLOCK_WIDTH 12
237 #define BLOCK_HEIGHT 12
247 #elif (LCD_WIDTH == 240) && (LCD_HEIGHT == 320)
249 #define BLOCK_WIDTH 15
250 #define BLOCK_HEIGHT 15
253 #define PREVIEW_X 171
254 #define PREVIEW_Y 241
259 #define HIGH_LABEL_X 172
260 #define HIGH_SCORE_Y 163
261 #define HIGH_LEVEL_Y 172
263 #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176)
265 #define BLOCK_WIDTH 8
266 #define BLOCK_HEIGHT 8
269 #define PREVIEW_X 158
270 #define PREVIEW_Y 130
276 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132)
278 #define BLOCK_WIDTH 6
279 #define BLOCK_HEIGHT 6
282 #define PREVIEW_X 126
283 #define PREVIEW_Y 102
289 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220)
291 #define BLOCK_WIDTH 10
292 #define BLOCK_HEIGHT 10
295 #define PREVIEW_X 124
296 #define PREVIEW_Y 167
301 #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128)
303 #define BLOCK_WIDTH 6
304 #define BLOCK_HEIGHT 6
307 #define PREVIEW_X 114
308 #define PREVIEW_Y 100
314 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 128)
316 #define BLOCK_WIDTH 6
317 #define BLOCK_HEIGHT 6
321 #define PREVIEW_Y 100
327 #elif (LCD_WIDTH == 132) && (LCD_HEIGHT == 80)
329 #define BLOCK_WIDTH 4
330 #define BLOCK_HEIGHT 4
340 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64)
342 #define BLOCK_WIDTH 3
343 #define BLOCK_HEIGHT 3
353 #elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
355 #define BLOCK_WIDTH 4
356 #define BLOCK_HEIGHT 3
367 #elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110)
369 #define BLOCK_WIDTH 5
370 #define BLOCK_HEIGHT 5
383 #define LEVEL_X LABEL_X
387 #define LINES_X LABEL_X
390 #define MYLCD(fn) rb->lcd_ ## fn
392 extern const fb_data rockblox_background
[];
394 #else /* HAVE_LCD_CHARCELLS */
396 #define BOARD_HEIGHT 14
398 #define BLOCK_WIDTH 1
399 #define BLOCK_HEIGHT 1
405 #define MYLCD(fn) pgfx_ ## fn
409 /* <<Explanation on Rockblox shapes>>
412 %% - O has 1 orientation
415 %% %% - Z has 2 orientations
419 %% %% - S has 2 orientations
423 % %%%% - I has 2 orientations
427 % % % %%% - L has 4 orientations
431 % % % %%% - J has 4 orientations
435 %% % %% % - T has 4 orientations
440 /* must have variable */
441 static struct plugin_api
*rb
;
443 static bool gameover
= false;
444 /* c=current f=figure o=orientation n=next */
445 static int lines
= 0, level
= 0, score
= 0, cx
, cy
, cf
, co
, nf
;
446 static short board
[BOARD_HEIGHT
][BOARD_WIDTH
]; /* 20 rows of 10 blocks */
449 int wheel_events
= 0, last_wheel_event
= 0;
450 bool wheel_enabled
= false;
453 static const short scoring
[4] = { /* scoring for each number of lines */
454 #if BOARD_HEIGHT == 20
455 40 /* single */ , 100 /* double */ , 300 /* triple */ , 1200 /* rockblox */
456 #elif BOARD_HEIGHT == 14 /* Player special values */
457 60 /* single */ , 150 /* double */ , 500 /* triple */ , 2000 /* rockblox */
464 unsigned short color
[3]; /* color of figure (light,middle,shadow) */
466 unsigned short max_or
; /* max orientations */
467 signed short shapeX
[4], shapeY
[4]; /* implementation of figures */
470 /* array of figures */
471 figures
[BLOCKS_NUM
] = {
475 {LCD_RGBPACK (153, 255, 255), LCD_RGBPACK(0, 255, 255),
476 LCD_RGBPACK(0,153,153)},
478 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
487 {LCD_RGBPACK (255, 153, 128), LCD_RGBPACK (255, 0, 0),
488 LCD_RGBPACK (153, 0, 0)},
490 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
499 {LCD_RGBPACK (153, 255, 153), LCD_RGBPACK (0, 255, 0),
500 LCD_RGBPACK (0, 153, 0)},
502 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
511 {LCD_RGBPACK (153, 153, 255), LCD_RGBPACK (0, 0, 255),
512 LCD_RGBPACK (0, 0, 153)},
514 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
523 {LCD_RGBPACK (255, 255, 153), LCD_RGBPACK (255, 255, 0),
524 LCD_RGBPACK (153, 153, 0)},
526 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
535 {LCD_RGBPACK (255, 153, 255), LCD_RGBPACK (255, 0, 255),
536 LCD_RGBPACK (153, 0, 153)},
538 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
547 {LCD_RGBPACK (204, 204, 204), LCD_RGBPACK (153, 153, 153),
548 LCD_RGBPACK (85, 85, 85)},
550 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
558 /* Rockbox File System only supports full filenames inc dir */
559 #define HIGH_SCORE PLUGIN_GAMES_DIR "/rockblox.score"
560 #define MAX_HIGH_SCORES 5
561 /* Default High Scores... */
562 struct highscore Highest
[MAX_HIGH_SCORES
];
564 /* get random number from (0) to (range-1) */
565 static int t_rand (int range
)
567 return rb
->rand () % range
;
570 /* init the board array to have no blocks */
571 static void init_board (void)
574 for (i
= 0; i
< BOARD_WIDTH
; i
++)
575 for (j
= 0; j
< BOARD_HEIGHT
; j
++)
576 board
[j
][i
] = EMPTY_BLOCK
;
579 /* show the score, level and lines */
580 static void show_details (void)
582 char str
[25]; /* for strings */
584 #ifdef HAVE_LCD_BITMAP
586 rb
->lcd_set_foreground (LCD_BLACK
);
587 rb
->lcd_set_background (LCD_WHITE
);
589 rb
->snprintf (str
, sizeof (str
), "%d", score
);
590 rb
->lcd_putsxy (LABEL_X
, SCORE_Y
, str
);
591 rb
->snprintf (str
, sizeof (str
), "%d", level
);
592 rb
->lcd_putsxy (LEVEL_X
, LEVEL_Y
, str
);
593 rb
->snprintf (str
, sizeof (str
), "%d", lines
);
594 rb
->lcd_putsxy (LINES_X
, LINES_Y
, str
);
595 #else /* HAVE_LCD_CHARCELLS */
596 rb
->snprintf (str
, sizeof (str
), "L%d/%d", level
, lines
);
597 rb
->lcd_puts (5, 0, str
);
598 rb
->snprintf (str
, sizeof (str
), "S%d", score
);
599 rb
->lcd_puts (5, 1, str
);
604 static void show_highscores (void)
607 char str
[25]; /* for strings */
609 for (i
= MAX_HIGH_SCORES
-1; i
>=0; i
--)
611 rb
->snprintf (str
, sizeof (str
), "%06d L%1d", Highest
[i
].score
, Highest
[i
].level
);
612 rb
->lcd_putsxy (HIGH_LABEL_X
, HIGH_SCORE_Y
+ (10 * ((MAX_HIGH_SCORES
-1) - i
)), str
);
617 static void init_rockblox (void)
619 highscore_update(score
, level
, Highest
, MAX_HIGH_SCORES
);
625 nf
= t_rand (BLOCKS_NUM
);
627 #ifdef HAVE_LCD_BITMAP
628 rb
->lcd_bitmap (rockblox_background
, 0, 0, LCD_WIDTH
, LCD_HEIGHT
);
629 #else /* HAVE_LCD_CHARCELLS */
631 pgfx_display_block (3, 0, 3, 1);
632 pgfx_display_block (4, 0, 3, 0);
633 pgfx_clear_display();
634 pgfx_fillrect (3, 0, 2, 14);
635 pgfx_fillrect (15, 7, 2, 7);
644 static inline int level_speed(int level
)
646 #if BOARD_HEIGHT == 20
647 return (5*HZ
) / (level
+ 9);
648 #elif BOARD_HEIGHT == 14
649 return (7*HZ
) / (level
+ 9);
653 static int getRelativeX (int figure
, int square
, int orientation
)
655 switch (orientation
) {
657 return figures
[figure
].shapeX
[square
];
659 return figures
[figure
].shapeY
[square
];
661 return -figures
[figure
].shapeX
[square
];
663 return -figures
[figure
].shapeY
[square
];
669 static int getRelativeY (int figure
, int square
, int orientation
)
671 switch (orientation
) {
673 return figures
[figure
].shapeY
[square
];
675 return -figures
[figure
].shapeX
[square
];
677 return -figures
[figure
].shapeY
[square
];
679 return figures
[figure
].shapeX
[square
];
685 /* redraw the while board on the screen */
686 static void refresh_board (void)
688 int i
, j
, x
, y
, block
;
691 rb
->lcd_set_foreground (LCD_BLACK
);
693 MYLCD(set_drawmode
) (DRMODE_SOLID
| DRMODE_INVERSEVID
);
696 MYLCD(fillrect
) (BOARD_X
, BOARD_Y
, BOARD_WIDTH
* BLOCK_WIDTH
,
697 BOARD_HEIGHT
* BLOCK_HEIGHT
);
700 MYLCD(set_drawmode
) (DRMODE_SOLID
);
703 for (i
= 0; i
< BOARD_WIDTH
; i
++)
704 for (j
= 0; j
< BOARD_HEIGHT
; j
++) {
706 if (block
!= EMPTY_BLOCK
) {
707 #ifdef HAVE_LCD_BITMAP
710 rb
->lcd_set_foreground (figures
[block
].color
[1]);
712 rb
->lcd_fillrect (BOARD_X
+ i
* BLOCK_WIDTH
,
713 BOARD_Y
+ j
* BLOCK_HEIGHT
,
714 BLOCK_WIDTH
, BLOCK_HEIGHT
);
717 rb
->lcd_set_foreground (figures
[block
].color
[0]);
719 rb
->lcd_vline (BOARD_X
+ i
* BLOCK_WIDTH
,
720 BOARD_Y
+ j
* BLOCK_HEIGHT
,
721 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 2);
722 rb
->lcd_hline (BOARD_X
+ i
* BLOCK_WIDTH
,
723 BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 2,
724 BOARD_Y
+ j
* BLOCK_HEIGHT
);
727 rb
->lcd_set_foreground (figures
[block
].color
[2]);
729 rb
->lcd_vline (BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 1,
730 BOARD_Y
+ j
* BLOCK_HEIGHT
+ 1,
731 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 1);
732 rb
->lcd_hline (BOARD_X
+ i
* BLOCK_WIDTH
+ 1,
733 BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 1,
734 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 1);
735 #else /* HAVE_LCD_CHARCELLS */
736 pgfx_drawpixel (BOARD_X
+ i
, BOARD_Y
+ j
);
741 for (i
= 0; i
< 4; i
++) {
742 x
= getRelativeX (cf
, i
, co
) + cx
;
743 y
= getRelativeY (cf
, i
, co
) + cy
;
744 #ifdef HAVE_LCD_BITMAP
746 rb
->lcd_set_foreground (figures
[cf
].color
[1]); /* middle drawing */
748 rb
->lcd_fillrect (BOARD_X
+ x
* BLOCK_WIDTH
,
749 BOARD_Y
+ y
* BLOCK_HEIGHT
,
750 BLOCK_WIDTH
, BLOCK_HEIGHT
);
752 rb
->lcd_set_foreground (figures
[cf
].color
[0]); /* light drawing */
754 rb
->lcd_vline (BOARD_X
+ x
* BLOCK_WIDTH
, BOARD_Y
+ y
* BLOCK_HEIGHT
,
755 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 2);
756 rb
->lcd_hline (BOARD_X
+ x
* BLOCK_WIDTH
,
757 BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 2,
758 BOARD_Y
+ y
* BLOCK_HEIGHT
);
760 rb
->lcd_set_foreground (figures
[cf
].color
[2]); /* shadow drawing */
762 rb
->lcd_vline (BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 1,
763 BOARD_Y
+ y
* BLOCK_HEIGHT
+ 1,
764 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 1);
765 rb
->lcd_hline (BOARD_X
+ x
* BLOCK_WIDTH
+ 1,
766 BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 1,
767 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 1);
768 #else /* HAVE_LCD_CHARCELLS */
769 pgfx_drawpixel (BOARD_X
+ x
, BOARD_Y
+ y
);
775 static bool canMoveTo (int x
, int y
, int newOrientation
)
778 for (i
= 0; i
< 4; i
++) {
779 ry
= getRelativeY (cf
, i
, newOrientation
) + y
;
780 rx
= getRelativeX (cf
, i
, newOrientation
) + x
;
781 if ((rx
< 0 || rx
>= BOARD_WIDTH
) ||
782 (ry
< 0 || ry
>= BOARD_HEIGHT
) || (board
[ry
][rx
] != EMPTY_BLOCK
))
788 /* draws the preview of next block in the preview window */
789 static void draw_next_block (void)
792 /* clear preview window first */
794 rb
->lcd_set_foreground (LCD_BLACK
);
796 MYLCD(set_drawmode
) (DRMODE_SOLID
| DRMODE_INVERSEVID
);
800 MYLCD(fillrect
) (PREVIEW_X
, PREVIEW_Y
, BLOCK_WIDTH
* 4, BLOCK_HEIGHT
* 4);
803 MYLCD(set_drawmode
) (DRMODE_SOLID
);
806 /* draw the lightgray rectangles */
808 rb
->lcd_set_foreground (LCD_RGBPACK (40, 40, 40));
810 rb
->lcd_set_foreground (LCD_DARKGRAY
);
814 for (rx
= 0; rx
< 4; rx
++)
815 for (ry
= 0; ry
< 4; ry
++)
816 rb
->lcd_drawrect (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
817 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
, BLOCK_WIDTH
,
821 /* draw the figure */
822 for (i
= 0; i
< 4; i
++) {
823 rx
= getRelativeX (nf
, i
, 0) + 2;
824 ry
= getRelativeY (nf
, i
, 0) + 2;
825 #ifdef HAVE_LCD_BITMAP
827 rb
->lcd_set_foreground (figures
[nf
].color
[1]); /* middle drawing */
829 rb
->lcd_fillrect (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
830 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
,
831 BLOCK_WIDTH
, BLOCK_HEIGHT
);
833 rb
->lcd_set_foreground (figures
[nf
].color
[0]); /* light drawing */
835 rb
->lcd_vline (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
836 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
,
837 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 2);
838 rb
->lcd_hline (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
839 PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 2,
840 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
);
842 rb
->lcd_set_foreground (figures
[nf
].color
[2]); /* shadow drawing */
844 rb
->lcd_vline (PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 1,
845 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
+ 1,
846 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 1);
847 rb
->lcd_hline (PREVIEW_X
+ rx
* BLOCK_WIDTH
+ 1,
848 PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 1,
849 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 1);
850 #else /* HAVE_LCD_CHARCELLS */
851 pgfx_drawpixel (PREVIEW_X
+ rx
, PREVIEW_Y
+ ry
);
857 /* move the block to a relative location */
858 static void move_block (int x
, int y
, int o
)
860 if (canMoveTo (cx
+ x
, cy
+ y
, o
)) {
867 /* try to add a new block to play with (return true if gameover) */
868 static void new_block (void)
873 co
= 0; /* start at the same orientation all time */
874 nf
= t_rand (BLOCKS_NUM
);
875 gameover
= !canMoveTo (cx
, cy
, co
);
881 /* check for filled lines and do what necessary */
882 static int check_lines (void)
887 for (j
= 0; j
< BOARD_HEIGHT
; j
++) {
888 for (i
= 0; ((i
< BOARD_WIDTH
) && (board
[j
][i
] != EMPTY_BLOCK
)); i
++);
889 if (i
== BOARD_WIDTH
) { /* woo hoo, we have a line */
891 for (y
= j
; y
> 0; y
--)
892 for (i
= 0; i
< BOARD_WIDTH
; i
++)
893 board
[y
][i
] = board
[y
- 1][i
]; /* fall line */
900 /* moves down the figure and returns true if gameover */
901 static void move_down (void)
905 if (!canMoveTo (cx
, cy
+ 1, co
)) {
906 /* save figure to board */
907 for (i
= 0; i
< 4; i
++) {
908 rx
= getRelativeX (cf
, i
, co
) + cx
;
909 ry
= getRelativeY (cf
, i
, co
) + cy
;
912 /* check if formed some lines */
915 /* the original scoring from "http://en.wikipedia.org/wiki/Rockblox" */
916 score
+= scoring
[l
- 1] * level
;
918 level
= (int) lines
/ 10 + 1;
924 /* generate a new figure */
927 move_block (0, 1, co
);
930 static int rockblox_loop (void)
933 int lastbutton
= BUTTON_NONE
;
934 long next_down_tick
= *rb
->current_tick
+ level_speed(level
);
939 #ifdef HAS_BUTTON_HOLD
940 if (rb
->button_hold ()) {
941 /* Turn on backlight timeout (revert to settings) */
942 backlight_use_settings(rb
); /* backlight control in lib/helper.c */
943 rb
->splash(0, "Paused");
944 while (rb
->button_hold ())
947 /* Turn off backlight timeout */
948 backlight_force_on(rb
); /* backlight control in lib/helper.c */
950 /* get rid of the splash text */
951 rb
->lcd_bitmap (rockblox_background
, 0, 0, LCD_WIDTH
, LCD_HEIGHT
);
961 button
= rb
->button_get_w_tmo (MAX(next_down_tick
- *rb
->current_tick
, 1));
963 #ifdef ROCKBLOX_RC_OFF
964 case ROCKBLOX_RC_OFF
:
969 #if defined(ROCKBLOX_ROTATE)
970 case ROCKBLOX_ROTATE
:
972 case ROCKBLOX_ROTATE_RIGHT
:
973 case ROCKBLOX_ROTATE_RIGHT
| BUTTON_REPEAT
:
975 /* if the wheel is disabled, add an event to the stack. */
976 if(wheel_enabled
== false)
979 /* if it's enabled, go ahead and rotate.. */
982 move_block (0, 0, (co
+ 1) % figures
[cf
].max_or
);
985 case ROCKBLOX_ROTATE_LEFT
:
986 case ROCKBLOX_ROTATE_LEFT
| BUTTON_REPEAT
:
988 if(wheel_enabled
== false)
994 (co
+ figures
[cf
].max_or
-
995 1) % figures
[cf
].max_or
);
998 #ifdef ROCKBLOX_ROTATE_RIGHT2
999 case ROCKBLOX_ROTATE_RIGHT2
:
1000 move_block (0, 0, (co
+ 1) % figures
[cf
].max_or
);
1005 case ROCKBLOX_DOWN
| BUTTON_REPEAT
:
1006 move_block (0, 1, co
);
1009 case ROCKBLOX_RIGHT
:
1010 case ROCKBLOX_RIGHT
| BUTTON_REPEAT
:
1011 move_block (1, 0, co
);
1015 case ROCKBLOX_LEFT
| BUTTON_REPEAT
:
1016 move_block (-1, 0, co
);
1020 #ifdef ROCKBLOX_DROP_PRE
1021 if (lastbutton
!= ROCKBLOX_DROP_PRE
)
1024 while (canMoveTo (cx
, cy
+ 1, co
))
1025 move_block (0, 1, co
);
1027 #ifdef ROCKBLOX_RESTART
1028 case ROCKBLOX_RESTART
:
1029 rb
->splash (HZ
* 1, "Restarting...");
1036 if (rb
->default_event_handler (button
) == SYS_USB_CONNECTED
)
1037 return PLUGIN_USB_CONNECTED
;
1040 if (button
!= BUTTON_NONE
)
1041 lastbutton
= button
;
1044 /* check if we should enable the scroll wheel, if events
1045 * begin to stack up... */
1046 if(wheel_enabled
== false)
1048 /* stopped rotating the wheel, reset the count */
1049 if(wheel_events
== last_wheel_event
)
1051 last_wheel_event
= 0;
1054 /* rotated the wheel a while constantly, enable it. */
1055 else if(wheel_events
> 3)
1057 wheel_enabled
= true;
1060 /* this evens out the last event and the "current" event.
1061 * if we get an event next time through button reading, it will
1062 * remain ahead of last_event. if we don't, they'll end up equaling
1063 * each other.. thus, the scroll count will be reset. */
1064 if(wheel_enabled
== false && wheel_events
> last_wheel_event
)
1069 if (TIME_AFTER(*rb
->current_tick
, next_down_tick
)) {
1071 next_down_tick
+= level_speed(level
);
1072 if (TIME_AFTER(*rb
->current_tick
, next_down_tick
))
1073 /* restart time "raster" when we had to wait longer than usual
1074 * (pause, game restart etc) */
1075 next_down_tick
= *rb
->current_tick
+ level_speed(level
);
1080 rb
->lcd_set_foreground (LCD_BLACK
);
1082 rb
->splash (HZ
* 2, "Game Over");
1093 enum plugin_status
plugin_start (struct plugin_api
*api
, void *parameter
)
1100 rb
->srand (*rb
->current_tick
);
1102 /* Load HighScore if any */
1104 highscore_load(HIGH_SCORE
,Highest
,MAX_HIGH_SCORES
);
1107 rb
->lcd_set_backdrop(NULL
);
1110 #ifdef HAVE_LCD_BITMAP
1111 rb
->lcd_setfont (FONT_SYSFIXED
);
1113 if (!pgfx_init(rb
, 4, 2))
1115 rb
->splash(HZ
*2, "Old LCD :(");
1119 /* Turn off backlight timeout */
1120 backlight_force_on(rb
); /* backlight control in lib/helper.c */
1123 ret
= rockblox_loop ();
1125 #ifdef HAVE_LCD_BITMAP
1126 rb
->lcd_setfont (FONT_UI
);
1130 /* Save user's HighScore */
1131 highscore_save(HIGH_SCORE
,Highest
,MAX_HIGH_SCORES
);
1132 backlight_use_settings(rb
); /* backlight control in lib/helper.c */