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_3G_PAD) || \
28 (CONFIG_KEYPAD == IPOD_4G_PAD)
30 #define ROCKBLOX_OFF (BUTTON_MENU | BUTTON_SELECT)
31 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_BACK
32 #define ROCKBLOX_ROTATE_RIGHT2 (BUTTON_MENU | BUTTON_REL)
33 #define ROCKBLOX_ROTATE_LEFT BUTTON_SCROLL_FWD
34 #define ROCKBLOX_LEFT BUTTON_LEFT
35 #define ROCKBLOX_RIGHT BUTTON_RIGHT
36 #define ROCKBLOX_DOWN BUTTON_PLAY
37 #define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_PLAY)
38 #define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
42 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
43 (CONFIG_KEYPAD == IRIVER_H300_PAD)
45 #define ROCKBLOX_OFF BUTTON_OFF
46 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
47 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
48 #define ROCKBLOX_DOWN BUTTON_DOWN
49 #define ROCKBLOX_LEFT BUTTON_LEFT
50 #define ROCKBLOX_RIGHT BUTTON_RIGHT
51 #define ROCKBLOX_DROP BUTTON_MODE
52 #define ROCKBLOX_RESTART BUTTON_ON
54 #define ROCKBLOX_RC_OFF BUTTON_RC_STOP
55 #elif CONFIG_KEYPAD == RECORDER_PAD
57 #define ROCKBLOX_OFF BUTTON_OFF
58 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
59 #define ROCKBLOX_ROTATE_LEFT BUTTON_PLAY
60 #define ROCKBLOX_DOWN BUTTON_DOWN
61 #define ROCKBLOX_LEFT BUTTON_LEFT
62 #define ROCKBLOX_RIGHT BUTTON_RIGHT
63 #define ROCKBLOX_DROP BUTTON_ON
64 #define ROCKBLOX_RESTART BUTTON_F1
66 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
68 #define ROCKBLOX_OFF BUTTON_OFF
69 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
70 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
71 #define ROCKBLOX_DOWN BUTTON_DOWN
72 #define ROCKBLOX_LEFT BUTTON_LEFT
73 #define ROCKBLOX_RIGHT BUTTON_RIGHT
74 #define ROCKBLOX_DROP BUTTON_ON
75 #define ROCKBLOX_RESTART BUTTON_F1
77 #elif CONFIG_KEYPAD == PLAYER_PAD
79 #define ROCKBLOX_OFF BUTTON_STOP
80 #define ROCKBLOX_ROTATE_RIGHT BUTTON_PLAY
81 #define ROCKBLOX_ROTATE_LEFT (BUTTON_ON|BUTTON_PLAY)
82 #define ROCKBLOX_DOWN BUTTON_MENU
83 #define ROCKBLOX_LEFT BUTTON_LEFT
84 #define ROCKBLOX_RIGHT BUTTON_RIGHT
85 #define ROCKBLOX_DROP_PRE BUTTON_ON
86 #define ROCKBLOX_DROP (BUTTON_ON|BUTTON_REL)
88 #elif CONFIG_KEYPAD == ONDIO_PAD
90 #define ROCKBLOX_OFF BUTTON_OFF
91 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
92 #define ROCKBLOX_ROTATE_LEFT (BUTTON_MENU|BUTTON_UP)
93 #define ROCKBLOX_DOWN BUTTON_DOWN
94 #define ROCKBLOX_LEFT BUTTON_LEFT
95 #define ROCKBLOX_RIGHT BUTTON_RIGHT
96 #define ROCKBLOX_DROP_PRE BUTTON_MENU
97 #define ROCKBLOX_DROP (BUTTON_MENU|BUTTON_REL)
99 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
101 #define ROCKBLOX_OFF BUTTON_POWER
102 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
103 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
104 #define ROCKBLOX_DOWN BUTTON_DOWN
105 #define ROCKBLOX_LEFT BUTTON_LEFT
106 #define ROCKBLOX_RIGHT BUTTON_RIGHT
107 #define ROCKBLOX_DROP BUTTON_REC
108 #define ROCKBLOX_RESTART BUTTON_PLAY
110 #elif CONFIG_KEYPAD == SANSA_E200_PAD
112 #define ROCKBLOX_OFF BUTTON_POWER
113 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_UP
114 #define ROCKBLOX_ROTATE_LEFT BUTTON_SCROLL_DOWN
115 #define ROCKBLOX_DOWN BUTTON_DOWN
116 #define ROCKBLOX_LEFT BUTTON_LEFT
117 #define ROCKBLOX_RIGHT BUTTON_RIGHT
118 #define ROCKBLOX_DROP BUTTON_SELECT
119 #define ROCKBLOX_RESTART BUTTON_REC
121 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
123 #define ROCKBLOX_OFF BUTTON_POWER
124 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_UP
125 #define ROCKBLOX_ROTATE_LEFT BUTTON_REW
126 #define ROCKBLOX_DOWN BUTTON_SCROLL_DOWN
127 #define ROCKBLOX_LEFT BUTTON_LEFT
128 #define ROCKBLOX_RIGHT BUTTON_RIGHT
129 #define ROCKBLOX_DROP BUTTON_FF
130 #define ROCKBLOX_RESTART BUTTON_PLAY
132 #elif CONFIG_KEYPAD == GIGABEAT_PAD
134 #define ROCKBLOX_OFF BUTTON_POWER
135 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
136 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
137 #define ROCKBLOX_ROTATE BUTTON_UP
138 #define ROCKBLOX_DOWN BUTTON_DOWN
139 #define ROCKBLOX_LEFT BUTTON_LEFT
140 #define ROCKBLOX_RIGHT BUTTON_RIGHT
141 #define ROCKBLOX_DROP BUTTON_SELECT
142 #define ROCKBLOX_RESTART BUTTON_A
144 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
146 #define ROCKBLOX_OFF BUTTON_PLAY
147 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
148 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
149 #define ROCKBLOX_DOWN BUTTON_DOWN
150 #define ROCKBLOX_LEFT BUTTON_LEFT
151 #define ROCKBLOX_RIGHT BUTTON_RIGHT
152 #define ROCKBLOX_DROP BUTTON_MODE
153 #define ROCKBLOX_RESTART BUTTON_EQ
158 #define EMPTY_BLOCK 7
160 #define BOARD_WIDTH 10
162 #ifdef HAVE_LCD_BITMAP
164 #define BOARD_HEIGHT 20
166 #if (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
168 #define BLOCK_WIDTH 12
169 #define BLOCK_HEIGHT 12
179 #elif (LCD_WIDTH == 240) && (LCD_HEIGHT == 320)
181 #define BLOCK_WIDTH 15
182 #define BLOCK_HEIGHT 15
185 #define PREVIEW_X 171
186 #define PREVIEW_Y 241
191 #define HIGH_LABEL_X 172
192 #define HIGH_SCORE_Y 163
193 #define HIGH_LEVEL_Y 172
195 #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176)
197 #define BLOCK_WIDTH 8
198 #define BLOCK_HEIGHT 8
201 #define PREVIEW_X 158
202 #define PREVIEW_Y 130
208 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132)
210 #define BLOCK_WIDTH 6
211 #define BLOCK_HEIGHT 6
214 #define PREVIEW_X 126
215 #define PREVIEW_Y 102
221 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220)
223 #define BLOCK_WIDTH 10
224 #define BLOCK_HEIGHT 10
227 #define PREVIEW_X 124
228 #define PREVIEW_Y 167
233 #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128)
235 #define BLOCK_WIDTH 6
236 #define BLOCK_HEIGHT 6
239 #define PREVIEW_X 114
240 #define PREVIEW_Y 100
246 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 128)
248 #define BLOCK_WIDTH 6
249 #define BLOCK_HEIGHT 6
253 #define PREVIEW_Y 100
259 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64)
261 #define BLOCK_WIDTH 3
262 #define BLOCK_HEIGHT 3
272 #elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
274 #define BLOCK_WIDTH 4
275 #define BLOCK_HEIGHT 3
286 #elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110)
288 #define BLOCK_WIDTH 5
289 #define BLOCK_HEIGHT 5
302 #define LEVEL_X LABEL_X
306 #define LINES_X LABEL_X
309 #define MYLCD(fn) rb->lcd_ ## fn
311 extern const fb_data rockblox_background
[];
313 #else /* HAVE_LCD_CHARCELLS */
315 #define BOARD_HEIGHT 14
317 #define BLOCK_WIDTH 1
318 #define BLOCK_HEIGHT 1
324 #define MYLCD(fn) pgfx_ ## fn
328 /* <<Explanation on Rockblox shapes>>
331 %% - O has 1 orientation
334 %% %% - Z has 2 orientations
338 %% %% - S has 2 orientations
342 % %%%% - I has 2 orientations
346 % % % %%% - L has 4 orientations
350 % % % %%% - J has 4 orientations
354 %% % %% % - T has 4 orientations
359 /* must have variable */
360 static struct plugin_api
*rb
;
362 static bool gameover
= false;
363 /* c=current f=figure o=orientation n=next */
364 static int lines
= 0, level
= 0, score
= 0, cx
, cy
, cf
, co
, nf
;
365 static short board
[BOARD_HEIGHT
][BOARD_WIDTH
]; /* 20 rows of 10 blocks */
368 int wheel_events
= 0, last_wheel_event
= 0;
369 bool wheel_enabled
= false;
372 static const short scoring
[4] = { /* scoring for each number of lines */
373 #if BOARD_HEIGHT == 20
374 40 /* single */ , 100 /* double */ , 300 /* triple */ , 1200 /* rockblox */
375 #elif BOARD_HEIGHT == 14 /* Player special values */
376 60 /* single */ , 150 /* double */ , 500 /* triple */ , 2000 /* rockblox */
383 unsigned short color
[3]; /* color of figure (light,middle,shadow) */
385 unsigned short max_or
; /* max orientations */
386 signed short shapeX
[4], shapeY
[4]; /* implementation of figures */
389 /* array of figures */
390 figures
[BLOCKS_NUM
] = {
394 {LCD_RGBPACK (153, 255, 255), LCD_RGBPACK(0, 255, 255),
395 LCD_RGBPACK(0,153,153)},
397 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
406 {LCD_RGBPACK (255, 153, 128), LCD_RGBPACK (255, 0, 0),
407 LCD_RGBPACK (153, 0, 0)},
409 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
418 {LCD_RGBPACK (153, 255, 153), LCD_RGBPACK (0, 255, 0),
419 LCD_RGBPACK (0, 153, 0)},
421 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
430 {LCD_RGBPACK (153, 153, 255), LCD_RGBPACK (0, 0, 255),
431 LCD_RGBPACK (0, 0, 153)},
433 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
442 {LCD_RGBPACK (255, 255, 153), LCD_RGBPACK (255, 255, 0),
443 LCD_RGBPACK (153, 153, 0)},
445 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
454 {LCD_RGBPACK (255, 153, 255), LCD_RGBPACK (255, 0, 255),
455 LCD_RGBPACK (153, 0, 153)},
457 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
466 {LCD_RGBPACK (204, 204, 204), LCD_RGBPACK (153, 153, 153),
467 LCD_RGBPACK (85, 85, 85)},
469 {LCD_WHITE
, LCD_LIGHTGRAY
, LCD_DARKGRAY
},
477 /* Rockbox File System only supports full filenames inc dir */
478 #define HIGH_SCORE "/.rockbox/rocks/rockblox.score"
479 #define MAX_HIGH_SCORES 5
480 /* Default High Scores... */
481 struct highscore Highest
[MAX_HIGH_SCORES
];
483 /* get random number from (0) to (range-1) */
484 static int t_rand (int range
)
486 return rb
->rand () % range
;
489 /* init the board array to have no blocks */
490 static void init_board (void)
493 for (i
= 0; i
< BOARD_WIDTH
; i
++)
494 for (j
= 0; j
< BOARD_HEIGHT
; j
++)
495 board
[j
][i
] = EMPTY_BLOCK
;
498 /* show the score, level and lines */
499 static void show_details (void)
501 char str
[25]; /* for strings */
503 #ifdef HAVE_LCD_BITMAP
505 rb
->lcd_set_foreground (LCD_BLACK
);
506 rb
->lcd_set_background (LCD_WHITE
);
508 rb
->snprintf (str
, sizeof (str
), "%d", score
);
509 rb
->lcd_putsxy (LABEL_X
, SCORE_Y
, str
);
510 rb
->snprintf (str
, sizeof (str
), "%d", level
);
511 rb
->lcd_putsxy (LEVEL_X
, LEVEL_Y
, str
);
512 rb
->snprintf (str
, sizeof (str
), "%d", lines
);
513 rb
->lcd_putsxy (LINES_X
, LINES_Y
, str
);
514 #else /* HAVE_LCD_CHARCELLS */
515 rb
->snprintf (str
, sizeof (str
), "L%d/%d", level
, lines
);
516 rb
->lcd_puts (5, 0, str
);
517 rb
->snprintf (str
, sizeof (str
), "S%d", score
);
518 rb
->lcd_puts (5, 1, str
);
522 static void init_rockblox (void)
526 char str
[25]; /* for strings */
528 highscore_update(score
, level
, Highest
, MAX_HIGH_SCORES
);
534 nf
= t_rand (BLOCKS_NUM
);
536 #ifdef HAVE_LCD_BITMAP
537 rb
->lcd_bitmap (rockblox_background
, 0, 0, LCD_WIDTH
, LCD_HEIGHT
);
538 #else /* HAVE_LCD_CHARCELLS */
540 pgfx_display_block (3, 0, 3, 1);
541 pgfx_display_block (4, 0, 3, 0);
542 pgfx_clear_display();
543 pgfx_fillrect (3, 0, 2, 14);
544 pgfx_fillrect (15, 7, 2, 7);
549 for (i
= MAX_HIGH_SCORES
-1; i
>=0; i
--)
551 rb
->snprintf (str
, sizeof (str
), "%06d L%1d", Highest
[i
].score
, Highest
[i
].level
);
552 rb
->lcd_putsxy (HIGH_LABEL_X
, HIGH_SCORE_Y
+ (10 * ((MAX_HIGH_SCORES
-1) - i
)), str
);
557 static inline int level_speed(int level
)
559 #if BOARD_HEIGHT == 20
560 return (5*HZ
) / (level
+ 9);
561 #elif BOARD_HEIGHT == 14
562 return (7*HZ
) / (level
+ 9);
566 static int getRelativeX (int figure
, int square
, int orientation
)
568 switch (orientation
) {
570 return figures
[figure
].shapeX
[square
];
572 return figures
[figure
].shapeY
[square
];
574 return -figures
[figure
].shapeX
[square
];
576 return -figures
[figure
].shapeY
[square
];
582 static int getRelativeY (int figure
, int square
, int orientation
)
584 switch (orientation
) {
586 return figures
[figure
].shapeY
[square
];
588 return -figures
[figure
].shapeX
[square
];
590 return -figures
[figure
].shapeY
[square
];
592 return figures
[figure
].shapeX
[square
];
598 /* redraw the while board on the screen */
599 static void refresh_board (void)
601 int i
, j
, x
, y
, block
;
604 rb
->lcd_set_foreground (LCD_BLACK
);
606 MYLCD(set_drawmode
) (DRMODE_SOLID
| DRMODE_INVERSEVID
);
609 MYLCD(fillrect
) (BOARD_X
, BOARD_Y
, BOARD_WIDTH
* BLOCK_WIDTH
,
610 BOARD_HEIGHT
* BLOCK_HEIGHT
);
613 MYLCD(set_drawmode
) (DRMODE_SOLID
);
616 for (i
= 0; i
< BOARD_WIDTH
; i
++)
617 for (j
= 0; j
< BOARD_HEIGHT
; j
++) {
619 if (block
!= EMPTY_BLOCK
) {
620 #ifdef HAVE_LCD_BITMAP
623 rb
->lcd_set_foreground (figures
[block
].color
[1]);
625 rb
->lcd_fillrect (BOARD_X
+ i
* BLOCK_WIDTH
,
626 BOARD_Y
+ j
* BLOCK_HEIGHT
,
627 BLOCK_WIDTH
, BLOCK_HEIGHT
);
630 rb
->lcd_set_foreground (figures
[block
].color
[0]);
632 rb
->lcd_vline (BOARD_X
+ i
* BLOCK_WIDTH
,
633 BOARD_Y
+ j
* BLOCK_HEIGHT
,
634 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 2);
635 rb
->lcd_hline (BOARD_X
+ i
* BLOCK_WIDTH
,
636 BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 2,
637 BOARD_Y
+ j
* BLOCK_HEIGHT
);
640 rb
->lcd_set_foreground (figures
[block
].color
[2]);
642 rb
->lcd_vline (BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 1,
643 BOARD_Y
+ j
* BLOCK_HEIGHT
+ 1,
644 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 1);
645 rb
->lcd_hline (BOARD_X
+ i
* BLOCK_WIDTH
+ 1,
646 BOARD_X
+ (i
+ 1) * BLOCK_WIDTH
- 1,
647 BOARD_Y
+ (j
+ 1) * BLOCK_HEIGHT
- 1);
648 #else /* HAVE_LCD_CHARCELLS */
649 pgfx_drawpixel (BOARD_X
+ i
, BOARD_Y
+ j
);
654 for (i
= 0; i
< 4; i
++) {
655 x
= getRelativeX (cf
, i
, co
) + cx
;
656 y
= getRelativeY (cf
, i
, co
) + cy
;
657 #ifdef HAVE_LCD_BITMAP
659 rb
->lcd_set_foreground (figures
[cf
].color
[1]); /* middle drawing */
661 rb
->lcd_fillrect (BOARD_X
+ x
* BLOCK_WIDTH
,
662 BOARD_Y
+ y
* BLOCK_HEIGHT
,
663 BLOCK_WIDTH
, BLOCK_HEIGHT
);
665 rb
->lcd_set_foreground (figures
[cf
].color
[0]); /* light drawing */
667 rb
->lcd_vline (BOARD_X
+ x
* BLOCK_WIDTH
, BOARD_Y
+ y
* BLOCK_HEIGHT
,
668 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 2);
669 rb
->lcd_hline (BOARD_X
+ x
* BLOCK_WIDTH
,
670 BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 2,
671 BOARD_Y
+ y
* BLOCK_HEIGHT
);
673 rb
->lcd_set_foreground (figures
[cf
].color
[2]); /* shadow drawing */
675 rb
->lcd_vline (BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 1,
676 BOARD_Y
+ y
* BLOCK_HEIGHT
+ 1,
677 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 1);
678 rb
->lcd_hline (BOARD_X
+ x
* BLOCK_WIDTH
+ 1,
679 BOARD_X
+ (x
+ 1) * BLOCK_WIDTH
- 1,
680 BOARD_Y
+ (y
+ 1) * BLOCK_HEIGHT
- 1);
681 #else /* HAVE_LCD_CHARCELLS */
682 pgfx_drawpixel (BOARD_X
+ x
, BOARD_Y
+ y
);
688 static bool canMoveTo (int x
, int y
, int newOrientation
)
691 for (i
= 0; i
< 4; i
++) {
692 ry
= getRelativeY (cf
, i
, newOrientation
) + y
;
693 rx
= getRelativeX (cf
, i
, newOrientation
) + x
;
694 if ((rx
< 0 || rx
>= BOARD_WIDTH
) ||
695 (ry
< 0 || ry
>= BOARD_HEIGHT
) || (board
[ry
][rx
] != EMPTY_BLOCK
))
701 /* draws the preview of next block in the preview window */
702 static void draw_next_block (void)
705 /* clear preview window first */
707 rb
->lcd_set_foreground (LCD_BLACK
);
709 MYLCD(set_drawmode
) (DRMODE_SOLID
| DRMODE_INVERSEVID
);
713 MYLCD(fillrect
) (PREVIEW_X
, PREVIEW_Y
, BLOCK_WIDTH
* 4, BLOCK_HEIGHT
* 4);
716 MYLCD(set_drawmode
) (DRMODE_SOLID
);
719 /* draw the lightgray rectangles */
721 rb
->lcd_set_foreground (LCD_RGBPACK (40, 40, 40));
723 rb
->lcd_set_foreground (LCD_DARKGRAY
);
727 for (rx
= 0; rx
< 4; rx
++)
728 for (ry
= 0; ry
< 4; ry
++)
729 rb
->lcd_drawrect (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
730 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
, BLOCK_WIDTH
,
734 /* draw the figure */
735 for (i
= 0; i
< 4; i
++) {
736 rx
= getRelativeX (nf
, i
, 0) + 2;
737 ry
= getRelativeY (nf
, i
, 0) + 2;
738 #ifdef HAVE_LCD_BITMAP
740 rb
->lcd_set_foreground (figures
[nf
].color
[1]); /* middle drawing */
742 rb
->lcd_fillrect (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
743 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
,
744 BLOCK_WIDTH
, BLOCK_HEIGHT
);
746 rb
->lcd_set_foreground (figures
[nf
].color
[0]); /* light drawing */
748 rb
->lcd_vline (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
749 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
,
750 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 2);
751 rb
->lcd_hline (PREVIEW_X
+ rx
* BLOCK_WIDTH
,
752 PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 2,
753 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
);
755 rb
->lcd_set_foreground (figures
[nf
].color
[2]); /* shadow drawing */
757 rb
->lcd_vline (PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 1,
758 PREVIEW_Y
+ ry
* BLOCK_HEIGHT
+ 1,
759 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 1);
760 rb
->lcd_hline (PREVIEW_X
+ rx
* BLOCK_WIDTH
+ 1,
761 PREVIEW_X
+ (rx
+ 1) * BLOCK_WIDTH
- 1,
762 PREVIEW_Y
+ (ry
+ 1) * BLOCK_HEIGHT
- 1);
763 #else /* HAVE_LCD_CHARCELLS */
764 pgfx_drawpixel (PREVIEW_X
+ rx
, PREVIEW_Y
+ ry
);
770 /* move the block to a relative location */
771 static void move_block (int x
, int y
, int o
)
773 if (canMoveTo (cx
+ x
, cy
+ y
, o
)) {
780 /* try to add a new block to play with (return true if gameover) */
781 static void new_block (void)
786 co
= 0; /* start at the same orientation all time */
787 nf
= t_rand (BLOCKS_NUM
);
788 gameover
= !canMoveTo (cx
, cy
, co
);
794 /* check for filled lines and do what necessary */
795 static int check_lines (void)
800 for (j
= 0; j
< BOARD_HEIGHT
; j
++) {
801 for (i
= 0; ((i
< BOARD_WIDTH
) && (board
[j
][i
] != EMPTY_BLOCK
)); i
++);
802 if (i
== BOARD_WIDTH
) { /* woo hoo, we have a line */
804 for (y
= j
; y
> 0; y
--)
805 for (i
= 0; i
< BOARD_WIDTH
; i
++)
806 board
[y
][i
] = board
[y
- 1][i
]; /* fall line */
813 /* moves down the figure and returns true if gameover */
814 static void move_down (void)
818 if (!canMoveTo (cx
, cy
+ 1, co
)) {
819 /* save figure to board */
820 for (i
= 0; i
< 4; i
++) {
821 rx
= getRelativeX (cf
, i
, co
) + cx
;
822 ry
= getRelativeY (cf
, i
, co
) + cy
;
825 /* check if formed some lines */
828 /* the original scoring from "http://en.wikipedia.org/wiki/Rockblox" */
829 score
+= scoring
[l
- 1] * level
;
831 level
= (int) lines
/ 10 + 1;
837 /* generate a new figure */
840 move_block (0, 1, co
);
843 static int rockblox_loop (void)
846 int lastbutton
= BUTTON_NONE
;
847 long next_down_tick
= *rb
->current_tick
+ level_speed(level
);
852 #ifdef HAS_BUTTON_HOLD
853 if (rb
->button_hold ()) {
854 /* Restore user's original backlight setting */
855 rb
->backlight_set_timeout (rb
->global_settings
->backlight_timeout
);
857 rb
->splash(0, "Paused");
858 while (rb
->button_hold ())
861 /* Permanently enable the backlight (unless the user has
863 if (rb
->global_settings
->backlight_timeout
> 0)
864 rb
->backlight_set_timeout (1);
866 /* get rid of the splash text */
867 rb
->lcd_bitmap (rockblox_background
, 0, 0, LCD_WIDTH
, LCD_HEIGHT
);
874 button
= rb
->button_get_w_tmo (MAX(next_down_tick
- *rb
->current_tick
, 1));
876 #ifdef ROCKBLOX_RC_OFF
877 case ROCKBLOX_RC_OFF
:
882 #if defined(ROCKBLOX_ROTATE)
883 case ROCKBLOX_ROTATE
:
885 case ROCKBLOX_ROTATE_RIGHT
:
886 case ROCKBLOX_ROTATE_RIGHT
| BUTTON_REPEAT
:
888 /* if the wheel is disabled, add an event to the stack. */
889 if(wheel_enabled
== false)
892 /* if it's enabled, go ahead and rotate.. */
895 move_block (0, 0, (co
+ 1) % figures
[cf
].max_or
);
898 case ROCKBLOX_ROTATE_LEFT
:
899 case ROCKBLOX_ROTATE_LEFT
| BUTTON_REPEAT
:
901 if(wheel_enabled
== false)
907 (co
+ figures
[cf
].max_or
-
908 1) % figures
[cf
].max_or
);
911 #ifdef ROCKBLOX_ROTATE_RIGHT2
912 case ROCKBLOX_ROTATE_RIGHT2
:
913 move_block (0, 0, (co
+ 1) % figures
[cf
].max_or
);
918 case ROCKBLOX_DOWN
| BUTTON_REPEAT
:
919 move_block (0, 1, co
);
923 case ROCKBLOX_RIGHT
| BUTTON_REPEAT
:
924 move_block (1, 0, co
);
928 case ROCKBLOX_LEFT
| BUTTON_REPEAT
:
929 move_block (-1, 0, co
);
933 #ifdef ROCKBLOX_DROP_PRE
934 if (lastbutton
!= ROCKBLOX_DROP_PRE
)
937 while (canMoveTo (cx
, cy
+ 1, co
))
938 move_block (0, 1, co
);
940 #ifdef ROCKBLOX_RESTART
941 case ROCKBLOX_RESTART
:
942 rb
->splash (HZ
* 1, "Restarting...");
949 if (rb
->default_event_handler (button
) == SYS_USB_CONNECTED
)
950 return PLUGIN_USB_CONNECTED
;
953 if (button
!= BUTTON_NONE
)
957 /* check if we should enable the scroll wheel, if events
958 * begin to stack up... */
959 if(wheel_enabled
== false)
961 /* stopped rotating the wheel, reset the count */
962 if(wheel_events
== last_wheel_event
)
964 last_wheel_event
= 0;
967 /* rotated the wheel a while constantly, enable it. */
968 else if(wheel_events
> 3)
970 wheel_enabled
= true;
973 /* this evens out the last event and the "current" event.
974 * if we get an event next time through button reading, it will
975 * remain ahead of last_event. if we don't, they'll end up equaling
976 * each other.. thus, the scroll count will be reset. */
977 if(wheel_enabled
== false && wheel_events
> last_wheel_event
)
982 if (TIME_AFTER(*rb
->current_tick
, next_down_tick
)) {
984 next_down_tick
+= level_speed(level
);
985 if (TIME_AFTER(*rb
->current_tick
, next_down_tick
))
986 /* restart time "raster" when we had to wait longer than usual
987 * (pause, game restart etc) */
988 next_down_tick
= *rb
->current_tick
+ level_speed(level
);
993 rb
->lcd_set_foreground (LCD_BLACK
);
995 rb
->splash (HZ
* 2, "Game Over");
1006 enum plugin_status
plugin_start (struct plugin_api
*api
, void *parameter
)
1013 rb
->srand (*rb
->current_tick
);
1015 /* Load HighScore if any */
1017 highscore_load(HIGH_SCORE
,Highest
,MAX_HIGH_SCORES
);
1020 rb
->lcd_set_backdrop(NULL
);
1023 #ifdef HAVE_LCD_BITMAP
1024 rb
->lcd_setfont (FONT_SYSFIXED
);
1026 if (!pgfx_init(rb
, 4, 2))
1028 rb
->splash(HZ
*2, "Old LCD :(");
1032 /* Permanently enable the backlight (unless the user has turned it off) */
1033 if (rb
->global_settings
->backlight_timeout
> 0)
1034 rb
->backlight_set_timeout (1);
1037 ret
= rockblox_loop ();
1039 #ifdef HAVE_LCD_BITMAP
1040 rb
->lcd_setfont (FONT_UI
);
1044 /* Save user's HighScore */
1045 highscore_save(HIGH_SCORE
,Highest
,MAX_HIGH_SCORES
);
1046 /* Restore user's original backlight setting */
1047 rb
->backlight_set_timeout (rb
->global_settings
->backlight_timeout
);