core_alloc: Provide a tiny test allocation, which can be freed for debug purposes.
[maemo-rb.git] / apps / plugins / rockblox.c
blob07e9c16b794982eb45f7d975b39df438d9597605
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 #else
373 #error No keymap defined!
374 #endif
376 #ifdef HAVE_TOUCHSCREEN
377 #ifndef ROCKBLOX_OFF
378 #define ROCKBLOX_OFF BUTTON_TOPLEFT
379 #endif
380 #ifdef ROCKBLOX_ROTATE_CCW
381 #define ROCKBLOX_ROTATE_CCW2 BUTTON_BOTTOMLEFT
382 #else
383 #define ROCKBLOX_ROTATE_CCW BUTTON_BOTTOMLEFT
384 #endif
385 #ifdef ROCKBLOX_ROTATE_CW
386 #define ROCKBLOX_ROTATE_CW2 BUTTON_BOTTOMRIGHT
387 #else
388 #define ROCKBLOX_ROTATE_CW BUTTON_BOTTOMRIGHT
389 #define ROCKBLOX_ROTATE_CW2 BUTTON_TOPMIDDLE
390 #endif
391 #ifndef ROCKBLOX_DOWN
392 #define ROCKBLOX_DOWN BUTTON_BOTTOMMIDDLE
393 #endif
394 #ifndef ROCKBLOX_LEFT
395 #define ROCKBLOX_LEFT BUTTON_MIDLEFT
396 #endif
397 #ifndef ROCKBLOX_RIGHT
398 #define ROCKBLOX_RIGHT BUTTON_MIDRIGHT
399 #endif
400 #ifndef ROCKBLOX_DROP
401 #define ROCKBLOX_DROP BUTTON_CENTER
402 #endif
403 #ifndef ROCKBLOX_RESTART
404 #define ROCKBLOX_RESTART BUTTON_TOPRIGHT
405 #endif
406 #endif
408 #define BLOCKS_NUM 7
409 #define EMPTY_BLOCK 7
411 #define BOARD_WIDTH 10
413 #ifdef HAVE_LCD_BITMAP
415 #define BOARD_HEIGHT 20
417 #if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
419 #define BLOCK_WIDTH 24
420 #define BLOCK_HEIGHT 24
421 #define BOARD_X 172
422 #define BOARD_Y 0
423 #define PREVIEW_X 24
424 #define PREVIEW_Y 22
425 #define LABEL_X 482
426 #define SCORE_Y 50
427 #define LEVEL_Y 140
428 #define LINES_Y 210
430 #elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640)
432 #define BLOCK_WIDTH 30
433 #define BLOCK_HEIGHT 30
434 #define BOARD_X 14
435 #define BOARD_Y 2
436 #define PREVIEW_X 342
437 #define PREVIEW_Y 482
438 #define LABEL_X 344
439 #define SCORE_Y 58
440 #define LEVEL_Y 142
441 #define LINES_Y 218
443 #elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
445 #define BLOCK_WIDTH 12
446 #define BLOCK_HEIGHT 12
447 #define BOARD_X 86
448 #define BOARD_Y 0
449 #define PREVIEW_X 12
450 #define PREVIEW_Y 11
451 #define LABEL_X 242
452 #define SCORE_Y 25
453 #define LEVEL_Y 70
454 #define LINES_Y 105
456 #elif (LCD_WIDTH == 240) && ((LCD_HEIGHT == 320) || (LCD_HEIGHT == 400))
458 #define BLOCK_WIDTH 15
459 #define BLOCK_HEIGHT 15
460 #define BOARD_X 7
461 #define BOARD_Y 1
462 #define PREVIEW_X 171
463 #define PREVIEW_Y 241
464 #define LABEL_X 172
465 #define SCORE_Y 29
466 #define LEVEL_Y 71
467 #define LINES_Y 109
468 #define HIGH_LABEL_X 172
469 #define HIGH_SCORE_Y 163
470 #define HIGH_LEVEL_Y 172
472 #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176)
474 #define BLOCK_WIDTH 8
475 #define BLOCK_HEIGHT 8
476 #define BOARD_X 27
477 #define BOARD_Y 5
478 #define PREVIEW_X 158
479 #define PREVIEW_Y 130
480 #define LABEL_X 147
481 #define SCORE_Y 20
482 #define LEVEL_Y 65
483 #define LINES_Y 100
485 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132)
487 #define BLOCK_WIDTH 6
488 #define BLOCK_HEIGHT 6
489 #define BOARD_X 25
490 #define BOARD_Y 1
491 #define PREVIEW_X 126
492 #define PREVIEW_Y 102
493 #define LABEL_X 112
494 #define SCORE_Y 17
495 #define LEVEL_Y 49
496 #define LINES_Y 81
498 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220)
500 /* no room for the space in the highscore list */
501 #define _SPACE ""
503 #define BLOCK_WIDTH 10
504 #define BLOCK_HEIGHT 10
505 #define BOARD_X 6
506 #define BOARD_Y 10
507 #define PREVIEW_X 124
508 #define PREVIEW_Y 174
509 #define LABEL_X 117
510 #define SCORE_Y 18
511 #define LEVEL_Y 52
512 #define LINES_Y 85
513 #define HIGH_SCORE_Y 119
514 #define HIGH_LEVEL_Y 126
515 #define HIGH_LABEL_X 114
517 #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128)
520 #define BLOCK_WIDTH 6
521 #define BLOCK_HEIGHT 6
522 #define BOARD_X 22
523 #define BOARD_Y 3
524 #define PREVIEW_X 114
525 #define PREVIEW_Y 100
526 #define LABEL_X 101
527 #define SCORE_Y 17
528 #define LEVEL_Y 49
529 #define LINES_Y 82
531 #elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110)
533 #define BLOCK_WIDTH 5
534 #define BLOCK_HEIGHT 5
535 #define BOARD_X 14
536 #define BOARD_Y 0
537 #define PREVIEW_X 98
538 #define PREVIEW_Y 88
539 #define LABEL_X 80
540 #define SCORE_Y 15
541 #define LEVEL_Y 45
542 #define LINES_Y 74
544 #elif (LCD_WIDTH == 132) && (LCD_HEIGHT == 80)
546 #define BLOCK_WIDTH 4
547 #define BLOCK_HEIGHT 4
548 #define BOARD_X 10
549 #define BOARD_Y 0
550 #define PREVIEW_X 89
551 #define PREVIEW_Y 61
552 #define LABEL_X 78
553 #define SCORE_Y 10
554 #define LEVEL_Y 30
555 #define LINES_Y 50
557 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 128)
559 #define BLOCK_WIDTH 6
560 #define BLOCK_HEIGHT 6
561 #define BOARD_X 4
562 #define BOARD_Y 3
563 #define PREVIEW_X 84
564 #define PREVIEW_Y 100
565 #define LABEL_X 71
566 #define SCORE_Y 17
567 #define LEVEL_Y 49
568 #define LINES_Y 82
570 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 160)
572 #define BLOCK_WIDTH 7
573 #define BLOCK_HEIGHT 7
574 #define BOARD_X 4
575 #define BOARD_Y 5
576 #define PREVIEW_X 88
577 #define PREVIEW_Y 111
578 #define LABEL_X 82
579 #define SCORE_Y (2+16)
580 #define LEVEL_Y (36+16)
581 #define LINES_Y (70+16)
583 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 96)
585 #define BLOCK_WIDTH 4
586 #define BLOCK_HEIGHT 4
587 #define BOARD_X 14
588 #define BOARD_Y 2
589 #define PREVIEW_X 89
590 #define PREVIEW_Y 76
591 #define LABEL_X 70
592 #define SCORE_Y 14
593 #define LEVEL_Y 39
594 #define LINES_Y 64
596 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64)
598 #define BLOCK_WIDTH 3
599 #define BLOCK_HEIGHT 3
600 #define BOARD_X 9
601 #define BOARD_Y 3
602 #define PREVIEW_X 53
603 #define PREVIEW_Y 5
604 #define LABEL_X 70
605 #define SCORE_Y 32
606 #define LEVEL_Y 13
607 #define LINES_Y 51
609 #elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
611 #define BLOCK_WIDTH 4
612 #define BLOCK_HEIGHT 3
613 #define BOARD_X 9
614 #define BOARD_Y 3
615 #define PREVIEW_X 59
616 #define PREVIEW_Y 5
617 #define LABEL_X 59
618 #define SCORE_Y 32
619 #define LEVEL_Y 13
620 #define LEVEL_X 78
621 #define LINES_Y 51
623 #endif
625 #ifndef LEVEL_X
626 #define LEVEL_X LABEL_X
627 #endif
629 #ifndef LINES_X
630 #define LINES_X LABEL_X
631 #endif
633 extern const fb_data rockblox_background[];
635 #else /* HAVE_LCD_CHARCELLS */
637 #define BOARD_HEIGHT 14
639 #define BLOCK_WIDTH 1
640 #define BLOCK_HEIGHT 1
641 #define BOARD_X 5
642 #define BOARD_Y 0
643 #define PREVIEW_X 15
644 #define PREVIEW_Y 1
646 #endif
648 #ifndef _SPACE
649 #define _SPACE " "
650 #endif
651 /* <<Explanation on Rockblox shapes>>
654 %% - O has 1 orientation
656 %% %
657 %% %% - Z has 2 orientations
660 %% %
661 %% %% - S has 2 orientations
665 % %%%% - I has 2 orientations
668 % %%
669 % % % %%% - L has 4 orientations
670 %% %%% % %
672 % %%
673 % % % %%% - J has 4 orientations
674 %% %%% % %
676 % % %%%
677 %% % %% % - T has 4 orientations
678 % %%% %
681 /* c=current f=figure o=orientation n=next */
682 static struct _rockblox_status
684 int gameover;
685 int lines;
686 int level;
687 int score;
688 int cx;
689 int cy;
690 int cf;
691 int co;
692 int nf;
693 short board[BOARD_HEIGHT][BOARD_WIDTH]; /* 20 rows of 10 blocks */
694 } rockblox_status;
696 /* prototypes */
697 static void draw_next_block(void);
698 static void new_block(void);
700 #ifdef HAVE_SCROLLWHEEL
701 int wheel_events = 0, last_wheel_event = 0;
702 bool wheel_enabled = false;
703 #endif
705 static const short scoring[4] = { /* scoring for each number of lines */
706 #if BOARD_HEIGHT == 20
707 40 /* single */ , 100 /* double */ , 300 /* triple */ , 1200 /* rockblox */
708 #elif BOARD_HEIGHT == 14 /* Player special values */
709 60 /* single */ , 150 /* double */ , 500 /* triple */ , 2000 /* rockblox */
710 #endif
713 struct figure
715 #if LCD_DEPTH >= 2
716 unsigned short color[3]; /* color of figure (light,middle,shadow) */
717 #endif
718 unsigned short max_or; /* max orientations */
719 signed short shapeX[4], shapeY[4]; /* implementation of figures */
722 /* array of figures */
723 figures[BLOCKS_NUM] = {
724 /* O */
726 #if LCD_DEPTH >= 16
727 {LCD_RGBPACK (153, 255, 255), LCD_RGBPACK(0, 255, 255),
728 LCD_RGBPACK(0,153,153)},
729 #elif LCD_DEPTH == 2
730 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
731 #endif
733 {-1, 0, -1, 0},
734 {0, 0, 1, 1}
736 /* I */
738 #if LCD_DEPTH >= 16
739 {LCD_RGBPACK (255, 153, 128), LCD_RGBPACK (255, 0, 0),
740 LCD_RGBPACK (153, 0, 0)},
741 #elif LCD_DEPTH == 2
742 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
743 #endif
745 {-2, -1, 0, 1},
746 {0, 0, 0, 0}
748 /* 'Z' */
750 #if LCD_DEPTH >= 16
751 {LCD_RGBPACK (153, 255, 153), LCD_RGBPACK (0, 255, 0),
752 LCD_RGBPACK (0, 153, 0)},
753 #elif LCD_DEPTH == 2
754 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
755 #endif
757 {0, 1, -1, 0},
758 {0, 0, 1, 1}
760 /* 'S' */
762 #if LCD_DEPTH >= 16
763 {LCD_RGBPACK (153, 153, 255), LCD_RGBPACK (0, 0, 255),
764 LCD_RGBPACK (0, 0, 153)},
765 #elif LCD_DEPTH == 2
766 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
767 #endif
769 {-1, 0, 0, 1},
770 {0, 0, 1, 1}
772 /* 'L' */
774 #if LCD_DEPTH >= 16
775 {LCD_RGBPACK (255, 255, 153), LCD_RGBPACK (255, 255, 0),
776 LCD_RGBPACK (153, 153, 0)},
777 #elif LCD_DEPTH == 2
778 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
779 #endif
781 {-1, 0, 1, 1},
782 {0, 0, 0, 1}
784 /* 'J' */
786 #if LCD_DEPTH >= 16
787 {LCD_RGBPACK (255, 153, 255), LCD_RGBPACK (255, 0, 255),
788 LCD_RGBPACK (153, 0, 153)},
789 #elif LCD_DEPTH == 2
790 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
791 #endif
793 {-1, 0, 1, -1},
794 {0, 0, 0, 1}
796 /* 'T' */
798 #if LCD_DEPTH >= 16
799 {LCD_RGBPACK (204, 204, 204), LCD_RGBPACK (153, 153, 153),
800 LCD_RGBPACK (85, 85, 85)},
801 #elif LCD_DEPTH == 2
802 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
803 #endif
805 {-1, 0, 1, 0},
806 {0, 0, 0, 1}
809 bool resume = false;
810 bool resume_file = false;
812 /* Rockbox File System only supports full filenames inc dir */
813 #define SCORE_FILE PLUGIN_GAMES_DATA_DIR "/rockblox.score"
814 #define RESUME_FILE PLUGIN_GAMES_DATA_DIR "/rockblox.resume"
815 #define NUM_SCORES 5
817 /* Default High Scores... */
818 struct highscore highscores[NUM_SCORES];
820 /* get random number from (0) to (range-1) */
821 static int t_rand (int range)
823 return rb->rand () % range;
826 static inline void show_game_over (void)
828 rb->splash(HZ,"Game over!");
831 /* init the board array to have no blocks */
832 static void init_board (void)
834 int i, j;
835 for (i = 0; i < BOARD_WIDTH; i++)
836 for (j = 0; j < BOARD_HEIGHT; j++)
837 rockblox_status.board[j][i] = EMPTY_BLOCK;
840 /* show the score, level and lines */
841 static void show_details (void)
843 #ifdef HAVE_LCD_BITMAP
844 #if LCD_DEPTH >= 2
845 rb->lcd_set_foreground (LCD_BLACK);
846 rb->lcd_set_background (LCD_WHITE);
847 #endif
848 rb->lcd_putsxyf (LABEL_X, SCORE_Y, "%d", rockblox_status.score);
849 rb->lcd_putsxyf (LEVEL_X, LEVEL_Y, "%d", rockblox_status.level);
850 rb->lcd_putsxyf (LINES_X, LINES_Y, "%d", rockblox_status.lines);
851 #else /* HAVE_LCD_CHARCELLS */
852 rb->lcd_putsf (5, 0, "L%d/%d", rockblox_status.level,
853 rockblox_status.lines);
854 rb->lcd_putsf (5, 1, "S%d", rockblox_status.score);
855 #endif
858 #ifdef HIGH_SCORE_Y
859 static void show_highscores (void)
861 int i;
863 for (i = 0; i<NUM_SCORES; i++)
864 rb->lcd_putsxyf (HIGH_LABEL_X, HIGH_SCORE_Y + (10 * i),
865 "%06d" _SPACE "L%1d", highscores[i].score, highscores[i].level);
867 #endif
869 static void load_game(void)
871 int fd;
873 resume = false;
875 fd = rb->open(RESUME_FILE, O_RDONLY);
876 if (fd < 0) return;
878 if (rb->read(fd, &rockblox_status, sizeof(struct _rockblox_status))
879 < (ssize_t)sizeof(struct _rockblox_status))
881 rb->splash(HZ/2, "Loading Rockblox resume info failed");
882 return;
883 } else {
884 resume = true;
887 rb->close(fd);
889 return;
892 static void dump_resume(void)
894 int fd;
896 fd = rb->open(RESUME_FILE, O_WRONLY|O_CREAT, 0666);
897 if (fd < 0)
898 goto fail;
900 if (rb->write(fd, &rockblox_status, sizeof(struct _rockblox_status))
901 <= 0)
903 rb->close(fd);
904 goto fail;
906 rb->close(fd);
907 return;
909 fail:
910 rb->splash(HZ/2, "Writing Rockblox resume info failed");
911 return;
914 static void init_rockblox (bool resume)
916 char score_name[50];
917 struct tm* tm;
919 tm = rb->get_time();
920 rb->snprintf(score_name, sizeof(score_name), "%04d%02d%02d %02d%02d%02d",
921 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
922 tm->tm_hour, tm->tm_min, tm->tm_sec);
924 #ifdef HAVE_LCD_BITMAP
925 rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
926 #else /* HAVE_LCD_CHARCELLS */
927 pgfx_display (0, 0);
928 pgfx_display_block (3, 0, 3, 1);
929 pgfx_display_block (4, 0, 3, 0);
930 rb->lcd_puts(4, 1, " ");
931 pgfx_clear_display();
932 pgfx_fillrect (3, 0, 2, 14);
933 pgfx_fillrect (15, 7, 2, 7);
934 pgfx_update();
935 #endif
936 if (!resume)
938 rockblox_status.level = 1;
939 rockblox_status.lines = 0;
940 rockblox_status.score = 0;
941 rockblox_status.nf = t_rand(BLOCKS_NUM);
942 init_board ();
943 new_block ();
945 draw_next_block();
947 show_details ();
948 #ifdef HIGH_SCORE_Y
949 show_highscores ();
950 #endif
953 static inline int level_speed(int level)
955 #if BOARD_HEIGHT == 20
956 return (5*HZ) / (level + 9);
957 #elif BOARD_HEIGHT == 14
958 return (7*HZ) / (level + 9);
959 #endif
962 static int getRelativeX (int figure, int square, int orientation)
964 switch (orientation) {
965 case 0:
966 return figures[figure].shapeX[square];
967 case 1:
968 return figures[figure].shapeY[square];
969 case 2:
970 return -figures[figure].shapeX[square];
971 case 3:
972 return -figures[figure].shapeY[square];
973 default:
974 return 0;
978 static int getRelativeY (int figure, int square, int orientation)
980 switch (orientation) {
981 case 0:
982 return figures[figure].shapeY[square];
983 case 1:
984 return -figures[figure].shapeX[square];
985 case 2:
986 return -figures[figure].shapeY[square];
987 case 3:
988 return figures[figure].shapeX[square];
989 default:
990 return 0;
994 /* redraw the while board on the screen */
995 static void refresh_board (void)
997 int i, j, x, y, block;
999 #if LCD_DEPTH >= 2
1000 rb->lcd_set_foreground (LCD_BLACK);
1001 #elif LCD_DEPTH == 1
1002 mylcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID);
1003 #endif
1005 mylcd_fillrect (BOARD_X, BOARD_Y, BOARD_WIDTH * BLOCK_WIDTH,
1006 BOARD_HEIGHT * BLOCK_HEIGHT);
1008 #if LCD_DEPTH == 1
1009 mylcd_set_drawmode (DRMODE_SOLID);
1010 #endif
1012 for (i = 0; i < BOARD_WIDTH; i++)
1013 for (j = 0; j < BOARD_HEIGHT; j++) {
1014 block = rockblox_status.board[j][i];
1015 if (block != EMPTY_BLOCK) {
1016 #ifdef HAVE_LCD_BITMAP
1017 #if LCD_DEPTH >= 2
1018 /* middle drawing */
1019 rb->lcd_set_foreground (figures[block].color[1]);
1020 #endif
1021 rb->lcd_fillrect (BOARD_X + i * BLOCK_WIDTH,
1022 BOARD_Y + j * BLOCK_HEIGHT,
1023 BLOCK_WIDTH, BLOCK_HEIGHT);
1024 #if LCD_DEPTH >= 2
1025 /* light drawing */
1026 rb->lcd_set_foreground (figures[block].color[0]);
1027 #endif
1028 rb->lcd_vline (BOARD_X + i * BLOCK_WIDTH,
1029 BOARD_Y + j * BLOCK_HEIGHT,
1030 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 2);
1031 rb->lcd_hline (BOARD_X + i * BLOCK_WIDTH,
1032 BOARD_X + (i + 1) * BLOCK_WIDTH - 2,
1033 BOARD_Y + j * BLOCK_HEIGHT);
1034 #if LCD_DEPTH >= 2
1035 /* shadow drawing */
1036 rb->lcd_set_foreground (figures[block].color[2]);
1037 #endif
1038 rb->lcd_vline (BOARD_X + (i + 1) * BLOCK_WIDTH - 1,
1039 BOARD_Y + j * BLOCK_HEIGHT + 1,
1040 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 1);
1041 rb->lcd_hline (BOARD_X + i * BLOCK_WIDTH + 1,
1042 BOARD_X + (i + 1) * BLOCK_WIDTH - 1,
1043 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 1);
1044 #else /* HAVE_LCD_CHARCELLS */
1045 pgfx_drawpixel (BOARD_X + i, BOARD_Y + j);
1046 #endif
1050 for (i = 0; i < 4; i++) {
1051 x = getRelativeX (rockblox_status.cf, i, rockblox_status.co)
1052 + rockblox_status.cx;
1053 y = getRelativeY (rockblox_status.cf, i, rockblox_status.co)
1054 + rockblox_status.cy;
1055 #ifdef HAVE_LCD_BITMAP
1056 #if LCD_DEPTH >= 2
1057 /* middle drawing */
1058 rb->lcd_set_foreground (figures[rockblox_status.cf].color[1]);
1059 #endif
1060 rb->lcd_fillrect (BOARD_X + x * BLOCK_WIDTH,
1061 BOARD_Y + y * BLOCK_HEIGHT,
1062 BLOCK_WIDTH, BLOCK_HEIGHT);
1063 #if LCD_DEPTH >= 2
1064 /* light drawing */
1065 rb->lcd_set_foreground (figures[rockblox_status.cf].color[0]);
1066 #endif
1067 rb->lcd_vline (BOARD_X + x * BLOCK_WIDTH, BOARD_Y + y * BLOCK_HEIGHT,
1068 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 2);
1069 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH,
1070 BOARD_X + (x + 1) * BLOCK_WIDTH - 2,
1071 BOARD_Y + y * BLOCK_HEIGHT);
1072 #if LCD_DEPTH >= 2
1073 /* shadow drawing */
1074 rb->lcd_set_foreground (figures[rockblox_status.cf].color[2]);
1075 #endif
1076 rb->lcd_vline (BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1077 BOARD_Y + y * BLOCK_HEIGHT + 1,
1078 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1079 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH + 1,
1080 BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1081 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1082 #else /* HAVE_LCD_CHARCELLS */
1083 pgfx_drawpixel (BOARD_X + x, BOARD_Y + y);
1084 #endif
1086 mylcd_update ();
1089 static bool canMoveTo (int x, int y, int newOrientation)
1091 int i, rx, ry;
1092 for (i = 0; i < 4; i++) {
1093 ry = getRelativeY (rockblox_status.cf, i, newOrientation) + y;
1094 rx = getRelativeX (rockblox_status.cf, i, newOrientation) + x;
1095 if ((rx < 0 || rx >= BOARD_WIDTH) ||
1096 (ry < 0 || ry >= BOARD_HEIGHT) ||
1097 (rockblox_status.board[ry][rx] != EMPTY_BLOCK))
1098 return false;
1100 return true;
1103 /* draws the preview of next block in the preview window */
1104 static void draw_next_block (void)
1106 int i, rx, ry;
1107 /* clear preview window first */
1108 #if LCD_DEPTH >= 2
1109 rb->lcd_set_foreground (LCD_BLACK);
1110 #elif LCD_DEPTH == 1
1111 mylcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID);
1112 #endif
1114 /* 4x4 */
1115 mylcd_fillrect (PREVIEW_X, PREVIEW_Y, BLOCK_WIDTH * 4, BLOCK_HEIGHT * 4);
1117 #if LCD_DEPTH == 1
1118 mylcd_set_drawmode (DRMODE_SOLID);
1119 #endif
1121 /* draw the lightgray rectangles */
1122 #if LCD_DEPTH >= 16
1123 rb->lcd_set_foreground (LCD_RGBPACK (40, 40, 40));
1124 #elif LCD_DEPTH == 2
1125 rb->lcd_set_foreground (LCD_DARKGRAY);
1126 #endif
1128 #if LCD_DEPTH >= 2
1129 for (rx = 0; rx < 4; rx++)
1130 for (ry = 0; ry < 4; ry++)
1131 rb->lcd_drawrect (PREVIEW_X + rx * BLOCK_WIDTH,
1132 PREVIEW_Y + ry * BLOCK_HEIGHT, BLOCK_WIDTH,
1133 BLOCK_HEIGHT);
1134 #endif
1136 /* draw the figure */
1137 for (i = 0; i < 4; i++) {
1138 rx = getRelativeX (rockblox_status.nf, i, 0) + 2;
1139 ry = getRelativeY (rockblox_status.nf, i, 0) + 2;
1140 #ifdef HAVE_LCD_BITMAP
1141 #if LCD_DEPTH >= 2
1142 rb->lcd_set_foreground (figures[rockblox_status.nf].color[1]); /* middle drawing */
1143 #endif
1144 rb->lcd_fillrect (PREVIEW_X + rx * BLOCK_WIDTH,
1145 PREVIEW_Y + ry * BLOCK_HEIGHT,
1146 BLOCK_WIDTH, BLOCK_HEIGHT);
1147 #if LCD_DEPTH >= 2
1148 rb->lcd_set_foreground (figures[rockblox_status.nf].color[0]); /* light drawing */
1149 #endif
1150 rb->lcd_vline (PREVIEW_X + rx * BLOCK_WIDTH,
1151 PREVIEW_Y + ry * BLOCK_HEIGHT,
1152 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 2);
1153 rb->lcd_hline (PREVIEW_X + rx * BLOCK_WIDTH,
1154 PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 2,
1155 PREVIEW_Y + ry * BLOCK_HEIGHT);
1156 #if LCD_DEPTH >= 2
1157 rb->lcd_set_foreground (figures[rockblox_status.nf].color[2]); /* shadow drawing */
1158 #endif
1159 rb->lcd_vline (PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 1,
1160 PREVIEW_Y + ry * BLOCK_HEIGHT + 1,
1161 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 1);
1162 rb->lcd_hline (PREVIEW_X + rx * BLOCK_WIDTH + 1,
1163 PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 1,
1164 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 1);
1165 #else /* HAVE_LCD_CHARCELLS */
1166 pgfx_drawpixel (PREVIEW_X + rx, PREVIEW_Y + ry);
1167 #endif
1172 /* move the block to a relative location */
1173 static void move_block (int x, int y, int o)
1175 if (canMoveTo (rockblox_status.cx + x, rockblox_status.cy + y, o)) {
1176 rockblox_status.cy += y;
1177 rockblox_status.cx += x;
1178 rockblox_status.co = o;
1182 /* try to add a new block to play with (return true if gameover) */
1183 static void new_block (void)
1185 rockblox_status.cy = 1;
1186 rockblox_status.cx = 5;
1187 rockblox_status.cf = rockblox_status.nf;
1188 rockblox_status.co = 0; /* start at the same orientation all time */
1189 rockblox_status.nf = t_rand (BLOCKS_NUM);
1190 rockblox_status.gameover = !canMoveTo (rockblox_status.cx,
1191 rockblox_status.cy, rockblox_status.co);
1193 draw_next_block ();
1197 /* check for filled rockblox_status.lines and do what necessary */
1198 static int check_lines (void)
1201 int i, j, y;
1202 int rockblox = 0;
1204 for (j = 0; j < BOARD_HEIGHT; j++) {
1205 for (i = 0; ((i < BOARD_WIDTH) &&
1206 (rockblox_status.board[j][i] != EMPTY_BLOCK)); i++);
1207 if (i == BOARD_WIDTH) { /* woo hoo, we have a line */
1208 rockblox++;
1209 for (y = j; y > 0; y--)
1211 for (i = 0; i < BOARD_WIDTH; i++)
1212 { /* fall line */
1213 rockblox_status.board[y][i] = rockblox_status.board[y - 1][i];
1219 return rockblox;
1222 /* moves down the figure and returns true if gameover */
1223 static void move_down (void)
1225 int l, i, rx, ry;
1227 if (!canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co)) {
1228 /* save figure to board */
1229 for (i = 0; i < 4; i++) {
1230 rx = getRelativeX (rockblox_status.cf, i, rockblox_status.co) + rockblox_status.cx;
1231 ry = getRelativeY (rockblox_status.cf, i, rockblox_status.co) + rockblox_status.cy;
1232 rockblox_status.board[ry][rx] = rockblox_status.cf;
1234 /* check if formed some lines */
1235 l = check_lines ();
1236 if (l) {
1237 /* the original scoring from "http://en.wikipedia.org/wiki/Rockblox" */
1238 rockblox_status.score += scoring[l - 1] * rockblox_status.level;
1239 rockblox_status.lines += l;
1240 rockblox_status.level = (int) rockblox_status.lines / 10 + 1;
1243 /* show details */
1244 show_details ();
1246 /* generate a new figure */
1247 new_block ();
1248 } else
1249 move_block (0, 1, rockblox_status.co);
1252 static bool rockblox_help(void)
1254 static char *help_text[] = {
1255 "Rockblox", "", "Aim", "",
1256 "Make", "the", "falling", "blocks", "of",
1257 "different", "shapes", "form", "full", "rows.",
1258 "Whenever", "a", "row", "is", "completed,",
1259 "it", "will", "be", "cleared", "away",
1260 "and", "you", "gain", "points."
1262 static struct style_text formation[]={
1263 { 0, TEXT_CENTER|TEXT_UNDERLINE },
1264 { 2, C_RED },
1265 LAST_STYLE_ITEM
1268 #ifdef HAVE_LCD_BITMAP
1269 rb->lcd_setfont(FONT_UI);
1270 #endif
1271 #ifdef HAVE_LCD_COLOR
1272 rb->lcd_set_background(LCD_BLACK);
1273 rb->lcd_set_foreground(LCD_WHITE);
1274 #endif
1275 if (display_text(ARRAYLEN(help_text), help_text, formation, NULL, true))
1276 return true;
1277 #ifdef HAVE_LCD_BITMAP
1278 rb->lcd_setfont(FONT_SYSFIXED);
1279 #endif
1281 return false;
1284 static int rockblox_menu_cb(int action, const struct menu_item_ex *this_item)
1286 int i = ((intptr_t)this_item);
1287 if(action == ACTION_REQUEST_MENUITEM
1288 && !resume && (i==0 || i==5))
1289 return ACTION_EXIT_MENUITEM;
1290 return action;
1293 static int rockblox_menu(void)
1295 int selected = 0;
1297 MENUITEM_STRINGLIST(main_menu, "Rockblox Menu", rockblox_menu_cb,
1298 "Resume Game", "Start New Game",
1299 "Help", "High Scores", "Playback Control",
1300 "Quit without Saving", "Quit");
1302 rb->button_clear_queue();
1303 while (true) {
1304 switch (rb->do_menu(&main_menu, &selected, NULL, false)) {
1305 case 0:
1306 if(resume_file)
1307 rb->remove(RESUME_FILE);
1308 init_rockblox(true);
1309 return 0;
1310 case 1:
1311 init_rockblox(false);
1312 return 0;
1313 case 2:
1314 if (rockblox_help())
1315 return 1;
1316 break;
1317 case 3:
1318 highscore_show(-1, highscores, NUM_SCORES, true);
1319 break;
1320 case 4:
1321 if (playback_control(NULL))
1322 return 1;
1323 break;
1324 case 5:
1325 return 1;
1326 case 6:
1327 if (resume) {
1328 rb->splash(HZ*1, "Saving game ...");
1329 dump_resume();
1331 return 1;
1332 case MENU_ATTACHED_USB:
1333 return 1;
1334 default:
1335 return 1;
1336 break;
1342 static int rockblox_loop (void)
1344 int button;
1345 #if defined(ROCKBLOX_OFF_PRE) || defined(ROCKBLOX_DROP_PRE)
1346 int lastbutton = BUTTON_NONE;
1347 #endif
1348 long next_down_tick = *rb->current_tick + level_speed(rockblox_status.level);
1350 if (rockblox_menu()) {
1351 return 1;
1353 resume = false;
1354 resume_file = false;
1356 while (1) {
1357 #ifdef HAS_BUTTON_HOLD
1358 if (rb->button_hold ()) {
1359 /* Turn on backlight timeout (revert to settings) */
1360 backlight_use_settings();
1361 rb->splash(0, "Paused");
1362 while (rb->button_hold ())
1363 rb->sleep(HZ/10);
1365 /* Turn off backlight timeout */
1366 backlight_ignore_timeout();
1368 /* get rid of the splash text */
1369 rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1370 show_details ();
1371 #ifdef HIGH_SCORE_Y
1372 show_highscores ();
1373 #endif
1374 draw_next_block ();
1375 refresh_board ();
1377 #endif
1379 button = rb->button_get_w_tmo (MAX(next_down_tick - *rb->current_tick, 1));
1380 switch (button) {
1381 #ifdef ROCKBLOX_RC_OFF
1382 case ROCKBLOX_RC_OFF:
1383 #endif
1384 case ROCKBLOX_OFF:
1385 #ifdef ROCKBLOX_OFF_PRE
1386 if (lastbutton != ROCKBLOX_OFF_PRE)
1387 break;
1388 #endif
1389 resume = true;
1390 return 0;
1391 break;
1393 #if defined(ROCKBLOX_ROTATE)
1394 case ROCKBLOX_ROTATE:
1395 #endif
1396 case ROCKBLOX_ROTATE_CCW:
1397 case ROCKBLOX_ROTATE_CCW | BUTTON_REPEAT:
1398 #ifdef HAVE_SCROLLWHEEL
1399 /* if the wheel is disabled, add an event to the stack. */
1400 if(wheel_enabled == false)
1401 wheel_events++;
1403 /* if it's enabled, go ahead and rotate.. */
1404 if(wheel_enabled)
1405 #endif
1406 #ifdef ROCKBLOX_ROTATE_CCW2
1407 /* fallback */
1408 case ROCKBLOX_ROTATE_CCW2:
1409 #endif
1410 move_block (0, 0, (rockblox_status.co + 1) % figures[rockblox_status.cf].max_or);
1411 break;
1413 case ROCKBLOX_ROTATE_CW:
1414 case ROCKBLOX_ROTATE_CW | BUTTON_REPEAT:
1415 #ifdef HAVE_SCROLLWHEEL
1416 if(wheel_enabled == false)
1417 wheel_events++;
1419 if(wheel_enabled)
1420 #endif
1421 #ifdef ROCKBLOX_ROTATE_CW2
1422 /* fallback */
1423 case ROCKBLOX_ROTATE_CW2:
1424 #endif
1425 move_block (0, 0,
1426 (rockblox_status.co + figures[rockblox_status.cf].max_or -
1427 1) % figures[rockblox_status.cf].max_or);
1428 break;
1430 case ROCKBLOX_DOWN:
1431 case ROCKBLOX_DOWN | BUTTON_REPEAT:
1432 move_block (0, 1, rockblox_status.co);
1433 break;
1435 case ROCKBLOX_RIGHT:
1436 case ROCKBLOX_RIGHT | BUTTON_REPEAT:
1437 move_block (1, 0, rockblox_status.co);
1438 break;
1440 case ROCKBLOX_LEFT:
1441 case ROCKBLOX_LEFT | BUTTON_REPEAT:
1442 move_block (-1, 0, rockblox_status.co);
1443 break;
1445 case ROCKBLOX_DROP:
1446 #ifdef ROCKBLOX_DROP_PRE
1447 if (lastbutton != ROCKBLOX_DROP_PRE)
1448 break;
1449 #endif
1450 while (canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co))
1451 move_block (0, 1, rockblox_status.co);
1452 break;
1453 #ifdef ROCKBLOX_RESTART
1454 case ROCKBLOX_RESTART:
1455 rb->splash (HZ * 1, "Restarting...");
1456 init_rockblox (false);
1457 break;
1458 #endif
1460 default:
1461 if (rb->default_event_handler (button) == SYS_USB_CONNECTED)
1462 return PLUGIN_USB_CONNECTED;
1463 break;
1465 #if defined(ROCKBLOX_OFF_PRE) || defined(ROCKBLOX_DROP_PRE)
1466 if (button != BUTTON_NONE)
1467 lastbutton = button;
1468 #endif
1470 #ifdef HAVE_SCROLLWHEEL
1471 /* check if we should enable the scroll wheel, if events
1472 * begin to stack up... */
1473 if(wheel_enabled == false)
1475 /* stopped rotating the wheel, reset the count */
1476 if(wheel_events == last_wheel_event)
1478 last_wheel_event = 0;
1479 wheel_events = 0;
1481 /* rotated the wheel a while constantly, enable it. */
1482 else if(wheel_events > 3)
1484 wheel_enabled = true;
1487 /* this evens out the last event and the "current" event.
1488 * if we get an event next time through button reading, it will
1489 * remain ahead of last_event. if we don't, they'll end up equaling
1490 * each other.. thus, the scroll count will be reset. */
1491 if(wheel_enabled == false && wheel_events > last_wheel_event)
1492 last_wheel_event++;
1494 #endif
1496 if (TIME_AFTER(*rb->current_tick, next_down_tick)) {
1497 move_down ();
1498 next_down_tick += level_speed(rockblox_status.level);
1499 if (TIME_AFTER(*rb->current_tick, next_down_tick))
1500 /* restart time "raster" when we had to wait longer than usual
1501 * (pause, game restart etc) */
1502 next_down_tick = *rb->current_tick + level_speed(rockblox_status.level);
1505 if (rockblox_status.gameover) {
1506 #if LCD_DEPTH >= 2
1507 rb->lcd_set_foreground (LCD_BLACK);
1508 #endif
1509 show_game_over();
1510 resume = false;
1511 return 0;
1514 refresh_board ();
1517 return 0;
1520 enum plugin_status plugin_start (const void *parameter)
1523 (void) parameter;
1525 rb->srand (*rb->current_tick);
1527 /* Load HighScore if any */
1528 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
1530 #if LCD_DEPTH > 1
1531 rb->lcd_set_backdrop(NULL);
1532 #endif
1534 #ifdef HAVE_LCD_BITMAP
1535 rb->lcd_setfont (FONT_SYSFIXED);
1536 #else
1537 if (!pgfx_init(4, 2))
1539 rb->splash(HZ*2, "Old LCD :(");
1540 return PLUGIN_OK;
1542 #endif
1543 /* Turn off backlight timeout */
1544 backlight_ignore_timeout();
1545 load_game();
1546 resume_file = resume;
1547 while(!rockblox_loop()) {
1548 if(!resume) {
1549 int position = highscore_update(rockblox_status.score,
1550 rockblox_status.level, "",
1551 highscores, NUM_SCORES);
1552 if (position != -1) {
1553 if (position == 0)
1554 rb->splash(HZ*2, "New High Score");
1555 highscore_show(position, highscores, NUM_SCORES, true);
1560 #ifndef HAVE_LCD_BITMAP
1561 pgfx_release();
1562 #endif
1563 /* Save user's HighScore */
1564 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
1565 backlight_use_settings();
1567 return PLUGIN_OK;