Packard Bell Vibe 500: Start committing plugin keymaps.
[kugel-rb.git] / apps / plugins / rockblox.c
bloba3d644e583604cd969a9c02e9f0acd5d8629cc7a
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"
30 PLUGIN_HEADER
32 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
33 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
34 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
36 #define ROCKBLOX_OFF (BUTTON_MENU | BUTTON_SELECT)
37 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_BACK
38 #define ROCKBLOX_ROTATE_RIGHT2 (BUTTON_MENU | BUTTON_REL)
39 #define ROCKBLOX_ROTATE_LEFT BUTTON_SCROLL_FWD
40 #define ROCKBLOX_LEFT BUTTON_LEFT
41 #define ROCKBLOX_RIGHT BUTTON_RIGHT
42 #define ROCKBLOX_DOWN BUTTON_PLAY
43 #define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_PLAY)
44 #define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
46 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
47 (CONFIG_KEYPAD == IRIVER_H300_PAD)
49 #define ROCKBLOX_OFF BUTTON_OFF
50 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
51 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
52 #define ROCKBLOX_DOWN BUTTON_DOWN
53 #define ROCKBLOX_LEFT BUTTON_LEFT
54 #define ROCKBLOX_RIGHT BUTTON_RIGHT
55 #define ROCKBLOX_DROP BUTTON_MODE
56 #define ROCKBLOX_RESTART BUTTON_ON
58 #define ROCKBLOX_RC_OFF BUTTON_RC_STOP
60 #elif CONFIG_KEYPAD == RECORDER_PAD
62 #define ROCKBLOX_OFF BUTTON_OFF
63 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
64 #define ROCKBLOX_ROTATE_LEFT BUTTON_PLAY
65 #define ROCKBLOX_DOWN BUTTON_DOWN
66 #define ROCKBLOX_LEFT BUTTON_LEFT
67 #define ROCKBLOX_RIGHT BUTTON_RIGHT
68 #define ROCKBLOX_DROP BUTTON_ON
69 #define ROCKBLOX_RESTART BUTTON_F1
71 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
73 #define ROCKBLOX_OFF BUTTON_OFF
74 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
75 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
76 #define ROCKBLOX_DOWN BUTTON_DOWN
77 #define ROCKBLOX_LEFT BUTTON_LEFT
78 #define ROCKBLOX_RIGHT BUTTON_RIGHT
79 #define ROCKBLOX_DROP BUTTON_ON
80 #define ROCKBLOX_RESTART BUTTON_F1
82 #elif CONFIG_KEYPAD == PLAYER_PAD
84 #define ROCKBLOX_OFF_PRE BUTTON_STOP
85 #define ROCKBLOX_OFF (BUTTON_STOP|BUTTON_REL)
86 #define ROCKBLOX_ROTATE_RIGHT BUTTON_PLAY
87 #define ROCKBLOX_ROTATE_LEFT (BUTTON_ON|BUTTON_PLAY)
88 #define ROCKBLOX_DOWN BUTTON_MENU
89 #define ROCKBLOX_LEFT BUTTON_LEFT
90 #define ROCKBLOX_RIGHT BUTTON_RIGHT
91 #define ROCKBLOX_DROP_PRE BUTTON_ON
92 #define ROCKBLOX_DROP (BUTTON_ON|BUTTON_REL)
93 #define ROCKBLOX_RESTART (BUTTON_STOP|BUTTON_MENU)
95 #elif CONFIG_KEYPAD == ONDIO_PAD
97 #define ROCKBLOX_OFF_PRE BUTTON_OFF
98 #define ROCKBLOX_OFF (BUTTON_OFF|BUTTON_REL)
99 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
100 #define ROCKBLOX_ROTATE_LEFT (BUTTON_MENU|BUTTON_UP)
101 #define ROCKBLOX_DOWN BUTTON_DOWN
102 #define ROCKBLOX_LEFT BUTTON_LEFT
103 #define ROCKBLOX_RIGHT BUTTON_RIGHT
104 #define ROCKBLOX_DROP_PRE BUTTON_MENU
105 #define ROCKBLOX_DROP (BUTTON_MENU|BUTTON_REL)
106 #define ROCKBLOX_RESTART (BUTTON_OFF|BUTTON_MENU)
108 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
110 #define ROCKBLOX_OFF BUTTON_POWER
111 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
112 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
113 #define ROCKBLOX_DOWN BUTTON_DOWN
114 #define ROCKBLOX_LEFT BUTTON_LEFT
115 #define ROCKBLOX_RIGHT BUTTON_RIGHT
116 #define ROCKBLOX_DROP BUTTON_REC
117 #define ROCKBLOX_RESTART BUTTON_PLAY
119 #elif CONFIG_KEYPAD == SANSA_E200_PAD
121 #define ROCKBLOX_OFF BUTTON_POWER
122 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_BACK
123 #define ROCKBLOX_ROTATE_RIGHT2 BUTTON_UP
124 #define ROCKBLOX_ROTATE_LEFT BUTTON_SCROLL_FWD
125 #define ROCKBLOX_DOWN BUTTON_DOWN
126 #define ROCKBLOX_LEFT BUTTON_LEFT
127 #define ROCKBLOX_RIGHT BUTTON_RIGHT
128 #define ROCKBLOX_DROP BUTTON_SELECT
129 #define ROCKBLOX_RESTART BUTTON_REC
131 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
133 #define ROCKBLOX_OFF (BUTTON_HOME|BUTTON_REPEAT)
134 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_BACK
135 #define ROCKBLOX_ROTATE_RIGHT2 BUTTON_UP
136 #define ROCKBLOX_ROTATE_LEFT BUTTON_SCROLL_FWD
137 #define ROCKBLOX_DOWN BUTTON_DOWN
138 #define ROCKBLOX_LEFT BUTTON_LEFT
139 #define ROCKBLOX_RIGHT BUTTON_RIGHT
140 #define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
141 #define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_UP)
144 #elif CONFIG_KEYPAD == SANSA_C200_PAD
146 #define ROCKBLOX_OFF BUTTON_POWER
147 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
148 #define ROCKBLOX_ROTATE_RIGHT2 BUTTON_VOL_DOWN
149 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
150 #define ROCKBLOX_DOWN BUTTON_DOWN
151 #define ROCKBLOX_LEFT BUTTON_LEFT
152 #define ROCKBLOX_RIGHT BUTTON_RIGHT
153 #define ROCKBLOX_DROP BUTTON_SELECT
154 #define ROCKBLOX_RESTART BUTTON_REC
156 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
158 #define ROCKBLOX_OFF BUTTON_POWER
159 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
160 #define ROCKBLOX_ROTATE_RIGHT2 BUTTON_VOL_DOWN
161 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
162 #define ROCKBLOX_DOWN BUTTON_DOWN
163 #define ROCKBLOX_LEFT BUTTON_LEFT
164 #define ROCKBLOX_RIGHT BUTTON_RIGHT
165 #define ROCKBLOX_DROP BUTTON_SELECT
166 #define ROCKBLOX_RESTART BUTTON_HOME
168 #elif CONFIG_KEYPAD == SANSA_M200_PAD
170 #define ROCKBLOX_OFF BUTTON_POWER
171 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
172 #define ROCKBLOX_ROTATE_RIGHT2 BUTTON_VOL_DOWN
173 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
174 #define ROCKBLOX_DOWN BUTTON_DOWN
175 #define ROCKBLOX_LEFT BUTTON_LEFT
176 #define ROCKBLOX_RIGHT BUTTON_RIGHT
177 #define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_UP)
178 #define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
180 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
182 #define ROCKBLOX_OFF BUTTON_POWER
183 #define ROCKBLOX_ROTATE_RIGHT BUTTON_SCROLL_UP
184 #define ROCKBLOX_ROTATE_LEFT BUTTON_REW
185 #define ROCKBLOX_DOWN BUTTON_SCROLL_DOWN
186 #define ROCKBLOX_LEFT BUTTON_LEFT
187 #define ROCKBLOX_RIGHT BUTTON_RIGHT
188 #define ROCKBLOX_DROP BUTTON_FF
189 #define ROCKBLOX_RESTART BUTTON_PLAY
191 #elif CONFIG_KEYPAD == GIGABEAT_PAD
193 #define ROCKBLOX_OFF BUTTON_POWER
194 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
195 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
196 #define ROCKBLOX_ROTATE BUTTON_UP
197 #define ROCKBLOX_DOWN BUTTON_DOWN
198 #define ROCKBLOX_LEFT BUTTON_LEFT
199 #define ROCKBLOX_RIGHT BUTTON_RIGHT
200 #define ROCKBLOX_DROP BUTTON_SELECT
201 #define ROCKBLOX_RESTART BUTTON_A
203 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
205 #define ROCKBLOX_OFF BUTTON_PLAY
206 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
207 #define ROCKBLOX_ROTATE_LEFT BUTTON_SELECT
208 #define ROCKBLOX_DOWN BUTTON_DOWN
209 #define ROCKBLOX_LEFT BUTTON_LEFT
210 #define ROCKBLOX_RIGHT BUTTON_RIGHT
211 #define ROCKBLOX_DROP BUTTON_MODE
212 #define ROCKBLOX_RESTART BUTTON_EQ
214 #elif CONFIG_KEYPAD == MROBE500_PAD
215 #define ROCKBLOX_OFF BUTTON_POWER
217 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
218 #define ROCKBLOX_OFF BUTTON_BACK
219 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
220 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
221 #define ROCKBLOX_ROTATE BUTTON_UP
222 #define ROCKBLOX_DOWN BUTTON_DOWN
223 #define ROCKBLOX_LEFT BUTTON_LEFT
224 #define ROCKBLOX_RIGHT BUTTON_RIGHT
225 #define ROCKBLOX_DROP BUTTON_SELECT
226 #define ROCKBLOX_RESTART BUTTON_PLAY
228 #elif CONFIG_KEYPAD == MROBE100_PAD
230 #define ROCKBLOX_OFF BUTTON_POWER
231 #define ROCKBLOX_ROTATE_RIGHT BUTTON_MENU
232 #define ROCKBLOX_ROTATE_LEFT BUTTON_PLAY
233 #define ROCKBLOX_ROTATE BUTTON_UP
234 #define ROCKBLOX_DOWN BUTTON_DOWN
235 #define ROCKBLOX_LEFT BUTTON_LEFT
236 #define ROCKBLOX_RIGHT BUTTON_RIGHT
237 #define ROCKBLOX_DROP BUTTON_SELECT
238 #define ROCKBLOX_RESTART BUTTON_DISPLAY
240 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
242 #define ROCKBLOX_OFF BUTTON_RC_REC
243 #define ROCKBLOX_ROTATE_RIGHT BUTTON_RC_VOL_DOWN
244 #define ROCKBLOX_ROTATE_LEFT BUTTON_RC_VOL_UP
245 #define ROCKBLOX_DOWN BUTTON_RC_MENU
246 #define ROCKBLOX_LEFT BUTTON_RC_REW
247 #define ROCKBLOX_RIGHT BUTTON_RC_FF
248 #define ROCKBLOX_DROP BUTTON_RC_PLAY
249 #define ROCKBLOX_RESTART BUTTON_RC_MODE
251 #elif CONFIG_KEYPAD == COWON_D2_PAD
252 #define ROCKBLOX_OFF BUTTON_POWER
253 #define ROCKBLOX_RESTART BUTTON_MENU
255 #elif CONFIG_KEYPAD == IAUDIO67_PAD
257 #define ROCKBLOX_OFF BUTTON_POWER
258 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOLDOWN
259 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOLUP
260 #define ROCKBLOX_DOWN BUTTON_STOP
261 #define ROCKBLOX_LEFT BUTTON_LEFT
262 #define ROCKBLOX_RIGHT BUTTON_RIGHT
263 #define ROCKBLOX_DROP BUTTON_PLAY
264 #define ROCKBLOX_RESTART BUTTON_MENU
266 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
267 #define ROCKBLOX_OFF BUTTON_BACK
268 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
269 #define ROCKBLOX_ROTATE_LEFT BUTTON_PLAY
270 #define ROCKBLOX_DOWN BUTTON_DOWN
271 #define ROCKBLOX_LEFT BUTTON_LEFT
272 #define ROCKBLOX_RIGHT BUTTON_RIGHT
273 #define ROCKBLOX_DROP BUTTON_SELECT
274 #define ROCKBLOX_RESTART BUTTON_CUSTOM
276 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
278 #define ROCKBLOX_OFF BUTTON_POWER
279 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
280 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
281 #define ROCKBLOX_ROTATE BUTTON_UP
282 #define ROCKBLOX_DOWN BUTTON_DOWN
283 #define ROCKBLOX_LEFT BUTTON_LEFT
284 #define ROCKBLOX_RIGHT BUTTON_RIGHT
285 #define ROCKBLOX_DROP BUTTON_SELECT
286 #define ROCKBLOX_RESTART BUTTON_MENU
288 # elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
290 #define ROCKBLOX_OFF BUTTON_POWER
291 #define ROCKBLOX_ROTATE_RIGHT BUTTON_VOL_DOWN
292 #define ROCKBLOX_ROTATE_LEFT BUTTON_VOL_UP
293 #define ROCKBLOX_ROTATE BUTTON_UP
294 #define ROCKBLOX_DOWN BUTTON_DOWN
295 #define ROCKBLOX_LEFT BUTTON_PREV
296 #define ROCKBLOX_RIGHT BUTTON_NEXT
297 #define ROCKBLOX_DROP BUTTON_PLAY
298 #define ROCKBLOX_RESTART BUTTON_MENU
300 #elif CONFIG_KEYPAD == ONDAVX747_PAD
301 #define ROCKBLOX_OFF BUTTON_POWER
302 #define ROCKBLOX_RESTART BUTTON_MENU
303 #elif CONFIG_KEYPAD == ONDAVX777_PAD
304 #define ROCKBLOX_OFF BUTTON_POWER
306 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
308 #define ROCKBLOX_OFF (BUTTON_REC|BUTTON_PLAY)
309 #define ROCKBLOX_ROTATE_RIGHT BUTTON_UP
310 #define ROCKBLOX_ROTATE_LEFT BUTTON_DOWN
311 #define ROCKBLOX_DOWN BUTTON_REW
312 #define ROCKBLOX_LEFT BUTTON_LEFT
313 #define ROCKBLOX_RIGHT BUTTON_RIGHT
314 #define ROCKBLOX_DROP BUTTON_FFWD
315 #define ROCKBLOX_RESTART (BUTTON_REC|BUTTON_REW)
317 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
319 #define ROCKBLOX_OFF BUTTON_REC
320 #define ROCKBLOX_ROTATE_RIGHT BUTTON_PLAY
321 #define ROCKBLOX_ROTATE_LEFT BUTTON_MENU
322 #define ROCKBLOX_DOWN BUTTON_DOWN
323 #define ROCKBLOX_LEFT BUTTON_PREV
324 #define ROCKBLOX_RIGHT BUTTON_NEXT
325 #define ROCKBLOX_DROP BUTTON_OK
326 #define ROCKBLOX_RESTART BUTTON_CANCEL
328 #else
329 #error No keymap defined!
330 #endif
332 #ifdef HAVE_TOUCHSCREEN
333 #ifndef ROCKBLOX_OFF
334 #define ROCKBLOX_OFF BUTTON_TOPLEFT
335 #endif
336 #ifndef ROCKBLOX_ROTATE_RIGHT
337 #define ROCKBLOX_ROTATE_RIGHT BUTTON_BOTTOMRIGHT
338 #endif
339 #ifndef ROCKBLOX_ROTATE_LEFT
340 #define ROCKBLOX_ROTATE_LEFT BUTTON_BOTTOMLEFT
341 #endif
342 #ifndef ROCKBLOX_DOWN
343 #define ROCKBLOX_DOWN BUTTON_BOTTOMMIDDLE
344 #endif
345 #ifndef ROCKBLOX_LEFT
346 #define ROCKBLOX_LEFT BUTTON_MIDLEFT
347 #endif
348 #ifndef ROCKBLOX_RIGHT
349 #define ROCKBLOX_RIGHT BUTTON_MIDRIGHT
350 #endif
351 #ifndef ROCKBLOX_DROP
352 #define ROCKBLOX_DROP BUTTON_CENTER
353 #endif
354 #ifndef ROCKBLOX_RESTART
355 #define ROCKBLOX_RESTART BUTTON_TOPRIGHT
356 #endif
357 #endif
359 #define BLOCKS_NUM 7
360 #define EMPTY_BLOCK 7
362 #define BOARD_WIDTH 10
364 #ifdef HAVE_LCD_BITMAP
366 #define BOARD_HEIGHT 20
368 #if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
370 #define BLOCK_WIDTH 24
371 #define BLOCK_HEIGHT 24
372 #define BOARD_X 172
373 #define BOARD_Y 0
374 #define PREVIEW_X 24
375 #define PREVIEW_Y 22
376 #define LABEL_X 482
377 #define SCORE_Y 50
378 #define LEVEL_Y 140
379 #define LINES_Y 210
381 #elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640)
383 #define BLOCK_WIDTH 30
384 #define BLOCK_HEIGHT 30
385 #define BOARD_X 14
386 #define BOARD_Y 2
387 #define PREVIEW_X 342
388 #define PREVIEW_Y 482
389 #define LABEL_X 344
390 #define SCORE_Y 58
391 #define LEVEL_Y 142
392 #define LINES_Y 218
394 #elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
396 #define BLOCK_WIDTH 12
397 #define BLOCK_HEIGHT 12
398 #define BOARD_X 86
399 #define BOARD_Y 0
400 #define PREVIEW_X 12
401 #define PREVIEW_Y 11
402 #define LABEL_X 242
403 #define SCORE_Y 25
404 #define LEVEL_Y 70
405 #define LINES_Y 105
407 #elif (LCD_WIDTH == 240) && ((LCD_HEIGHT == 320) || (LCD_HEIGHT == 400))
409 #define BLOCK_WIDTH 15
410 #define BLOCK_HEIGHT 15
411 #define BOARD_X 7
412 #define BOARD_Y 1
413 #define PREVIEW_X 171
414 #define PREVIEW_Y 241
415 #define LABEL_X 172
416 #define SCORE_Y 29
417 #define LEVEL_Y 71
418 #define LINES_Y 109
419 #define HIGH_LABEL_X 172
420 #define HIGH_SCORE_Y 163
421 #define HIGH_LEVEL_Y 172
423 #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176)
425 #define BLOCK_WIDTH 8
426 #define BLOCK_HEIGHT 8
427 #define BOARD_X 27
428 #define BOARD_Y 5
429 #define PREVIEW_X 158
430 #define PREVIEW_Y 130
431 #define LABEL_X 147
432 #define SCORE_Y 20
433 #define LEVEL_Y 65
434 #define LINES_Y 100
436 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132)
438 #define BLOCK_WIDTH 6
439 #define BLOCK_HEIGHT 6
440 #define BOARD_X 25
441 #define BOARD_Y 1
442 #define PREVIEW_X 126
443 #define PREVIEW_Y 102
444 #define LABEL_X 112
445 #define SCORE_Y 17
446 #define LEVEL_Y 49
447 #define LINES_Y 81
449 #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220)
451 /* no room for the space in the highscore list */
452 #define _SPACE ""
454 #define BLOCK_WIDTH 10
455 #define BLOCK_HEIGHT 10
456 #define BOARD_X 6
457 #define BOARD_Y 10
458 #define PREVIEW_X 124
459 #define PREVIEW_Y 174
460 #define LABEL_X 117
461 #define SCORE_Y 18
462 #define LEVEL_Y 52
463 #define LINES_Y 85
464 #define HIGH_SCORE_Y 119
465 #define HIGH_LEVEL_Y 126
466 #define HIGH_LABEL_X 114
468 #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128)
471 #define BLOCK_WIDTH 6
472 #define BLOCK_HEIGHT 6
473 #define BOARD_X 22
474 #define BOARD_Y 3
475 #define PREVIEW_X 114
476 #define PREVIEW_Y 100
477 #define LABEL_X 101
478 #define SCORE_Y 17
479 #define LEVEL_Y 49
480 #define LINES_Y 82
482 #elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110)
484 #define BLOCK_WIDTH 5
485 #define BLOCK_HEIGHT 5
486 #define BOARD_X 14
487 #define BOARD_Y 0
488 #define PREVIEW_X 98
489 #define PREVIEW_Y 88
490 #define LABEL_X 80
491 #define SCORE_Y 15
492 #define LEVEL_Y 45
493 #define LINES_Y 74
495 #elif (LCD_WIDTH == 132) && (LCD_HEIGHT == 80)
497 #define BLOCK_WIDTH 4
498 #define BLOCK_HEIGHT 4
499 #define BOARD_X 10
500 #define BOARD_Y 0
501 #define PREVIEW_X 89
502 #define PREVIEW_Y 61
503 #define LABEL_X 78
504 #define SCORE_Y 10
505 #define LEVEL_Y 30
506 #define LINES_Y 50
508 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 128)
510 #define BLOCK_WIDTH 6
511 #define BLOCK_HEIGHT 6
512 #define BOARD_X 4
513 #define BOARD_Y 3
514 #define PREVIEW_X 84
515 #define PREVIEW_Y 100
516 #define LABEL_X 71
517 #define SCORE_Y 17
518 #define LEVEL_Y 49
519 #define LINES_Y 82
521 /* NOTE: This is for the GoGear SA9200 and is only
522 temporary until I can get better coordinates! */
523 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 160)
525 #define BLOCK_WIDTH 6
526 #define BLOCK_HEIGHT 6
527 #define BOARD_X 4
528 #define BOARD_Y 3
529 #define PREVIEW_X 84
530 #define PREVIEW_Y 100
531 #define LABEL_X 71
532 #define SCORE_Y 17
533 #define LEVEL_Y 49
534 #define LINES_Y 82
536 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 96)
538 #define BLOCK_WIDTH 4
539 #define BLOCK_HEIGHT 4
540 #define BOARD_X 14
541 #define BOARD_Y 2
542 #define PREVIEW_X 89
543 #define PREVIEW_Y 76
544 #define LABEL_X 70
545 #define SCORE_Y 14
546 #define LEVEL_Y 39
547 #define LINES_Y 64
549 #elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64)
551 #define BLOCK_WIDTH 3
552 #define BLOCK_HEIGHT 3
553 #define BOARD_X 9
554 #define BOARD_Y 3
555 #define PREVIEW_X 53
556 #define PREVIEW_Y 5
557 #define LABEL_X 70
558 #define SCORE_Y 32
559 #define LEVEL_Y 13
560 #define LINES_Y 51
562 #elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
564 #define BLOCK_WIDTH 4
565 #define BLOCK_HEIGHT 3
566 #define BOARD_X 9
567 #define BOARD_Y 3
568 #define PREVIEW_X 59
569 #define PREVIEW_Y 5
570 #define LABEL_X 59
571 #define SCORE_Y 32
572 #define LEVEL_Y 13
573 #define LEVEL_X 78
574 #define LINES_Y 51
576 #endif
578 #ifndef LEVEL_X
579 #define LEVEL_X LABEL_X
580 #endif
582 #ifndef LINES_X
583 #define LINES_X LABEL_X
584 #endif
586 #define MYLCD(fn) rb->lcd_ ## fn
588 extern const fb_data rockblox_background[];
590 #else /* HAVE_LCD_CHARCELLS */
592 #define BOARD_HEIGHT 14
594 #define BLOCK_WIDTH 1
595 #define BLOCK_HEIGHT 1
596 #define BOARD_X 5
597 #define BOARD_Y 0
598 #define PREVIEW_X 15
599 #define PREVIEW_Y 1
601 #define MYLCD(fn) pgfx_ ## fn
603 #endif
605 #ifndef _SPACE
606 #define _SPACE " "
607 #endif
608 /* <<Explanation on Rockblox shapes>>
611 %% - O has 1 orientation
613 %% %
614 %% %% - Z has 2 orientations
617 %% %
618 %% %% - S has 2 orientations
622 % %%%% - I has 2 orientations
625 % %%
626 % % % %%% - L has 4 orientations
627 %% %%% % %
629 % %%
630 % % % %%% - J has 4 orientations
631 %% %%% % %
633 % % %%%
634 %% % %% % - T has 4 orientations
635 % %%% %
638 /* c=current f=figure o=orientation n=next */
639 static struct _rockblox_status
641 int gameover;
642 int lines;
643 int level;
644 int score;
645 int cx;
646 int cy;
647 int cf;
648 int co;
649 int nf;
650 short board[BOARD_HEIGHT][BOARD_WIDTH]; /* 20 rows of 10 blocks */
651 } rockblox_status;
653 /* prototypes */
654 static void draw_next_block(void);
655 static void new_block(void);
657 #ifdef HAVE_SCROLLWHEEL
658 int wheel_events = 0, last_wheel_event = 0;
659 bool wheel_enabled = false;
660 #endif
662 static const short scoring[4] = { /* scoring for each number of lines */
663 #if BOARD_HEIGHT == 20
664 40 /* single */ , 100 /* double */ , 300 /* triple */ , 1200 /* rockblox */
665 #elif BOARD_HEIGHT == 14 /* Player special values */
666 60 /* single */ , 150 /* double */ , 500 /* triple */ , 2000 /* rockblox */
667 #endif
670 struct figure
672 #if LCD_DEPTH >= 2
673 unsigned short color[3]; /* color of figure (light,middle,shadow) */
674 #endif
675 unsigned short max_or; /* max orientations */
676 signed short shapeX[4], shapeY[4]; /* implementation of figures */
679 /* array of figures */
680 figures[BLOCKS_NUM] = {
681 /* O */
683 #if LCD_DEPTH >= 16
684 {LCD_RGBPACK (153, 255, 255), LCD_RGBPACK(0, 255, 255),
685 LCD_RGBPACK(0,153,153)},
686 #elif LCD_DEPTH == 2
687 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
688 #endif
690 {-1, 0, -1, 0},
691 {0, 0, 1, 1}
693 /* I */
695 #if LCD_DEPTH >= 16
696 {LCD_RGBPACK (255, 153, 128), LCD_RGBPACK (255, 0, 0),
697 LCD_RGBPACK (153, 0, 0)},
698 #elif LCD_DEPTH == 2
699 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
700 #endif
702 {-2, -1, 0, 1},
703 {0, 0, 0, 0}
705 /* 'Z' */
707 #if LCD_DEPTH >= 16
708 {LCD_RGBPACK (153, 255, 153), LCD_RGBPACK (0, 255, 0),
709 LCD_RGBPACK (0, 153, 0)},
710 #elif LCD_DEPTH == 2
711 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
712 #endif
714 {0, 1, -1, 0},
715 {0, 0, 1, 1}
717 /* 'S' */
719 #if LCD_DEPTH >= 16
720 {LCD_RGBPACK (153, 153, 255), LCD_RGBPACK (0, 0, 255),
721 LCD_RGBPACK (0, 0, 153)},
722 #elif LCD_DEPTH == 2
723 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
724 #endif
726 {-1, 0, 0, 1},
727 {0, 0, 1, 1}
729 /* 'L' */
731 #if LCD_DEPTH >= 16
732 {LCD_RGBPACK (255, 255, 153), LCD_RGBPACK (255, 255, 0),
733 LCD_RGBPACK (153, 153, 0)},
734 #elif LCD_DEPTH == 2
735 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
736 #endif
738 {-1, 0, 1, 1},
739 {0, 0, 0, 1}
741 /* 'J' */
743 #if LCD_DEPTH >= 16
744 {LCD_RGBPACK (255, 153, 255), LCD_RGBPACK (255, 0, 255),
745 LCD_RGBPACK (153, 0, 153)},
746 #elif LCD_DEPTH == 2
747 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
748 #endif
750 {-1, 0, 1, -1},
751 {0, 0, 0, 1}
753 /* 'T' */
755 #if LCD_DEPTH >= 16
756 {LCD_RGBPACK (204, 204, 204), LCD_RGBPACK (153, 153, 153),
757 LCD_RGBPACK (85, 85, 85)},
758 #elif LCD_DEPTH == 2
759 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
760 #endif
762 {-1, 0, 1, 0},
763 {0, 0, 0, 1}
766 bool resume = false;
767 bool resume_file = false;
769 /* Rockbox File System only supports full filenames inc dir */
770 #define HIGH_SCORE PLUGIN_GAMES_DIR "/rockblox.score"
771 #define RESUME_FILE PLUGIN_GAMES_DIR "/rockblox.resume"
772 #define MAX_HIGH_SCORES 5
774 /* Default High Scores... */
775 struct highscore highest[MAX_HIGH_SCORES];
777 /* get random number from (0) to (range-1) */
778 static int t_rand (int range)
780 return rb->rand () % range;
783 static inline void show_game_over (void)
785 rb->splash(HZ,"Game over!");
788 /* init the board array to have no blocks */
789 static void init_board (void)
791 int i, j;
792 for (i = 0; i < BOARD_WIDTH; i++)
793 for (j = 0; j < BOARD_HEIGHT; j++)
794 rockblox_status.board[j][i] = EMPTY_BLOCK;
797 /* show the score, level and lines */
798 static void show_details (void)
800 char str[25]; /* for strings */
802 #ifdef HAVE_LCD_BITMAP
803 #if LCD_DEPTH >= 2
804 rb->lcd_set_foreground (LCD_BLACK);
805 rb->lcd_set_background (LCD_WHITE);
806 #endif
807 rb->snprintf (str, sizeof (str), "%d", rockblox_status.score);
808 rb->lcd_putsxy (LABEL_X, SCORE_Y, str);
809 rb->snprintf (str, sizeof (str), "%d", rockblox_status.level);
810 rb->lcd_putsxy (LEVEL_X, LEVEL_Y, str);
811 rb->snprintf (str, sizeof (str), "%d", rockblox_status.lines);
812 rb->lcd_putsxy (LINES_X, LINES_Y, str);
813 #else /* HAVE_LCD_CHARCELLS */
814 rb->snprintf (str, sizeof (str), "L%d/%d", rockblox_status.level,
815 rockblox_status.lines);
816 rb->lcd_puts (5, 0, str);
817 rb->snprintf (str, sizeof (str), "S%d", rockblox_status.score);
818 rb->lcd_puts (5, 1, str);
819 #endif
822 #ifdef HIGH_SCORE_Y
823 static void show_highscores (void)
825 int i;
826 char str[25]; /* for strings */
828 for (i = 0; i<MAX_HIGH_SCORES; i++)
830 rb->snprintf (str, sizeof (str), "%06d" _SPACE "L%1d",
831 highest[i].score, highest[i].level);
832 rb->lcd_putsxy (HIGH_LABEL_X, HIGH_SCORE_Y + (10 * i), str);
835 #endif
837 static void load_game(void)
839 int fd;
841 resume = false;
843 fd = rb->open(RESUME_FILE, O_RDONLY);
844 if (fd < 0) return;
846 if (rb->read(fd, &rockblox_status, sizeof(struct _rockblox_status))
847 < (ssize_t)sizeof(struct _rockblox_status))
849 rb->splash(HZ/2, "Loading Rockblox resume info failed");
850 return;
851 } else {
852 resume = true;
855 rb->close(fd);
857 return;
860 static void dump_resume(void)
862 int fd;
864 fd = rb->open(RESUME_FILE, O_WRONLY|O_CREAT);
865 if (fd < 0)
866 goto fail;
868 if (rb->write(fd, &rockblox_status, sizeof(struct _rockblox_status))
869 <= 0)
871 rb->close(fd);
872 goto fail;
874 rb->close(fd);
875 return;
877 fail:
878 rb->splash(HZ/2, "Writing Rockblox resume info failed");
879 return;
882 static void init_rockblox (bool resume)
884 char score_name[50];
885 struct tm* tm;
887 tm = rb->get_time();
888 rb->snprintf(score_name, sizeof(score_name), "%04d%02d%02d %02d%02d%02d",
889 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
890 tm->tm_hour, tm->tm_min, tm->tm_sec);
892 #ifdef HAVE_LCD_BITMAP
893 rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
894 #else /* HAVE_LCD_CHARCELLS */
895 pgfx_display (0, 0);
896 pgfx_display_block (3, 0, 3, 1);
897 pgfx_display_block (4, 0, 3, 0);
898 pgfx_clear_display();
899 pgfx_fillrect (3, 0, 2, 14);
900 pgfx_fillrect (15, 7, 2, 7);
901 pgfx_update();
902 #endif
903 if (!resume)
905 rockblox_status.level = 1;
906 rockblox_status.lines = 0;
907 rockblox_status.score = 0;
908 rockblox_status.nf = t_rand(BLOCKS_NUM);
909 init_board ();
910 new_block ();
912 draw_next_block();
914 show_details ();
915 #ifdef HIGH_SCORE_Y
916 show_highscores ();
917 #endif
920 static inline int level_speed(int level)
922 #if BOARD_HEIGHT == 20
923 return (5*HZ) / (level + 9);
924 #elif BOARD_HEIGHT == 14
925 return (7*HZ) / (level + 9);
926 #endif
929 static int getRelativeX (int figure, int square, int orientation)
931 switch (orientation) {
932 case 0:
933 return figures[figure].shapeX[square];
934 case 1:
935 return figures[figure].shapeY[square];
936 case 2:
937 return -figures[figure].shapeX[square];
938 case 3:
939 return -figures[figure].shapeY[square];
940 default:
941 return 0;
945 static int getRelativeY (int figure, int square, int orientation)
947 switch (orientation) {
948 case 0:
949 return figures[figure].shapeY[square];
950 case 1:
951 return -figures[figure].shapeX[square];
952 case 2:
953 return -figures[figure].shapeY[square];
954 case 3:
955 return figures[figure].shapeX[square];
956 default:
957 return 0;
961 /* redraw the while board on the screen */
962 static void refresh_board (void)
964 int i, j, x, y, block;
966 #if LCD_DEPTH >= 2
967 rb->lcd_set_foreground (LCD_BLACK);
968 #elif LCD_DEPTH == 1
969 MYLCD(set_drawmode) (DRMODE_SOLID | DRMODE_INVERSEVID);
970 #endif
972 MYLCD(fillrect) (BOARD_X, BOARD_Y, BOARD_WIDTH * BLOCK_WIDTH,
973 BOARD_HEIGHT * BLOCK_HEIGHT);
975 #if LCD_DEPTH == 1
976 MYLCD(set_drawmode) (DRMODE_SOLID);
977 #endif
979 for (i = 0; i < BOARD_WIDTH; i++)
980 for (j = 0; j < BOARD_HEIGHT; j++) {
981 block = rockblox_status.board[j][i];
982 if (block != EMPTY_BLOCK) {
983 #ifdef HAVE_LCD_BITMAP
984 #if LCD_DEPTH >= 2
985 /* middle drawing */
986 rb->lcd_set_foreground (figures[block].color[1]);
987 #endif
988 rb->lcd_fillrect (BOARD_X + i * BLOCK_WIDTH,
989 BOARD_Y + j * BLOCK_HEIGHT,
990 BLOCK_WIDTH, BLOCK_HEIGHT);
991 #if LCD_DEPTH >= 2
992 /* light drawing */
993 rb->lcd_set_foreground (figures[block].color[0]);
994 #endif
995 rb->lcd_vline (BOARD_X + i * BLOCK_WIDTH,
996 BOARD_Y + j * BLOCK_HEIGHT,
997 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 2);
998 rb->lcd_hline (BOARD_X + i * BLOCK_WIDTH,
999 BOARD_X + (i + 1) * BLOCK_WIDTH - 2,
1000 BOARD_Y + j * BLOCK_HEIGHT);
1001 #if LCD_DEPTH >= 2
1002 /* shadow drawing */
1003 rb->lcd_set_foreground (figures[block].color[2]);
1004 #endif
1005 rb->lcd_vline (BOARD_X + (i + 1) * BLOCK_WIDTH - 1,
1006 BOARD_Y + j * BLOCK_HEIGHT + 1,
1007 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 1);
1008 rb->lcd_hline (BOARD_X + i * BLOCK_WIDTH + 1,
1009 BOARD_X + (i + 1) * BLOCK_WIDTH - 1,
1010 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 1);
1011 #else /* HAVE_LCD_CHARCELLS */
1012 pgfx_drawpixel (BOARD_X + i, BOARD_Y + j);
1013 #endif
1017 for (i = 0; i < 4; i++) {
1018 x = getRelativeX (rockblox_status.cf, i, rockblox_status.co)
1019 + rockblox_status.cx;
1020 y = getRelativeY (rockblox_status.cf, i, rockblox_status.co)
1021 + rockblox_status.cy;
1022 #ifdef HAVE_LCD_BITMAP
1023 #if LCD_DEPTH >= 2
1024 /* middle drawing */
1025 rb->lcd_set_foreground (figures[rockblox_status.cf].color[1]);
1026 #endif
1027 rb->lcd_fillrect (BOARD_X + x * BLOCK_WIDTH,
1028 BOARD_Y + y * BLOCK_HEIGHT,
1029 BLOCK_WIDTH, BLOCK_HEIGHT);
1030 #if LCD_DEPTH >= 2
1031 /* light drawing */
1032 rb->lcd_set_foreground (figures[rockblox_status.cf].color[0]);
1033 #endif
1034 rb->lcd_vline (BOARD_X + x * BLOCK_WIDTH, BOARD_Y + y * BLOCK_HEIGHT,
1035 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 2);
1036 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH,
1037 BOARD_X + (x + 1) * BLOCK_WIDTH - 2,
1038 BOARD_Y + y * BLOCK_HEIGHT);
1039 #if LCD_DEPTH >= 2
1040 /* shadow drawing */
1041 rb->lcd_set_foreground (figures[rockblox_status.cf].color[2]);
1042 #endif
1043 rb->lcd_vline (BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1044 BOARD_Y + y * BLOCK_HEIGHT + 1,
1045 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1046 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH + 1,
1047 BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1048 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1049 #else /* HAVE_LCD_CHARCELLS */
1050 pgfx_drawpixel (BOARD_X + x, BOARD_Y + y);
1051 #endif
1053 MYLCD(update) ();
1056 static bool canMoveTo (int x, int y, int newOrientation)
1058 int i, rx, ry;
1059 for (i = 0; i < 4; i++) {
1060 ry = getRelativeY (rockblox_status.cf, i, newOrientation) + y;
1061 rx = getRelativeX (rockblox_status.cf, i, newOrientation) + x;
1062 if ((rx < 0 || rx >= BOARD_WIDTH) ||
1063 (ry < 0 || ry >= BOARD_HEIGHT) ||
1064 (rockblox_status.board[ry][rx] != EMPTY_BLOCK))
1065 return false;
1067 return true;
1070 /* draws the preview of next block in the preview window */
1071 static void draw_next_block (void)
1073 int i, rx, ry;
1074 /* clear preview window first */
1075 #if LCD_DEPTH >= 2
1076 rb->lcd_set_foreground (LCD_BLACK);
1077 #elif LCD_DEPTH == 1
1078 MYLCD(set_drawmode) (DRMODE_SOLID | DRMODE_INVERSEVID);
1079 #endif
1081 /* 4x4 */
1082 MYLCD(fillrect) (PREVIEW_X, PREVIEW_Y, BLOCK_WIDTH * 4, BLOCK_HEIGHT * 4);
1084 #if LCD_DEPTH == 1
1085 MYLCD(set_drawmode) (DRMODE_SOLID);
1086 #endif
1088 /* draw the lightgray rectangles */
1089 #if LCD_DEPTH >= 16
1090 rb->lcd_set_foreground (LCD_RGBPACK (40, 40, 40));
1091 #elif LCD_DEPTH == 2
1092 rb->lcd_set_foreground (LCD_DARKGRAY);
1093 #endif
1095 #if LCD_DEPTH >= 2
1096 for (rx = 0; rx < 4; rx++)
1097 for (ry = 0; ry < 4; ry++)
1098 rb->lcd_drawrect (PREVIEW_X + rx * BLOCK_WIDTH,
1099 PREVIEW_Y + ry * BLOCK_HEIGHT, BLOCK_WIDTH,
1100 BLOCK_HEIGHT);
1101 #endif
1103 /* draw the figure */
1104 for (i = 0; i < 4; i++) {
1105 rx = getRelativeX (rockblox_status.nf, i, 0) + 2;
1106 ry = getRelativeY (rockblox_status.nf, i, 0) + 2;
1107 #ifdef HAVE_LCD_BITMAP
1108 #if LCD_DEPTH >= 2
1109 rb->lcd_set_foreground (figures[rockblox_status.nf].color[1]); /* middle drawing */
1110 #endif
1111 rb->lcd_fillrect (PREVIEW_X + rx * BLOCK_WIDTH,
1112 PREVIEW_Y + ry * BLOCK_HEIGHT,
1113 BLOCK_WIDTH, BLOCK_HEIGHT);
1114 #if LCD_DEPTH >= 2
1115 rb->lcd_set_foreground (figures[rockblox_status.nf].color[0]); /* light drawing */
1116 #endif
1117 rb->lcd_vline (PREVIEW_X + rx * BLOCK_WIDTH,
1118 PREVIEW_Y + ry * BLOCK_HEIGHT,
1119 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 2);
1120 rb->lcd_hline (PREVIEW_X + rx * BLOCK_WIDTH,
1121 PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 2,
1122 PREVIEW_Y + ry * BLOCK_HEIGHT);
1123 #if LCD_DEPTH >= 2
1124 rb->lcd_set_foreground (figures[rockblox_status.nf].color[2]); /* shadow drawing */
1125 #endif
1126 rb->lcd_vline (PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 1,
1127 PREVIEW_Y + ry * BLOCK_HEIGHT + 1,
1128 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 1);
1129 rb->lcd_hline (PREVIEW_X + rx * BLOCK_WIDTH + 1,
1130 PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 1,
1131 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 1);
1132 #else /* HAVE_LCD_CHARCELLS */
1133 pgfx_drawpixel (PREVIEW_X + rx, PREVIEW_Y + ry);
1134 #endif
1139 /* move the block to a relative location */
1140 static void move_block (int x, int y, int o)
1142 if (canMoveTo (rockblox_status.cx + x, rockblox_status.cy + y, o)) {
1143 rockblox_status.cy += y;
1144 rockblox_status.cx += x;
1145 rockblox_status.co = o;
1149 /* try to add a new block to play with (return true if gameover) */
1150 static void new_block (void)
1152 rockblox_status.cy = 1;
1153 rockblox_status.cx = 5;
1154 rockblox_status.cf = rockblox_status.nf;
1155 rockblox_status.co = 0; /* start at the same orientation all time */
1156 rockblox_status.nf = t_rand (BLOCKS_NUM);
1157 rockblox_status.gameover = !canMoveTo (rockblox_status.cx,
1158 rockblox_status.cy, rockblox_status.co);
1160 draw_next_block ();
1164 /* check for filled rockblox_status.lines and do what necessary */
1165 static int check_lines (void)
1168 int i, j, y;
1169 int rockblox = 0;
1171 for (j = 0; j < BOARD_HEIGHT; j++) {
1172 for (i = 0; ((i < BOARD_WIDTH) &&
1173 (rockblox_status.board[j][i] != EMPTY_BLOCK)); i++);
1174 if (i == BOARD_WIDTH) { /* woo hoo, we have a line */
1175 rockblox++;
1176 for (y = j; y > 0; y--)
1178 for (i = 0; i < BOARD_WIDTH; i++)
1179 { /* fall line */
1180 rockblox_status.board[y][i] = rockblox_status.board[y - 1][i];
1186 return rockblox;
1189 /* moves down the figure and returns true if gameover */
1190 static void move_down (void)
1192 int l, i, rx, ry;
1194 if (!canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co)) {
1195 /* save figure to board */
1196 for (i = 0; i < 4; i++) {
1197 rx = getRelativeX (rockblox_status.cf, i, rockblox_status.co) + rockblox_status.cx;
1198 ry = getRelativeY (rockblox_status.cf, i, rockblox_status.co) + rockblox_status.cy;
1199 rockblox_status.board[ry][rx] = rockblox_status.cf;
1201 /* check if formed some lines */
1202 l = check_lines ();
1203 if (l) {
1204 /* the original scoring from "http://en.wikipedia.org/wiki/Rockblox" */
1205 rockblox_status.score += scoring[l - 1] * rockblox_status.level;
1206 rockblox_status.lines += l;
1207 rockblox_status.level = (int) rockblox_status.lines / 10 + 1;
1210 /* show details */
1211 show_details ();
1213 /* generate a new figure */
1214 new_block ();
1215 } else
1216 move_block (0, 1, rockblox_status.co);
1219 static bool rockblox_help(void)
1221 int button;
1223 #define WORDS (sizeof help_text / sizeof (char*))
1224 char *help_text[] = {
1225 "Rockblox", "", "Aim", "", "Make", "the", "falling", "blocks", "of", "different",
1226 "shapes", "form", "full", "rows.", "Whenever", "a", "row", "is", "completed,", "it",
1227 "will", "be", "cleared", "away", "and", "you", "gain", "points."
1230 static struct style_text formation[]={
1231 { 0, TEXT_CENTER|TEXT_UNDERLINE },
1232 { 2, C_RED },
1233 { -1, 0 }
1235 #ifdef HAVE_LCD_BITMAP
1236 rb->lcd_setfont(FONT_UI);
1237 #endif
1238 #ifdef HAVE_LCD_COLOR
1239 rb->lcd_set_background(LCD_BLACK);
1240 rb->lcd_set_foreground(LCD_WHITE);
1241 #endif
1242 if (display_text(WORDS, help_text, formation, NULL))
1243 return true;
1244 do {
1245 button = rb->button_get(true);
1246 if ( rb->default_event_handler( button ) == SYS_USB_CONNECTED )
1247 return true;
1248 } while( ( button == BUTTON_NONE )
1249 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
1250 #ifdef HAVE_LCD_BITMAP
1251 rb->lcd_setfont(FONT_SYSFIXED);
1252 #endif
1253 return false;
1256 static int rockblox_menu_cb(int action, const struct menu_item_ex *this_item)
1258 int i = ((intptr_t)this_item);
1259 if(action == ACTION_REQUEST_MENUITEM
1260 && !resume && (i==0 || i==5))
1261 return ACTION_EXIT_MENUITEM;
1262 return action;
1265 static int rockblox_menu(void)
1267 int selected = 0;
1269 MENUITEM_STRINGLIST(main_menu, "Rockblox Menu", rockblox_menu_cb,
1270 "Resume Game", "Start New Game",
1271 "Help", "High Scores", "Playback Control",
1272 "Quit without Saving", "Quit");
1274 rb->button_clear_queue();
1275 while (true) {
1276 switch (rb->do_menu(&main_menu, &selected, NULL, false)) {
1277 case 0:
1278 if(resume_file)
1279 rb->remove(RESUME_FILE);
1280 init_rockblox(true);
1281 return 0;
1282 case 1:
1283 init_rockblox(false);
1284 return 0;
1285 case 2:
1286 if (rockblox_help())
1287 return 1;
1288 break;
1289 case 3:
1290 #ifdef HAVE_LCD_BITMAP
1291 highscore_show(MAX_HIGH_SCORES, highest, MAX_HIGH_SCORES, true);
1292 #else
1293 rb->splashf(2*HZ, "High Score: %d", highest[0].score);
1294 #endif
1295 break;
1296 case 4:
1297 if (playback_control(NULL))
1298 return 1;
1299 break;
1300 case 5:
1301 return 1;
1302 case 6:
1303 if (resume) {
1304 rb->splash(HZ*1, "Saving game ...");
1305 dump_resume();
1307 return 1;
1308 case MENU_ATTACHED_USB:
1309 return 1;
1310 default:
1311 return 1;
1312 break;
1318 static int rockblox_loop (void)
1320 int button;
1321 int lastbutton = BUTTON_NONE;
1322 long next_down_tick = *rb->current_tick + level_speed(rockblox_status.level);
1324 if (rockblox_menu()) {
1325 return 1;
1327 resume = false;
1328 resume_file = false;
1330 while (1) {
1331 #ifdef HAS_BUTTON_HOLD
1332 if (rb->button_hold ()) {
1333 /* Turn on backlight timeout (revert to settings) */
1334 backlight_use_settings(); /* backlight control in lib/helper.c */
1335 rb->splash(0, "Paused");
1336 while (rb->button_hold ())
1337 rb->sleep(HZ/10);
1339 /* Turn off backlight timeout */
1340 backlight_force_on(); /* backlight control in lib/helper.c */
1342 /* get rid of the splash text */
1343 rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1344 show_details ();
1345 #ifdef HIGH_SCORE_Y
1346 show_highscores ();
1347 #endif
1348 draw_next_block ();
1349 refresh_board ();
1351 #endif
1353 button = rb->button_get_w_tmo (MAX(next_down_tick - *rb->current_tick, 1));
1354 switch (button) {
1355 #ifdef ROCKBLOX_RC_OFF
1356 case ROCKBLOX_RC_OFF:
1357 #endif
1358 case ROCKBLOX_OFF:
1359 #ifdef ROCKBLOX_OFF_PRE
1360 if (lastbutton != ROCKBLOX_OFF_PRE)
1361 break;
1362 #endif
1363 resume = true;
1364 return 0;
1365 break;
1367 #if defined(ROCKBLOX_ROTATE)
1368 case ROCKBLOX_ROTATE:
1369 #endif
1370 case ROCKBLOX_ROTATE_RIGHT:
1371 case ROCKBLOX_ROTATE_RIGHT | BUTTON_REPEAT:
1372 #ifdef HAVE_SCROLLWHEEL
1373 /* if the wheel is disabled, add an event to the stack. */
1374 if(wheel_enabled == false)
1375 wheel_events++;
1377 /* if it's enabled, go ahead and rotate.. */
1378 if(wheel_enabled)
1379 #endif
1380 move_block (0, 0, (rockblox_status.co + 1) % figures[rockblox_status.cf].max_or);
1381 break;
1383 case ROCKBLOX_ROTATE_LEFT:
1384 case ROCKBLOX_ROTATE_LEFT | BUTTON_REPEAT:
1385 #ifdef HAVE_SCROLLWHEEL
1386 if(wheel_enabled == false)
1387 wheel_events++;
1389 if(wheel_enabled)
1390 #endif
1391 move_block (0, 0,
1392 (rockblox_status.co + figures[rockblox_status.cf].max_or -
1393 1) % figures[rockblox_status.cf].max_or);
1394 break;
1396 #ifdef ROCKBLOX_ROTATE_RIGHT2
1397 case ROCKBLOX_ROTATE_RIGHT2:
1398 move_block (0, 0, (rockblox_status.co + 1) % figures[rockblox_status.cf].max_or);
1399 break;
1400 #endif
1402 case ROCKBLOX_DOWN:
1403 case ROCKBLOX_DOWN | BUTTON_REPEAT:
1404 move_block (0, 1, rockblox_status.co);
1405 break;
1407 case ROCKBLOX_RIGHT:
1408 case ROCKBLOX_RIGHT | BUTTON_REPEAT:
1409 move_block (1, 0, rockblox_status.co);
1410 break;
1412 case ROCKBLOX_LEFT:
1413 case ROCKBLOX_LEFT | BUTTON_REPEAT:
1414 move_block (-1, 0, rockblox_status.co);
1415 break;
1417 case ROCKBLOX_DROP:
1418 #ifdef ROCKBLOX_DROP_PRE
1419 if (lastbutton != ROCKBLOX_DROP_PRE)
1420 break;
1421 #endif
1422 while (canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co))
1423 move_block (0, 1, rockblox_status.co);
1424 break;
1425 #ifdef ROCKBLOX_RESTART
1426 case ROCKBLOX_RESTART:
1427 rb->splash (HZ * 1, "Restarting...");
1428 init_rockblox (false);
1429 break;
1430 #endif
1432 default:
1433 if (rb->default_event_handler (button) == SYS_USB_CONNECTED)
1434 return PLUGIN_USB_CONNECTED;
1435 break;
1437 if (button != BUTTON_NONE)
1438 lastbutton = button;
1440 #ifdef HAVE_SCROLLWHEEL
1441 /* check if we should enable the scroll wheel, if events
1442 * begin to stack up... */
1443 if(wheel_enabled == false)
1445 /* stopped rotating the wheel, reset the count */
1446 if(wheel_events == last_wheel_event)
1448 last_wheel_event = 0;
1449 wheel_events = 0;
1451 /* rotated the wheel a while constantly, enable it. */
1452 else if(wheel_events > 3)
1454 wheel_enabled = true;
1457 /* this evens out the last event and the "current" event.
1458 * if we get an event next time through button reading, it will
1459 * remain ahead of last_event. if we don't, they'll end up equaling
1460 * each other.. thus, the scroll count will be reset. */
1461 if(wheel_enabled == false && wheel_events > last_wheel_event)
1462 last_wheel_event++;
1464 #endif
1466 if (TIME_AFTER(*rb->current_tick, next_down_tick)) {
1467 move_down ();
1468 next_down_tick += level_speed(rockblox_status.level);
1469 if (TIME_AFTER(*rb->current_tick, next_down_tick))
1470 /* restart time "raster" when we had to wait longer than usual
1471 * (pause, game restart etc) */
1472 next_down_tick = *rb->current_tick + level_speed(rockblox_status.level);
1475 if (rockblox_status.gameover) {
1476 #if LCD_DEPTH >= 2
1477 rb->lcd_set_foreground (LCD_BLACK);
1478 #endif
1479 show_game_over();
1480 resume = false;
1481 return 0;
1484 refresh_board ();
1487 return 0;
1490 enum plugin_status plugin_start (const void *parameter)
1493 (void) parameter;
1495 rb->srand (*rb->current_tick);
1497 /* Load HighScore if any */
1498 highscore_load(HIGH_SCORE, highest, MAX_HIGH_SCORES);
1500 #if LCD_DEPTH > 1
1501 rb->lcd_set_backdrop(NULL);
1502 #endif
1504 #ifdef HAVE_LCD_BITMAP
1505 rb->lcd_setfont (FONT_SYSFIXED);
1506 #else
1507 if (!pgfx_init(4, 2))
1509 rb->splash(HZ*2, "Old LCD :(");
1510 return PLUGIN_OK;
1512 #endif
1513 /* Turn off backlight timeout */
1514 backlight_force_on(); /* backlight control in lib/helper.c */
1515 load_game();
1516 resume_file = resume;
1517 while(!rockblox_loop()) {
1518 if(!resume) {
1519 int position = highscore_update(rockblox_status.score, rockblox_status.level, "", highest,
1520 MAX_HIGH_SCORES);
1521 if (position == 0) {
1522 rb->splash(HZ*2, "New High Score");
1524 if (position != -1) {
1525 #ifdef HAVE_LCD_BITMAP
1526 highscore_show(position, highest, MAX_HIGH_SCORES, true);
1527 #else
1528 rb->splashf(2*HZ, "High Score: %d", highest[position].score);
1529 #endif
1534 #ifndef HAVE_LCD_BITMAP
1535 pgfx_release();
1536 #endif
1537 /* Save user's HighScore */
1538 highscore_save(HIGH_SCORE, highest, MAX_HIGH_SCORES);
1539 backlight_use_settings(); /* backlight control in lib/helper.c */
1541 return PLUGIN_OK;