Fix warning about missing newline at the EOF
[maemo-rb.git] / apps / plugins / rockblox.c
blobc23c6b11cb25a2209c52dc313c9c5b67121d152d
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"
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_HDD6330_PAD
292 #define ROCKBLOX_OFF BUTTON_POWER
293 #define ROCKBLOX_ROTATE_CCW BUTTON_PREV
294 #define ROCKBLOX_ROTATE_CW BUTTON_NEXT
295 #define ROCKBLOX_ROTATE BUTTON_UP
296 #define ROCKBLOX_DOWN BUTTON_DOWN
297 #define ROCKBLOX_LEFT BUTTON_LEFT
298 #define ROCKBLOX_RIGHT BUTTON_RIGHT
299 #define ROCKBLOX_DROP BUTTON_PLAY
300 #define ROCKBLOX_RESTART BUTTON_MENU
302 # elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
304 #define ROCKBLOX_OFF BUTTON_POWER
305 #define ROCKBLOX_ROTATE_CCW BUTTON_VOL_DOWN
306 #define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
307 #define ROCKBLOX_ROTATE BUTTON_UP
308 #define ROCKBLOX_DOWN BUTTON_DOWN
309 #define ROCKBLOX_LEFT BUTTON_PREV
310 #define ROCKBLOX_RIGHT BUTTON_NEXT
311 #define ROCKBLOX_DROP BUTTON_PLAY
312 #define ROCKBLOX_RESTART BUTTON_MENU
314 #elif CONFIG_KEYPAD == ONDAVX747_PAD
315 #define ROCKBLOX_OFF BUTTON_POWER
316 #define ROCKBLOX_RESTART BUTTON_MENU
317 #elif CONFIG_KEYPAD == ONDAVX777_PAD
318 #define ROCKBLOX_OFF BUTTON_POWER
320 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
322 #define ROCKBLOX_OFF (BUTTON_REC|BUTTON_PLAY)
323 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
324 #define ROCKBLOX_ROTATE_CW BUTTON_DOWN
325 #define ROCKBLOX_DOWN BUTTON_REW
326 #define ROCKBLOX_LEFT BUTTON_LEFT
327 #define ROCKBLOX_RIGHT BUTTON_RIGHT
328 #define ROCKBLOX_DROP BUTTON_FFWD
329 #define ROCKBLOX_RESTART (BUTTON_REC|BUTTON_REW)
331 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
333 #define ROCKBLOX_OFF BUTTON_REC
334 #define ROCKBLOX_ROTATE_CCW BUTTON_PLAY
335 #define ROCKBLOX_ROTATE_CW BUTTON_MENU
336 #define ROCKBLOX_DOWN BUTTON_DOWN
337 #define ROCKBLOX_LEFT BUTTON_PREV
338 #define ROCKBLOX_RIGHT BUTTON_NEXT
339 #define ROCKBLOX_DROP BUTTON_OK
340 #define ROCKBLOX_RESTART BUTTON_CANCEL
342 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
343 #define ROCKBLOX_OFF (BUTTON_REC|BUTTON_PLAY)
344 #define ROCKBLOX_ROTATE_CCW BUTTON_REW
345 #define ROCKBLOX_ROTATE_CW BUTTON_FF
346 #define ROCKBLOX_DOWN BUTTON_FUNC
347 #define ROCKBLOX_LEFT BUTTON_VOL_DOWN
348 #define ROCKBLOX_RIGHT BUTTON_VOL_UP
349 #define ROCKBLOX_DROP BUTTON_PLAY
350 #define ROCKBLOX_RESTART BUTTON_REC
352 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
353 #define ROCKBLOX_OFF (BUTTON_REC|BUTTON_REPEAT)
354 #define ROCKBLOX_ROTATE_CCW BUTTON_REW
355 #define ROCKBLOX_ROTATE_CW BUTTON_FF
356 #define ROCKBLOX_DOWN BUTTON_DOWN
357 #define ROCKBLOX_LEFT BUTTON_MENU
358 #define ROCKBLOX_RIGHT BUTTON_ENTER
359 #define ROCKBLOX_DROP BUTTON_PLAY
360 #define ROCKBLOX_RESTART BUTTON_REC
362 #elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
363 #define ROCKBLOX_OFF BUTTON_POWER
364 #define ROCKBLOX_ROTATE_CW BUTTON_SELECT
365 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
366 #define ROCKBLOX_DOWN BUTTON_DOWN
367 #define ROCKBLOX_LEFT BUTTON_LEFT
368 #define ROCKBLOX_RIGHT BUTTON_RIGHT
369 #define ROCKBLOX_DROP BUTTON_PLAYPAUSE
370 #define ROCKBLOX_RESTART BUTTON_BACK
372 #elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
373 #define ROCKBLOX_OFF BUTTON_POWER
374 #define ROCKBLOX_ROTATE_CW BUTTON_NEXT
375 #define ROCKBLOX_ROTATE_CCW BUTTON_PREV
376 #define ROCKBLOX_DOWN BUTTON_DOWN
377 #define ROCKBLOX_LEFT BUTTON_LEFT
378 #define ROCKBLOX_RIGHT BUTTON_RIGHT
379 #define ROCKBLOX_DROP BUTTON_SELECT
380 #define ROCKBLOX_RESTART BUTTON_VOL_DOWN
382 #elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
384 #define ROCKBLOX_OFF BUTTON_BACK
385 #define ROCKBLOX_ROTATE_CCW BUTTON_POWER
386 #define ROCKBLOX_ROTATE_CW BUTTON_MENU
387 #define ROCKBLOX_ROTATE BUTTON_UP
388 #define ROCKBLOX_DOWN BUTTON_DOWN
389 #define ROCKBLOX_LEFT BUTTON_LEFT
390 #define ROCKBLOX_RIGHT BUTTON_RIGHT
391 #define ROCKBLOX_DROP BUTTON_SELECT
392 #define ROCKBLOX_RESTART BUTTON_USER
394 #else
395 #error No keymap defined!
396 #endif
398 #ifdef HAVE_TOUCHSCREEN
399 #ifndef ROCKBLOX_OFF
400 #define ROCKBLOX_OFF BUTTON_TOPLEFT
401 #endif
402 #ifdef ROCKBLOX_ROTATE_CCW
403 #define ROCKBLOX_ROTATE_CCW2 BUTTON_BOTTOMLEFT
404 #else
405 #define ROCKBLOX_ROTATE_CCW BUTTON_BOTTOMLEFT
406 #endif
407 #ifdef ROCKBLOX_ROTATE_CW
408 #define ROCKBLOX_ROTATE_CW2 BUTTON_BOTTOMRIGHT
409 #else
410 #define ROCKBLOX_ROTATE_CW BUTTON_BOTTOMRIGHT
411 #define ROCKBLOX_ROTATE_CW2 BUTTON_TOPMIDDLE
412 #endif
413 #ifndef ROCKBLOX_DOWN
414 #define ROCKBLOX_DOWN BUTTON_BOTTOMMIDDLE
415 #endif
416 #ifndef ROCKBLOX_LEFT
417 #define ROCKBLOX_LEFT BUTTON_MIDLEFT
418 #endif
419 #ifndef ROCKBLOX_RIGHT
420 #define ROCKBLOX_RIGHT BUTTON_MIDRIGHT
421 #endif
422 #ifndef ROCKBLOX_DROP
423 #define ROCKBLOX_DROP BUTTON_CENTER
424 #endif
425 #ifndef ROCKBLOX_RESTART
426 #define ROCKBLOX_RESTART BUTTON_TOPRIGHT
427 #endif
428 #endif
430 #define BLOCKS_NUM 7
431 #define EMPTY_BLOCK 7
433 #define BOARD_WIDTH 10
435 #ifdef HAVE_LCD_BITMAP
437 #define BOARD_HEIGHT 20
439 #if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
441 #define BLOCK_WIDTH 24
442 #define BLOCK_HEIGHT 24
443 #define BOARD_X 172
444 #define BOARD_Y 0
445 #define PREVIEW_X 24
446 #define PREVIEW_Y 22
447 #define LABEL_X 482
448 #define SCORE_Y 50
449 #define LEVEL_Y 140
450 #define LINES_Y 210
452 #elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640)
454 #define BLOCK_WIDTH 30
455 #define BLOCK_HEIGHT 30
456 #define BOARD_X 14
457 #define BOARD_Y 2
458 #define PREVIEW_X 342
459 #define PREVIEW_Y 482
460 #define LABEL_X 344
461 #define SCORE_Y 58
462 #define LEVEL_Y 142
463 #define LINES_Y 218
465 #elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
467 #define BLOCK_WIDTH 12
468 #define BLOCK_HEIGHT 12
469 #define BOARD_X 86
470 #define BOARD_Y 0
471 #define PREVIEW_X 12
472 #define PREVIEW_Y 11
473 #define LABEL_X 242
474 #define SCORE_Y 25
475 #define LEVEL_Y 70
476 #define LINES_Y 105
478 #elif (LCD_WIDTH == 240) && ((LCD_HEIGHT == 320) || (LCD_HEIGHT == 400))
480 #define BLOCK_WIDTH 15
481 #define BLOCK_HEIGHT 15
482 #define BOARD_X 7
483 #define BOARD_Y 1
484 #define PREVIEW_X 171
485 #define PREVIEW_Y 241
486 #define LABEL_X 172
487 #define SCORE_Y 29
488 #define LEVEL_Y 71
489 #define LINES_Y 109
490 #define HIGH_LABEL_X 172
491 #define HIGH_SCORE_Y 163
492 #define HIGH_LEVEL_Y 172
494 #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176)
496 #define BLOCK_WIDTH 8
497 #define BLOCK_HEIGHT 8
498 #define BOARD_X 27
499 #define BOARD_Y 5
500 #define PREVIEW_X 158
501 #define PREVIEW_Y 130
502 #define LABEL_X 147
503 #define SCORE_Y 20
504 #define LEVEL_Y 65
505 #define LINES_Y 100
507 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132)
509 #define BLOCK_WIDTH 6
510 #define BLOCK_HEIGHT 6
511 #define BOARD_X 25
512 #define BOARD_Y 1
513 #define PREVIEW_X 126
514 #define PREVIEW_Y 102
515 #define LABEL_X 112
516 #define SCORE_Y 17
517 #define LEVEL_Y 49
518 #define LINES_Y 81
520 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220)
522 /* no room for the space in the highscore list */
523 #define _SPACE ""
525 #define BLOCK_WIDTH 10
526 #define BLOCK_HEIGHT 10
527 #define BOARD_X 6
528 #define BOARD_Y 10
529 #define PREVIEW_X 124
530 #define PREVIEW_Y 174
531 #define LABEL_X 117
532 #define SCORE_Y 18
533 #define LEVEL_Y 52
534 #define LINES_Y 85
535 #define HIGH_SCORE_Y 119
536 #define HIGH_LEVEL_Y 126
537 #define HIGH_LABEL_X 114
539 #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128)
542 #define BLOCK_WIDTH 6
543 #define BLOCK_HEIGHT 6
544 #define BOARD_X 22
545 #define BOARD_Y 3
546 #define PREVIEW_X 114
547 #define PREVIEW_Y 100
548 #define LABEL_X 101
549 #define SCORE_Y 17
550 #define LEVEL_Y 49
551 #define LINES_Y 82
553 #elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110)
555 #define BLOCK_WIDTH 5
556 #define BLOCK_HEIGHT 5
557 #define BOARD_X 14
558 #define BOARD_Y 0
559 #define PREVIEW_X 98
560 #define PREVIEW_Y 88
561 #define LABEL_X 80
562 #define SCORE_Y 15
563 #define LEVEL_Y 45
564 #define LINES_Y 74
566 #elif (LCD_WIDTH == 132) && (LCD_HEIGHT == 80)
568 #define BLOCK_WIDTH 4
569 #define BLOCK_HEIGHT 4
570 #define BOARD_X 10
571 #define BOARD_Y 0
572 #define PREVIEW_X 89
573 #define PREVIEW_Y 61
574 #define LABEL_X 78
575 #define SCORE_Y 10
576 #define LEVEL_Y 30
577 #define LINES_Y 50
579 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 128)
581 #define BLOCK_WIDTH 6
582 #define BLOCK_HEIGHT 6
583 #define BOARD_X 4
584 #define BOARD_Y 3
585 #define PREVIEW_X 84
586 #define PREVIEW_Y 100
587 #define LABEL_X 71
588 #define SCORE_Y 17
589 #define LEVEL_Y 49
590 #define LINES_Y 82
592 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 160)
594 #define BLOCK_WIDTH 7
595 #define BLOCK_HEIGHT 7
596 #define BOARD_X 4
597 #define BOARD_Y 5
598 #define PREVIEW_X 88
599 #define PREVIEW_Y 111
600 #define LABEL_X 82
601 #define SCORE_Y (2+16)
602 #define LEVEL_Y (36+16)
603 #define LINES_Y (70+16)
605 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 96)
607 #define BLOCK_WIDTH 4
608 #define BLOCK_HEIGHT 4
609 #define BOARD_X 14
610 #define BOARD_Y 2
611 #define PREVIEW_X 89
612 #define PREVIEW_Y 76
613 #define LABEL_X 70
614 #define SCORE_Y 14
615 #define LEVEL_Y 39
616 #define LINES_Y 64
618 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64)
620 #define BLOCK_WIDTH 3
621 #define BLOCK_HEIGHT 3
622 #define BOARD_X 9
623 #define BOARD_Y 3
624 #define PREVIEW_X 53
625 #define PREVIEW_Y 5
626 #define LABEL_X 70
627 #define SCORE_Y 32
628 #define LEVEL_Y 13
629 #define LINES_Y 51
631 #elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
633 #define BLOCK_WIDTH 4
634 #define BLOCK_HEIGHT 3
635 #define BOARD_X 9
636 #define BOARD_Y 3
637 #define PREVIEW_X 59
638 #define PREVIEW_Y 5
639 #define LABEL_X 59
640 #define SCORE_Y 32
641 #define LEVEL_Y 13
642 #define LEVEL_X 78
643 #define LINES_Y 51
645 #elif LCD_WIDTH == 96 && LCD_HEIGHT == 96
647 #define BLOCK_WIDTH 3
648 #define BLOCK_HEIGHT 3
649 #define BOARD_X 9
650 #define BOARD_Y 3
651 #define PREVIEW_X 59
652 #define PREVIEW_Y 5
653 #define LABEL_X 59
654 #define SCORE_Y 32
655 #define LEVEL_Y 13
656 #define LEVEL_X 78
657 #define LINES_Y 51
658 #endif
660 #ifndef LEVEL_X
661 #define LEVEL_X LABEL_X
662 #endif
664 #ifndef LINES_X
665 #define LINES_X LABEL_X
666 #endif
668 extern const fb_data rockblox_background[];
670 #else /* HAVE_LCD_CHARCELLS */
672 #define BOARD_HEIGHT 14
674 #define BLOCK_WIDTH 1
675 #define BLOCK_HEIGHT 1
676 #define BOARD_X 5
677 #define BOARD_Y 0
678 #define PREVIEW_X 15
679 #define PREVIEW_Y 1
681 #endif
683 #ifndef _SPACE
684 #define _SPACE " "
685 #endif
686 /* <<Explanation on Rockblox shapes>>
689 %% - O has 1 orientation
691 %% %
692 %% %% - Z has 2 orientations
695 %% %
696 %% %% - S has 2 orientations
700 % %%%% - I has 2 orientations
703 % %%
704 % % % %%% - L has 4 orientations
705 %% %%% % %
707 % %%
708 % % % %%% - J has 4 orientations
709 %% %%% % %
711 % % %%%
712 %% % %% % - T has 4 orientations
713 % %%% %
716 /* c=current f=figure o=orientation n=next */
717 static struct _rockblox_status
719 int gameover;
720 int lines;
721 int level;
722 int score;
723 int cx;
724 int cy;
725 int cf;
726 int co;
727 int nf;
728 short board[BOARD_HEIGHT][BOARD_WIDTH]; /* 20 rows of 10 blocks */
729 } rockblox_status;
731 /* prototypes */
732 static void draw_next_block(void);
733 static void new_block(void);
735 #ifdef HAVE_SCROLLWHEEL
736 int wheel_events = 0, last_wheel_event = 0;
737 bool wheel_enabled = false;
738 #endif
740 static const short scoring[4] = { /* scoring for each number of lines */
741 #if BOARD_HEIGHT == 20
742 40 /* single */ , 100 /* double */ , 300 /* triple */ , 1200 /* rockblox */
743 #elif BOARD_HEIGHT == 14 /* Player special values */
744 60 /* single */ , 150 /* double */ , 500 /* triple */ , 2000 /* rockblox */
745 #endif
748 struct figure
750 #if LCD_DEPTH >= 2
751 unsigned short color[3]; /* color of figure (light,middle,shadow) */
752 #endif
753 unsigned short max_or; /* max orientations */
754 signed short shapeX[4], shapeY[4]; /* implementation of figures */
757 /* array of figures */
758 figures[BLOCKS_NUM] = {
759 /* O */
761 #if LCD_DEPTH >= 16
762 {LCD_RGBPACK (153, 255, 255), LCD_RGBPACK(0, 255, 255),
763 LCD_RGBPACK(0,153,153)},
764 #elif LCD_DEPTH == 2
765 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
766 #endif
768 {-1, 0, -1, 0},
769 {0, 0, 1, 1}
771 /* I */
773 #if LCD_DEPTH >= 16
774 {LCD_RGBPACK (255, 153, 128), LCD_RGBPACK (255, 0, 0),
775 LCD_RGBPACK (153, 0, 0)},
776 #elif LCD_DEPTH == 2
777 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
778 #endif
780 {-2, -1, 0, 1},
781 {0, 0, 0, 0}
783 /* 'Z' */
785 #if LCD_DEPTH >= 16
786 {LCD_RGBPACK (153, 255, 153), LCD_RGBPACK (0, 255, 0),
787 LCD_RGBPACK (0, 153, 0)},
788 #elif LCD_DEPTH == 2
789 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
790 #endif
792 {0, 1, -1, 0},
793 {0, 0, 1, 1}
795 /* 'S' */
797 #if LCD_DEPTH >= 16
798 {LCD_RGBPACK (153, 153, 255), LCD_RGBPACK (0, 0, 255),
799 LCD_RGBPACK (0, 0, 153)},
800 #elif LCD_DEPTH == 2
801 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
802 #endif
804 {-1, 0, 0, 1},
805 {0, 0, 1, 1}
807 /* 'L' */
809 #if LCD_DEPTH >= 16
810 {LCD_RGBPACK (255, 255, 153), LCD_RGBPACK (255, 255, 0),
811 LCD_RGBPACK (153, 153, 0)},
812 #elif LCD_DEPTH == 2
813 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
814 #endif
816 {-1, 0, 1, 1},
817 {0, 0, 0, 1}
819 /* 'J' */
821 #if LCD_DEPTH >= 16
822 {LCD_RGBPACK (255, 153, 255), LCD_RGBPACK (255, 0, 255),
823 LCD_RGBPACK (153, 0, 153)},
824 #elif LCD_DEPTH == 2
825 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
826 #endif
828 {-1, 0, 1, -1},
829 {0, 0, 0, 1}
831 /* 'T' */
833 #if LCD_DEPTH >= 16
834 {LCD_RGBPACK (204, 204, 204), LCD_RGBPACK (153, 153, 153),
835 LCD_RGBPACK (85, 85, 85)},
836 #elif LCD_DEPTH == 2
837 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
838 #endif
840 {-1, 0, 1, 0},
841 {0, 0, 0, 1}
844 bool resume = false;
845 bool resume_file = false;
847 /* Rockbox File System only supports full filenames inc dir */
848 #define SCORE_FILE PLUGIN_GAMES_DATA_DIR "/rockblox.score"
849 #define RESUME_FILE PLUGIN_GAMES_DATA_DIR "/rockblox.resume"
850 #define NUM_SCORES 5
852 /* Default High Scores... */
853 struct highscore highscores[NUM_SCORES];
855 /* get random number from (0) to (range-1) */
856 static int t_rand (int range)
858 return rb->rand () % range;
861 static inline void show_game_over (void)
863 rb->splash(HZ,"Game over!");
866 /* init the board array to have no blocks */
867 static void init_board (void)
869 int i, j;
870 for (i = 0; i < BOARD_WIDTH; i++)
871 for (j = 0; j < BOARD_HEIGHT; j++)
872 rockblox_status.board[j][i] = EMPTY_BLOCK;
875 /* show the score, level and lines */
876 static void show_details (void)
878 #ifdef HAVE_LCD_BITMAP
879 #if LCD_DEPTH >= 2
880 rb->lcd_set_foreground (LCD_BLACK);
881 rb->lcd_set_background (LCD_WHITE);
882 #endif
883 rb->lcd_putsxyf (LABEL_X, SCORE_Y, "%d", rockblox_status.score);
884 rb->lcd_putsxyf (LEVEL_X, LEVEL_Y, "%d", rockblox_status.level);
885 rb->lcd_putsxyf (LINES_X, LINES_Y, "%d", rockblox_status.lines);
886 #else /* HAVE_LCD_CHARCELLS */
887 rb->lcd_putsf (5, 0, "L%d/%d", rockblox_status.level,
888 rockblox_status.lines);
889 rb->lcd_putsf (5, 1, "S%d", rockblox_status.score);
890 #endif
893 #ifdef HIGH_SCORE_Y
894 static void show_highscores (void)
896 int i;
898 for (i = 0; i<NUM_SCORES; i++)
899 rb->lcd_putsxyf (HIGH_LABEL_X, HIGH_SCORE_Y + (10 * i),
900 "%06d" _SPACE "L%1d", highscores[i].score, highscores[i].level);
902 #endif
904 static void load_game(void)
906 int fd;
908 resume = false;
910 fd = rb->open(RESUME_FILE, O_RDONLY);
911 if (fd < 0) return;
913 if (rb->read(fd, &rockblox_status, sizeof(struct _rockblox_status))
914 < (ssize_t)sizeof(struct _rockblox_status))
916 rb->splash(HZ/2, "Loading Rockblox resume info failed");
917 } else {
918 resume = true;
921 rb->close(fd);
923 return;
926 static void dump_resume(void)
928 int fd;
930 fd = rb->open(RESUME_FILE, O_WRONLY|O_CREAT, 0666);
931 if (fd < 0)
932 goto fail;
934 if (rb->write(fd, &rockblox_status, sizeof(struct _rockblox_status))
935 <= 0)
937 rb->close(fd);
938 goto fail;
940 rb->close(fd);
941 return;
943 fail:
944 rb->splash(HZ/2, "Writing Rockblox resume info failed");
945 return;
948 static void init_rockblox (bool resume)
950 char score_name[50];
951 struct tm* tm;
953 tm = rb->get_time();
954 rb->snprintf(score_name, sizeof(score_name), "%04d%02d%02d %02d%02d%02d",
955 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
956 tm->tm_hour, tm->tm_min, tm->tm_sec);
958 #ifdef HAVE_LCD_BITMAP
959 rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
960 #else /* HAVE_LCD_CHARCELLS */
961 pgfx_display (0, 0);
962 pgfx_display_block (3, 0, 3, 1);
963 pgfx_display_block (4, 0, 3, 0);
964 rb->lcd_puts(4, 1, " ");
965 pgfx_clear_display();
966 pgfx_fillrect (3, 0, 2, 14);
967 pgfx_fillrect (15, 7, 2, 7);
968 pgfx_update();
969 #endif
970 if (!resume)
972 rockblox_status.level = 1;
973 rockblox_status.lines = 0;
974 rockblox_status.score = 0;
975 rockblox_status.nf = t_rand(BLOCKS_NUM);
976 init_board ();
977 new_block ();
979 draw_next_block();
981 show_details ();
982 #ifdef HIGH_SCORE_Y
983 show_highscores ();
984 #endif
987 static inline int level_speed(int level)
989 #if BOARD_HEIGHT == 20
990 return (5*HZ) / (level + 9);
991 #elif BOARD_HEIGHT == 14
992 return (7*HZ) / (level + 9);
993 #endif
996 static int getRelativeX (int figure, int square, int orientation)
998 switch (orientation) {
999 case 0:
1000 return figures[figure].shapeX[square];
1001 case 1:
1002 return figures[figure].shapeY[square];
1003 case 2:
1004 return -figures[figure].shapeX[square];
1005 case 3:
1006 return -figures[figure].shapeY[square];
1007 default:
1008 return 0;
1012 static int getRelativeY (int figure, int square, int orientation)
1014 switch (orientation) {
1015 case 0:
1016 return figures[figure].shapeY[square];
1017 case 1:
1018 return -figures[figure].shapeX[square];
1019 case 2:
1020 return -figures[figure].shapeY[square];
1021 case 3:
1022 return figures[figure].shapeX[square];
1023 default:
1024 return 0;
1028 /* redraw the while board on the screen */
1029 static void refresh_board (void)
1031 int i, j, x, y, block;
1033 #if LCD_DEPTH >= 2
1034 rb->lcd_set_foreground (LCD_BLACK);
1035 #elif LCD_DEPTH == 1
1036 mylcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID);
1037 #endif
1039 mylcd_fillrect (BOARD_X, BOARD_Y, BOARD_WIDTH * BLOCK_WIDTH,
1040 BOARD_HEIGHT * BLOCK_HEIGHT);
1042 #if LCD_DEPTH == 1
1043 mylcd_set_drawmode (DRMODE_SOLID);
1044 #endif
1046 for (i = 0; i < BOARD_WIDTH; i++)
1047 for (j = 0; j < BOARD_HEIGHT; j++) {
1048 block = rockblox_status.board[j][i];
1049 if (block != EMPTY_BLOCK) {
1050 #ifdef HAVE_LCD_BITMAP
1051 #if LCD_DEPTH >= 2
1052 /* middle drawing */
1053 rb->lcd_set_foreground (figures[block].color[1]);
1054 #endif
1055 rb->lcd_fillrect (BOARD_X + i * BLOCK_WIDTH,
1056 BOARD_Y + j * BLOCK_HEIGHT,
1057 BLOCK_WIDTH, BLOCK_HEIGHT);
1058 #if LCD_DEPTH >= 2
1059 /* light drawing */
1060 rb->lcd_set_foreground (figures[block].color[0]);
1061 #endif
1062 rb->lcd_vline (BOARD_X + i * BLOCK_WIDTH,
1063 BOARD_Y + j * BLOCK_HEIGHT,
1064 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 2);
1065 rb->lcd_hline (BOARD_X + i * BLOCK_WIDTH,
1066 BOARD_X + (i + 1) * BLOCK_WIDTH - 2,
1067 BOARD_Y + j * BLOCK_HEIGHT);
1068 #if LCD_DEPTH >= 2
1069 /* shadow drawing */
1070 rb->lcd_set_foreground (figures[block].color[2]);
1071 #endif
1072 rb->lcd_vline (BOARD_X + (i + 1) * BLOCK_WIDTH - 1,
1073 BOARD_Y + j * BLOCK_HEIGHT + 1,
1074 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 1);
1075 rb->lcd_hline (BOARD_X + i * BLOCK_WIDTH + 1,
1076 BOARD_X + (i + 1) * BLOCK_WIDTH - 1,
1077 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 1);
1078 #else /* HAVE_LCD_CHARCELLS */
1079 pgfx_drawpixel (BOARD_X + i, BOARD_Y + j);
1080 #endif
1084 for (i = 0; i < 4; i++) {
1085 x = getRelativeX (rockblox_status.cf, i, rockblox_status.co)
1086 + rockblox_status.cx;
1087 y = getRelativeY (rockblox_status.cf, i, rockblox_status.co)
1088 + rockblox_status.cy;
1089 #ifdef HAVE_LCD_BITMAP
1090 #if LCD_DEPTH >= 2
1091 /* middle drawing */
1092 rb->lcd_set_foreground (figures[rockblox_status.cf].color[1]);
1093 #endif
1094 rb->lcd_fillrect (BOARD_X + x * BLOCK_WIDTH,
1095 BOARD_Y + y * BLOCK_HEIGHT,
1096 BLOCK_WIDTH, BLOCK_HEIGHT);
1097 #if LCD_DEPTH >= 2
1098 /* light drawing */
1099 rb->lcd_set_foreground (figures[rockblox_status.cf].color[0]);
1100 #endif
1101 rb->lcd_vline (BOARD_X + x * BLOCK_WIDTH, BOARD_Y + y * BLOCK_HEIGHT,
1102 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 2);
1103 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH,
1104 BOARD_X + (x + 1) * BLOCK_WIDTH - 2,
1105 BOARD_Y + y * BLOCK_HEIGHT);
1106 #if LCD_DEPTH >= 2
1107 /* shadow drawing */
1108 rb->lcd_set_foreground (figures[rockblox_status.cf].color[2]);
1109 #endif
1110 rb->lcd_vline (BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1111 BOARD_Y + y * BLOCK_HEIGHT + 1,
1112 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1113 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH + 1,
1114 BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1115 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1116 #else /* HAVE_LCD_CHARCELLS */
1117 pgfx_drawpixel (BOARD_X + x, BOARD_Y + y);
1118 #endif
1120 mylcd_update ();
1123 static bool canMoveTo (int x, int y, int newOrientation)
1125 int i, rx, ry;
1126 for (i = 0; i < 4; i++) {
1127 ry = getRelativeY (rockblox_status.cf, i, newOrientation) + y;
1128 rx = getRelativeX (rockblox_status.cf, i, newOrientation) + x;
1129 if ((rx < 0 || rx >= BOARD_WIDTH) ||
1130 (ry < 0 || ry >= BOARD_HEIGHT) ||
1131 (rockblox_status.board[ry][rx] != EMPTY_BLOCK))
1132 return false;
1134 return true;
1137 /* draws the preview of next block in the preview window */
1138 static void draw_next_block (void)
1140 int i, rx, ry;
1141 /* clear preview window first */
1142 #if LCD_DEPTH >= 2
1143 rb->lcd_set_foreground (LCD_BLACK);
1144 #elif LCD_DEPTH == 1
1145 mylcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID);
1146 #endif
1148 /* 4x4 */
1149 mylcd_fillrect (PREVIEW_X, PREVIEW_Y, BLOCK_WIDTH * 4, BLOCK_HEIGHT * 4);
1151 #if LCD_DEPTH == 1
1152 mylcd_set_drawmode (DRMODE_SOLID);
1153 #endif
1155 /* draw the lightgray rectangles */
1156 #if LCD_DEPTH >= 16
1157 rb->lcd_set_foreground (LCD_RGBPACK (40, 40, 40));
1158 #elif LCD_DEPTH == 2
1159 rb->lcd_set_foreground (LCD_DARKGRAY);
1160 #endif
1162 #if LCD_DEPTH >= 2
1163 for (rx = 0; rx < 4; rx++)
1164 for (ry = 0; ry < 4; ry++)
1165 rb->lcd_drawrect (PREVIEW_X + rx * BLOCK_WIDTH,
1166 PREVIEW_Y + ry * BLOCK_HEIGHT, BLOCK_WIDTH,
1167 BLOCK_HEIGHT);
1168 #endif
1170 /* draw the figure */
1171 for (i = 0; i < 4; i++) {
1172 rx = getRelativeX (rockblox_status.nf, i, 0) + 2;
1173 ry = getRelativeY (rockblox_status.nf, i, 0) + 2;
1174 #ifdef HAVE_LCD_BITMAP
1175 #if LCD_DEPTH >= 2
1176 rb->lcd_set_foreground (figures[rockblox_status.nf].color[1]); /* middle drawing */
1177 #endif
1178 rb->lcd_fillrect (PREVIEW_X + rx * BLOCK_WIDTH,
1179 PREVIEW_Y + ry * BLOCK_HEIGHT,
1180 BLOCK_WIDTH, BLOCK_HEIGHT);
1181 #if LCD_DEPTH >= 2
1182 rb->lcd_set_foreground (figures[rockblox_status.nf].color[0]); /* light drawing */
1183 #endif
1184 rb->lcd_vline (PREVIEW_X + rx * BLOCK_WIDTH,
1185 PREVIEW_Y + ry * BLOCK_HEIGHT,
1186 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 2);
1187 rb->lcd_hline (PREVIEW_X + rx * BLOCK_WIDTH,
1188 PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 2,
1189 PREVIEW_Y + ry * BLOCK_HEIGHT);
1190 #if LCD_DEPTH >= 2
1191 rb->lcd_set_foreground (figures[rockblox_status.nf].color[2]); /* shadow drawing */
1192 #endif
1193 rb->lcd_vline (PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 1,
1194 PREVIEW_Y + ry * BLOCK_HEIGHT + 1,
1195 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 1);
1196 rb->lcd_hline (PREVIEW_X + rx * BLOCK_WIDTH + 1,
1197 PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 1,
1198 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 1);
1199 #else /* HAVE_LCD_CHARCELLS */
1200 pgfx_drawpixel (PREVIEW_X + rx, PREVIEW_Y + ry);
1201 #endif
1206 /* move the block to a relative location */
1207 static void move_block (int x, int y, int o)
1209 if (canMoveTo (rockblox_status.cx + x, rockblox_status.cy + y, o)) {
1210 rockblox_status.cy += y;
1211 rockblox_status.cx += x;
1212 rockblox_status.co = o;
1216 /* try to add a new block to play with (return true if gameover) */
1217 static void new_block (void)
1219 rockblox_status.cy = 1;
1220 rockblox_status.cx = 5;
1221 rockblox_status.cf = rockblox_status.nf;
1222 rockblox_status.co = 0; /* start at the same orientation all time */
1223 rockblox_status.nf = t_rand (BLOCKS_NUM);
1224 rockblox_status.gameover = !canMoveTo (rockblox_status.cx,
1225 rockblox_status.cy, rockblox_status.co);
1227 draw_next_block ();
1231 /* check for filled rockblox_status.lines and do what necessary */
1232 static int check_lines (void)
1235 int i, j, y;
1236 int rockblox = 0;
1238 for (j = 0; j < BOARD_HEIGHT; j++) {
1239 for (i = 0; ((i < BOARD_WIDTH) &&
1240 (rockblox_status.board[j][i] != EMPTY_BLOCK)); i++);
1241 if (i == BOARD_WIDTH) { /* woo hoo, we have a line */
1242 rockblox++;
1243 for (y = j; y > 0; y--)
1245 for (i = 0; i < BOARD_WIDTH; i++)
1246 { /* fall line */
1247 rockblox_status.board[y][i] = rockblox_status.board[y - 1][i];
1253 return rockblox;
1256 /* moves down the figure and returns true if gameover */
1257 static void move_down (void)
1259 int l, i, rx, ry;
1261 if (!canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co)) {
1262 /* save figure to board */
1263 for (i = 0; i < 4; i++) {
1264 rx = getRelativeX (rockblox_status.cf, i, rockblox_status.co) + rockblox_status.cx;
1265 ry = getRelativeY (rockblox_status.cf, i, rockblox_status.co) + rockblox_status.cy;
1266 rockblox_status.board[ry][rx] = rockblox_status.cf;
1268 /* check if formed some lines */
1269 l = check_lines ();
1270 if (l) {
1271 /* the original scoring from "http://en.wikipedia.org/wiki/Rockblox" */
1272 rockblox_status.score += scoring[l - 1] * rockblox_status.level;
1273 rockblox_status.lines += l;
1274 rockblox_status.level = (int) rockblox_status.lines / 10 + 1;
1277 /* show details */
1278 show_details ();
1280 /* generate a new figure */
1281 new_block ();
1282 } else
1283 move_block (0, 1, rockblox_status.co);
1286 static bool rockblox_help(void)
1288 static char *help_text[] = {
1289 "Rockblox", "", "Aim", "",
1290 "Make", "the", "falling", "blocks", "of",
1291 "different", "shapes", "form", "full", "rows.",
1292 "Whenever", "a", "row", "is", "completed,",
1293 "it", "will", "be", "cleared", "away",
1294 "and", "you", "gain", "points."
1296 static struct style_text formation[]={
1297 { 0, TEXT_CENTER|TEXT_UNDERLINE },
1298 { 2, C_RED },
1299 LAST_STYLE_ITEM
1302 #ifdef HAVE_LCD_BITMAP
1303 rb->lcd_setfont(FONT_UI);
1304 #endif
1305 #ifdef HAVE_LCD_COLOR
1306 rb->lcd_set_background(LCD_BLACK);
1307 rb->lcd_set_foreground(LCD_WHITE);
1308 #endif
1309 if (display_text(ARRAYLEN(help_text), help_text, formation, NULL, true))
1310 return true;
1311 #ifdef HAVE_LCD_BITMAP
1312 rb->lcd_setfont(FONT_SYSFIXED);
1313 #endif
1315 return false;
1318 static int rockblox_menu_cb(int action, const struct menu_item_ex *this_item)
1320 int i = ((intptr_t)this_item);
1321 if(action == ACTION_REQUEST_MENUITEM
1322 && !resume && (i==0 || i==5))
1323 return ACTION_EXIT_MENUITEM;
1324 return action;
1327 static int rockblox_menu(void)
1329 int selected = 0;
1331 MENUITEM_STRINGLIST(main_menu, "Rockblox Menu", rockblox_menu_cb,
1332 "Resume Game", "Start New Game",
1333 "Help", "High Scores", "Playback Control",
1334 "Quit without Saving", "Quit");
1336 rb->button_clear_queue();
1337 while (true) {
1338 switch (rb->do_menu(&main_menu, &selected, NULL, false)) {
1339 case 0:
1340 if(resume_file)
1341 rb->remove(RESUME_FILE);
1342 init_rockblox(true);
1343 return 0;
1344 case 1:
1345 init_rockblox(false);
1346 return 0;
1347 case 2:
1348 if (rockblox_help())
1349 return 1;
1350 break;
1351 case 3:
1352 highscore_show(-1, highscores, NUM_SCORES, true);
1353 break;
1354 case 4:
1355 if (playback_control(NULL))
1356 return 1;
1357 break;
1358 case 5:
1359 return 1;
1360 case 6:
1361 if (resume) {
1362 rb->splash(HZ*1, "Saving game ...");
1363 dump_resume();
1365 return 1;
1366 case MENU_ATTACHED_USB:
1367 return 1;
1368 default:
1369 return 1;
1370 break;
1376 static int rockblox_loop (void)
1378 int button;
1379 #if defined(ROCKBLOX_OFF_PRE) || defined(ROCKBLOX_DROP_PRE)
1380 int lastbutton = BUTTON_NONE;
1381 #endif
1382 long next_down_tick = *rb->current_tick + level_speed(rockblox_status.level);
1384 if (rockblox_menu()) {
1385 return 1;
1387 resume = false;
1388 resume_file = false;
1390 while (1) {
1391 #ifdef HAS_BUTTON_HOLD
1392 if (rb->button_hold ()) {
1393 /* Turn on backlight timeout (revert to settings) */
1394 backlight_use_settings();
1395 rb->splash(0, "Paused");
1396 while (rb->button_hold ())
1397 rb->sleep(HZ/10);
1399 /* Turn off backlight timeout */
1400 backlight_ignore_timeout();
1402 /* get rid of the splash text */
1403 rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1404 show_details ();
1405 #ifdef HIGH_SCORE_Y
1406 show_highscores ();
1407 #endif
1408 draw_next_block ();
1409 refresh_board ();
1411 #endif
1413 button = rb->button_get_w_tmo (MAX(next_down_tick - *rb->current_tick, 1));
1414 switch (button) {
1415 #ifdef ROCKBLOX_RC_OFF
1416 case ROCKBLOX_RC_OFF:
1417 #endif
1418 case ROCKBLOX_OFF:
1419 #ifdef ROCKBLOX_OFF_PRE
1420 if (lastbutton != ROCKBLOX_OFF_PRE)
1421 break;
1422 #endif
1423 resume = true;
1424 return 0;
1425 break;
1427 #if defined(ROCKBLOX_ROTATE)
1428 case ROCKBLOX_ROTATE:
1429 #endif
1430 case ROCKBLOX_ROTATE_CCW:
1431 case ROCKBLOX_ROTATE_CCW | BUTTON_REPEAT:
1432 #ifdef HAVE_SCROLLWHEEL
1433 /* if the wheel is disabled, add an event to the stack. */
1434 if(wheel_enabled == false)
1435 wheel_events++;
1437 /* if it's enabled, go ahead and rotate.. */
1438 if(wheel_enabled)
1439 #endif
1440 #ifdef ROCKBLOX_ROTATE_CCW2
1441 /* fallback */
1442 case ROCKBLOX_ROTATE_CCW2:
1443 #endif
1444 move_block (0, 0, (rockblox_status.co + 1) % figures[rockblox_status.cf].max_or);
1445 break;
1447 case ROCKBLOX_ROTATE_CW:
1448 case ROCKBLOX_ROTATE_CW | BUTTON_REPEAT:
1449 #ifdef HAVE_SCROLLWHEEL
1450 if(wheel_enabled == false)
1451 wheel_events++;
1453 if(wheel_enabled)
1454 #endif
1455 #ifdef ROCKBLOX_ROTATE_CW2
1456 /* fallback */
1457 case ROCKBLOX_ROTATE_CW2:
1458 #endif
1459 move_block (0, 0,
1460 (rockblox_status.co + figures[rockblox_status.cf].max_or -
1461 1) % figures[rockblox_status.cf].max_or);
1462 break;
1464 case ROCKBLOX_DOWN:
1465 case ROCKBLOX_DOWN | BUTTON_REPEAT:
1466 move_block (0, 1, rockblox_status.co);
1467 break;
1469 case ROCKBLOX_RIGHT:
1470 case ROCKBLOX_RIGHT | BUTTON_REPEAT:
1471 move_block (1, 0, rockblox_status.co);
1472 break;
1474 case ROCKBLOX_LEFT:
1475 case ROCKBLOX_LEFT | BUTTON_REPEAT:
1476 move_block (-1, 0, rockblox_status.co);
1477 break;
1479 case ROCKBLOX_DROP:
1480 #ifdef ROCKBLOX_DROP_PRE
1481 if (lastbutton != ROCKBLOX_DROP_PRE)
1482 break;
1483 #endif
1484 while (canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co))
1485 move_block (0, 1, rockblox_status.co);
1486 break;
1487 #ifdef ROCKBLOX_RESTART
1488 case ROCKBLOX_RESTART:
1489 rb->splash (HZ * 1, "Restarting...");
1490 init_rockblox (false);
1491 break;
1492 #endif
1494 default:
1495 if (rb->default_event_handler (button) == SYS_USB_CONNECTED)
1496 return PLUGIN_USB_CONNECTED;
1497 break;
1499 #if defined(ROCKBLOX_OFF_PRE) || defined(ROCKBLOX_DROP_PRE)
1500 if (button != BUTTON_NONE)
1501 lastbutton = button;
1502 #endif
1504 #ifdef HAVE_SCROLLWHEEL
1505 /* check if we should enable the scroll wheel, if events
1506 * begin to stack up... */
1507 if(wheel_enabled == false)
1509 /* stopped rotating the wheel, reset the count */
1510 if(wheel_events == last_wheel_event)
1512 last_wheel_event = 0;
1513 wheel_events = 0;
1515 /* rotated the wheel a while constantly, enable it. */
1516 else if(wheel_events > 3)
1518 wheel_enabled = true;
1521 /* this evens out the last event and the "current" event.
1522 * if we get an event next time through button reading, it will
1523 * remain ahead of last_event. if we don't, they'll end up equaling
1524 * each other.. thus, the scroll count will be reset. */
1525 if(wheel_enabled == false && wheel_events > last_wheel_event)
1526 last_wheel_event++;
1528 #endif
1530 if (TIME_AFTER(*rb->current_tick, next_down_tick)) {
1531 move_down ();
1532 next_down_tick += level_speed(rockblox_status.level);
1533 if (TIME_AFTER(*rb->current_tick, next_down_tick))
1534 /* restart time "raster" when we had to wait longer than usual
1535 * (pause, game restart etc) */
1536 next_down_tick = *rb->current_tick + level_speed(rockblox_status.level);
1539 if (rockblox_status.gameover) {
1540 #if LCD_DEPTH >= 2
1541 rb->lcd_set_foreground (LCD_BLACK);
1542 #endif
1543 show_game_over();
1544 resume = false;
1545 return 0;
1548 refresh_board ();
1551 return 0;
1554 enum plugin_status plugin_start (const void *parameter)
1557 (void) parameter;
1559 rb->srand (*rb->current_tick);
1561 /* Load HighScore if any */
1562 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
1564 #if LCD_DEPTH > 1
1565 rb->lcd_set_backdrop(NULL);
1566 #endif
1568 #ifdef HAVE_LCD_BITMAP
1569 rb->lcd_setfont (FONT_SYSFIXED);
1570 #else
1571 if (!pgfx_init(4, 2))
1573 rb->splash(HZ*2, "Old LCD :(");
1574 return PLUGIN_OK;
1576 #endif
1577 /* Turn off backlight timeout */
1578 backlight_ignore_timeout();
1579 load_game();
1580 resume_file = resume;
1581 while(!rockblox_loop()) {
1582 if(!resume) {
1583 int position = highscore_update(rockblox_status.score,
1584 rockblox_status.level, "",
1585 highscores, NUM_SCORES);
1586 if (position != -1) {
1587 if (position == 0)
1588 rb->splash(HZ*2, "New High Score");
1589 highscore_show(position, highscores, NUM_SCORES, true);
1594 #ifndef HAVE_LCD_BITMAP
1595 pgfx_release();
1596 #endif
1597 /* Save user's HighScore */
1598 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
1599 backlight_use_settings();
1601 return PLUGIN_OK;