Prepare new maemo release
[maemo-rb.git] / apps / plugins / rockblox.c
blob6676ace8b14155bdce7ac5729dbfc04802b8a20f
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_MENU|BUTTON_REPEAT)
354 #define ROCKBLOX_ROTATE_CCW BUTTON_UP
355 #define ROCKBLOX_ROTATE_CW BUTTON_DOWN
356 #define ROCKBLOX_DOWN (BUTTON_ENTER | BUTTON_REL)
357 #define ROCKBLOX_LEFT BUTTON_REW
358 #define ROCKBLOX_RIGHT BUTTON_FF
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_BOTTOMRIGHT
365 #define ROCKBLOX_ROTATE_CCW BUTTON_BOTTOMLEFT
366 #define ROCKBLOX_DOWN BUTTON_SELECT
367 #define ROCKBLOX_LEFT BUTTON_LEFT
368 #define ROCKBLOX_RIGHT BUTTON_RIGHT
369 #define ROCKBLOX_DROP_PRE BUTTON_DOWN
370 #define ROCKBLOX_DROP BUTTON_DOWN|BUTTON_REL
371 #define ROCKBLOX_ROTATE_CCW2 BUTTON_VOL_UP
372 #define ROCKBLOX_ROTATE_CW2 BUTTON_VOL_DOWN
374 #elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
375 #define ROCKBLOX_OFF BUTTON_POWER
376 #define ROCKBLOX_ROTATE_CW BUTTON_NEXT
377 #define ROCKBLOX_ROTATE_CCW BUTTON_PREV
378 #define ROCKBLOX_DOWN BUTTON_DOWN
379 #define ROCKBLOX_LEFT BUTTON_LEFT
380 #define ROCKBLOX_RIGHT BUTTON_RIGHT
381 #define ROCKBLOX_DROP BUTTON_SELECT
382 #define ROCKBLOX_RESTART BUTTON_VOL_DOWN
384 #elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
386 #define ROCKBLOX_OFF BUTTON_BACK
387 #define ROCKBLOX_ROTATE_CCW BUTTON_POWER
388 #define ROCKBLOX_ROTATE_CW BUTTON_MENU
389 #define ROCKBLOX_ROTATE BUTTON_UP
390 #define ROCKBLOX_DOWN BUTTON_DOWN
391 #define ROCKBLOX_LEFT BUTTON_LEFT
392 #define ROCKBLOX_RIGHT BUTTON_RIGHT
393 #define ROCKBLOX_DROP BUTTON_SELECT
394 #define ROCKBLOX_RESTART BUTTON_USER
396 #elif CONFIG_KEYPAD == HM60X_PAD
398 #define ROCKBLOX_OFF BUTTON_POWER
399 #define ROCKBLOX_ROTATE_CCW (BUTTON_LEFT|BUTTON_POWER)
400 #define ROCKBLOX_ROTATE_CW (BUTTON_RIGHT|BUTTON_POWER)
401 #define ROCKBLOX_ROTATE BUTTON_UP
402 #define ROCKBLOX_DOWN BUTTON_DOWN
403 #define ROCKBLOX_LEFT BUTTON_LEFT
404 #define ROCKBLOX_RIGHT BUTTON_RIGHT
405 #define ROCKBLOX_DROP BUTTON_SELECT
406 #define ROCKBLOX_RESTART (BUTTON_DOWN|BUTTON_POWER)
408 #elif CONFIG_KEYPAD == HM801_PAD
410 #define ROCKBLOX_OFF BUTTON_POWER
411 #define ROCKBLOX_ROTATE_CCW BUTTON_PREV
412 #define ROCKBLOX_ROTATE_CW BUTTON_NEXT
413 #define ROCKBLOX_ROTATE BUTTON_UP
414 #define ROCKBLOX_DOWN BUTTON_DOWN
415 #define ROCKBLOX_LEFT BUTTON_LEFT
416 #define ROCKBLOX_RIGHT BUTTON_RIGHT
417 #define ROCKBLOX_DROP BUTTON_SELECT
418 #define ROCKBLOX_RESTART BUTTON_PLAY
420 #else
421 #error No keymap defined!
422 #endif
424 #ifdef HAVE_TOUCHSCREEN
425 #ifndef ROCKBLOX_OFF
426 #define ROCKBLOX_OFF BUTTON_TOPLEFT
427 #endif
428 #ifdef ROCKBLOX_ROTATE_CCW
429 #define ROCKBLOX_ROTATE_CCW2 BUTTON_BOTTOMLEFT
430 #else
431 #define ROCKBLOX_ROTATE_CCW BUTTON_BOTTOMLEFT
432 #endif
433 #ifdef ROCKBLOX_ROTATE_CW
434 #define ROCKBLOX_ROTATE_CW2 BUTTON_BOTTOMRIGHT
435 #else
436 #define ROCKBLOX_ROTATE_CW BUTTON_BOTTOMRIGHT
437 #define ROCKBLOX_ROTATE_CW2 BUTTON_TOPMIDDLE
438 #endif
439 #ifndef ROCKBLOX_DOWN
440 #define ROCKBLOX_DOWN BUTTON_BOTTOMMIDDLE
441 #endif
442 #ifndef ROCKBLOX_LEFT
443 #define ROCKBLOX_LEFT BUTTON_MIDLEFT
444 #endif
445 #ifndef ROCKBLOX_RIGHT
446 #define ROCKBLOX_RIGHT BUTTON_MIDRIGHT
447 #endif
448 #ifndef ROCKBLOX_DROP
449 #define ROCKBLOX_DROP BUTTON_CENTER
450 #endif
451 #ifndef ROCKBLOX_RESTART
452 #define ROCKBLOX_RESTART BUTTON_TOPRIGHT
453 #endif
454 #endif
456 #define BLOCKS_NUM 7
457 #define EMPTY_BLOCK 7
459 #define BOARD_WIDTH 10
461 #ifdef HAVE_LCD_BITMAP
463 #define BOARD_HEIGHT 20
465 #if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
467 #define BLOCK_WIDTH 24
468 #define BLOCK_HEIGHT 24
469 #define BOARD_X 172
470 #define BOARD_Y 0
471 #define PREVIEW_X 24
472 #define PREVIEW_Y 22
473 #define LABEL_X 482
474 #define SCORE_Y 50
475 #define LEVEL_Y 140
476 #define LINES_Y 210
478 #elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640)
480 #define BLOCK_WIDTH 30
481 #define BLOCK_HEIGHT 30
482 #define BOARD_X 14
483 #define BOARD_Y 2
484 #define PREVIEW_X 342
485 #define PREVIEW_Y 482
486 #define LABEL_X 344
487 #define SCORE_Y 58
488 #define LEVEL_Y 142
489 #define LINES_Y 218
491 #elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
493 #define BLOCK_WIDTH 12
494 #define BLOCK_HEIGHT 12
495 #define BOARD_X 86
496 #define BOARD_Y 0
497 #define PREVIEW_X 12
498 #define PREVIEW_Y 11
499 #define LABEL_X 242
500 #define SCORE_Y 25
501 #define LEVEL_Y 70
502 #define LINES_Y 105
504 #elif (LCD_WIDTH == 240) && ((LCD_HEIGHT == 320) || (LCD_HEIGHT == 400))
506 #define BLOCK_WIDTH 15
507 #define BLOCK_HEIGHT 15
508 #define BOARD_X 7
509 #define BOARD_Y 1
510 #define PREVIEW_X 171
511 #define PREVIEW_Y 241
512 #define LABEL_X 172
513 #define SCORE_Y 29
514 #define LEVEL_Y 71
515 #define LINES_Y 109
516 #define HIGH_LABEL_X 172
517 #define HIGH_SCORE_Y 163
518 #define HIGH_LEVEL_Y 172
520 #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176)
522 #define BLOCK_WIDTH 8
523 #define BLOCK_HEIGHT 8
524 #define BOARD_X 27
525 #define BOARD_Y 5
526 #define PREVIEW_X 158
527 #define PREVIEW_Y 130
528 #define LABEL_X 147
529 #define SCORE_Y 20
530 #define LEVEL_Y 65
531 #define LINES_Y 100
533 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132)
535 #define BLOCK_WIDTH 6
536 #define BLOCK_HEIGHT 6
537 #define BOARD_X 25
538 #define BOARD_Y 1
539 #define PREVIEW_X 126
540 #define PREVIEW_Y 102
541 #define LABEL_X 112
542 #define SCORE_Y 17
543 #define LEVEL_Y 49
544 #define LINES_Y 81
546 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220)
548 /* no room for the space in the highscore list */
549 #define _SPACE ""
551 #define BLOCK_WIDTH 10
552 #define BLOCK_HEIGHT 10
553 #define BOARD_X 6
554 #define BOARD_Y 10
555 #define PREVIEW_X 124
556 #define PREVIEW_Y 174
557 #define LABEL_X 117
558 #define SCORE_Y 18
559 #define LEVEL_Y 52
560 #define LINES_Y 85
561 #define HIGH_SCORE_Y 119
562 #define HIGH_LEVEL_Y 126
563 #define HIGH_LABEL_X 114
565 #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128)
568 #define BLOCK_WIDTH 6
569 #define BLOCK_HEIGHT 6
570 #define BOARD_X 22
571 #define BOARD_Y 3
572 #define PREVIEW_X 114
573 #define PREVIEW_Y 100
574 #define LABEL_X 101
575 #define SCORE_Y 17
576 #define LEVEL_Y 49
577 #define LINES_Y 82
579 #elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110)
581 #define BLOCK_WIDTH 5
582 #define BLOCK_HEIGHT 5
583 #define BOARD_X 14
584 #define BOARD_Y 0
585 #define PREVIEW_X 98
586 #define PREVIEW_Y 88
587 #define LABEL_X 80
588 #define SCORE_Y 15
589 #define LEVEL_Y 45
590 #define LINES_Y 74
592 #elif (LCD_WIDTH == 132) && (LCD_HEIGHT == 80)
594 #define BLOCK_WIDTH 4
595 #define BLOCK_HEIGHT 4
596 #define BOARD_X 10
597 #define BOARD_Y 0
598 #define PREVIEW_X 89
599 #define PREVIEW_Y 61
600 #define LABEL_X 78
601 #define SCORE_Y 10
602 #define LEVEL_Y 30
603 #define LINES_Y 50
605 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 128)
607 #define BLOCK_WIDTH 6
608 #define BLOCK_HEIGHT 6
609 #define BOARD_X 4
610 #define BOARD_Y 3
611 #define PREVIEW_X 84
612 #define PREVIEW_Y 100
613 #define LABEL_X 71
614 #define SCORE_Y 17
615 #define LEVEL_Y 49
616 #define LINES_Y 82
618 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 160)
620 #define BLOCK_WIDTH 7
621 #define BLOCK_HEIGHT 7
622 #define BOARD_X 4
623 #define BOARD_Y 5
624 #define PREVIEW_X 88
625 #define PREVIEW_Y 111
626 #define LABEL_X 82
627 #define SCORE_Y (2+16)
628 #define LEVEL_Y (36+16)
629 #define LINES_Y (70+16)
631 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 96)
633 #define BLOCK_WIDTH 4
634 #define BLOCK_HEIGHT 4
635 #define BOARD_X 14
636 #define BOARD_Y 2
637 #define PREVIEW_X 89
638 #define PREVIEW_Y 76
639 #define LABEL_X 70
640 #define SCORE_Y 14
641 #define LEVEL_Y 39
642 #define LINES_Y 64
644 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64)
646 #define BLOCK_WIDTH 3
647 #define BLOCK_HEIGHT 3
648 #define BOARD_X 9
649 #define BOARD_Y 3
650 #define PREVIEW_X 53
651 #define PREVIEW_Y 5
652 #define LABEL_X 70
653 #define SCORE_Y 32
654 #define LEVEL_Y 13
655 #define LINES_Y 51
657 #elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
659 #define BLOCK_WIDTH 4
660 #define BLOCK_HEIGHT 3
661 #define BOARD_X 9
662 #define BOARD_Y 3
663 #define PREVIEW_X 59
664 #define PREVIEW_Y 5
665 #define LABEL_X 59
666 #define SCORE_Y 32
667 #define LEVEL_Y 13
668 #define LEVEL_X 78
669 #define LINES_Y 51
671 #elif (LCD_WIDTH == 96) && (LCD_HEIGHT == 96)
673 #define BLOCK_WIDTH 4
674 #define BLOCK_HEIGHT 4
675 #define BOARD_X 5
676 #define BOARD_Y 4
677 #define PREVIEW_X 64
678 #define PREVIEW_Y 76
679 #define LABEL_X 59
680 #define SCORE_Y 15
681 #define SCORE_X 58
682 #define LEVEL_Y 39
683 #define LEVEL_X 58
684 #define LINES_Y 62
685 #define LINES_X 58
686 #endif
688 #ifndef LEVEL_X
689 #define LEVEL_X LABEL_X
690 #endif
692 #ifndef LINES_X
693 #define LINES_X LABEL_X
694 #endif
696 extern const fb_data rockblox_background[];
698 #else /* HAVE_LCD_CHARCELLS */
700 #define BOARD_HEIGHT 14
702 #define BLOCK_WIDTH 1
703 #define BLOCK_HEIGHT 1
704 #define BOARD_X 5
705 #define BOARD_Y 0
706 #define PREVIEW_X 15
707 #define PREVIEW_Y 1
709 #endif
711 #ifndef _SPACE
712 #define _SPACE " "
713 #endif
714 /* <<Explanation on Rockblox shapes>>
717 %% - O has 1 orientation
719 %% %
720 %% %% - Z has 2 orientations
723 %% %
724 %% %% - S has 2 orientations
728 % %%%% - I has 2 orientations
731 % %%
732 % % % %%% - L has 4 orientations
733 %% %%% % %
735 % %%
736 % % % %%% - J has 4 orientations
737 %% %%% % %
739 % % %%%
740 %% % %% % - T has 4 orientations
741 % %%% %
744 /* c=current f=figure o=orientation n=next */
745 static struct _rockblox_status
747 int gameover;
748 int lines;
749 int level;
750 int score;
751 int cx;
752 int cy;
753 int cf;
754 int co;
755 int nf;
756 short board[BOARD_HEIGHT][BOARD_WIDTH]; /* 20 rows of 10 blocks */
757 } rockblox_status;
759 /* prototypes */
760 static void draw_next_block(void);
761 static void new_block(void);
763 #ifdef HAVE_SCROLLWHEEL
764 int wheel_events = 0, last_wheel_event = 0;
765 bool wheel_enabled = false;
766 #endif
768 static const short scoring[4] = { /* scoring for each number of lines */
769 #if BOARD_HEIGHT == 20
770 40 /* single */ , 100 /* double */ , 300 /* triple */ , 1200 /* rockblox */
771 #elif BOARD_HEIGHT == 14 /* Player special values */
772 60 /* single */ , 150 /* double */ , 500 /* triple */ , 2000 /* rockblox */
773 #endif
776 struct figure
778 #if LCD_DEPTH >= 2
779 unsigned short color[3]; /* color of figure (light,middle,shadow) */
780 #endif
781 unsigned short max_or; /* max orientations */
782 signed short shapeX[4], shapeY[4]; /* implementation of figures */
785 /* array of figures */
786 figures[BLOCKS_NUM] = {
787 /* O */
789 #if LCD_DEPTH >= 16
790 {LCD_RGBPACK (153, 255, 255), LCD_RGBPACK(0, 255, 255),
791 LCD_RGBPACK(0,153,153)},
792 #elif LCD_DEPTH == 2
793 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
794 #endif
796 {-1, 0, -1, 0},
797 {0, 0, 1, 1}
799 /* I */
801 #if LCD_DEPTH >= 16
802 {LCD_RGBPACK (255, 153, 128), LCD_RGBPACK (255, 0, 0),
803 LCD_RGBPACK (153, 0, 0)},
804 #elif LCD_DEPTH == 2
805 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
806 #endif
808 {-2, -1, 0, 1},
809 {0, 0, 0, 0}
811 /* 'Z' */
813 #if LCD_DEPTH >= 16
814 {LCD_RGBPACK (153, 255, 153), LCD_RGBPACK (0, 255, 0),
815 LCD_RGBPACK (0, 153, 0)},
816 #elif LCD_DEPTH == 2
817 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
818 #endif
820 {0, 1, -1, 0},
821 {0, 0, 1, 1}
823 /* 'S' */
825 #if LCD_DEPTH >= 16
826 {LCD_RGBPACK (153, 153, 255), LCD_RGBPACK (0, 0, 255),
827 LCD_RGBPACK (0, 0, 153)},
828 #elif LCD_DEPTH == 2
829 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
830 #endif
832 {-1, 0, 0, 1},
833 {0, 0, 1, 1}
835 /* 'L' */
837 #if LCD_DEPTH >= 16
838 {LCD_RGBPACK (255, 255, 153), LCD_RGBPACK (255, 255, 0),
839 LCD_RGBPACK (153, 153, 0)},
840 #elif LCD_DEPTH == 2
841 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
842 #endif
844 {-1, 0, 1, 1},
845 {0, 0, 0, 1}
847 /* 'J' */
849 #if LCD_DEPTH >= 16
850 {LCD_RGBPACK (255, 153, 255), LCD_RGBPACK (255, 0, 255),
851 LCD_RGBPACK (153, 0, 153)},
852 #elif LCD_DEPTH == 2
853 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
854 #endif
856 {-1, 0, 1, -1},
857 {0, 0, 0, 1}
859 /* 'T' */
861 #if LCD_DEPTH >= 16
862 {LCD_RGBPACK (204, 204, 204), LCD_RGBPACK (153, 153, 153),
863 LCD_RGBPACK (85, 85, 85)},
864 #elif LCD_DEPTH == 2
865 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
866 #endif
868 {-1, 0, 1, 0},
869 {0, 0, 0, 1}
872 bool resume = false;
873 bool resume_file = false;
875 /* Rockbox File System only supports full filenames inc dir */
876 #define SCORE_FILE PLUGIN_GAMES_DATA_DIR "/rockblox.score"
877 #define RESUME_FILE PLUGIN_GAMES_DATA_DIR "/rockblox.resume"
878 #define NUM_SCORES 5
880 /* Default High Scores... */
881 struct highscore highscores[NUM_SCORES];
883 /* get random number from (0) to (range-1) */
884 static int t_rand (int range)
886 return rb->rand () % range;
889 static inline void show_game_over (void)
891 rb->splash(HZ,"Game over!");
894 /* init the board array to have no blocks */
895 static void init_board (void)
897 int i, j;
898 for (i = 0; i < BOARD_WIDTH; i++)
899 for (j = 0; j < BOARD_HEIGHT; j++)
900 rockblox_status.board[j][i] = EMPTY_BLOCK;
903 /* show the score, level and lines */
904 static void show_details (void)
906 #ifdef HAVE_LCD_BITMAP
907 #if LCD_DEPTH >= 2
908 rb->lcd_set_foreground (LCD_BLACK);
909 rb->lcd_set_background (LCD_WHITE);
910 #endif
911 rb->lcd_putsxyf (LABEL_X, SCORE_Y, "%d", rockblox_status.score);
912 rb->lcd_putsxyf (LEVEL_X, LEVEL_Y, "%d", rockblox_status.level);
913 rb->lcd_putsxyf (LINES_X, LINES_Y, "%d", rockblox_status.lines);
914 #else /* HAVE_LCD_CHARCELLS */
915 rb->lcd_putsf (5, 0, "L%d/%d", rockblox_status.level,
916 rockblox_status.lines);
917 rb->lcd_putsf (5, 1, "S%d", rockblox_status.score);
918 #endif
921 #ifdef HIGH_SCORE_Y
922 static void show_highscores (void)
924 int i;
926 for (i = 0; i<NUM_SCORES; i++)
927 rb->lcd_putsxyf (HIGH_LABEL_X, HIGH_SCORE_Y + (10 * i),
928 "%06d" _SPACE "L%1d", highscores[i].score, highscores[i].level);
930 #endif
932 static void load_game(void)
934 int fd;
936 resume = false;
938 fd = rb->open(RESUME_FILE, O_RDONLY);
939 if (fd < 0) return;
941 if (rb->read(fd, &rockblox_status, sizeof(struct _rockblox_status))
942 < (ssize_t)sizeof(struct _rockblox_status))
944 rb->splash(HZ/2, "Loading Rockblox resume info failed");
945 } else {
946 resume = true;
949 rb->close(fd);
951 return;
954 static void dump_resume(void)
956 int fd;
958 fd = rb->open(RESUME_FILE, O_WRONLY|O_CREAT, 0666);
959 if (fd < 0)
960 goto fail;
962 if (rb->write(fd, &rockblox_status, sizeof(struct _rockblox_status))
963 <= 0)
965 rb->close(fd);
966 goto fail;
968 rb->close(fd);
969 return;
971 fail:
972 rb->splash(HZ/2, "Writing Rockblox resume info failed");
973 return;
976 static void init_rockblox (bool resume)
978 char score_name[50];
979 struct tm* tm;
981 tm = rb->get_time();
982 rb->snprintf(score_name, sizeof(score_name), "%04d%02d%02d %02d%02d%02d",
983 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
984 tm->tm_hour, tm->tm_min, tm->tm_sec);
986 #ifdef HAVE_LCD_BITMAP
987 rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
988 #else /* HAVE_LCD_CHARCELLS */
989 pgfx_display (0, 0);
990 pgfx_display_block (3, 0, 3, 1);
991 pgfx_display_block (4, 0, 3, 0);
992 rb->lcd_puts(4, 1, " ");
993 pgfx_clear_display();
994 pgfx_fillrect (3, 0, 2, 14);
995 pgfx_fillrect (15, 7, 2, 7);
996 pgfx_update();
997 #endif
998 if (!resume)
1000 rockblox_status.level = 1;
1001 rockblox_status.lines = 0;
1002 rockblox_status.score = 0;
1003 rockblox_status.nf = t_rand(BLOCKS_NUM);
1004 init_board ();
1005 new_block ();
1007 draw_next_block();
1009 show_details ();
1010 #ifdef HIGH_SCORE_Y
1011 show_highscores ();
1012 #endif
1015 static inline int level_speed(int level)
1017 #if BOARD_HEIGHT == 20
1018 return (5*HZ) / (level + 9);
1019 #elif BOARD_HEIGHT == 14
1020 return (7*HZ) / (level + 9);
1021 #endif
1024 static int getRelativeX (int figure, int square, int orientation)
1026 switch (orientation) {
1027 case 0:
1028 return figures[figure].shapeX[square];
1029 case 1:
1030 return figures[figure].shapeY[square];
1031 case 2:
1032 return -figures[figure].shapeX[square];
1033 case 3:
1034 return -figures[figure].shapeY[square];
1035 default:
1036 return 0;
1040 static int getRelativeY (int figure, int square, int orientation)
1042 switch (orientation) {
1043 case 0:
1044 return figures[figure].shapeY[square];
1045 case 1:
1046 return -figures[figure].shapeX[square];
1047 case 2:
1048 return -figures[figure].shapeY[square];
1049 case 3:
1050 return figures[figure].shapeX[square];
1051 default:
1052 return 0;
1056 /* redraw the while board on the screen */
1057 static void refresh_board (void)
1059 int i, j, x, y, block;
1061 #if LCD_DEPTH >= 2
1062 rb->lcd_set_foreground (LCD_BLACK);
1063 #elif LCD_DEPTH == 1
1064 mylcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID);
1065 #endif
1067 mylcd_fillrect (BOARD_X, BOARD_Y, BOARD_WIDTH * BLOCK_WIDTH,
1068 BOARD_HEIGHT * BLOCK_HEIGHT);
1070 #if LCD_DEPTH == 1
1071 mylcd_set_drawmode (DRMODE_SOLID);
1072 #endif
1074 for (i = 0; i < BOARD_WIDTH; i++)
1075 for (j = 0; j < BOARD_HEIGHT; j++) {
1076 block = rockblox_status.board[j][i];
1077 if (block != EMPTY_BLOCK) {
1078 #ifdef HAVE_LCD_BITMAP
1079 #if LCD_DEPTH >= 2
1080 /* middle drawing */
1081 rb->lcd_set_foreground (figures[block].color[1]);
1082 #endif
1083 rb->lcd_fillrect (BOARD_X + i * BLOCK_WIDTH,
1084 BOARD_Y + j * BLOCK_HEIGHT,
1085 BLOCK_WIDTH, BLOCK_HEIGHT);
1086 #if LCD_DEPTH >= 2
1087 /* light drawing */
1088 rb->lcd_set_foreground (figures[block].color[0]);
1089 #endif
1090 rb->lcd_vline (BOARD_X + i * BLOCK_WIDTH,
1091 BOARD_Y + j * BLOCK_HEIGHT,
1092 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 2);
1093 rb->lcd_hline (BOARD_X + i * BLOCK_WIDTH,
1094 BOARD_X + (i + 1) * BLOCK_WIDTH - 2,
1095 BOARD_Y + j * BLOCK_HEIGHT);
1096 #if LCD_DEPTH >= 2
1097 /* shadow drawing */
1098 rb->lcd_set_foreground (figures[block].color[2]);
1099 #endif
1100 rb->lcd_vline (BOARD_X + (i + 1) * BLOCK_WIDTH - 1,
1101 BOARD_Y + j * BLOCK_HEIGHT + 1,
1102 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 1);
1103 rb->lcd_hline (BOARD_X + i * BLOCK_WIDTH + 1,
1104 BOARD_X + (i + 1) * BLOCK_WIDTH - 1,
1105 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 1);
1106 #else /* HAVE_LCD_CHARCELLS */
1107 pgfx_drawpixel (BOARD_X + i, BOARD_Y + j);
1108 #endif
1112 for (i = 0; i < 4; i++) {
1113 x = getRelativeX (rockblox_status.cf, i, rockblox_status.co)
1114 + rockblox_status.cx;
1115 y = getRelativeY (rockblox_status.cf, i, rockblox_status.co)
1116 + rockblox_status.cy;
1117 #ifdef HAVE_LCD_BITMAP
1118 #if LCD_DEPTH >= 2
1119 /* middle drawing */
1120 rb->lcd_set_foreground (figures[rockblox_status.cf].color[1]);
1121 #endif
1122 rb->lcd_fillrect (BOARD_X + x * BLOCK_WIDTH,
1123 BOARD_Y + y * BLOCK_HEIGHT,
1124 BLOCK_WIDTH, BLOCK_HEIGHT);
1125 #if LCD_DEPTH >= 2
1126 /* light drawing */
1127 rb->lcd_set_foreground (figures[rockblox_status.cf].color[0]);
1128 #endif
1129 rb->lcd_vline (BOARD_X + x * BLOCK_WIDTH, BOARD_Y + y * BLOCK_HEIGHT,
1130 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 2);
1131 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH,
1132 BOARD_X + (x + 1) * BLOCK_WIDTH - 2,
1133 BOARD_Y + y * BLOCK_HEIGHT);
1134 #if LCD_DEPTH >= 2
1135 /* shadow drawing */
1136 rb->lcd_set_foreground (figures[rockblox_status.cf].color[2]);
1137 #endif
1138 rb->lcd_vline (BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1139 BOARD_Y + y * BLOCK_HEIGHT + 1,
1140 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1141 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH + 1,
1142 BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1143 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1144 #else /* HAVE_LCD_CHARCELLS */
1145 pgfx_drawpixel (BOARD_X + x, BOARD_Y + y);
1146 #endif
1148 mylcd_update ();
1151 static bool canMoveTo (int x, int y, int newOrientation)
1153 int i, rx, ry;
1154 for (i = 0; i < 4; i++) {
1155 ry = getRelativeY (rockblox_status.cf, i, newOrientation) + y;
1156 rx = getRelativeX (rockblox_status.cf, i, newOrientation) + x;
1157 if ((rx < 0 || rx >= BOARD_WIDTH) ||
1158 (ry < 0 || ry >= BOARD_HEIGHT) ||
1159 (rockblox_status.board[ry][rx] != EMPTY_BLOCK))
1160 return false;
1162 return true;
1165 /* draws the preview of next block in the preview window */
1166 static void draw_next_block (void)
1168 int i, rx, ry;
1169 /* clear preview window first */
1170 #if LCD_DEPTH >= 2
1171 rb->lcd_set_foreground (LCD_BLACK);
1172 #elif LCD_DEPTH == 1
1173 mylcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID);
1174 #endif
1176 /* 4x4 */
1177 mylcd_fillrect (PREVIEW_X, PREVIEW_Y, BLOCK_WIDTH * 4, BLOCK_HEIGHT * 4);
1179 #if LCD_DEPTH == 1
1180 mylcd_set_drawmode (DRMODE_SOLID);
1181 #endif
1183 /* draw the lightgray rectangles */
1184 #if LCD_DEPTH >= 16
1185 rb->lcd_set_foreground (LCD_RGBPACK (40, 40, 40));
1186 #elif LCD_DEPTH == 2
1187 rb->lcd_set_foreground (LCD_DARKGRAY);
1188 #endif
1190 #if LCD_DEPTH >= 2
1191 for (rx = 0; rx < 4; rx++)
1192 for (ry = 0; ry < 4; ry++)
1193 rb->lcd_drawrect (PREVIEW_X + rx * BLOCK_WIDTH,
1194 PREVIEW_Y + ry * BLOCK_HEIGHT, BLOCK_WIDTH,
1195 BLOCK_HEIGHT);
1196 #endif
1198 /* draw the figure */
1199 for (i = 0; i < 4; i++) {
1200 rx = getRelativeX (rockblox_status.nf, i, 0) + 2;
1201 ry = getRelativeY (rockblox_status.nf, i, 0) + 2;
1202 #ifdef HAVE_LCD_BITMAP
1203 #if LCD_DEPTH >= 2
1204 rb->lcd_set_foreground (figures[rockblox_status.nf].color[1]); /* middle drawing */
1205 #endif
1206 rb->lcd_fillrect (PREVIEW_X + rx * BLOCK_WIDTH,
1207 PREVIEW_Y + ry * BLOCK_HEIGHT,
1208 BLOCK_WIDTH, BLOCK_HEIGHT);
1209 #if LCD_DEPTH >= 2
1210 rb->lcd_set_foreground (figures[rockblox_status.nf].color[0]); /* light drawing */
1211 #endif
1212 rb->lcd_vline (PREVIEW_X + rx * BLOCK_WIDTH,
1213 PREVIEW_Y + ry * BLOCK_HEIGHT,
1214 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 2);
1215 rb->lcd_hline (PREVIEW_X + rx * BLOCK_WIDTH,
1216 PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 2,
1217 PREVIEW_Y + ry * BLOCK_HEIGHT);
1218 #if LCD_DEPTH >= 2
1219 rb->lcd_set_foreground (figures[rockblox_status.nf].color[2]); /* shadow drawing */
1220 #endif
1221 rb->lcd_vline (PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 1,
1222 PREVIEW_Y + ry * BLOCK_HEIGHT + 1,
1223 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 1);
1224 rb->lcd_hline (PREVIEW_X + rx * BLOCK_WIDTH + 1,
1225 PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 1,
1226 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 1);
1227 #else /* HAVE_LCD_CHARCELLS */
1228 pgfx_drawpixel (PREVIEW_X + rx, PREVIEW_Y + ry);
1229 #endif
1234 /* move the block to a relative location */
1235 static void move_block (int x, int y, int o)
1237 if (canMoveTo (rockblox_status.cx + x, rockblox_status.cy + y, o)) {
1238 rockblox_status.cy += y;
1239 rockblox_status.cx += x;
1240 rockblox_status.co = o;
1244 /* try to add a new block to play with (return true if gameover) */
1245 static void new_block (void)
1247 rockblox_status.cy = 1;
1248 rockblox_status.cx = 5;
1249 rockblox_status.cf = rockblox_status.nf;
1250 rockblox_status.co = 0; /* start at the same orientation all time */
1251 rockblox_status.nf = t_rand (BLOCKS_NUM);
1252 rockblox_status.gameover = !canMoveTo (rockblox_status.cx,
1253 rockblox_status.cy, rockblox_status.co);
1255 draw_next_block ();
1259 /* check for filled rockblox_status.lines and do what necessary */
1260 static int check_lines (void)
1263 int i, j, y;
1264 int rockblox = 0;
1266 for (j = 0; j < BOARD_HEIGHT; j++) {
1267 for (i = 0; ((i < BOARD_WIDTH) &&
1268 (rockblox_status.board[j][i] != EMPTY_BLOCK)); i++);
1269 if (i == BOARD_WIDTH) { /* woo hoo, we have a line */
1270 rockblox++;
1271 for (y = j; y > 0; y--)
1273 for (i = 0; i < BOARD_WIDTH; i++)
1274 { /* fall line */
1275 rockblox_status.board[y][i] = rockblox_status.board[y - 1][i];
1281 return rockblox;
1284 /* moves down the figure and returns true if gameover */
1285 static void move_down (void)
1287 int l, i, rx, ry;
1289 if (!canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co)) {
1290 /* save figure to board */
1291 for (i = 0; i < 4; i++) {
1292 rx = getRelativeX (rockblox_status.cf, i, rockblox_status.co) + rockblox_status.cx;
1293 ry = getRelativeY (rockblox_status.cf, i, rockblox_status.co) + rockblox_status.cy;
1294 rockblox_status.board[ry][rx] = rockblox_status.cf;
1296 /* check if formed some lines */
1297 l = check_lines ();
1298 if (l) {
1299 /* the original scoring from "http://en.wikipedia.org/wiki/Rockblox" */
1300 rockblox_status.score += scoring[l - 1] * rockblox_status.level;
1301 rockblox_status.lines += l;
1302 rockblox_status.level = (int) rockblox_status.lines / 10 + 1;
1305 /* show details */
1306 show_details ();
1308 /* generate a new figure */
1309 new_block ();
1310 } else
1311 move_block (0, 1, rockblox_status.co);
1314 static bool rockblox_help(void)
1316 static char *help_text[] = {
1317 "Rockblox", "", "Aim", "",
1318 "Make", "the", "falling", "blocks", "of",
1319 "different", "shapes", "form", "full", "rows.",
1320 "Whenever", "a", "row", "is", "completed,",
1321 "it", "will", "be", "cleared", "away",
1322 "and", "you", "gain", "points."
1324 static struct style_text formation[]={
1325 { 0, TEXT_CENTER|TEXT_UNDERLINE },
1326 { 2, C_RED },
1327 LAST_STYLE_ITEM
1330 #ifdef HAVE_LCD_BITMAP
1331 rb->lcd_setfont(FONT_UI);
1332 #endif
1333 #ifdef HAVE_LCD_COLOR
1334 rb->lcd_set_background(LCD_BLACK);
1335 rb->lcd_set_foreground(LCD_WHITE);
1336 #endif
1337 if (display_text(ARRAYLEN(help_text), help_text, formation, NULL, true))
1338 return true;
1339 #ifdef HAVE_LCD_BITMAP
1340 rb->lcd_setfont(FONT_SYSFIXED);
1341 #endif
1343 return false;
1346 static int rockblox_menu_cb(int action, const struct menu_item_ex *this_item)
1348 int i = ((intptr_t)this_item);
1349 if(action == ACTION_REQUEST_MENUITEM
1350 && !resume && (i==0 || i==5))
1351 return ACTION_EXIT_MENUITEM;
1352 return action;
1355 static int rockblox_menu(void)
1357 int selected = 0;
1359 MENUITEM_STRINGLIST(main_menu, "Rockblox Menu", rockblox_menu_cb,
1360 "Resume Game", "Start New Game",
1361 "Help", "High Scores", "Playback Control",
1362 "Quit without Saving", "Quit");
1364 rb->button_clear_queue();
1365 while (true) {
1366 switch (rb->do_menu(&main_menu, &selected, NULL, false)) {
1367 case 0:
1368 if(resume_file)
1369 rb->remove(RESUME_FILE);
1370 init_rockblox(true);
1371 return 0;
1372 case 1:
1373 init_rockblox(false);
1374 return 0;
1375 case 2:
1376 if (rockblox_help())
1377 return 1;
1378 break;
1379 case 3:
1380 highscore_show(-1, highscores, NUM_SCORES, true);
1381 break;
1382 case 4:
1383 if (playback_control(NULL))
1384 return 1;
1385 break;
1386 case 5:
1387 return 1;
1388 case 6:
1389 if (resume) {
1390 rb->splash(HZ*1, "Saving game ...");
1391 dump_resume();
1393 return 1;
1394 case MENU_ATTACHED_USB:
1395 return 1;
1396 default:
1397 return 1;
1398 break;
1404 static int rockblox_loop (void)
1406 int button;
1407 #if defined(ROCKBLOX_OFF_PRE) || defined(ROCKBLOX_DROP_PRE)
1408 int lastbutton = BUTTON_NONE;
1409 #endif
1410 long next_down_tick = *rb->current_tick + level_speed(rockblox_status.level);
1412 if (rockblox_menu()) {
1413 return 1;
1415 resume = false;
1416 resume_file = false;
1418 while (1) {
1419 #ifdef HAS_BUTTON_HOLD
1420 if (rb->button_hold ()) {
1421 /* Turn on backlight timeout (revert to settings) */
1422 backlight_use_settings();
1423 rb->splash(0, "Paused");
1424 while (rb->button_hold ())
1425 rb->sleep(HZ/10);
1427 /* Turn off backlight timeout */
1428 backlight_ignore_timeout();
1430 /* get rid of the splash text */
1431 rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1432 show_details ();
1433 #ifdef HIGH_SCORE_Y
1434 show_highscores ();
1435 #endif
1436 draw_next_block ();
1437 refresh_board ();
1439 #endif
1441 button = rb->button_get_w_tmo (MAX(next_down_tick - *rb->current_tick, 1));
1442 switch (button) {
1443 #ifdef ROCKBLOX_RC_OFF
1444 case ROCKBLOX_RC_OFF:
1445 #endif
1446 case ROCKBLOX_OFF:
1447 #ifdef ROCKBLOX_OFF_PRE
1448 if (lastbutton != ROCKBLOX_OFF_PRE)
1449 break;
1450 #endif
1451 resume = true;
1452 return 0;
1453 break;
1455 #if defined(ROCKBLOX_ROTATE)
1456 case ROCKBLOX_ROTATE:
1457 #endif
1458 case ROCKBLOX_ROTATE_CCW:
1459 case ROCKBLOX_ROTATE_CCW | BUTTON_REPEAT:
1460 #ifdef HAVE_SCROLLWHEEL
1461 /* if the wheel is disabled, add an event to the stack. */
1462 if(wheel_enabled == false)
1463 wheel_events++;
1465 /* if it's enabled, go ahead and rotate.. */
1466 if(wheel_enabled)
1467 #endif
1468 #ifdef ROCKBLOX_ROTATE_CCW2
1469 /* fallback */
1470 case ROCKBLOX_ROTATE_CCW2:
1471 #endif
1472 move_block (0, 0, (rockblox_status.co + 1) % figures[rockblox_status.cf].max_or);
1473 break;
1475 case ROCKBLOX_ROTATE_CW:
1476 case ROCKBLOX_ROTATE_CW | BUTTON_REPEAT:
1477 #ifdef HAVE_SCROLLWHEEL
1478 if(wheel_enabled == false)
1479 wheel_events++;
1481 if(wheel_enabled)
1482 #endif
1483 #ifdef ROCKBLOX_ROTATE_CW2
1484 /* fallback */
1485 case ROCKBLOX_ROTATE_CW2:
1486 #endif
1487 move_block (0, 0,
1488 (rockblox_status.co + figures[rockblox_status.cf].max_or -
1489 1) % figures[rockblox_status.cf].max_or);
1490 break;
1492 case ROCKBLOX_DOWN:
1493 case ROCKBLOX_DOWN | BUTTON_REPEAT:
1494 move_block (0, 1, rockblox_status.co);
1495 break;
1497 case ROCKBLOX_RIGHT:
1498 case ROCKBLOX_RIGHT | BUTTON_REPEAT:
1499 move_block (1, 0, rockblox_status.co);
1500 break;
1502 case ROCKBLOX_LEFT:
1503 case ROCKBLOX_LEFT | BUTTON_REPEAT:
1504 move_block (-1, 0, rockblox_status.co);
1505 break;
1507 case ROCKBLOX_DROP:
1508 #ifdef ROCKBLOX_DROP_PRE
1509 if (lastbutton != ROCKBLOX_DROP_PRE)
1510 break;
1511 #endif
1512 while (canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co))
1513 move_block (0, 1, rockblox_status.co);
1514 break;
1515 #ifdef ROCKBLOX_RESTART
1516 case ROCKBLOX_RESTART:
1517 rb->splash (HZ * 1, "Restarting...");
1518 init_rockblox (false);
1519 break;
1520 #endif
1522 default:
1523 if (rb->default_event_handler (button) == SYS_USB_CONNECTED)
1524 return PLUGIN_USB_CONNECTED;
1525 break;
1527 #if defined(ROCKBLOX_OFF_PRE) || defined(ROCKBLOX_DROP_PRE)
1528 if (button != BUTTON_NONE)
1529 lastbutton = button;
1530 #endif
1532 #ifdef HAVE_SCROLLWHEEL
1533 /* check if we should enable the scroll wheel, if events
1534 * begin to stack up... */
1535 if(wheel_enabled == false)
1537 /* stopped rotating the wheel, reset the count */
1538 if(wheel_events == last_wheel_event)
1540 last_wheel_event = 0;
1541 wheel_events = 0;
1543 /* rotated the wheel a while constantly, enable it. */
1544 else if(wheel_events > 3)
1546 wheel_enabled = true;
1549 /* this evens out the last event and the "current" event.
1550 * if we get an event next time through button reading, it will
1551 * remain ahead of last_event. if we don't, they'll end up equaling
1552 * each other.. thus, the scroll count will be reset. */
1553 if(wheel_enabled == false && wheel_events > last_wheel_event)
1554 last_wheel_event++;
1556 #endif
1558 if (TIME_AFTER(*rb->current_tick, next_down_tick)) {
1559 move_down ();
1560 next_down_tick += level_speed(rockblox_status.level);
1561 if (TIME_AFTER(*rb->current_tick, next_down_tick))
1562 /* restart time "raster" when we had to wait longer than usual
1563 * (pause, game restart etc) */
1564 next_down_tick = *rb->current_tick + level_speed(rockblox_status.level);
1567 if (rockblox_status.gameover) {
1568 #if LCD_DEPTH >= 2
1569 rb->lcd_set_foreground (LCD_BLACK);
1570 #endif
1571 show_game_over();
1572 resume = false;
1573 return 0;
1576 refresh_board ();
1579 return 0;
1582 enum plugin_status plugin_start (const void *parameter)
1585 (void) parameter;
1587 rb->srand (*rb->current_tick);
1589 /* Load HighScore if any */
1590 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
1592 #if LCD_DEPTH > 1
1593 rb->lcd_set_backdrop(NULL);
1594 #endif
1596 #ifdef HAVE_LCD_BITMAP
1597 rb->lcd_setfont (FONT_SYSFIXED);
1598 #else
1599 if (!pgfx_init(4, 2))
1601 rb->splash(HZ*2, "Old LCD :(");
1602 return PLUGIN_OK;
1604 #endif
1605 /* Turn off backlight timeout */
1606 backlight_ignore_timeout();
1607 load_game();
1608 resume_file = resume;
1609 while(!rockblox_loop()) {
1610 if(!resume) {
1611 int position = highscore_update(rockblox_status.score,
1612 rockblox_status.level, "",
1613 highscores, NUM_SCORES);
1614 if (position != -1) {
1615 if (position == 0)
1616 rb->splash(HZ*2, "New High Score");
1617 highscore_show(position, highscores, NUM_SCORES, true);
1622 #ifndef HAVE_LCD_BITMAP
1623 pgfx_release();
1624 #endif
1625 /* Save user's HighScore */
1626 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
1627 backlight_use_settings();
1629 return PLUGIN_OK;