Build doom on clipv2 and clip+
[kugel-rb.git] / apps / plugins / rockblox.c
blob084eaa5830ca79e6d300ebee9b1db81a203866cc
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
23 #include "plugin.h"
24 #include "lib/display_text.h"
25 #include "lib/helper.h"
26 #include "lib/highscore.h"
27 #include "lib/playback_control.h"
28 #include "lib/playergfx.h"
29 #include "lib/mylcd.h"
31 PLUGIN_HEADER
33 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
34 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
35 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
37 #define ROCKBLOX_OFF (BUTTON_MENU | BUTTON_SELECT)
38 #define ROCKBLOX_ROTATE_CCW BUTTON_SCROLL_BACK
39 #define ROCKBLOX_ROTATE_CCW2 (BUTTON_MENU | BUTTON_REL)
40 #define ROCKBLOX_ROTATE_CW BUTTON_SCROLL_FWD
41 #define ROCKBLOX_LEFT BUTTON_LEFT
42 #define ROCKBLOX_RIGHT BUTTON_RIGHT
43 #define ROCKBLOX_DOWN BUTTON_PLAY
44 #define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_PLAY)
45 #define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
47 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
48 (CONFIG_KEYPAD == IRIVER_H300_PAD)
50 #define ROCKBLOX_OFF BUTTON_OFF
51 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
52 #define ROCKBLOX_ROTATE_CW BUTTON_SELECT
53 #define ROCKBLOX_DOWN BUTTON_DOWN
54 #define ROCKBLOX_LEFT BUTTON_LEFT
55 #define ROCKBLOX_RIGHT BUTTON_RIGHT
56 #define ROCKBLOX_DROP BUTTON_MODE
57 #define ROCKBLOX_RESTART BUTTON_ON
59 #define ROCKBLOX_RC_OFF BUTTON_RC_STOP
61 #elif CONFIG_KEYPAD == RECORDER_PAD
63 #define ROCKBLOX_OFF BUTTON_OFF
64 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
65 #define ROCKBLOX_ROTATE_CW BUTTON_PLAY
66 #define ROCKBLOX_DOWN BUTTON_DOWN
67 #define ROCKBLOX_LEFT BUTTON_LEFT
68 #define ROCKBLOX_RIGHT BUTTON_RIGHT
69 #define ROCKBLOX_DROP BUTTON_ON
70 #define ROCKBLOX_RESTART BUTTON_F1
72 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
74 #define ROCKBLOX_OFF BUTTON_OFF
75 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
76 #define ROCKBLOX_ROTATE_CW BUTTON_SELECT
77 #define ROCKBLOX_DOWN BUTTON_DOWN
78 #define ROCKBLOX_LEFT BUTTON_LEFT
79 #define ROCKBLOX_RIGHT BUTTON_RIGHT
80 #define ROCKBLOX_DROP BUTTON_ON
81 #define ROCKBLOX_RESTART BUTTON_F1
83 #elif CONFIG_KEYPAD == PLAYER_PAD
85 #define ROCKBLOX_OFF_PRE BUTTON_STOP
86 #define ROCKBLOX_OFF (BUTTON_STOP|BUTTON_REL)
87 #define ROCKBLOX_ROTATE_CCW BUTTON_PLAY
88 #define ROCKBLOX_ROTATE_CW (BUTTON_ON|BUTTON_PLAY)
89 #define ROCKBLOX_DOWN BUTTON_MENU
90 #define ROCKBLOX_LEFT BUTTON_LEFT
91 #define ROCKBLOX_RIGHT BUTTON_RIGHT
92 #define ROCKBLOX_DROP_PRE BUTTON_ON
93 #define ROCKBLOX_DROP (BUTTON_ON|BUTTON_REL)
94 #define ROCKBLOX_RESTART (BUTTON_STOP|BUTTON_MENU)
96 #elif CONFIG_KEYPAD == ONDIO_PAD
98 #define ROCKBLOX_OFF_PRE BUTTON_OFF
99 #define ROCKBLOX_OFF (BUTTON_OFF|BUTTON_REL)
100 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
101 #define ROCKBLOX_ROTATE_CW (BUTTON_MENU|BUTTON_UP)
102 #define ROCKBLOX_DOWN BUTTON_DOWN
103 #define ROCKBLOX_LEFT BUTTON_LEFT
104 #define ROCKBLOX_RIGHT BUTTON_RIGHT
105 #define ROCKBLOX_DROP_PRE BUTTON_MENU
106 #define ROCKBLOX_DROP (BUTTON_MENU|BUTTON_REL)
107 #define ROCKBLOX_RESTART (BUTTON_OFF|BUTTON_MENU)
109 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
111 #define ROCKBLOX_OFF BUTTON_POWER
112 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
113 #define ROCKBLOX_ROTATE_CW BUTTON_SELECT
114 #define ROCKBLOX_DOWN BUTTON_DOWN
115 #define ROCKBLOX_LEFT BUTTON_LEFT
116 #define ROCKBLOX_RIGHT BUTTON_RIGHT
117 #define ROCKBLOX_DROP BUTTON_REC
118 #define ROCKBLOX_RESTART BUTTON_PLAY
120 #elif CONFIG_KEYPAD == SANSA_E200_PAD
122 #define ROCKBLOX_OFF BUTTON_POWER
123 #define ROCKBLOX_ROTATE_CCW BUTTON_SCROLL_BACK
124 #define ROCKBLOX_ROTATE_CCW2 BUTTON_UP
125 #define ROCKBLOX_ROTATE_CW BUTTON_SCROLL_FWD
126 #define ROCKBLOX_DOWN BUTTON_DOWN
127 #define ROCKBLOX_LEFT BUTTON_LEFT
128 #define ROCKBLOX_RIGHT BUTTON_RIGHT
129 #define ROCKBLOX_DROP BUTTON_SELECT
130 #define ROCKBLOX_RESTART BUTTON_REC
132 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
134 #define ROCKBLOX_OFF (BUTTON_HOME|BUTTON_REPEAT)
135 #define ROCKBLOX_ROTATE_CCW BUTTON_SCROLL_BACK
136 #define ROCKBLOX_ROTATE_CCW2 BUTTON_UP
137 #define ROCKBLOX_ROTATE_CW BUTTON_SCROLL_FWD
138 #define ROCKBLOX_DOWN BUTTON_DOWN
139 #define ROCKBLOX_LEFT BUTTON_LEFT
140 #define ROCKBLOX_RIGHT BUTTON_RIGHT
141 #define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
142 #define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_UP)
145 #elif CONFIG_KEYPAD == SANSA_C200_PAD
147 #define ROCKBLOX_OFF BUTTON_POWER
148 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
149 #define ROCKBLOX_ROTATE_CCW2 BUTTON_VOL_DOWN
150 #define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
151 #define ROCKBLOX_DOWN BUTTON_DOWN
152 #define ROCKBLOX_LEFT BUTTON_LEFT
153 #define ROCKBLOX_RIGHT BUTTON_RIGHT
154 #define ROCKBLOX_DROP BUTTON_SELECT
155 #define ROCKBLOX_RESTART BUTTON_REC
157 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
159 #define ROCKBLOX_OFF BUTTON_POWER
160 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
161 #define ROCKBLOX_ROTATE_CCW2 BUTTON_VOL_DOWN
162 #define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
163 #define ROCKBLOX_DOWN BUTTON_DOWN
164 #define ROCKBLOX_LEFT BUTTON_LEFT
165 #define ROCKBLOX_RIGHT BUTTON_RIGHT
166 #define ROCKBLOX_DROP BUTTON_SELECT
167 #define ROCKBLOX_RESTART BUTTON_HOME
169 #elif CONFIG_KEYPAD == SANSA_M200_PAD
171 #define ROCKBLOX_OFF BUTTON_POWER
172 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
173 #define ROCKBLOX_ROTATE_CCW2 BUTTON_VOL_DOWN
174 #define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
175 #define ROCKBLOX_DOWN BUTTON_DOWN
176 #define ROCKBLOX_LEFT BUTTON_LEFT
177 #define ROCKBLOX_RIGHT BUTTON_RIGHT
178 #define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_UP)
179 #define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
181 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
183 #define ROCKBLOX_OFF BUTTON_POWER
184 #define ROCKBLOX_ROTATE_CCW BUTTON_SCROLL_UP
185 #define ROCKBLOX_ROTATE_CW BUTTON_REW
186 #define ROCKBLOX_DOWN BUTTON_SCROLL_DOWN
187 #define ROCKBLOX_LEFT BUTTON_LEFT
188 #define ROCKBLOX_RIGHT BUTTON_RIGHT
189 #define ROCKBLOX_DROP BUTTON_FF
190 #define ROCKBLOX_RESTART BUTTON_PLAY
192 #elif CONFIG_KEYPAD == GIGABEAT_PAD
194 #define ROCKBLOX_OFF BUTTON_POWER
195 #define ROCKBLOX_ROTATE_CCW BUTTON_VOL_DOWN
196 #define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
197 #define ROCKBLOX_ROTATE BUTTON_UP
198 #define ROCKBLOX_DOWN BUTTON_DOWN
199 #define ROCKBLOX_LEFT BUTTON_LEFT
200 #define ROCKBLOX_RIGHT BUTTON_RIGHT
201 #define ROCKBLOX_DROP BUTTON_SELECT
202 #define ROCKBLOX_RESTART BUTTON_A
204 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
206 #define ROCKBLOX_OFF BUTTON_PLAY
207 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
208 #define ROCKBLOX_ROTATE_CW BUTTON_SELECT
209 #define ROCKBLOX_DOWN BUTTON_DOWN
210 #define ROCKBLOX_LEFT BUTTON_LEFT
211 #define ROCKBLOX_RIGHT BUTTON_RIGHT
212 #define ROCKBLOX_DROP BUTTON_MODE
213 #define ROCKBLOX_RESTART BUTTON_EQ
215 #elif CONFIG_KEYPAD == MROBE500_PAD
216 #define ROCKBLOX_OFF BUTTON_POWER
218 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
219 #define ROCKBLOX_OFF BUTTON_BACK
220 #define ROCKBLOX_ROTATE_CCW BUTTON_VOL_DOWN
221 #define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
222 #define ROCKBLOX_ROTATE BUTTON_UP
223 #define ROCKBLOX_DOWN BUTTON_DOWN
224 #define ROCKBLOX_LEFT BUTTON_LEFT
225 #define ROCKBLOX_RIGHT BUTTON_RIGHT
226 #define ROCKBLOX_DROP BUTTON_SELECT
227 #define ROCKBLOX_RESTART BUTTON_PLAY
229 #elif CONFIG_KEYPAD == MROBE100_PAD
231 #define ROCKBLOX_OFF BUTTON_POWER
232 #define ROCKBLOX_ROTATE_CCW BUTTON_MENU
233 #define ROCKBLOX_ROTATE_CW BUTTON_PLAY
234 #define ROCKBLOX_ROTATE BUTTON_UP
235 #define ROCKBLOX_DOWN BUTTON_DOWN
236 #define ROCKBLOX_LEFT BUTTON_LEFT
237 #define ROCKBLOX_RIGHT BUTTON_RIGHT
238 #define ROCKBLOX_DROP BUTTON_SELECT
239 #define ROCKBLOX_RESTART BUTTON_DISPLAY
241 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
243 #define ROCKBLOX_OFF BUTTON_RC_REC
244 #define ROCKBLOX_ROTATE_CCW BUTTON_RC_VOL_DOWN
245 #define ROCKBLOX_ROTATE_CW BUTTON_RC_VOL_UP
246 #define ROCKBLOX_DOWN BUTTON_RC_MENU
247 #define ROCKBLOX_LEFT BUTTON_RC_REW
248 #define ROCKBLOX_RIGHT BUTTON_RC_FF
249 #define ROCKBLOX_DROP BUTTON_RC_PLAY
250 #define ROCKBLOX_RESTART BUTTON_RC_MODE
252 #elif CONFIG_KEYPAD == COWON_D2_PAD
254 #define ROCKBLOX_OFF BUTTON_POWER
255 #define ROCKBLOX_RESTART BUTTON_MENU
257 #elif CONFIG_KEYPAD == IAUDIO67_PAD
259 #define ROCKBLOX_OFF BUTTON_POWER
260 #define ROCKBLOX_ROTATE_CCW BUTTON_VOLDOWN
261 #define ROCKBLOX_ROTATE_CW BUTTON_VOLUP
262 #define ROCKBLOX_DOWN BUTTON_STOP
263 #define ROCKBLOX_LEFT BUTTON_LEFT
264 #define ROCKBLOX_RIGHT BUTTON_RIGHT
265 #define ROCKBLOX_DROP BUTTON_PLAY
266 #define ROCKBLOX_RESTART BUTTON_MENU
268 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
269 #define ROCKBLOX_OFF BUTTON_BACK
270 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
271 #define ROCKBLOX_ROTATE_CW BUTTON_PLAY
272 #define ROCKBLOX_DOWN BUTTON_DOWN
273 #define ROCKBLOX_LEFT BUTTON_LEFT
274 #define ROCKBLOX_RIGHT BUTTON_RIGHT
275 #define ROCKBLOX_DROP BUTTON_SELECT
276 #define ROCKBLOX_RESTART BUTTON_CUSTOM
278 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
280 #define ROCKBLOX_OFF BUTTON_POWER
281 #define ROCKBLOX_ROTATE_CCW BUTTON_VOL_DOWN
282 #define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
283 #define ROCKBLOX_ROTATE BUTTON_UP
284 #define ROCKBLOX_DOWN BUTTON_DOWN
285 #define ROCKBLOX_LEFT BUTTON_LEFT
286 #define ROCKBLOX_RIGHT BUTTON_RIGHT
287 #define ROCKBLOX_DROP BUTTON_SELECT
288 #define ROCKBLOX_RESTART BUTTON_MENU
290 # elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
292 #define ROCKBLOX_OFF BUTTON_POWER
293 #define ROCKBLOX_ROTATE_CCW BUTTON_VOL_DOWN
294 #define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
295 #define ROCKBLOX_ROTATE BUTTON_UP
296 #define ROCKBLOX_DOWN BUTTON_DOWN
297 #define ROCKBLOX_LEFT BUTTON_PREV
298 #define ROCKBLOX_RIGHT BUTTON_NEXT
299 #define ROCKBLOX_DROP BUTTON_PLAY
300 #define ROCKBLOX_RESTART BUTTON_MENU
302 #elif CONFIG_KEYPAD == ONDAVX747_PAD
303 #define ROCKBLOX_OFF BUTTON_POWER
304 #define ROCKBLOX_RESTART BUTTON_MENU
305 #elif CONFIG_KEYPAD == ONDAVX777_PAD
306 #define ROCKBLOX_OFF BUTTON_POWER
308 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
310 #define ROCKBLOX_OFF (BUTTON_REC|BUTTON_PLAY)
311 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
312 #define ROCKBLOX_ROTATE_CW BUTTON_DOWN
313 #define ROCKBLOX_DOWN BUTTON_REW
314 #define ROCKBLOX_LEFT BUTTON_LEFT
315 #define ROCKBLOX_RIGHT BUTTON_RIGHT
316 #define ROCKBLOX_DROP BUTTON_FFWD
317 #define ROCKBLOX_RESTART (BUTTON_REC|BUTTON_REW)
319 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
321 #define ROCKBLOX_OFF BUTTON_REC
322 #define ROCKBLOX_ROTATE_CCW BUTTON_PLAY
323 #define ROCKBLOX_ROTATE_CW BUTTON_MENU
324 #define ROCKBLOX_DOWN BUTTON_DOWN
325 #define ROCKBLOX_LEFT BUTTON_PREV
326 #define ROCKBLOX_RIGHT BUTTON_NEXT
327 #define ROCKBLOX_DROP BUTTON_OK
328 #define ROCKBLOX_RESTART BUTTON_CANCEL
330 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
331 #define ROCKBLOX_OFF (BUTTON_REC|BUTTON_PLAY)
332 #define ROCKBLOX_ROTATE_CCW BUTTON_PREV
333 #define ROCKBLOX_ROTATE_CW BUTTON_NEXT
334 #define ROCKBLOX_DOWN BUTTON_SELECT
335 #define ROCKBLOX_LEFT BUTTON_VOL_DOWN
336 #define ROCKBLOX_RIGHT BUTTON_VOL_UP
337 #define ROCKBLOX_DROP BUTTON_PLAY
338 #define ROCKBLOX_RESTART BUTTON_REC
340 #else
341 #error No keymap defined!
342 #endif
344 #ifdef HAVE_TOUCHSCREEN
345 #ifndef ROCKBLOX_OFF
346 #define ROCKBLOX_OFF BUTTON_TOPLEFT
347 #endif
348 #ifdef ROCKBLOX_ROTATE_CCW
349 #define ROCKBLOX_ROTATE_CCW2 BUTTON_BOTTOMLEFT
350 #else
351 #define ROCKBLOX_ROTATE_CCW BUTTON_BOTTOMLEFT
352 #endif
353 #ifdef ROCKBLOX_ROTATE_CW
354 #define ROCKBLOX_ROTATE_CW2 BUTTON_BOTTOMRIGHT
355 #else
356 #define ROCKBLOX_ROTATE_CW BUTTON_BOTTOMRIGHT
357 #define ROCKBLOX_ROTATE_CW2 BUTTON_TOPMIDDLE
358 #endif
359 #ifndef ROCKBLOX_DOWN
360 #define ROCKBLOX_DOWN BUTTON_BOTTOMMIDDLE
361 #endif
362 #ifndef ROCKBLOX_LEFT
363 #define ROCKBLOX_LEFT BUTTON_MIDLEFT
364 #endif
365 #ifndef ROCKBLOX_RIGHT
366 #define ROCKBLOX_RIGHT BUTTON_MIDRIGHT
367 #endif
368 #ifndef ROCKBLOX_DROP
369 #define ROCKBLOX_DROP BUTTON_CENTER
370 #endif
371 #ifndef ROCKBLOX_RESTART
372 #define ROCKBLOX_RESTART BUTTON_TOPRIGHT
373 #endif
374 #endif
376 #define BLOCKS_NUM 7
377 #define EMPTY_BLOCK 7
379 #define BOARD_WIDTH 10
381 #ifdef HAVE_LCD_BITMAP
383 #define BOARD_HEIGHT 20
385 #if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
387 #define BLOCK_WIDTH 24
388 #define BLOCK_HEIGHT 24
389 #define BOARD_X 172
390 #define BOARD_Y 0
391 #define PREVIEW_X 24
392 #define PREVIEW_Y 22
393 #define LABEL_X 482
394 #define SCORE_Y 50
395 #define LEVEL_Y 140
396 #define LINES_Y 210
398 #elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640)
400 #define BLOCK_WIDTH 30
401 #define BLOCK_HEIGHT 30
402 #define BOARD_X 14
403 #define BOARD_Y 2
404 #define PREVIEW_X 342
405 #define PREVIEW_Y 482
406 #define LABEL_X 344
407 #define SCORE_Y 58
408 #define LEVEL_Y 142
409 #define LINES_Y 218
411 #elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
413 #define BLOCK_WIDTH 12
414 #define BLOCK_HEIGHT 12
415 #define BOARD_X 86
416 #define BOARD_Y 0
417 #define PREVIEW_X 12
418 #define PREVIEW_Y 11
419 #define LABEL_X 242
420 #define SCORE_Y 25
421 #define LEVEL_Y 70
422 #define LINES_Y 105
424 #elif (LCD_WIDTH == 240) && ((LCD_HEIGHT == 320) || (LCD_HEIGHT == 400))
426 #define BLOCK_WIDTH 15
427 #define BLOCK_HEIGHT 15
428 #define BOARD_X 7
429 #define BOARD_Y 1
430 #define PREVIEW_X 171
431 #define PREVIEW_Y 241
432 #define LABEL_X 172
433 #define SCORE_Y 29
434 #define LEVEL_Y 71
435 #define LINES_Y 109
436 #define HIGH_LABEL_X 172
437 #define HIGH_SCORE_Y 163
438 #define HIGH_LEVEL_Y 172
440 #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176)
442 #define BLOCK_WIDTH 8
443 #define BLOCK_HEIGHT 8
444 #define BOARD_X 27
445 #define BOARD_Y 5
446 #define PREVIEW_X 158
447 #define PREVIEW_Y 130
448 #define LABEL_X 147
449 #define SCORE_Y 20
450 #define LEVEL_Y 65
451 #define LINES_Y 100
453 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132)
455 #define BLOCK_WIDTH 6
456 #define BLOCK_HEIGHT 6
457 #define BOARD_X 25
458 #define BOARD_Y 1
459 #define PREVIEW_X 126
460 #define PREVIEW_Y 102
461 #define LABEL_X 112
462 #define SCORE_Y 17
463 #define LEVEL_Y 49
464 #define LINES_Y 81
466 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220)
468 /* no room for the space in the highscore list */
469 #define _SPACE ""
471 #define BLOCK_WIDTH 10
472 #define BLOCK_HEIGHT 10
473 #define BOARD_X 6
474 #define BOARD_Y 10
475 #define PREVIEW_X 124
476 #define PREVIEW_Y 174
477 #define LABEL_X 117
478 #define SCORE_Y 18
479 #define LEVEL_Y 52
480 #define LINES_Y 85
481 #define HIGH_SCORE_Y 119
482 #define HIGH_LEVEL_Y 126
483 #define HIGH_LABEL_X 114
485 #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128)
488 #define BLOCK_WIDTH 6
489 #define BLOCK_HEIGHT 6
490 #define BOARD_X 22
491 #define BOARD_Y 3
492 #define PREVIEW_X 114
493 #define PREVIEW_Y 100
494 #define LABEL_X 101
495 #define SCORE_Y 17
496 #define LEVEL_Y 49
497 #define LINES_Y 82
499 #elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110)
501 #define BLOCK_WIDTH 5
502 #define BLOCK_HEIGHT 5
503 #define BOARD_X 14
504 #define BOARD_Y 0
505 #define PREVIEW_X 98
506 #define PREVIEW_Y 88
507 #define LABEL_X 80
508 #define SCORE_Y 15
509 #define LEVEL_Y 45
510 #define LINES_Y 74
512 #elif (LCD_WIDTH == 132) && (LCD_HEIGHT == 80)
514 #define BLOCK_WIDTH 4
515 #define BLOCK_HEIGHT 4
516 #define BOARD_X 10
517 #define BOARD_Y 0
518 #define PREVIEW_X 89
519 #define PREVIEW_Y 61
520 #define LABEL_X 78
521 #define SCORE_Y 10
522 #define LEVEL_Y 30
523 #define LINES_Y 50
525 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 128)
527 #define BLOCK_WIDTH 6
528 #define BLOCK_HEIGHT 6
529 #define BOARD_X 4
530 #define BOARD_Y 3
531 #define PREVIEW_X 84
532 #define PREVIEW_Y 100
533 #define LABEL_X 71
534 #define SCORE_Y 17
535 #define LEVEL_Y 49
536 #define LINES_Y 82
538 /* NOTE: This is for the GoGear SA9200 and is only
539 temporary until I can get better coordinates! */
540 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 160)
542 #define BLOCK_WIDTH 6
543 #define BLOCK_HEIGHT 6
544 #define BOARD_X 4
545 #define BOARD_Y 3
546 #define PREVIEW_X 84
547 #define PREVIEW_Y 100
548 #define LABEL_X 71
549 #define SCORE_Y 17
550 #define LEVEL_Y 49
551 #define LINES_Y 82
553 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 96)
555 #define BLOCK_WIDTH 4
556 #define BLOCK_HEIGHT 4
557 #define BOARD_X 14
558 #define BOARD_Y 2
559 #define PREVIEW_X 89
560 #define PREVIEW_Y 76
561 #define LABEL_X 70
562 #define SCORE_Y 14
563 #define LEVEL_Y 39
564 #define LINES_Y 64
566 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64)
568 #define BLOCK_WIDTH 3
569 #define BLOCK_HEIGHT 3
570 #define BOARD_X 9
571 #define BOARD_Y 3
572 #define PREVIEW_X 53
573 #define PREVIEW_Y 5
574 #define LABEL_X 70
575 #define SCORE_Y 32
576 #define LEVEL_Y 13
577 #define LINES_Y 51
579 #elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
581 #define BLOCK_WIDTH 4
582 #define BLOCK_HEIGHT 3
583 #define BOARD_X 9
584 #define BOARD_Y 3
585 #define PREVIEW_X 59
586 #define PREVIEW_Y 5
587 #define LABEL_X 59
588 #define SCORE_Y 32
589 #define LEVEL_Y 13
590 #define LEVEL_X 78
591 #define LINES_Y 51
593 #endif
595 #ifndef LEVEL_X
596 #define LEVEL_X LABEL_X
597 #endif
599 #ifndef LINES_X
600 #define LINES_X LABEL_X
601 #endif
603 extern const fb_data rockblox_background[];
605 #else /* HAVE_LCD_CHARCELLS */
607 #define BOARD_HEIGHT 14
609 #define BLOCK_WIDTH 1
610 #define BLOCK_HEIGHT 1
611 #define BOARD_X 5
612 #define BOARD_Y 0
613 #define PREVIEW_X 15
614 #define PREVIEW_Y 1
616 #endif
618 #ifndef _SPACE
619 #define _SPACE " "
620 #endif
621 /* <<Explanation on Rockblox shapes>>
624 %% - O has 1 orientation
626 %% %
627 %% %% - Z has 2 orientations
630 %% %
631 %% %% - S has 2 orientations
635 % %%%% - I has 2 orientations
638 % %%
639 % % % %%% - L has 4 orientations
640 %% %%% % %
642 % %%
643 % % % %%% - J has 4 orientations
644 %% %%% % %
646 % % %%%
647 %% % %% % - T has 4 orientations
648 % %%% %
651 /* c=current f=figure o=orientation n=next */
652 static struct _rockblox_status
654 int gameover;
655 int lines;
656 int level;
657 int score;
658 int cx;
659 int cy;
660 int cf;
661 int co;
662 int nf;
663 short board[BOARD_HEIGHT][BOARD_WIDTH]; /* 20 rows of 10 blocks */
664 } rockblox_status;
666 /* prototypes */
667 static void draw_next_block(void);
668 static void new_block(void);
670 #ifdef HAVE_SCROLLWHEEL
671 int wheel_events = 0, last_wheel_event = 0;
672 bool wheel_enabled = false;
673 #endif
675 static const short scoring[4] = { /* scoring for each number of lines */
676 #if BOARD_HEIGHT == 20
677 40 /* single */ , 100 /* double */ , 300 /* triple */ , 1200 /* rockblox */
678 #elif BOARD_HEIGHT == 14 /* Player special values */
679 60 /* single */ , 150 /* double */ , 500 /* triple */ , 2000 /* rockblox */
680 #endif
683 struct figure
685 #if LCD_DEPTH >= 2
686 unsigned short color[3]; /* color of figure (light,middle,shadow) */
687 #endif
688 unsigned short max_or; /* max orientations */
689 signed short shapeX[4], shapeY[4]; /* implementation of figures */
692 /* array of figures */
693 figures[BLOCKS_NUM] = {
694 /* O */
696 #if LCD_DEPTH >= 16
697 {LCD_RGBPACK (153, 255, 255), LCD_RGBPACK(0, 255, 255),
698 LCD_RGBPACK(0,153,153)},
699 #elif LCD_DEPTH == 2
700 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
701 #endif
703 {-1, 0, -1, 0},
704 {0, 0, 1, 1}
706 /* I */
708 #if LCD_DEPTH >= 16
709 {LCD_RGBPACK (255, 153, 128), LCD_RGBPACK (255, 0, 0),
710 LCD_RGBPACK (153, 0, 0)},
711 #elif LCD_DEPTH == 2
712 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
713 #endif
715 {-2, -1, 0, 1},
716 {0, 0, 0, 0}
718 /* 'Z' */
720 #if LCD_DEPTH >= 16
721 {LCD_RGBPACK (153, 255, 153), LCD_RGBPACK (0, 255, 0),
722 LCD_RGBPACK (0, 153, 0)},
723 #elif LCD_DEPTH == 2
724 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
725 #endif
727 {0, 1, -1, 0},
728 {0, 0, 1, 1}
730 /* 'S' */
732 #if LCD_DEPTH >= 16
733 {LCD_RGBPACK (153, 153, 255), LCD_RGBPACK (0, 0, 255),
734 LCD_RGBPACK (0, 0, 153)},
735 #elif LCD_DEPTH == 2
736 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
737 #endif
739 {-1, 0, 0, 1},
740 {0, 0, 1, 1}
742 /* 'L' */
744 #if LCD_DEPTH >= 16
745 {LCD_RGBPACK (255, 255, 153), LCD_RGBPACK (255, 255, 0),
746 LCD_RGBPACK (153, 153, 0)},
747 #elif LCD_DEPTH == 2
748 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
749 #endif
751 {-1, 0, 1, 1},
752 {0, 0, 0, 1}
754 /* 'J' */
756 #if LCD_DEPTH >= 16
757 {LCD_RGBPACK (255, 153, 255), LCD_RGBPACK (255, 0, 255),
758 LCD_RGBPACK (153, 0, 153)},
759 #elif LCD_DEPTH == 2
760 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
761 #endif
763 {-1, 0, 1, -1},
764 {0, 0, 0, 1}
766 /* 'T' */
768 #if LCD_DEPTH >= 16
769 {LCD_RGBPACK (204, 204, 204), LCD_RGBPACK (153, 153, 153),
770 LCD_RGBPACK (85, 85, 85)},
771 #elif LCD_DEPTH == 2
772 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
773 #endif
775 {-1, 0, 1, 0},
776 {0, 0, 0, 1}
779 bool resume = false;
780 bool resume_file = false;
782 /* Rockbox File System only supports full filenames inc dir */
783 #define SCORE_FILE PLUGIN_GAMES_DIR "/rockblox.score"
784 #define RESUME_FILE PLUGIN_GAMES_DIR "/rockblox.resume"
785 #define NUM_SCORES 5
787 /* Default High Scores... */
788 struct highscore highscores[NUM_SCORES];
790 /* get random number from (0) to (range-1) */
791 static int t_rand (int range)
793 return rb->rand () % range;
796 static inline void show_game_over (void)
798 rb->splash(HZ,"Game over!");
801 /* init the board array to have no blocks */
802 static void init_board (void)
804 int i, j;
805 for (i = 0; i < BOARD_WIDTH; i++)
806 for (j = 0; j < BOARD_HEIGHT; j++)
807 rockblox_status.board[j][i] = EMPTY_BLOCK;
810 /* show the score, level and lines */
811 static void show_details (void)
813 char str[25]; /* for strings */
815 #ifdef HAVE_LCD_BITMAP
816 #if LCD_DEPTH >= 2
817 rb->lcd_set_foreground (LCD_BLACK);
818 rb->lcd_set_background (LCD_WHITE);
819 #endif
820 rb->snprintf (str, sizeof (str), "%d", rockblox_status.score);
821 rb->lcd_putsxy (LABEL_X, SCORE_Y, str);
822 rb->snprintf (str, sizeof (str), "%d", rockblox_status.level);
823 rb->lcd_putsxy (LEVEL_X, LEVEL_Y, str);
824 rb->snprintf (str, sizeof (str), "%d", rockblox_status.lines);
825 rb->lcd_putsxy (LINES_X, LINES_Y, str);
826 #else /* HAVE_LCD_CHARCELLS */
827 rb->snprintf (str, sizeof (str), "L%d/%d", rockblox_status.level,
828 rockblox_status.lines);
829 rb->lcd_puts (5, 0, str);
830 rb->snprintf (str, sizeof (str), "S%d", rockblox_status.score);
831 rb->lcd_puts (5, 1, str);
832 #endif
835 #ifdef HIGH_SCORE_Y
836 static void show_highscores (void)
838 int i;
839 char str[25]; /* for strings */
841 for (i = 0; i<NUM_SCORES; i++)
843 rb->snprintf (str, sizeof (str), "%06d" _SPACE "L%1d",
844 highscores[i].score, highscores[i].level);
845 rb->lcd_putsxy (HIGH_LABEL_X, HIGH_SCORE_Y + (10 * i), str);
848 #endif
850 static void load_game(void)
852 int fd;
854 resume = false;
856 fd = rb->open(RESUME_FILE, O_RDONLY);
857 if (fd < 0) return;
859 if (rb->read(fd, &rockblox_status, sizeof(struct _rockblox_status))
860 < (ssize_t)sizeof(struct _rockblox_status))
862 rb->splash(HZ/2, "Loading Rockblox resume info failed");
863 return;
864 } else {
865 resume = true;
868 rb->close(fd);
870 return;
873 static void dump_resume(void)
875 int fd;
877 fd = rb->open(RESUME_FILE, O_WRONLY|O_CREAT, 0666);
878 if (fd < 0)
879 goto fail;
881 if (rb->write(fd, &rockblox_status, sizeof(struct _rockblox_status))
882 <= 0)
884 rb->close(fd);
885 goto fail;
887 rb->close(fd);
888 return;
890 fail:
891 rb->splash(HZ/2, "Writing Rockblox resume info failed");
892 return;
895 static void init_rockblox (bool resume)
897 char score_name[50];
898 struct tm* tm;
900 tm = rb->get_time();
901 rb->snprintf(score_name, sizeof(score_name), "%04d%02d%02d %02d%02d%02d",
902 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
903 tm->tm_hour, tm->tm_min, tm->tm_sec);
905 #ifdef HAVE_LCD_BITMAP
906 rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
907 #else /* HAVE_LCD_CHARCELLS */
908 pgfx_display (0, 0);
909 pgfx_display_block (3, 0, 3, 1);
910 pgfx_display_block (4, 0, 3, 0);
911 rb->lcd_puts(4, 1, " ");
912 pgfx_clear_display();
913 pgfx_fillrect (3, 0, 2, 14);
914 pgfx_fillrect (15, 7, 2, 7);
915 pgfx_update();
916 #endif
917 if (!resume)
919 rockblox_status.level = 1;
920 rockblox_status.lines = 0;
921 rockblox_status.score = 0;
922 rockblox_status.nf = t_rand(BLOCKS_NUM);
923 init_board ();
924 new_block ();
926 draw_next_block();
928 show_details ();
929 #ifdef HIGH_SCORE_Y
930 show_highscores ();
931 #endif
934 static inline int level_speed(int level)
936 #if BOARD_HEIGHT == 20
937 return (5*HZ) / (level + 9);
938 #elif BOARD_HEIGHT == 14
939 return (7*HZ) / (level + 9);
940 #endif
943 static int getRelativeX (int figure, int square, int orientation)
945 switch (orientation) {
946 case 0:
947 return figures[figure].shapeX[square];
948 case 1:
949 return figures[figure].shapeY[square];
950 case 2:
951 return -figures[figure].shapeX[square];
952 case 3:
953 return -figures[figure].shapeY[square];
954 default:
955 return 0;
959 static int getRelativeY (int figure, int square, int orientation)
961 switch (orientation) {
962 case 0:
963 return figures[figure].shapeY[square];
964 case 1:
965 return -figures[figure].shapeX[square];
966 case 2:
967 return -figures[figure].shapeY[square];
968 case 3:
969 return figures[figure].shapeX[square];
970 default:
971 return 0;
975 /* redraw the while board on the screen */
976 static void refresh_board (void)
978 int i, j, x, y, block;
980 #if LCD_DEPTH >= 2
981 rb->lcd_set_foreground (LCD_BLACK);
982 #elif LCD_DEPTH == 1
983 mylcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID);
984 #endif
986 mylcd_fillrect (BOARD_X, BOARD_Y, BOARD_WIDTH * BLOCK_WIDTH,
987 BOARD_HEIGHT * BLOCK_HEIGHT);
989 #if LCD_DEPTH == 1
990 mylcd_set_drawmode (DRMODE_SOLID);
991 #endif
993 for (i = 0; i < BOARD_WIDTH; i++)
994 for (j = 0; j < BOARD_HEIGHT; j++) {
995 block = rockblox_status.board[j][i];
996 if (block != EMPTY_BLOCK) {
997 #ifdef HAVE_LCD_BITMAP
998 #if LCD_DEPTH >= 2
999 /* middle drawing */
1000 rb->lcd_set_foreground (figures[block].color[1]);
1001 #endif
1002 rb->lcd_fillrect (BOARD_X + i * BLOCK_WIDTH,
1003 BOARD_Y + j * BLOCK_HEIGHT,
1004 BLOCK_WIDTH, BLOCK_HEIGHT);
1005 #if LCD_DEPTH >= 2
1006 /* light drawing */
1007 rb->lcd_set_foreground (figures[block].color[0]);
1008 #endif
1009 rb->lcd_vline (BOARD_X + i * BLOCK_WIDTH,
1010 BOARD_Y + j * BLOCK_HEIGHT,
1011 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 2);
1012 rb->lcd_hline (BOARD_X + i * BLOCK_WIDTH,
1013 BOARD_X + (i + 1) * BLOCK_WIDTH - 2,
1014 BOARD_Y + j * BLOCK_HEIGHT);
1015 #if LCD_DEPTH >= 2
1016 /* shadow drawing */
1017 rb->lcd_set_foreground (figures[block].color[2]);
1018 #endif
1019 rb->lcd_vline (BOARD_X + (i + 1) * BLOCK_WIDTH - 1,
1020 BOARD_Y + j * BLOCK_HEIGHT + 1,
1021 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 1);
1022 rb->lcd_hline (BOARD_X + i * BLOCK_WIDTH + 1,
1023 BOARD_X + (i + 1) * BLOCK_WIDTH - 1,
1024 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 1);
1025 #else /* HAVE_LCD_CHARCELLS */
1026 pgfx_drawpixel (BOARD_X + i, BOARD_Y + j);
1027 #endif
1031 for (i = 0; i < 4; i++) {
1032 x = getRelativeX (rockblox_status.cf, i, rockblox_status.co)
1033 + rockblox_status.cx;
1034 y = getRelativeY (rockblox_status.cf, i, rockblox_status.co)
1035 + rockblox_status.cy;
1036 #ifdef HAVE_LCD_BITMAP
1037 #if LCD_DEPTH >= 2
1038 /* middle drawing */
1039 rb->lcd_set_foreground (figures[rockblox_status.cf].color[1]);
1040 #endif
1041 rb->lcd_fillrect (BOARD_X + x * BLOCK_WIDTH,
1042 BOARD_Y + y * BLOCK_HEIGHT,
1043 BLOCK_WIDTH, BLOCK_HEIGHT);
1044 #if LCD_DEPTH >= 2
1045 /* light drawing */
1046 rb->lcd_set_foreground (figures[rockblox_status.cf].color[0]);
1047 #endif
1048 rb->lcd_vline (BOARD_X + x * BLOCK_WIDTH, BOARD_Y + y * BLOCK_HEIGHT,
1049 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 2);
1050 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH,
1051 BOARD_X + (x + 1) * BLOCK_WIDTH - 2,
1052 BOARD_Y + y * BLOCK_HEIGHT);
1053 #if LCD_DEPTH >= 2
1054 /* shadow drawing */
1055 rb->lcd_set_foreground (figures[rockblox_status.cf].color[2]);
1056 #endif
1057 rb->lcd_vline (BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1058 BOARD_Y + y * BLOCK_HEIGHT + 1,
1059 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1060 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH + 1,
1061 BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1062 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1063 #else /* HAVE_LCD_CHARCELLS */
1064 pgfx_drawpixel (BOARD_X + x, BOARD_Y + y);
1065 #endif
1067 mylcd_update ();
1070 static bool canMoveTo (int x, int y, int newOrientation)
1072 int i, rx, ry;
1073 for (i = 0; i < 4; i++) {
1074 ry = getRelativeY (rockblox_status.cf, i, newOrientation) + y;
1075 rx = getRelativeX (rockblox_status.cf, i, newOrientation) + x;
1076 if ((rx < 0 || rx >= BOARD_WIDTH) ||
1077 (ry < 0 || ry >= BOARD_HEIGHT) ||
1078 (rockblox_status.board[ry][rx] != EMPTY_BLOCK))
1079 return false;
1081 return true;
1084 /* draws the preview of next block in the preview window */
1085 static void draw_next_block (void)
1087 int i, rx, ry;
1088 /* clear preview window first */
1089 #if LCD_DEPTH >= 2
1090 rb->lcd_set_foreground (LCD_BLACK);
1091 #elif LCD_DEPTH == 1
1092 mylcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID);
1093 #endif
1095 /* 4x4 */
1096 mylcd_fillrect (PREVIEW_X, PREVIEW_Y, BLOCK_WIDTH * 4, BLOCK_HEIGHT * 4);
1098 #if LCD_DEPTH == 1
1099 mylcd_set_drawmode (DRMODE_SOLID);
1100 #endif
1102 /* draw the lightgray rectangles */
1103 #if LCD_DEPTH >= 16
1104 rb->lcd_set_foreground (LCD_RGBPACK (40, 40, 40));
1105 #elif LCD_DEPTH == 2
1106 rb->lcd_set_foreground (LCD_DARKGRAY);
1107 #endif
1109 #if LCD_DEPTH >= 2
1110 for (rx = 0; rx < 4; rx++)
1111 for (ry = 0; ry < 4; ry++)
1112 rb->lcd_drawrect (PREVIEW_X + rx * BLOCK_WIDTH,
1113 PREVIEW_Y + ry * BLOCK_HEIGHT, BLOCK_WIDTH,
1114 BLOCK_HEIGHT);
1115 #endif
1117 /* draw the figure */
1118 for (i = 0; i < 4; i++) {
1119 rx = getRelativeX (rockblox_status.nf, i, 0) + 2;
1120 ry = getRelativeY (rockblox_status.nf, i, 0) + 2;
1121 #ifdef HAVE_LCD_BITMAP
1122 #if LCD_DEPTH >= 2
1123 rb->lcd_set_foreground (figures[rockblox_status.nf].color[1]); /* middle drawing */
1124 #endif
1125 rb->lcd_fillrect (PREVIEW_X + rx * BLOCK_WIDTH,
1126 PREVIEW_Y + ry * BLOCK_HEIGHT,
1127 BLOCK_WIDTH, BLOCK_HEIGHT);
1128 #if LCD_DEPTH >= 2
1129 rb->lcd_set_foreground (figures[rockblox_status.nf].color[0]); /* light drawing */
1130 #endif
1131 rb->lcd_vline (PREVIEW_X + rx * BLOCK_WIDTH,
1132 PREVIEW_Y + ry * BLOCK_HEIGHT,
1133 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 2);
1134 rb->lcd_hline (PREVIEW_X + rx * BLOCK_WIDTH,
1135 PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 2,
1136 PREVIEW_Y + ry * BLOCK_HEIGHT);
1137 #if LCD_DEPTH >= 2
1138 rb->lcd_set_foreground (figures[rockblox_status.nf].color[2]); /* shadow drawing */
1139 #endif
1140 rb->lcd_vline (PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 1,
1141 PREVIEW_Y + ry * BLOCK_HEIGHT + 1,
1142 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 1);
1143 rb->lcd_hline (PREVIEW_X + rx * BLOCK_WIDTH + 1,
1144 PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 1,
1145 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 1);
1146 #else /* HAVE_LCD_CHARCELLS */
1147 pgfx_drawpixel (PREVIEW_X + rx, PREVIEW_Y + ry);
1148 #endif
1153 /* move the block to a relative location */
1154 static void move_block (int x, int y, int o)
1156 if (canMoveTo (rockblox_status.cx + x, rockblox_status.cy + y, o)) {
1157 rockblox_status.cy += y;
1158 rockblox_status.cx += x;
1159 rockblox_status.co = o;
1163 /* try to add a new block to play with (return true if gameover) */
1164 static void new_block (void)
1166 rockblox_status.cy = 1;
1167 rockblox_status.cx = 5;
1168 rockblox_status.cf = rockblox_status.nf;
1169 rockblox_status.co = 0; /* start at the same orientation all time */
1170 rockblox_status.nf = t_rand (BLOCKS_NUM);
1171 rockblox_status.gameover = !canMoveTo (rockblox_status.cx,
1172 rockblox_status.cy, rockblox_status.co);
1174 draw_next_block ();
1178 /* check for filled rockblox_status.lines and do what necessary */
1179 static int check_lines (void)
1182 int i, j, y;
1183 int rockblox = 0;
1185 for (j = 0; j < BOARD_HEIGHT; j++) {
1186 for (i = 0; ((i < BOARD_WIDTH) &&
1187 (rockblox_status.board[j][i] != EMPTY_BLOCK)); i++);
1188 if (i == BOARD_WIDTH) { /* woo hoo, we have a line */
1189 rockblox++;
1190 for (y = j; y > 0; y--)
1192 for (i = 0; i < BOARD_WIDTH; i++)
1193 { /* fall line */
1194 rockblox_status.board[y][i] = rockblox_status.board[y - 1][i];
1200 return rockblox;
1203 /* moves down the figure and returns true if gameover */
1204 static void move_down (void)
1206 int l, i, rx, ry;
1208 if (!canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co)) {
1209 /* save figure to board */
1210 for (i = 0; i < 4; i++) {
1211 rx = getRelativeX (rockblox_status.cf, i, rockblox_status.co) + rockblox_status.cx;
1212 ry = getRelativeY (rockblox_status.cf, i, rockblox_status.co) + rockblox_status.cy;
1213 rockblox_status.board[ry][rx] = rockblox_status.cf;
1215 /* check if formed some lines */
1216 l = check_lines ();
1217 if (l) {
1218 /* the original scoring from "http://en.wikipedia.org/wiki/Rockblox" */
1219 rockblox_status.score += scoring[l - 1] * rockblox_status.level;
1220 rockblox_status.lines += l;
1221 rockblox_status.level = (int) rockblox_status.lines / 10 + 1;
1224 /* show details */
1225 show_details ();
1227 /* generate a new figure */
1228 new_block ();
1229 } else
1230 move_block (0, 1, rockblox_status.co);
1233 static bool rockblox_help(void)
1235 static char *help_text[] = {
1236 "Rockblox", "", "Aim", "",
1237 "Make", "the", "falling", "blocks", "of",
1238 "different", "shapes", "form", "full", "rows.",
1239 "Whenever", "a", "row", "is", "completed,",
1240 "it", "will", "be", "cleared", "away",
1241 "and", "you", "gain", "points."
1243 static struct style_text formation[]={
1244 { 0, TEXT_CENTER|TEXT_UNDERLINE },
1245 { 2, C_RED },
1246 LAST_STYLE_ITEM
1249 #ifdef HAVE_LCD_BITMAP
1250 rb->lcd_setfont(FONT_UI);
1251 #endif
1252 #ifdef HAVE_LCD_COLOR
1253 rb->lcd_set_background(LCD_BLACK);
1254 rb->lcd_set_foreground(LCD_WHITE);
1255 #endif
1256 if (display_text(ARRAYLEN(help_text), help_text, formation, NULL, true))
1257 return true;
1258 #ifdef HAVE_LCD_BITMAP
1259 rb->lcd_setfont(FONT_SYSFIXED);
1260 #endif
1262 return false;
1265 static int rockblox_menu_cb(int action, const struct menu_item_ex *this_item)
1267 int i = ((intptr_t)this_item);
1268 if(action == ACTION_REQUEST_MENUITEM
1269 && !resume && (i==0 || i==5))
1270 return ACTION_EXIT_MENUITEM;
1271 return action;
1274 static int rockblox_menu(void)
1276 int selected = 0;
1278 MENUITEM_STRINGLIST(main_menu, "Rockblox Menu", rockblox_menu_cb,
1279 "Resume Game", "Start New Game",
1280 "Help", "High Scores", "Playback Control",
1281 "Quit without Saving", "Quit");
1283 rb->button_clear_queue();
1284 while (true) {
1285 switch (rb->do_menu(&main_menu, &selected, NULL, false)) {
1286 case 0:
1287 if(resume_file)
1288 rb->remove(RESUME_FILE);
1289 init_rockblox(true);
1290 return 0;
1291 case 1:
1292 init_rockblox(false);
1293 return 0;
1294 case 2:
1295 if (rockblox_help())
1296 return 1;
1297 break;
1298 case 3:
1299 highscore_show(-1, highscores, NUM_SCORES, true);
1300 break;
1301 case 4:
1302 if (playback_control(NULL))
1303 return 1;
1304 break;
1305 case 5:
1306 return 1;
1307 case 6:
1308 if (resume) {
1309 rb->splash(HZ*1, "Saving game ...");
1310 dump_resume();
1312 return 1;
1313 case MENU_ATTACHED_USB:
1314 return 1;
1315 default:
1316 return 1;
1317 break;
1323 static int rockblox_loop (void)
1325 int button;
1326 int lastbutton = BUTTON_NONE;
1327 long next_down_tick = *rb->current_tick + level_speed(rockblox_status.level);
1329 if (rockblox_menu()) {
1330 return 1;
1332 resume = false;
1333 resume_file = false;
1335 while (1) {
1336 #ifdef HAS_BUTTON_HOLD
1337 if (rb->button_hold ()) {
1338 /* Turn on backlight timeout (revert to settings) */
1339 backlight_use_settings(); /* backlight control in lib/helper.c */
1340 rb->splash(0, "Paused");
1341 while (rb->button_hold ())
1342 rb->sleep(HZ/10);
1344 /* Turn off backlight timeout */
1345 backlight_force_on(); /* backlight control in lib/helper.c */
1347 /* get rid of the splash text */
1348 rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1349 show_details ();
1350 #ifdef HIGH_SCORE_Y
1351 show_highscores ();
1352 #endif
1353 draw_next_block ();
1354 refresh_board ();
1356 #endif
1358 button = rb->button_get_w_tmo (MAX(next_down_tick - *rb->current_tick, 1));
1359 switch (button) {
1360 #ifdef ROCKBLOX_RC_OFF
1361 case ROCKBLOX_RC_OFF:
1362 #endif
1363 case ROCKBLOX_OFF:
1364 #ifdef ROCKBLOX_OFF_PRE
1365 if (lastbutton != ROCKBLOX_OFF_PRE)
1366 break;
1367 #endif
1368 resume = true;
1369 return 0;
1370 break;
1372 #if defined(ROCKBLOX_ROTATE)
1373 case ROCKBLOX_ROTATE:
1374 #endif
1375 case ROCKBLOX_ROTATE_CCW:
1376 case ROCKBLOX_ROTATE_CCW | BUTTON_REPEAT:
1377 #ifdef HAVE_SCROLLWHEEL
1378 /* if the wheel is disabled, add an event to the stack. */
1379 if(wheel_enabled == false)
1380 wheel_events++;
1382 /* if it's enabled, go ahead and rotate.. */
1383 if(wheel_enabled)
1384 #endif
1385 #ifdef ROCKBLOX_ROTATE_CCW2
1386 /* fallback */
1387 case ROCKBLOX_ROTATE_CCW2:
1388 #endif
1389 move_block (0, 0, (rockblox_status.co + 1) % figures[rockblox_status.cf].max_or);
1390 break;
1392 case ROCKBLOX_ROTATE_CW:
1393 case ROCKBLOX_ROTATE_CW | BUTTON_REPEAT:
1394 #ifdef HAVE_SCROLLWHEEL
1395 if(wheel_enabled == false)
1396 wheel_events++;
1398 if(wheel_enabled)
1399 #endif
1400 #ifdef ROCKBLOX_ROTATE_CW2
1401 /* fallback */
1402 case ROCKBLOX_ROTATE_CW2:
1403 #endif
1404 move_block (0, 0,
1405 (rockblox_status.co + figures[rockblox_status.cf].max_or -
1406 1) % figures[rockblox_status.cf].max_or);
1407 break;
1409 case ROCKBLOX_DOWN:
1410 case ROCKBLOX_DOWN | BUTTON_REPEAT:
1411 move_block (0, 1, rockblox_status.co);
1412 break;
1414 case ROCKBLOX_RIGHT:
1415 case ROCKBLOX_RIGHT | BUTTON_REPEAT:
1416 move_block (1, 0, rockblox_status.co);
1417 break;
1419 case ROCKBLOX_LEFT:
1420 case ROCKBLOX_LEFT | BUTTON_REPEAT:
1421 move_block (-1, 0, rockblox_status.co);
1422 break;
1424 case ROCKBLOX_DROP:
1425 #ifdef ROCKBLOX_DROP_PRE
1426 if (lastbutton != ROCKBLOX_DROP_PRE)
1427 break;
1428 #endif
1429 while (canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co))
1430 move_block (0, 1, rockblox_status.co);
1431 break;
1432 #ifdef ROCKBLOX_RESTART
1433 case ROCKBLOX_RESTART:
1434 rb->splash (HZ * 1, "Restarting...");
1435 init_rockblox (false);
1436 break;
1437 #endif
1439 default:
1440 if (rb->default_event_handler (button) == SYS_USB_CONNECTED)
1441 return PLUGIN_USB_CONNECTED;
1442 break;
1444 if (button != BUTTON_NONE)
1445 lastbutton = button;
1447 #ifdef HAVE_SCROLLWHEEL
1448 /* check if we should enable the scroll wheel, if events
1449 * begin to stack up... */
1450 if(wheel_enabled == false)
1452 /* stopped rotating the wheel, reset the count */
1453 if(wheel_events == last_wheel_event)
1455 last_wheel_event = 0;
1456 wheel_events = 0;
1458 /* rotated the wheel a while constantly, enable it. */
1459 else if(wheel_events > 3)
1461 wheel_enabled = true;
1464 /* this evens out the last event and the "current" event.
1465 * if we get an event next time through button reading, it will
1466 * remain ahead of last_event. if we don't, they'll end up equaling
1467 * each other.. thus, the scroll count will be reset. */
1468 if(wheel_enabled == false && wheel_events > last_wheel_event)
1469 last_wheel_event++;
1471 #endif
1473 if (TIME_AFTER(*rb->current_tick, next_down_tick)) {
1474 move_down ();
1475 next_down_tick += level_speed(rockblox_status.level);
1476 if (TIME_AFTER(*rb->current_tick, next_down_tick))
1477 /* restart time "raster" when we had to wait longer than usual
1478 * (pause, game restart etc) */
1479 next_down_tick = *rb->current_tick + level_speed(rockblox_status.level);
1482 if (rockblox_status.gameover) {
1483 #if LCD_DEPTH >= 2
1484 rb->lcd_set_foreground (LCD_BLACK);
1485 #endif
1486 show_game_over();
1487 resume = false;
1488 return 0;
1491 refresh_board ();
1494 return 0;
1497 enum plugin_status plugin_start (const void *parameter)
1500 (void) parameter;
1502 rb->srand (*rb->current_tick);
1504 /* Load HighScore if any */
1505 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
1507 #if LCD_DEPTH > 1
1508 rb->lcd_set_backdrop(NULL);
1509 #endif
1511 #ifdef HAVE_LCD_BITMAP
1512 rb->lcd_setfont (FONT_SYSFIXED);
1513 #else
1514 if (!pgfx_init(4, 2))
1516 rb->splash(HZ*2, "Old LCD :(");
1517 return PLUGIN_OK;
1519 #endif
1520 /* Turn off backlight timeout */
1521 backlight_force_on(); /* backlight control in lib/helper.c */
1522 load_game();
1523 resume_file = resume;
1524 while(!rockblox_loop()) {
1525 if(!resume) {
1526 int position = highscore_update(rockblox_status.score,
1527 rockblox_status.level, "",
1528 highscores, NUM_SCORES);
1529 if (position != -1) {
1530 if (position == 0)
1531 rb->splash(HZ*2, "New High Score");
1532 highscore_show(position, highscores, NUM_SCORES, true);
1537 #ifndef HAVE_LCD_BITMAP
1538 pgfx_release();
1539 #endif
1540 /* Save user's HighScore */
1541 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
1542 backlight_use_settings(); /* backlight control in lib/helper.c */
1544 return PLUGIN_OK;