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"
27 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
28 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
29 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
31 #define ROCKBLOX_OFF (BUTTON_MENU | BUTTON_SELECT)
32 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_BACK
33 #define ROCKBLOX_ROTATE_RIGHT2 (BUTTON_MENU | BUTTON_REL)
34 #define ROCKBLOX_ROTATE_LEFT BUTTON_SCROLL_FWD
35 #define ROCKBLOX_LEFT BUTTON_LEFT
36 #define ROCKBLOX_RIGHT BUTTON_RIGHT
37 #define ROCKBLOX_DOWN BUTTON_PLAY
38 #define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_PLAY)
39 #define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
43 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
44 (CONFIG_KEYPAD == IRIVER_H300_PAD)
46 #define ROCKBLOX_OFF BUTTON_OFF
47 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
48 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
49 #define ROCKBLOX_DOWN BUTTON_DOWN
50 #define ROCKBLOX_LEFT BUTTON_LEFT
51 #define ROCKBLOX_RIGHT BUTTON_RIGHT
52 #define ROCKBLOX_DROP BUTTON_MODE
53 #define ROCKBLOX_RESTART BUTTON_ON
55 #define ROCKBLOX_RC_OFF BUTTON_RC_STOP
57 #elif CONFIG_KEYPAD == RECORDER_PAD
59 #define ROCKBLOX_OFF BUTTON_OFF
60 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
61 #define ROCKBLOX_ROTATE_LEFT BUTTON_PLAY
62 #define ROCKBLOX_DOWN BUTTON_DOWN
63 #define ROCKBLOX_LEFT BUTTON_LEFT
64 #define ROCKBLOX_RIGHT BUTTON_RIGHT
65 #define ROCKBLOX_DROP BUTTON_ON
66 #define ROCKBLOX_RESTART BUTTON_F1
68 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
70 #define ROCKBLOX_OFF BUTTON_OFF
71 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
72 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
73 #define ROCKBLOX_DOWN BUTTON_DOWN
74 #define ROCKBLOX_LEFT BUTTON_LEFT
75 #define ROCKBLOX_RIGHT BUTTON_RIGHT
76 #define ROCKBLOX_DROP BUTTON_ON
77 #define ROCKBLOX_RESTART BUTTON_F1
79 #elif CONFIG_KEYPAD == PLAYER_PAD
81 #define ROCKBLOX_OFF BUTTON_STOP
82 #define ROCKBLOX_ROTATE_RIGHT BUTTON_PLAY
83 #define ROCKBLOX_ROTATE_LEFT (BUTTON_ON|BUTTON_PLAY)
84 #define ROCKBLOX_DOWN BUTTON_MENU
85 #define ROCKBLOX_LEFT BUTTON_LEFT
86 #define ROCKBLOX_RIGHT BUTTON_RIGHT
87 #define ROCKBLOX_DROP_PRE BUTTON_ON
88 #define ROCKBLOX_DROP (BUTTON_ON|BUTTON_REL)
90 #elif CONFIG_KEYPAD == ONDIO_PAD
92 #define ROCKBLOX_OFF BUTTON_OFF
93 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
94 #define ROCKBLOX_ROTATE_LEFT (BUTTON_MENU|BUTTON_UP)
95 #define ROCKBLOX_DOWN BUTTON_DOWN
96 #define ROCKBLOX_LEFT BUTTON_LEFT
97 #define ROCKBLOX_RIGHT BUTTON_RIGHT
98 #define ROCKBLOX_DROP_PRE BUTTON_MENU
99 #define ROCKBLOX_DROP (BUTTON_MENU|BUTTON_REL)
101 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
103 #define ROCKBLOX_OFF BUTTON_POWER
104 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
105 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
106 #define ROCKBLOX_DOWN BUTTON_DOWN
107 #define ROCKBLOX_LEFT BUTTON_LEFT
108 #define ROCKBLOX_RIGHT BUTTON_RIGHT
109 #define ROCKBLOX_DROP BUTTON_REC
110 #define ROCKBLOX_RESTART BUTTON_PLAY
112 #elif CONFIG_KEYPAD == SANSA_E200_PAD
114 #define ROCKBLOX_OFF BUTTON_POWER
115 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_UP
116 #define ROCKBLOX_ROTATE_LEFT BUTTON_SCROLL_DOWN
117 #define ROCKBLOX_DOWN BUTTON_DOWN
118 #define ROCKBLOX_LEFT BUTTON_LEFT
119 #define ROCKBLOX_RIGHT BUTTON_RIGHT
120 #define ROCKBLOX_DROP BUTTON_SELECT
121 #define ROCKBLOX_RESTART BUTTON_REC
123 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
125 #define ROCKBLOX_OFF BUTTON_POWER
126 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_UP
127 #define ROCKBLOX_ROTATE_LEFT BUTTON_REW
128 #define ROCKBLOX_DOWN BUTTON_SCROLL_DOWN
129 #define ROCKBLOX_LEFT BUTTON_LEFT
130 #define ROCKBLOX_RIGHT BUTTON_RIGHT
131 #define ROCKBLOX_DROP BUTTON_FF
132 #define ROCKBLOX_RESTART BUTTON_PLAY
134 #elif CONFIG_KEYPAD == GIGABEAT_PAD
136 #define ROCKBLOX_OFF BUTTON_POWER
137 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
138 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
139 #define ROCKBLOX_ROTATE BUTTON_UP
140 #define ROCKBLOX_DOWN BUTTON_DOWN
141 #define ROCKBLOX_LEFT BUTTON_LEFT
142 #define ROCKBLOX_RIGHT BUTTON_RIGHT
143 #define ROCKBLOX_DROP BUTTON_SELECT
144 #define ROCKBLOX_RESTART BUTTON_A
146 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
148 #define ROCKBLOX_OFF BUTTON_PLAY
149 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
150 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
151 #define ROCKBLOX_DOWN BUTTON_DOWN
152 #define ROCKBLOX_LEFT BUTTON_LEFT
153 #define ROCKBLOX_RIGHT BUTTON_RIGHT
154 #define ROCKBLOX_DROP BUTTON_MODE
155 #define ROCKBLOX_RESTART BUTTON_EQ
160 #define EMPTY_BLOCK 7
162 #define BOARD_WIDTH 10
164 #ifdef HAVE_LCD_BITMAP
166 #define BOARD_HEIGHT 20
168 #if (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
170 #define BLOCK_WIDTH 12
171 #define BLOCK_HEIGHT 12
181 #elif (LCD_WIDTH == 240) && (LCD_HEIGHT == 320)
183 #define BLOCK_WIDTH 15
184 #define BLOCK_HEIGHT 15
187 #define PREVIEW_X 171
188 #define PREVIEW_Y 241
193 #define HIGH_LABEL_X 172
194 #define HIGH_SCORE_Y 163
195 #define HIGH_LEVEL_Y 172
197 #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176)
199 #define BLOCK_WIDTH 8
200 #define BLOCK_HEIGHT 8
203 #define PREVIEW_X 158
204 #define PREVIEW_Y 130
210 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132)
212 #define BLOCK_WIDTH 6
213 #define BLOCK_HEIGHT 6
216 #define PREVIEW_X 126
217 #define PREVIEW_Y 102
223 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220)
225 #define BLOCK_WIDTH 10
226 #define BLOCK_HEIGHT 10
229 #define PREVIEW_X 124
230 #define PREVIEW_Y 167
235 #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128)
237 #define BLOCK_WIDTH 6
238 #define BLOCK_HEIGHT 6
241 #define PREVIEW_X 114
242 #define PREVIEW_Y 100
248 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 128)
250 #define BLOCK_WIDTH 6
251 #define BLOCK_HEIGHT 6
255 #define PREVIEW_Y 100
261 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64)
263 #define BLOCK_WIDTH 3
264 #define BLOCK_HEIGHT 3
274 #elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
276 #define BLOCK_WIDTH 4
277 #define BLOCK_HEIGHT 3
288 #elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110)
290 #define BLOCK_WIDTH 5
291 #define BLOCK_HEIGHT 5
304 #define LEVEL_X LABEL_X
308 #define LINES_X LABEL_X
311 #define MYLCD(fn) rb->lcd_ ## fn
313 extern const fb_data rockblox_background
[];
315 #else /* HAVE_LCD_CHARCELLS */
317 #define BOARD_HEIGHT 14
319 #define BLOCK_WIDTH 1
320 #define BLOCK_HEIGHT 1
326 #define MYLCD(fn) pgfx_ ## fn
330 /* <<Explanation on Rockblox shapes>>
333 %% - O has 1 orientation
336 %% %% - Z has 2 orientations
340 %% %% - S has 2 orientations
344 % %%%% - I has 2 orientations
348 % % % %%% - L has 4 orientations
352 % % % %%% - J has 4 orientations
356 %% % %% % - T has 4 orientations
361 /* must have variable */
362 static struct plugin_api
*rb
;
364 static bool gameover
= false;
365 /* c=current f=figure o=orientation n=next */
366 static int lines
= 0, level
= 0, score
= 0, cx
, cy
, cf
, co
, nf
;
367 static short board
[BOARD_HEIGHT
][BOARD_WIDTH
]; /* 20 rows of 10 blocks */
370 int wheel_events
= 0, last_wheel_event
= 0;
371 bool wheel_enabled
= false;
374 static const short scoring
[4] = { /* scoring for each number of lines */
375 #if BOARD_HEIGHT == 20
376 40 /* single */ , 100 /* double */ , 300 /* triple */ , 1200 /* rockblox */
377 #elif BOARD_HEIGHT == 14 /* Player special values */
378 60 /* single */ , 150 /* double */ , 500 /* triple */ , 2000 /* rockblox */
385 unsigned short color
[3]; /* color of figure (light,middle,shadow) */
387 unsigned short max_or
; /* max orientations */
388 signed short shapeX
[4], shapeY
[4]; /* implementation of figures */
391 /* array of figures */
392 figures
[BLOCKS_NUM
] = {
396 {LCD_RGBPACK (153, 255, 255), LCD_RGBPACK(0, 255, 255),
397 LCD_RGBPACK(0,153,153)},
399 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
408 {LCD_RGBPACK (255, 153, 128), LCD_RGBPACK (255, 0, 0),
409 LCD_RGBPACK (153, 0, 0)},
411 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
420 {LCD_RGBPACK (153, 255, 153), LCD_RGBPACK (0, 255, 0),
421 LCD_RGBPACK (0, 153, 0)},
423 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
432 {LCD_RGBPACK (153, 153, 255), LCD_RGBPACK (0, 0, 255),
433 LCD_RGBPACK (0, 0, 153)},
435 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
444 {LCD_RGBPACK (255, 255, 153), LCD_RGBPACK (255, 255, 0),
445 LCD_RGBPACK (153, 153, 0)},
447 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
456 {LCD_RGBPACK (255, 153, 255), LCD_RGBPACK (255, 0, 255),
457 LCD_RGBPACK (153, 0, 153)},
459 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
468 {LCD_RGBPACK (204, 204, 204), LCD_RGBPACK (153, 153, 153),
469 LCD_RGBPACK (85, 85, 85)},
471 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
479 /* Rockbox File System only supports full filenames inc dir */
480 #define HIGH_SCORE "/.rockbox/rocks/rockblox.score"
481 #define MAX_HIGH_SCORES 5
482 /* Default High Scores... */
483 struct highscore Highest
[MAX_HIGH_SCORES
];
485 /* get random number from (0) to (range-1) */
486 static int t_rand (int range
)
488 return rb
->rand () % range
;
491 /* init the board array to have no blocks */
492 static void init_board (void)
495 for (i
= 0; i
< BOARD_WIDTH
; i
++)
496 for (j
= 0; j
< BOARD_HEIGHT
; j
++)
497 board
[j
][i
] = EMPTY_BLOCK
;
500 /* show the score, level and lines */
501 static void show_details (void)
503 char str
[25]; /* for strings */
505 #ifdef HAVE_LCD_BITMAP
507 rb
->lcd_set_foreground (LCD_BLACK
);
508 rb
->lcd_set_background (LCD_WHITE
);
510 rb
->snprintf (str
, sizeof (str
), "%d", score
);
511 rb
->lcd_putsxy (LABEL_X
, SCORE_Y
, str
);
512 rb
->snprintf (str
, sizeof (str
), "%d", level
);
513 rb
->lcd_putsxy (LEVEL_X
, LEVEL_Y
, str
);
514 rb
->snprintf (str
, sizeof (str
), "%d", lines
);
515 rb
->lcd_putsxy (LINES_X
, LINES_Y
, str
);
516 #else /* HAVE_LCD_CHARCELLS */
517 rb
->snprintf (str
, sizeof (str
), "L%d/%d", level
, lines
);
518 rb
->lcd_puts (5, 0, str
);
519 rb
->snprintf (str
, sizeof (str
), "S%d", score
);
520 rb
->lcd_puts (5, 1, str
);
524 static void init_rockblox (void)
528 char str
[25]; /* for strings */
530 highscore_update(score
, level
, Highest
, MAX_HIGH_SCORES
);
536 nf
= t_rand (BLOCKS_NUM
);
538 #ifdef HAVE_LCD_BITMAP
539 rb
->lcd_bitmap (rockblox_background
, 0, 0, LCD_WIDTH
, LCD_HEIGHT
);
540 #else /* HAVE_LCD_CHARCELLS */
542 pgfx_display_block (3, 0, 3, 1);
543 pgfx_display_block (4, 0, 3, 0);
544 pgfx_clear_display();
545 pgfx_fillrect (3, 0, 2, 14);
546 pgfx_fillrect (15, 7, 2, 7);
551 for (i
= MAX_HIGH_SCORES
-1; i
>=0; i
--)
553 rb
->snprintf (str
, sizeof (str
), "%06d L%1d", Highest
[i
].score
, Highest
[i
].level
);
554 rb
->lcd_putsxy (HIGH_LABEL_X
, HIGH_SCORE_Y
+ (10 * ((MAX_HIGH_SCORES
-1) - i
)), str
);
559 static inline int level_speed(int level
)
561 #if BOARD_HEIGHT == 20
562 return (5*HZ
) / (level
+ 9);
563 #elif BOARD_HEIGHT == 14
564 return (7*HZ
) / (level
+ 9);
568 static int getRelativeX (int figure
, int square
, int orientation
)
570 switch (orientation
) {
572 return figures
[figure
].shapeX
[square
];
574 return figures
[figure
].shapeY
[square
];
576 return -figures
[figure
].shapeX
[square
];
578 return -figures
[figure
].shapeY
[square
];
584 static int getRelativeY (int figure
, int square
, int orientation
)
586 switch (orientation
) {
588 return figures
[figure
].shapeY
[square
];
590 return -figures
[figure
].shapeX
[square
];
592 return -figures
[figure
].shapeY
[square
];
594 return figures
[figure
].shapeX
[square
];
600 /* redraw the while board on the screen */
601 static void refresh_board (void)
603 int i
, j
, x
, y
, block
;
606 rb
->lcd_set_foreground (LCD_BLACK
);
608 MYLCD(set_drawmode
) (DRMODE_SOLID
| DRMODE_INVERSEVID
);
611 MYLCD(fillrect
) (BOARD_X
, BOARD_Y
, BOARD_WIDTH
* BLOCK_WIDTH
,
612 BOARD_HEIGHT
* BLOCK_HEIGHT
);
615 MYLCD(set_drawmode
) (DRMODE_SOLID
);
618 for (i
= 0; i
< BOARD_WIDTH
; i
++)
619 for (j
= 0; j
< BOARD_HEIGHT
; j
++) {
621 if (block
!= EMPTY_BLOCK
) {
622 #ifdef HAVE_LCD_BITMAP
625 rb
->lcd_set_foreground (figures
[block
].color
[1]);
627 rb
->lcd_fillrect (BOARD_X
+ i
* BLOCK_WIDTH
,
628 BOARD_Y
+ j
* BLOCK_HEIGHT
,
629 BLOCK_WIDTH
, BLOCK_HEIGHT
);
632 rb
->lcd_set_foreground (figures
[block
].color
[0]);
634 rb
->lcd_vline (BOARD_X
+ i
* BLOCK_WIDTH
,
635 BOARD_Y
+ j
* BLOCK_HEIGHT
,
636 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 2);
637 rb
->lcd_hline (BOARD_X
+ i
* BLOCK_WIDTH
,
638 BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 2,
639 BOARD_Y
+ j
* BLOCK_HEIGHT
);
642 rb
->lcd_set_foreground (figures
[block
].color
[2]);
644 rb
->lcd_vline (BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 1,
645 BOARD_Y
+ j
* BLOCK_HEIGHT
+ 1,
646 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 1);
647 rb
->lcd_hline (BOARD_X
+ i
* BLOCK_WIDTH
+ 1,
648 BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 1,
649 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 1);
650 #else /* HAVE_LCD_CHARCELLS */
651 pgfx_drawpixel (BOARD_X
+ i
, BOARD_Y
+ j
);
656 for (i
= 0; i
< 4; i
++) {
657 x
= getRelativeX (cf
, i
, co
) + cx
;
658 y
= getRelativeY (cf
, i
, co
) + cy
;
659 #ifdef HAVE_LCD_BITMAP
661 rb
->lcd_set_foreground (figures
[cf
].color
[1]); /* middle drawing */
663 rb
->lcd_fillrect (BOARD_X
+ x
* BLOCK_WIDTH
,
664 BOARD_Y
+ y
* BLOCK_HEIGHT
,
665 BLOCK_WIDTH
, BLOCK_HEIGHT
);
667 rb
->lcd_set_foreground (figures
[cf
].color
[0]); /* light drawing */
669 rb
->lcd_vline (BOARD_X
+ x
* BLOCK_WIDTH
, BOARD_Y
+ y
* BLOCK_HEIGHT
,
670 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 2);
671 rb
->lcd_hline (BOARD_X
+ x
* BLOCK_WIDTH
,
672 BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 2,
673 BOARD_Y
+ y
* BLOCK_HEIGHT
);
675 rb
->lcd_set_foreground (figures
[cf
].color
[2]); /* shadow drawing */
677 rb
->lcd_vline (BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 1,
678 BOARD_Y
+ y
* BLOCK_HEIGHT
+ 1,
679 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 1);
680 rb
->lcd_hline (BOARD_X
+ x
* BLOCK_WIDTH
+ 1,
681 BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 1,
682 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 1);
683 #else /* HAVE_LCD_CHARCELLS */
684 pgfx_drawpixel (BOARD_X
+ x
, BOARD_Y
+ y
);
690 static bool canMoveTo (int x
, int y
, int newOrientation
)
693 for (i
= 0; i
< 4; i
++) {
694 ry
= getRelativeY (cf
, i
, newOrientation
) + y
;
695 rx
= getRelativeX (cf
, i
, newOrientation
) + x
;
696 if ((rx
< 0 || rx
>= BOARD_WIDTH
) ||
697 (ry
< 0 || ry
>= BOARD_HEIGHT
) || (board
[ry
][rx
] != EMPTY_BLOCK
))
703 /* draws the preview of next block in the preview window */
704 static void draw_next_block (void)
707 /* clear preview window first */
709 rb
->lcd_set_foreground (LCD_BLACK
);
711 MYLCD(set_drawmode
) (DRMODE_SOLID
| DRMODE_INVERSEVID
);
715 MYLCD(fillrect
) (PREVIEW_X
, PREVIEW_Y
, BLOCK_WIDTH
* 4, BLOCK_HEIGHT
* 4);
718 MYLCD(set_drawmode
) (DRMODE_SOLID
);
721 /* draw the lightgray rectangles */
723 rb
->lcd_set_foreground (LCD_RGBPACK (40, 40, 40));
725 rb
->lcd_set_foreground (LCD_DARKGRAY
);
729 for (rx
= 0; rx
< 4; rx
++)
730 for (ry
= 0; ry
< 4; ry
++)
731 rb
->lcd_drawrect (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
732 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
, BLOCK_WIDTH
,
736 /* draw the figure */
737 for (i
= 0; i
< 4; i
++) {
738 rx
= getRelativeX (nf
, i
, 0) + 2;
739 ry
= getRelativeY (nf
, i
, 0) + 2;
740 #ifdef HAVE_LCD_BITMAP
742 rb
->lcd_set_foreground (figures
[nf
].color
[1]); /* middle drawing */
744 rb
->lcd_fillrect (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
745 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
,
746 BLOCK_WIDTH
, BLOCK_HEIGHT
);
748 rb
->lcd_set_foreground (figures
[nf
].color
[0]); /* light drawing */
750 rb
->lcd_vline (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
751 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
,
752 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 2);
753 rb
->lcd_hline (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
754 PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 2,
755 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
);
757 rb
->lcd_set_foreground (figures
[nf
].color
[2]); /* shadow drawing */
759 rb
->lcd_vline (PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 1,
760 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
+ 1,
761 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 1);
762 rb
->lcd_hline (PREVIEW_X
+ rx
* BLOCK_WIDTH
+ 1,
763 PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 1,
764 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 1);
765 #else /* HAVE_LCD_CHARCELLS */
766 pgfx_drawpixel (PREVIEW_X
+ rx
, PREVIEW_Y
+ ry
);
772 /* move the block to a relative location */
773 static void move_block (int x
, int y
, int o
)
775 if (canMoveTo (cx
+ x
, cy
+ y
, o
)) {
782 /* try to add a new block to play with (return true if gameover) */
783 static void new_block (void)
788 co
= 0; /* start at the same orientation all time */
789 nf
= t_rand (BLOCKS_NUM
);
790 gameover
= !canMoveTo (cx
, cy
, co
);
796 /* check for filled lines and do what necessary */
797 static int check_lines (void)
802 for (j
= 0; j
< BOARD_HEIGHT
; j
++) {
803 for (i
= 0; ((i
< BOARD_WIDTH
) && (board
[j
][i
] != EMPTY_BLOCK
)); i
++);
804 if (i
== BOARD_WIDTH
) { /* woo hoo, we have a line */
806 for (y
= j
; y
> 0; y
--)
807 for (i
= 0; i
< BOARD_WIDTH
; i
++)
808 board
[y
][i
] = board
[y
- 1][i
]; /* fall line */
815 /* moves down the figure and returns true if gameover */
816 static void move_down (void)
820 if (!canMoveTo (cx
, cy
+ 1, co
)) {
821 /* save figure to board */
822 for (i
= 0; i
< 4; i
++) {
823 rx
= getRelativeX (cf
, i
, co
) + cx
;
824 ry
= getRelativeY (cf
, i
, co
) + cy
;
827 /* check if formed some lines */
830 /* the original scoring from "http://en.wikipedia.org/wiki/Rockblox" */
831 score
+= scoring
[l
- 1] * level
;
833 level
= (int) lines
/ 10 + 1;
839 /* generate a new figure */
842 move_block (0, 1, co
);
845 static int rockblox_loop (void)
848 int lastbutton
= BUTTON_NONE
;
849 long next_down_tick
= *rb
->current_tick
+ level_speed(level
);
854 #ifdef HAS_BUTTON_HOLD
855 if (rb
->button_hold ()) {
856 /* Restore user's original backlight setting */
857 rb
->backlight_set_timeout (rb
->global_settings
->backlight_timeout
);
859 rb
->splash(0, "Paused");
860 while (rb
->button_hold ())
863 /* Permanently enable the backlight (unless the user has
865 if (rb
->global_settings
->backlight_timeout
> 0)
866 rb
->backlight_set_timeout (1);
868 /* get rid of the splash text */
869 rb
->lcd_bitmap (rockblox_background
, 0, 0, LCD_WIDTH
, LCD_HEIGHT
);
876 button
= rb
->button_get_w_tmo (MAX(next_down_tick
- *rb
->current_tick
, 1));
878 #ifdef ROCKBLOX_RC_OFF
879 case ROCKBLOX_RC_OFF
:
884 #if defined(ROCKBLOX_ROTATE)
885 case ROCKBLOX_ROTATE
:
887 case ROCKBLOX_ROTATE_RIGHT
:
888 case ROCKBLOX_ROTATE_RIGHT
| BUTTON_REPEAT
:
890 /* if the wheel is disabled, add an event to the stack. */
891 if(wheel_enabled
== false)
894 /* if it's enabled, go ahead and rotate.. */
897 move_block (0, 0, (co
+ 1) % figures
[cf
].max_or
);
900 case ROCKBLOX_ROTATE_LEFT
:
901 case ROCKBLOX_ROTATE_LEFT
| BUTTON_REPEAT
:
903 if(wheel_enabled
== false)
909 (co
+ figures
[cf
].max_or
-
910 1) % figures
[cf
].max_or
);
913 #ifdef ROCKBLOX_ROTATE_RIGHT2
914 case ROCKBLOX_ROTATE_RIGHT2
:
915 move_block (0, 0, (co
+ 1) % figures
[cf
].max_or
);
920 case ROCKBLOX_DOWN
| BUTTON_REPEAT
:
921 move_block (0, 1, co
);
925 case ROCKBLOX_RIGHT
| BUTTON_REPEAT
:
926 move_block (1, 0, co
);
930 case ROCKBLOX_LEFT
| BUTTON_REPEAT
:
931 move_block (-1, 0, co
);
935 #ifdef ROCKBLOX_DROP_PRE
936 if (lastbutton
!= ROCKBLOX_DROP_PRE
)
939 while (canMoveTo (cx
, cy
+ 1, co
))
940 move_block (0, 1, co
);
942 #ifdef ROCKBLOX_RESTART
943 case ROCKBLOX_RESTART
:
944 rb
->splash (HZ
* 1, "Restarting...");
951 if (rb
->default_event_handler (button
) == SYS_USB_CONNECTED
)
952 return PLUGIN_USB_CONNECTED
;
955 if (button
!= BUTTON_NONE
)
959 /* check if we should enable the scroll wheel, if events
960 * begin to stack up... */
961 if(wheel_enabled
== false)
963 /* stopped rotating the wheel, reset the count */
964 if(wheel_events
== last_wheel_event
)
966 last_wheel_event
= 0;
969 /* rotated the wheel a while constantly, enable it. */
970 else if(wheel_events
> 3)
972 wheel_enabled
= true;
975 /* this evens out the last event and the "current" event.
976 * if we get an event next time through button reading, it will
977 * remain ahead of last_event. if we don't, they'll end up equaling
978 * each other.. thus, the scroll count will be reset. */
979 if(wheel_enabled
== false && wheel_events
> last_wheel_event
)
984 if (TIME_AFTER(*rb
->current_tick
, next_down_tick
)) {
986 next_down_tick
+= level_speed(level
);
987 if (TIME_AFTER(*rb
->current_tick
, next_down_tick
))
988 /* restart time "raster" when we had to wait longer than usual
989 * (pause, game restart etc) */
990 next_down_tick
= *rb
->current_tick
+ level_speed(level
);
995 rb
->lcd_set_foreground (LCD_BLACK
);
997 rb
->splash (HZ
* 2, "Game Over");
1008 enum plugin_status
plugin_start (struct plugin_api
*api
, void *parameter
)
1015 rb
->srand (*rb
->current_tick
);
1017 /* Load HighScore if any */
1019 highscore_load(HIGH_SCORE
,Highest
,MAX_HIGH_SCORES
);
1022 rb
->lcd_set_backdrop(NULL
);
1025 #ifdef HAVE_LCD_BITMAP
1026 rb
->lcd_setfont (FONT_SYSFIXED
);
1028 if (!pgfx_init(rb
, 4, 2))
1030 rb
->splash(HZ
*2, "Old LCD :(");
1034 /* Permanently enable the backlight (unless the user has turned it off) */
1035 if (rb
->global_settings
->backlight_timeout
> 0)
1036 rb
->backlight_set_timeout (1);
1039 ret
= rockblox_loop ();
1041 #ifdef HAVE_LCD_BITMAP
1042 rb
->lcd_setfont (FONT_UI
);
1046 /* Save user's HighScore */
1047 highscore_save(HIGH_SCORE
,Highest
,MAX_HIGH_SCORES
);
1048 /* Restore user's original backlight setting */
1049 rb
->backlight_set_timeout (rb
->global_settings
->backlight_timeout
);