A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Eli Sherer
11 *
12 * Heavily modified for embedded use by Björn Stenberg (bjorn@haxx.se)
13 *
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.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
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/mylcd.h"
29
30
31
32#if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
33 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
34 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
35
36#define ROCKBLOX_OFF (BUTTON_SELECT | BUTTON_REPEAT)
37#define ROCKBLOX_ROTATE_CCW BUTTON_SCROLL_BACK
38#define ROCKBLOX_ROTATE_CCW2 (BUTTON_MENU | BUTTON_REL)
39#define ROCKBLOX_ROTATE_CW 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_PRE BUTTON_SELECT
45#define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
46
47#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
48 (CONFIG_KEYPAD == IRIVER_H300_PAD)
49
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
58
59#define ROCKBLOX_RC_OFF BUTTON_RC_STOP
60
61#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
62
63#define ROCKBLOX_OFF BUTTON_POWER
64#define ROCKBLOX_ROTATE_CCW BUTTON_UP
65#define ROCKBLOX_ROTATE_CW BUTTON_SELECT
66#define ROCKBLOX_DOWN BUTTON_DOWN
67#define ROCKBLOX_LEFT BUTTON_LEFT
68#define ROCKBLOX_RIGHT BUTTON_RIGHT
69#define ROCKBLOX_DROP BUTTON_REC
70#define ROCKBLOX_RESTART BUTTON_PLAY
71
72#elif CONFIG_KEYPAD == SANSA_E200_PAD
73
74#define ROCKBLOX_OFF BUTTON_POWER
75#define ROCKBLOX_ROTATE_CCW BUTTON_SCROLL_BACK
76#define ROCKBLOX_ROTATE_CCW2 BUTTON_UP
77#define ROCKBLOX_ROTATE_CW BUTTON_SCROLL_FWD
78#define ROCKBLOX_DOWN BUTTON_DOWN
79#define ROCKBLOX_LEFT BUTTON_LEFT
80#define ROCKBLOX_RIGHT BUTTON_RIGHT
81#define ROCKBLOX_DROP BUTTON_SELECT
82#define ROCKBLOX_RESTART BUTTON_REC
83
84#elif CONFIG_KEYPAD == SANSA_FUZE_PAD
85
86#define ROCKBLOX_OFF (BUTTON_HOME|BUTTON_REPEAT)
87#define ROCKBLOX_ROTATE_CCW BUTTON_SCROLL_BACK
88#define ROCKBLOX_ROTATE_CCW2 BUTTON_UP
89#define ROCKBLOX_ROTATE_CW BUTTON_SCROLL_FWD
90#define ROCKBLOX_DOWN BUTTON_DOWN
91#define ROCKBLOX_LEFT BUTTON_LEFT
92#define ROCKBLOX_RIGHT BUTTON_RIGHT
93#define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
94#define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_UP)
95
96
97#elif CONFIG_KEYPAD == SANSA_C200_PAD
98
99#define ROCKBLOX_OFF BUTTON_POWER
100#define ROCKBLOX_ROTATE_CCW BUTTON_UP
101#define ROCKBLOX_ROTATE_CCW2 BUTTON_VOL_DOWN
102#define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
103#define ROCKBLOX_DOWN BUTTON_DOWN
104#define ROCKBLOX_LEFT BUTTON_LEFT
105#define ROCKBLOX_RIGHT BUTTON_RIGHT
106#define ROCKBLOX_DROP BUTTON_SELECT
107#define ROCKBLOX_RESTART BUTTON_REC
108
109#elif CONFIG_KEYPAD == SANSA_CLIP_PAD
110
111#define ROCKBLOX_OFF BUTTON_POWER
112#define ROCKBLOX_ROTATE_CCW BUTTON_UP
113#define ROCKBLOX_ROTATE_CCW2 BUTTON_VOL_DOWN
114#define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
115#define ROCKBLOX_DOWN BUTTON_DOWN
116#define ROCKBLOX_LEFT BUTTON_LEFT
117#define ROCKBLOX_RIGHT BUTTON_RIGHT
118#define ROCKBLOX_DROP BUTTON_SELECT
119#define ROCKBLOX_RESTART BUTTON_HOME
120
121#elif CONFIG_KEYPAD == SANSA_M200_PAD
122
123#define ROCKBLOX_OFF BUTTON_POWER
124#define ROCKBLOX_ROTATE_CCW BUTTON_UP
125#define ROCKBLOX_ROTATE_CCW2 BUTTON_VOL_DOWN
126#define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
127#define ROCKBLOX_DOWN BUTTON_DOWN
128#define ROCKBLOX_LEFT BUTTON_LEFT
129#define ROCKBLOX_RIGHT BUTTON_RIGHT
130#define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_UP)
131#define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
132
133#elif CONFIG_KEYPAD == IRIVER_H10_PAD
134
135#define ROCKBLOX_OFF BUTTON_POWER
136#define ROCKBLOX_ROTATE_CCW BUTTON_SCROLL_UP
137#define ROCKBLOX_ROTATE_CW BUTTON_REW
138#define ROCKBLOX_DOWN BUTTON_SCROLL_DOWN
139#define ROCKBLOX_LEFT BUTTON_LEFT
140#define ROCKBLOX_RIGHT BUTTON_RIGHT
141#define ROCKBLOX_DROP BUTTON_FF
142#define ROCKBLOX_RESTART BUTTON_PLAY
143
144#elif CONFIG_KEYPAD == GIGABEAT_PAD
145
146#define ROCKBLOX_OFF BUTTON_POWER
147#define ROCKBLOX_ROTATE_CCW BUTTON_VOL_DOWN
148#define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
149#define ROCKBLOX_ROTATE BUTTON_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_A
155
156#elif CONFIG_KEYPAD == MROBE500_PAD
157#define ROCKBLOX_OFF BUTTON_POWER
158
159#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
160#define ROCKBLOX_OFF BUTTON_BACK
161#define ROCKBLOX_ROTATE_CCW BUTTON_VOL_DOWN
162#define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
163#define ROCKBLOX_ROTATE BUTTON_UP
164#define ROCKBLOX_DOWN BUTTON_DOWN
165#define ROCKBLOX_LEFT BUTTON_LEFT
166#define ROCKBLOX_RIGHT BUTTON_RIGHT
167#define ROCKBLOX_DROP BUTTON_SELECT
168#define ROCKBLOX_RESTART BUTTON_PLAY
169
170#elif CONFIG_KEYPAD == MROBE100_PAD
171
172#define ROCKBLOX_OFF BUTTON_POWER
173#define ROCKBLOX_ROTATE_CCW BUTTON_MENU
174#define ROCKBLOX_ROTATE_CW BUTTON_PLAY
175#define ROCKBLOX_ROTATE BUTTON_UP
176#define ROCKBLOX_DOWN BUTTON_DOWN
177#define ROCKBLOX_LEFT BUTTON_LEFT
178#define ROCKBLOX_RIGHT BUTTON_RIGHT
179#define ROCKBLOX_DROP BUTTON_SELECT
180#define ROCKBLOX_RESTART BUTTON_DISPLAY
181
182#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
183
184#define ROCKBLOX_OFF BUTTON_RC_REC
185#define ROCKBLOX_ROTATE_CCW BUTTON_RC_VOL_DOWN
186#define ROCKBLOX_ROTATE_CW BUTTON_RC_VOL_UP
187#define ROCKBLOX_DOWN BUTTON_RC_MENU
188#define ROCKBLOX_LEFT BUTTON_RC_REW
189#define ROCKBLOX_RIGHT BUTTON_RC_FF
190#define ROCKBLOX_DROP BUTTON_RC_PLAY
191#define ROCKBLOX_RESTART BUTTON_RC_MODE
192
193#elif CONFIG_KEYPAD == COWON_D2_PAD
194
195#define ROCKBLOX_OFF BUTTON_POWER
196#define ROCKBLOX_RESTART BUTTON_MENU
197
198#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
199#define ROCKBLOX_OFF BUTTON_BACK
200#define ROCKBLOX_ROTATE_CCW BUTTON_UP
201#define ROCKBLOX_ROTATE_CW BUTTON_PLAY
202#define ROCKBLOX_DOWN BUTTON_DOWN
203#define ROCKBLOX_LEFT BUTTON_LEFT
204#define ROCKBLOX_RIGHT BUTTON_RIGHT
205#define ROCKBLOX_DROP BUTTON_SELECT
206#define ROCKBLOX_RESTART BUTTON_CUSTOM
207
208#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD
209#define ROCKBLOX_OFF BUTTON_POWER
210#define ROCKBLOX_ROTATE_CCW BUTTON_VOL_DOWN
211#define ROCKBLOX_ROTATE_CCW2 BUTTON_UP
212#define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
213#define ROCKBLOX_DOWN BUTTON_DOWN
214#define ROCKBLOX_LEFT BUTTON_BACK
215#define ROCKBLOX_RIGHT BUTTON_MENU
216#define ROCKBLOX_DROP (BUTTON_PLAY|BUTTON_REL)
217#define ROCKBLOX_RESTART (BUTTON_PLAY|BUTTON_REPEAT)
218
219#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
220
221#define ROCKBLOX_OFF BUTTON_POWER
222#define ROCKBLOX_ROTATE_CCW BUTTON_VOL_DOWN
223#define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
224#define ROCKBLOX_ROTATE BUTTON_UP
225#define ROCKBLOX_DOWN BUTTON_DOWN
226#define ROCKBLOX_LEFT BUTTON_LEFT
227#define ROCKBLOX_RIGHT BUTTON_RIGHT
228#define ROCKBLOX_DROP BUTTON_SELECT
229#define ROCKBLOX_RESTART BUTTON_MENU
230
231#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
232
233#define ROCKBLOX_OFF BUTTON_POWER
234#define ROCKBLOX_ROTATE_CCW BUTTON_PREV
235#define ROCKBLOX_ROTATE_CW BUTTON_NEXT
236#define ROCKBLOX_ROTATE BUTTON_UP
237#define ROCKBLOX_DOWN BUTTON_DOWN
238#define ROCKBLOX_LEFT BUTTON_LEFT
239#define ROCKBLOX_RIGHT BUTTON_RIGHT
240#define ROCKBLOX_DROP BUTTON_PLAY
241#define ROCKBLOX_RESTART BUTTON_MENU
242
243# elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
244
245#define ROCKBLOX_OFF BUTTON_POWER
246#define ROCKBLOX_ROTATE_CCW BUTTON_VOL_DOWN
247#define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
248#define ROCKBLOX_ROTATE BUTTON_UP
249#define ROCKBLOX_DOWN BUTTON_DOWN
250#define ROCKBLOX_LEFT BUTTON_PREV
251#define ROCKBLOX_RIGHT BUTTON_NEXT
252#define ROCKBLOX_DROP BUTTON_PLAY
253#define ROCKBLOX_RESTART BUTTON_MENU
254
255#elif CONFIG_KEYPAD == ONDAVX747_PAD
256#define ROCKBLOX_OFF BUTTON_POWER
257#define ROCKBLOX_RESTART BUTTON_MENU
258#elif CONFIG_KEYPAD == ONDAVX777_PAD
259#define ROCKBLOX_OFF BUTTON_POWER
260
261#elif CONFIG_KEYPAD == SAMSUNG_YH92X_PAD
262
263#define ROCKBLOX_OFF BUTTON_FFWD
264#define ROCKBLOX_ROTATE_CCW BUTTON_UP
265#define ROCKBLOX_ROTATE_CW BUTTON_DOWN
266#define ROCKBLOX_DOWN BUTTON_REW
267#define ROCKBLOX_LEFT BUTTON_LEFT
268#define ROCKBLOX_RIGHT BUTTON_RIGHT
269#define ROCKBLOX_DROP BUTTON_PLAY
270
271#elif CONFIG_KEYPAD == SAMSUNG_YH820_PAD
272
273#define ROCKBLOX_OFF BUTTON_REW
274#define ROCKBLOX_ROTATE_CCW BUTTON_UP
275#define ROCKBLOX_ROTATE_CW BUTTON_DOWN
276#define ROCKBLOX_DOWN BUTTON_FFWD
277#define ROCKBLOX_LEFT BUTTON_LEFT
278#define ROCKBLOX_RIGHT BUTTON_RIGHT
279#define ROCKBLOX_DROP BUTTON_PLAY
280#define ROCKBLOX_RESTART BUTTON_REC
281
282#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
283
284#define ROCKBLOX_OFF BUTTON_REC
285#define ROCKBLOX_ROTATE_CCW BUTTON_PLAY
286#define ROCKBLOX_ROTATE_CW BUTTON_MENU
287#define ROCKBLOX_DOWN BUTTON_DOWN
288#define ROCKBLOX_LEFT BUTTON_PREV
289#define ROCKBLOX_RIGHT BUTTON_NEXT
290#define ROCKBLOX_DROP BUTTON_OK
291#define ROCKBLOX_RESTART BUTTON_CANCEL
292
293#elif CONFIG_KEYPAD == MPIO_HD200_PAD
294#define ROCKBLOX_OFF (BUTTON_REC|BUTTON_PLAY)
295#define ROCKBLOX_ROTATE_CCW BUTTON_REW
296#define ROCKBLOX_ROTATE_CW BUTTON_FF
297#define ROCKBLOX_DOWN BUTTON_FUNC
298#define ROCKBLOX_LEFT BUTTON_VOL_DOWN
299#define ROCKBLOX_RIGHT BUTTON_VOL_UP
300#define ROCKBLOX_DROP BUTTON_PLAY
301#define ROCKBLOX_RESTART BUTTON_REC
302
303#elif CONFIG_KEYPAD == MPIO_HD300_PAD
304#define ROCKBLOX_OFF (BUTTON_MENU|BUTTON_REPEAT)
305#define ROCKBLOX_ROTATE_CCW BUTTON_UP
306#define ROCKBLOX_ROTATE_CW BUTTON_DOWN
307#define ROCKBLOX_DOWN (BUTTON_ENTER | BUTTON_REL)
308#define ROCKBLOX_LEFT BUTTON_REW
309#define ROCKBLOX_RIGHT BUTTON_FF
310#define ROCKBLOX_DROP BUTTON_PLAY
311#define ROCKBLOX_RESTART BUTTON_REC
312
313#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
314#define ROCKBLOX_OFF BUTTON_POWER
315#define ROCKBLOX_ROTATE_CW BUTTON_BOTTOMRIGHT
316#define ROCKBLOX_ROTATE_CCW BUTTON_BOTTOMLEFT
317#define ROCKBLOX_DOWN BUTTON_SELECT
318#define ROCKBLOX_LEFT BUTTON_LEFT
319#define ROCKBLOX_RIGHT BUTTON_RIGHT
320#define ROCKBLOX_DROP_PRE BUTTON_DOWN
321#define ROCKBLOX_DROP BUTTON_DOWN|BUTTON_REL
322#define ROCKBLOX_ROTATE_CCW2 BUTTON_VOL_UP
323#define ROCKBLOX_ROTATE_CW2 BUTTON_VOL_DOWN
324
325#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
326#define ROCKBLOX_OFF BUTTON_POWER
327#define ROCKBLOX_ROTATE_CW BUTTON_NEXT
328#define ROCKBLOX_ROTATE_CCW BUTTON_PREV
329#define ROCKBLOX_DOWN BUTTON_DOWN
330#define ROCKBLOX_LEFT BUTTON_LEFT
331#define ROCKBLOX_RIGHT BUTTON_RIGHT
332#define ROCKBLOX_DROP BUTTON_SELECT
333#define ROCKBLOX_RESTART BUTTON_VOL_DOWN
334
335#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
336
337#define ROCKBLOX_OFF BUTTON_BACK
338#define ROCKBLOX_ROTATE_CCW BUTTON_POWER
339#define ROCKBLOX_ROTATE_CW BUTTON_MENU
340#define ROCKBLOX_ROTATE BUTTON_UP
341#define ROCKBLOX_DOWN BUTTON_DOWN
342#define ROCKBLOX_LEFT BUTTON_LEFT
343#define ROCKBLOX_RIGHT BUTTON_RIGHT
344#define ROCKBLOX_DROP BUTTON_SELECT
345#define ROCKBLOX_RESTART BUTTON_USER
346
347#elif CONFIG_KEYPAD == HM60X_PAD
348
349#define ROCKBLOX_OFF BUTTON_POWER
350#define ROCKBLOX_ROTATE_CCW (BUTTON_LEFT|BUTTON_POWER)
351#define ROCKBLOX_ROTATE_CW (BUTTON_RIGHT|BUTTON_POWER)
352#define ROCKBLOX_ROTATE BUTTON_UP
353#define ROCKBLOX_DOWN BUTTON_DOWN
354#define ROCKBLOX_LEFT BUTTON_LEFT
355#define ROCKBLOX_RIGHT BUTTON_RIGHT
356#define ROCKBLOX_DROP BUTTON_SELECT
357#define ROCKBLOX_RESTART (BUTTON_DOWN|BUTTON_POWER)
358
359#elif CONFIG_KEYPAD == HM801_PAD
360
361#define ROCKBLOX_OFF BUTTON_POWER
362#define ROCKBLOX_ROTATE_CCW BUTTON_PREV
363#define ROCKBLOX_ROTATE_CW BUTTON_NEXT
364#define ROCKBLOX_ROTATE BUTTON_UP
365#define ROCKBLOX_DOWN BUTTON_DOWN
366#define ROCKBLOX_LEFT BUTTON_LEFT
367#define ROCKBLOX_RIGHT BUTTON_RIGHT
368#define ROCKBLOX_DROP BUTTON_SELECT
369#define ROCKBLOX_RESTART BUTTON_PLAY
370
371#elif CONFIG_KEYPAD == SONY_NWZ_PAD
372#define ROCKBLOX_OFF (BUTTON_BACK|BUTTON_REPEAT)
373#define ROCKBLOX_ROTATE_CCW BUTTON_POWER
374#define ROCKBLOX_ROTATE_CW BUTTON_UP
375#define ROCKBLOX_DOWN BUTTON_DOWN
376#define ROCKBLOX_LEFT BUTTON_LEFT
377#define ROCKBLOX_RIGHT BUTTON_RIGHT
378#define ROCKBLOX_DROP BUTTON_PLAY
379#define ROCKBLOX_RESTART BUTTON_BACK
380
381#elif CONFIG_KEYPAD == CREATIVE_ZEN_PAD
382#define ROCKBLOX_OFF BUTTON_BACK
383#define ROCKBLOX_ROTATE_CCW BUTTON_MENU
384#define ROCKBLOX_ROTATE_CW BUTTON_UP
385#define ROCKBLOX_DOWN BUTTON_DOWN
386#define ROCKBLOX_LEFT BUTTON_LEFT
387#define ROCKBLOX_RIGHT BUTTON_RIGHT
388#define ROCKBLOX_DROP BUTTON_SELECT
389#define ROCKBLOX_RESTART BUTTON_SHORTCUT
390
391#elif CONFIG_KEYPAD == DX50_PAD
392#define ROCKBLOX_OFF BUTTON_POWER
393#define ROCKBLOX_ROTATE BUTTON_RIGHT
394#define ROCKBLOX_LEFT BUTTON_LEFT
395#define ROCKBLOX_RIGHT BUTTON_PLAY
396#define ROCKBLOX_DROP BUTTON_VOL_DOWN
397#define ROCKBLOX_RESTART BUTTON_VOL_UP
398
399#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD
400#define ROCKBLOX_OFF BUTTON_POWER
401#define ROCKBLOX_ROTATE BUTTON_MENU
402
403#elif CONFIG_KEYPAD == AGPTEK_ROCKER_PAD
404#define ROCKBLOX_OFF BUTTON_POWER
405#define ROCKBLOX_LEFT BUTTON_LEFT
406#define ROCKBLOX_RIGHT BUTTON_RIGHT
407#define ROCKBLOX_DROP BUTTON_UP
408#define ROCKBLOX_RESTART (BUTTON_SELECT|BUTTON_LEFT)
409#define ROCKBLOX_ROTATE_CW BUTTON_VOLUP
410#define ROCKBLOX_ROTATE_CCW BUTTON_VOLDOWN
411#define ROCKBLOX_DOWN BUTTON_DOWN
412
413#elif (CONFIG_KEYPAD == XDUOO_X3_PAD) || (CONFIG_KEYPAD == XDUOO_X3II_PAD) || (CONFIG_KEYPAD == XDUOO_X20_PAD)
414
415#define ROCKBLOX_OFF BUTTON_POWER
416#define ROCKBLOX_ROTATE_CCW BUTTON_HOME
417#define ROCKBLOX_ROTATE_CCW2 BUTTON_VOL_DOWN
418#define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
419#define ROCKBLOX_DOWN BUTTON_OPTION
420#define ROCKBLOX_LEFT BUTTON_PREV
421#define ROCKBLOX_RIGHT BUTTON_NEXT
422#define ROCKBLOX_DROP (BUTTON_PLAY|BUTTON_REL)
423#define ROCKBLOX_RESTART (BUTTON_PLAY|BUTTON_REPEAT)
424
425#elif CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD
426
427#define ROCKBLOX_OFF BUTTON_POWER
428#define ROCKBLOX_ROTATE_CCW BUTTON_HOME
429#define ROCKBLOX_ROTATE_CCW2 BUTTON_VOL_DOWN
430#define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
431#define ROCKBLOX_DOWN BUTTON_OPTION
432#define ROCKBLOX_LEFT BUTTON_PREV
433#define ROCKBLOX_RIGHT BUTTON_NEXT
434#define ROCKBLOX_DROP (BUTTON_PLAY|BUTTON_REL)
435#define ROCKBLOX_RESTART (BUTTON_PLAY|BUTTON_REPEAT)
436#define ROCKBLOX_SCROLL_ENABLED 1 //Untested Probably needed
437
438#elif (CONFIG_KEYPAD == IHIFI_770_PAD) || (CONFIG_KEYPAD == IHIFI_800_PAD)
439
440#define ROCKBLOX_OFF BUTTON_POWER
441#define ROCKBLOX_ROTATE_CCW BUTTON_HOME
442#define ROCKBLOX_ROTATE_CCW2 BUTTON_VOL_DOWN
443#define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
444#define ROCKBLOX_DOWN BUTTON_PLAY
445#define ROCKBLOX_LEFT BUTTON_PREV
446#define ROCKBLOX_RIGHT BUTTON_NEXT
447#define ROCKBLOX_DROP (BUTTON_POWER|BUTTON_PLAY)
448#define ROCKBLOX_RESTART (BUTTON_POWER|BUTTON_REPEAT)
449
450#elif CONFIG_KEYPAD == EROSQ_PAD
451#define ROCKBLOX_OFF BUTTON_POWER
452#define ROCKBLOX_ROTATE_CCW BUTTON_SCROLL_BACK
453#define ROCKBLOX_ROTATE_CW BUTTON_SCROLL_FWD
454#define ROCKBLOX_DOWN BUTTON_MENU
455#define ROCKBLOX_LEFT BUTTON_PREV
456#define ROCKBLOX_RIGHT BUTTON_NEXT
457#define ROCKBLOX_DROP BUTTON_PLAY
458#define ROCKBLOX_RESTART BUTTON_BACK
459
460#elif CONFIG_KEYPAD == FIIO_M3K_PAD
461#define ROCKBLOX_OFF BUTTON_POWER
462#define ROCKBLOX_ROTATE_CCW BUTTON_UP
463#define ROCKBLOX_ROTATE_CW BUTTON_DOWN
464#define ROCKBLOX_DOWN BUTTON_SELECT
465#define ROCKBLOX_LEFT BUTTON_LEFT
466#define ROCKBLOX_RIGHT BUTTON_RIGHT
467#define ROCKBLOX_DROP BUTTON_PLAY
468#define ROCKBLOX_RESTART BUTTON_BACK
469#define ROCKBLOX_SCROLL_ENABLED 1
470
471#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
472/* use touchscreen */
473
474#elif CONFIG_KEYPAD == SDL_PAD
475/* use SDL keys */
476#elif CONFIG_KEYPAD == MA_PAD
477#define ROCKBLOX_OFF (BUTTON_BACK|BUTTON_REPEAT)
478#define ROCKBLOX_ROTATE_CCW BUTTON_UP
479#define ROCKBLOX_ROTATE_CW BUTTON_DOWN
480#define ROCKBLOX_DOWN BUTTON_PLAY
481#define ROCKBLOX_LEFT BUTTON_LEFT
482#define ROCKBLOX_RIGHT BUTTON_RIGHT
483#define ROCKBLOX_DROP BUTTON_MENU
484#define ROCKBLOX_RESTART BUTTON_BACK
485
486#elif CONFIG_KEYPAD == RG_NANO_PAD
487
488#define ROCKBLOX_OFF BUTTON_START
489#define ROCKBLOX_ROTATE_CCW BUTTON_X
490#define ROCKBLOX_ROTATE_CW BUTTON_Y
491#define ROCKBLOX_ROTATE BUTTON_UP
492#define ROCKBLOX_DOWN BUTTON_DOWN
493#define ROCKBLOX_LEFT BUTTON_LEFT
494#define ROCKBLOX_RIGHT BUTTON_RIGHT
495#define ROCKBLOX_DROP BUTTON_A
496#define ROCKBLOX_RESTART BUTTON_B
497
498#else
499#error No keymap defined!
500#endif
501
502#ifdef HAVE_TOUCHSCREEN
503#ifndef ROCKBLOX_OFF
504#define ROCKBLOX_OFF BUTTON_TOPLEFT
505#endif
506#ifdef ROCKBLOX_ROTATE_CCW
507#define ROCKBLOX_ROTATE_CCW2 BUTTON_BOTTOMLEFT
508#else
509#define ROCKBLOX_ROTATE_CCW BUTTON_BOTTOMLEFT
510#endif
511#ifdef ROCKBLOX_ROTATE_CW
512#define ROCKBLOX_ROTATE_CW2 BUTTON_BOTTOMRIGHT
513#else
514#define ROCKBLOX_ROTATE_CW BUTTON_BOTTOMRIGHT
515#define ROCKBLOX_ROTATE_CW2 BUTTON_TOPMIDDLE
516#endif
517#ifndef ROCKBLOX_DOWN
518#define ROCKBLOX_DOWN BUTTON_BOTTOMMIDDLE
519#endif
520#ifndef ROCKBLOX_LEFT
521#define ROCKBLOX_LEFT BUTTON_MIDLEFT
522#endif
523#ifndef ROCKBLOX_RIGHT
524#define ROCKBLOX_RIGHT BUTTON_MIDRIGHT
525#endif
526#ifndef ROCKBLOX_DROP
527#define ROCKBLOX_DROP BUTTON_CENTER
528#endif
529#ifndef ROCKBLOX_RESTART
530#define ROCKBLOX_RESTART BUTTON_TOPRIGHT
531#endif
532#endif
533
534#define BLOCKS_NUM 7
535#define EMPTY_BLOCK 7
536
537#define BOARD_WIDTH 10
538
539#define BOARD_HEIGHT 20
540
541#if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
542
543#define BLOCK_WIDTH 24
544#define BLOCK_HEIGHT 24
545#define BOARD_X 172
546#define BOARD_Y 0
547#define PREVIEW_X 24
548#define PREVIEW_Y 22
549#define LABEL_X 482
550#define SCORE_Y 50
551#define LEVEL_Y 140
552#define LINES_Y 210
553
554#elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640)
555
556#define BLOCK_WIDTH 30
557#define BLOCK_HEIGHT 30
558#define BOARD_X 14
559#define BOARD_Y 2
560#define PREVIEW_X 342
561#define PREVIEW_Y 482
562#define LABEL_X 344
563#define SCORE_Y 58
564#define LEVEL_Y 142
565#define LINES_Y 218
566
567#elif (LCD_WIDTH == 360) && (LCD_HEIGHT == 400)
568
569#define BLOCK_WIDTH 19
570#define BLOCK_HEIGHT 19
571#define BOARD_X 27
572#define BOARD_Y 0
573#define LABEL_X 258
574#define SCORE_Y 40
575#define LEVEL_Y 92
576#define LINES_Y 140
577#define HIGH_LABEL_X 258
578#define HIGH_SCORE_Y 200
579#define HIGH_LEVEL_Y 258
580#define PREVIEW_X 258
581#define PREVIEW_Y 300
582
583#elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
584
585#define BLOCK_WIDTH 12
586#define BLOCK_HEIGHT 12
587#define BOARD_X 86
588#define BOARD_Y 0
589#define PREVIEW_X 12
590#define PREVIEW_Y 11
591#define LABEL_X 242
592#define SCORE_Y 25
593#define LEVEL_Y 70
594#define LINES_Y 105
595
596#elif (LCD_WIDTH == 240) && ((LCD_HEIGHT == 320) || (LCD_HEIGHT == 400))
597
598#define BLOCK_WIDTH 15
599#define BLOCK_HEIGHT 15
600#define BOARD_X 7
601#define BOARD_Y 1
602#define PREVIEW_X 171
603#define PREVIEW_Y 241
604#define LABEL_X 172
605#define SCORE_Y 29
606#define LEVEL_Y 71
607#define LINES_Y 109
608#define HIGH_LABEL_X 172
609#define HIGH_SCORE_Y 163
610#define HIGH_LEVEL_Y 172
611
612#elif (LCD_WIDTH == 240) && (LCD_HEIGHT == 240)
613
614#define BLOCK_WIDTH 12
615#define BLOCK_HEIGHT 12
616#define BOARD_X 20
617#define BOARD_Y 0
618#define PREVIEW_X 176
619#define PREVIEW_Y 187
620#define LABEL_X 172
621#define SCORE_Y 19
622#define LEVEL_Y 51
623#define LINES_Y 84
624#define HIGH_LABEL_X 172
625#define HIGH_SCORE_Y 122
626#define HIGH_LEVEL_Y 172
627
628#elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176)
629
630#define BLOCK_WIDTH 8
631#define BLOCK_HEIGHT 8
632#define BOARD_X 27
633#define BOARD_Y 5
634#define PREVIEW_X 158
635#define PREVIEW_Y 130
636#define LABEL_X 147
637#define SCORE_Y 20
638#define LEVEL_Y 65
639#define LINES_Y 100
640
641#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132)
642
643#define BLOCK_WIDTH 6
644#define BLOCK_HEIGHT 6
645#define BOARD_X 25
646#define BOARD_Y 1
647#define PREVIEW_X 126
648#define PREVIEW_Y 102
649#define LABEL_X 112
650#define SCORE_Y 17
651#define LEVEL_Y 49
652#define LINES_Y 81
653
654#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220)
655
656/* no room for the space in the highscore list */
657#define HIGHSCORE_SPACE ""
658
659#define BLOCK_WIDTH 10
660#define BLOCK_HEIGHT 10
661#define BOARD_X 6
662#define BOARD_Y 10
663#define PREVIEW_X 124
664#define PREVIEW_Y 174
665#define LABEL_X 117
666#define SCORE_Y 18
667#define LEVEL_Y 52
668#define LINES_Y 85
669#define HIGH_SCORE_Y 119
670#define HIGH_LEVEL_Y 126
671#define HIGH_LABEL_X 114
672
673#elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128)
674
675
676#define BLOCK_WIDTH 6
677#define BLOCK_HEIGHT 6
678#define BOARD_X 22
679#define BOARD_Y 3
680#define PREVIEW_X 114
681#define PREVIEW_Y 100
682#define LABEL_X 101
683#define SCORE_Y 17
684#define LEVEL_Y 49
685#define LINES_Y 82
686
687#elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110)
688
689#define BLOCK_WIDTH 5
690#define BLOCK_HEIGHT 5
691#define BOARD_X 14
692#define BOARD_Y 0
693#define PREVIEW_X 98
694#define PREVIEW_Y 88
695#define LABEL_X 80
696#define SCORE_Y 15
697#define LEVEL_Y 45
698#define LINES_Y 74
699
700#elif (LCD_WIDTH == 132) && (LCD_HEIGHT == 80)
701
702#define BLOCK_WIDTH 4
703#define BLOCK_HEIGHT 4
704#define BOARD_X 10
705#define BOARD_Y 0
706#define PREVIEW_X 89
707#define PREVIEW_Y 61
708#define LABEL_X 78
709#define SCORE_Y 10
710#define LEVEL_Y 30
711#define LINES_Y 50
712
713#elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 128)
714
715#define BLOCK_WIDTH 6
716#define BLOCK_HEIGHT 6
717#define BOARD_X 4
718#define BOARD_Y 3
719#define PREVIEW_X 84
720#define PREVIEW_Y 100
721#define LABEL_X 71
722#define SCORE_Y 17
723#define LEVEL_Y 49
724#define LINES_Y 82
725
726#elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 160)
727
728#define BLOCK_WIDTH 7
729#define BLOCK_HEIGHT 7
730#define BOARD_X 4
731#define BOARD_Y 5
732#define PREVIEW_X 88
733#define PREVIEW_Y 111
734#define LABEL_X 82
735#define SCORE_Y (2+16)
736#define LEVEL_Y (36+16)
737#define LINES_Y (70+16)
738
739#elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 96)
740
741#define BLOCK_WIDTH 4
742#define BLOCK_HEIGHT 4
743#define BOARD_X 14
744#define BOARD_Y 2
745#define PREVIEW_X 89
746#define PREVIEW_Y 76
747#define LABEL_X 70
748#define SCORE_Y 14
749#define LEVEL_Y 39
750#define LINES_Y 64
751
752#elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64)
753
754#define BLOCK_WIDTH 3
755#define BLOCK_HEIGHT 3
756#define BOARD_X 9
757#define BOARD_Y 3
758#define PREVIEW_X 53
759#define PREVIEW_Y 5
760#define LABEL_X 70
761#define SCORE_Y 32
762#define LEVEL_Y 13
763#define LINES_Y 51
764
765#elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
766
767#define BLOCK_WIDTH 4
768#define BLOCK_HEIGHT 3
769#define BOARD_X 9
770#define BOARD_Y 3
771#define PREVIEW_X 59
772#define PREVIEW_Y 5
773#define LABEL_X 59
774#define SCORE_Y 32
775#define LEVEL_Y 13
776#define LEVEL_X 78
777#define LINES_Y 51
778
779#elif (LCD_WIDTH == 96) && (LCD_HEIGHT == 96)
780
781#define BLOCK_WIDTH 4
782#define BLOCK_HEIGHT 4
783#define BOARD_X 5
784#define BOARD_Y 4
785#define PREVIEW_X 64
786#define PREVIEW_Y 76
787#define LABEL_X 59
788#define SCORE_Y 15
789#define SCORE_X 58
790#define LEVEL_Y 39
791#define LEVEL_X 58
792#define LINES_Y 62
793#define LINES_X 58
794
795#else
796#error "lcd screen size not defined!"
797#endif
798
799#ifndef LEVEL_X
800#define LEVEL_X LABEL_X
801#endif
802
803#ifndef LINES_X
804#define LINES_X LABEL_X
805#endif
806
807extern const fb_data rockblox_background[];
808
809#ifndef HIGHSCORE_SPACE
810#define HIGHSCORE_SPACE " "
811#endif
812/* <<Explanation on Rockblox shapes>>
813
814 %%
815 %% - O has 1 orientation
816
817 %% %
818 %% %% - Z has 2 orientations
819 %
820
821 %% %
822 %% %% - S has 2 orientations
823 %
824 %
825 %
826 % %%%% - I has 2 orientations
827 %
828
829 % %%
830 % % % %%% - L has 4 orientations
831 %% %%% % %
832
833 % %%
834 % % % %%% - J has 4 orientations
835 %% %%% % %
836
837 % % %%%
838 %% % %% % - T has 4 orientations
839 % %%% %
840*/
841
842/* c=current f=figure o=orientation n=next */
843static struct _rockblox_status
844{
845 int gameover;
846 int lines;
847 int level;
848 int score;
849 int cx; /* current piece, x-coord */
850 int cy; /* current piece, y-coord */
851 int cf; /* current figure number, index in figures[] */
852 int co; /* orientation of figure */
853 int nf; /* next figure */
854 int hf; /* hold figure */
855 bool dropped;
856 short board[BOARD_HEIGHT][BOARD_WIDTH]; /* 20 rows of 10 blocks */
857} rockblox_status;
858
859/* prototypes */
860static void draw_next_block(void);
861static void new_block(void);
862
863#ifdef HAVE_SCROLLWHEEL
864int wheel_events = 0, last_wheel_event = 0;
865#ifdef ROCKBLOX_SCROLL_ENABLED
866 /* Bugfix M3K has a scrollpad that is also up down buttons */
867 bool wheel_enabled = true;
868#else
869 bool wheel_enabled = false;
870#endif
871#endif
872
873static const short scoring[4] = { /* scoring for each number of lines */
874#if BOARD_HEIGHT == 20
875 40 /* single */ , 100 /* double */ , 300 /* triple */ , 1200 /* rockblox */
876#elif BOARD_HEIGHT == 14 /* Player special values */
877 60 /* single */ , 150 /* double */ , 500 /* triple */ , 2000 /* rockblox */
878#endif
879};
880
881struct figure
882{
883#if LCD_DEPTH >= 2
884 unsigned int color[3]; /* color of figure (light,middle,shadow) */
885#endif
886 unsigned short max_or; /* max orientations */
887 signed short shapeX[4], shapeY[4]; /* implementation of figures */
888}
889
890/* array of figures */
891 figures[BLOCKS_NUM] = {
892 /* O */
893 {
894#if LCD_DEPTH >= 16
895 {LCD_RGBPACK (153, 255, 255), LCD_RGBPACK(0, 255, 255),
896 LCD_RGBPACK(0,153,153)},
897#elif LCD_DEPTH == 2
898 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
899#endif
900 1,
901 {-1, 0, -1, 0},
902 {0, 0, 1, 1}
903 },
904 /* I */
905 {
906#if LCD_DEPTH >= 16
907 {LCD_RGBPACK (255, 153, 128), LCD_RGBPACK (255, 0, 0),
908 LCD_RGBPACK (153, 0, 0)},
909#elif LCD_DEPTH == 2
910 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
911#endif
912 2,
913 {-2, -1, 0, 1},
914 {0, 0, 0, 0}
915 },
916 /* 'Z' */
917 {
918#if LCD_DEPTH >= 16
919 {LCD_RGBPACK (153, 255, 153), LCD_RGBPACK (0, 255, 0),
920 LCD_RGBPACK (0, 153, 0)},
921#elif LCD_DEPTH == 2
922 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
923#endif
924 2,
925 {0, 1, -1, 0},
926 {0, 0, 1, 1}
927 },
928 /* 'S' */
929 {
930#if LCD_DEPTH >= 16
931 {LCD_RGBPACK (153, 153, 255), LCD_RGBPACK (0, 0, 255),
932 LCD_RGBPACK (0, 0, 153)},
933#elif LCD_DEPTH == 2
934 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
935#endif
936 2,
937 {-1, 0, 0, 1},
938 {0, 0, 1, 1}
939 },
940 /* 'L' */
941 {
942#if LCD_DEPTH >= 16
943 {LCD_RGBPACK (255, 255, 153), LCD_RGBPACK (255, 255, 0),
944 LCD_RGBPACK (153, 153, 0)},
945#elif LCD_DEPTH == 2
946 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
947#endif
948 4,
949 {-1, 0, 1, 1},
950 {0, 0, 0, 1}
951 },
952 /* 'J' */
953 {
954#if LCD_DEPTH >= 16
955 {LCD_RGBPACK (255, 153, 255), LCD_RGBPACK (255, 0, 255),
956 LCD_RGBPACK (153, 0, 153)},
957#elif LCD_DEPTH == 2
958 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
959#endif
960 4,
961 {-1, 0, 1, -1},
962 {0, 0, 0, 1}
963 },
964 /* 'T' */
965 {
966#if LCD_DEPTH >= 16
967 {LCD_RGBPACK (204, 204, 204), LCD_RGBPACK (153, 153, 153),
968 LCD_RGBPACK (85, 85, 85)},
969#elif LCD_DEPTH == 2
970 {LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY},
971#endif
972 4,
973 {-1, 0, 1, 0},
974 {0, 0, 0, 1}
975 }
976 };
977
978#if LCD_DEPTH >=2
979unsigned int ghost_colors[BLOCKS_NUM][3]; /* same format as figure.colors[] */
980#endif
981bool resume = false;
982bool resume_file = false;
983
984/* Rockbox File System only supports full filenames inc dir */
985#define SCORE_FILE PLUGIN_GAMES_DATA_DIR "/rockblox.score"
986#define RESUME_FILE PLUGIN_GAMES_DATA_DIR "/rockblox.resume"
987#define NUM_SCORES 5
988
989/* Default High Scores... */
990struct highscore highscores[NUM_SCORES];
991
992/* get random number from (0) to (range-1) */
993static int t_rand (int range)
994{
995 return rb->rand () % range;
996}
997
998static inline void show_game_over (void)
999{
1000 rb->splash(HZ,"Game over!");
1001}
1002
1003/* init the board array to have no blocks */
1004static void init_board (void)
1005{
1006 int i, j;
1007 for (i = 0; i < BOARD_WIDTH; i++)
1008 for (j = 0; j < BOARD_HEIGHT; j++)
1009 rockblox_status.board[j][i] = EMPTY_BLOCK;
1010}
1011
1012/* show the score, level and lines */
1013static void show_details (void)
1014{
1015#if LCD_DEPTH >= 2
1016 rb->lcd_set_foreground (LCD_BLACK);
1017 rb->lcd_set_background (LCD_WHITE);
1018#endif
1019 rb->lcd_putsxyf (LABEL_X, SCORE_Y, "%d", rockblox_status.score);
1020 rb->lcd_putsxyf (LEVEL_X, LEVEL_Y, "%d", rockblox_status.level);
1021 rb->lcd_putsxyf (LINES_X, LINES_Y, "%d", rockblox_status.lines);
1022}
1023
1024#ifdef HIGH_SCORE_Y
1025static void show_highscores (void)
1026{
1027 int i;
1028
1029 for (i = 0; i<NUM_SCORES; i++)
1030 rb->lcd_putsxyf (HIGH_LABEL_X, HIGH_SCORE_Y + (10 * i),
1031 "%06d" HIGHSCORE_SPACE "L%1d", highscores[i].score, highscores[i].level);
1032}
1033#endif
1034
1035static void load_game(void)
1036{
1037 int fd;
1038
1039 resume = false;
1040
1041 fd = rb->open(RESUME_FILE, O_RDONLY);
1042 if (fd < 0) return;
1043
1044 if (rb->read(fd, &rockblox_status, sizeof(struct _rockblox_status))
1045 < (ssize_t)sizeof(struct _rockblox_status))
1046 {
1047 rb->splash(HZ/2, "Loading failed");
1048 } else {
1049 resume = true;
1050 }
1051
1052 rb->close(fd);
1053
1054 return;
1055}
1056
1057static void dump_resume(void)
1058{
1059 int fd;
1060
1061 fd = rb->open(RESUME_FILE, O_WRONLY|O_CREAT, 0666);
1062 if (fd < 0)
1063 goto fail;
1064
1065 if (rb->write(fd, &rockblox_status, sizeof(struct _rockblox_status))
1066 <= 0)
1067 {
1068 rb->close(fd);
1069 goto fail;
1070 }
1071 rb->close(fd);
1072 return;
1073
1074fail:
1075 rb->splash(HZ/2, "Saving failed");
1076 return;
1077}
1078
1079static void init_rockblox (bool resume)
1080{
1081 char score_name[50];
1082 struct tm* tm;
1083
1084 tm = rb->get_time();
1085 rb->snprintf(score_name, sizeof(score_name), "%04d%02d%02d %02d%02d%02d",
1086 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1087 tm->tm_hour, tm->tm_min, tm->tm_sec);
1088
1089 rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1090 if (!resume)
1091 {
1092 rockblox_status.level = 1;
1093 rockblox_status.lines = 0;
1094 rockblox_status.score = 0;
1095 rockblox_status.nf = t_rand(BLOCKS_NUM);
1096 init_board ();
1097 new_block ();
1098 }
1099 draw_next_block();
1100
1101 show_details ();
1102#ifdef HIGH_SCORE_Y
1103 show_highscores ();
1104#endif
1105}
1106
1107static inline int level_speed(int level)
1108{
1109#if BOARD_HEIGHT == 20
1110 return (5*HZ) / (level + 9);
1111#elif BOARD_HEIGHT == 14
1112 return (7*HZ) / (level + 9);
1113#endif
1114}
1115
1116static int getRelativeX (int figure, int square, int orientation)
1117{
1118 switch (orientation) {
1119 case 0:
1120 return figures[figure].shapeX[square];
1121 case 1:
1122 return figures[figure].shapeY[square];
1123 case 2:
1124 return -figures[figure].shapeX[square];
1125 case 3:
1126 return -figures[figure].shapeY[square];
1127 default:
1128 return 0;
1129 }
1130}
1131
1132static int getRelativeY (int figure, int square, int orientation)
1133{
1134 switch (orientation) {
1135 case 0:
1136 return figures[figure].shapeY[square];
1137 case 1:
1138 return -figures[figure].shapeX[square];
1139 case 2:
1140 return -figures[figure].shapeY[square];
1141 case 3:
1142 return figures[figure].shapeX[square];
1143 default:
1144 return 0;
1145 }
1146}
1147
1148static bool canMoveTo (int x, int y, int newOrientation)
1149{
1150 int i, rx, ry;
1151 for (i = 0; i < 4; i++) {
1152 ry = getRelativeY (rockblox_status.cf, i, newOrientation) + y;
1153 rx = getRelativeX (rockblox_status.cf, i, newOrientation) + x;
1154 if ((rx < 0 || rx >= BOARD_WIDTH) ||
1155 (ry < 0 || ry >= BOARD_HEIGHT) ||
1156 (rockblox_status.board[ry][rx] != EMPTY_BLOCK))
1157 return false;
1158 }
1159 return true;
1160}
1161
1162/* redraw the while board on the screen */
1163static void refresh_board (void)
1164{
1165 int i, j, x, y, block;
1166
1167#if LCD_DEPTH >= 2
1168 rb->lcd_set_foreground (LCD_BLACK);
1169#elif LCD_DEPTH == 1
1170 mylcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID);
1171#endif
1172
1173 mylcd_fillrect (BOARD_X, BOARD_Y, BOARD_WIDTH * BLOCK_WIDTH,
1174 BOARD_HEIGHT * BLOCK_HEIGHT);
1175
1176#if LCD_DEPTH == 1
1177 mylcd_set_drawmode (DRMODE_SOLID);
1178#endif
1179
1180 /* draw board (not including current piece) */
1181
1182 for (i = 0; i < BOARD_WIDTH; i++)
1183 for (j = 0; j < BOARD_HEIGHT; j++) {
1184 block = rockblox_status.board[j][i];
1185 if (block != EMPTY_BLOCK) {
1186#if LCD_DEPTH >= 2
1187 /* middle drawing */
1188 rb->lcd_set_foreground (figures[block].color[1]);
1189#endif
1190 rb->lcd_fillrect (BOARD_X + i * BLOCK_WIDTH,
1191 BOARD_Y + j * BLOCK_HEIGHT,
1192 BLOCK_WIDTH, BLOCK_HEIGHT);
1193#if LCD_DEPTH >= 2
1194 /* light drawing */
1195 rb->lcd_set_foreground (figures[block].color[0]);
1196#endif
1197 rb->lcd_vline (BOARD_X + i * BLOCK_WIDTH,
1198 BOARD_Y + j * BLOCK_HEIGHT,
1199 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 2);
1200 rb->lcd_hline (BOARD_X + i * BLOCK_WIDTH,
1201 BOARD_X + (i + 1) * BLOCK_WIDTH - 2,
1202 BOARD_Y + j * BLOCK_HEIGHT);
1203#if LCD_DEPTH >= 2
1204 /* shadow drawing */
1205 rb->lcd_set_foreground (figures[block].color[2]);
1206#endif
1207 rb->lcd_vline (BOARD_X + (i + 1) * BLOCK_WIDTH - 1,
1208 BOARD_Y + j * BLOCK_HEIGHT + 1,
1209 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 1);
1210 rb->lcd_hline (BOARD_X + i * BLOCK_WIDTH + 1,
1211 BOARD_X + (i + 1) * BLOCK_WIDTH - 1,
1212 BOARD_Y + (j + 1) * BLOCK_HEIGHT - 1);
1213 }
1214 }
1215
1216 /* draw ghost piece first so that it appears underneath the "real" piece */
1217
1218 int ghost_y=rockblox_status.cy;
1219
1220 /* find the position to draw it in */
1221 while(canMoveTo(rockblox_status.cx, ghost_y+1, rockblox_status.co))
1222 ghost_y++;
1223
1224 for (i = 0; i < 4; i++) {
1225 x = getRelativeX (rockblox_status.cf, i, rockblox_status.co)
1226 + rockblox_status.cx;
1227 y = getRelativeY (rockblox_status.cf, i, rockblox_status.co)
1228 + ghost_y;
1229#if LCD_DEPTH >= 2
1230 /* middle drawing */
1231 rb->lcd_set_foreground (ghost_colors[rockblox_status.cf][0]);
1232#endif
1233 rb->lcd_fillrect (BOARD_X + x * BLOCK_WIDTH,
1234 BOARD_Y + y * BLOCK_HEIGHT,
1235 BLOCK_WIDTH, BLOCK_HEIGHT);
1236#if LCD_DEPTH >= 2
1237 /* light drawing */
1238 rb->lcd_set_foreground (ghost_colors[rockblox_status.cf][1]);
1239#endif
1240 rb->lcd_vline (BOARD_X + x * BLOCK_WIDTH, BOARD_Y + y * BLOCK_HEIGHT,
1241 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 2);
1242 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH,
1243 BOARD_X + (x + 1) * BLOCK_WIDTH - 2,
1244 BOARD_Y + y * BLOCK_HEIGHT);
1245#if LCD_DEPTH >= 2
1246 /* shadow drawing */
1247 rb->lcd_set_foreground (ghost_colors[rockblox_status.cf][2]);
1248#endif
1249 rb->lcd_vline (BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1250 BOARD_Y + y * BLOCK_HEIGHT + 1,
1251 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1252 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH + 1,
1253 BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1254 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1255 }
1256
1257 /* draw current piece */
1258
1259 for (i = 0; i < 4; i++) {
1260 x = getRelativeX (rockblox_status.cf, i, rockblox_status.co)
1261 + rockblox_status.cx;
1262 y = getRelativeY (rockblox_status.cf, i, rockblox_status.co)
1263 + rockblox_status.cy;
1264#if LCD_DEPTH >= 2
1265 /* middle drawing */
1266 rb->lcd_set_foreground (figures[rockblox_status.cf].color[1]);
1267#endif
1268 rb->lcd_fillrect (BOARD_X + x * BLOCK_WIDTH,
1269 BOARD_Y + y * BLOCK_HEIGHT,
1270 BLOCK_WIDTH, BLOCK_HEIGHT);
1271#if LCD_DEPTH >= 2
1272 /* light drawing */
1273 rb->lcd_set_foreground (figures[rockblox_status.cf].color[0]);
1274#endif
1275 rb->lcd_vline (BOARD_X + x * BLOCK_WIDTH, BOARD_Y + y * BLOCK_HEIGHT,
1276 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 2);
1277 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH,
1278 BOARD_X + (x + 1) * BLOCK_WIDTH - 2,
1279 BOARD_Y + y * BLOCK_HEIGHT);
1280#if LCD_DEPTH >= 2
1281 /* shadow drawing */
1282 rb->lcd_set_foreground (figures[rockblox_status.cf].color[2]);
1283#endif
1284 rb->lcd_vline (BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1285 BOARD_Y + y * BLOCK_HEIGHT + 1,
1286 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1287 rb->lcd_hline (BOARD_X + x * BLOCK_WIDTH + 1,
1288 BOARD_X + (x + 1) * BLOCK_WIDTH - 1,
1289 BOARD_Y + (y + 1) * BLOCK_HEIGHT - 1);
1290 }
1291
1292 mylcd_update ();
1293}
1294
1295/* draws the preview of next block in the preview window */
1296static void draw_next_block (void)
1297{
1298 int i, rx, ry;
1299 /* clear preview window first */
1300#if LCD_DEPTH >= 2
1301 rb->lcd_set_foreground (LCD_BLACK);
1302#elif LCD_DEPTH == 1
1303 mylcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID);
1304#endif
1305
1306 /* 4x4 */
1307 mylcd_fillrect (PREVIEW_X, PREVIEW_Y, BLOCK_WIDTH * 4, BLOCK_HEIGHT * 4);
1308
1309#if LCD_DEPTH == 1
1310 mylcd_set_drawmode (DRMODE_SOLID);
1311#endif
1312
1313 /* draw the lightgray rectangles */
1314#if LCD_DEPTH >= 16
1315 rb->lcd_set_foreground (LCD_RGBPACK (40, 40, 40));
1316#elif LCD_DEPTH == 2
1317 rb->lcd_set_foreground (LCD_DARKGRAY);
1318#endif
1319
1320#if LCD_DEPTH >= 2
1321 for (rx = 0; rx < 4; rx++)
1322 for (ry = 0; ry < 4; ry++)
1323 rb->lcd_drawrect (PREVIEW_X + rx * BLOCK_WIDTH,
1324 PREVIEW_Y + ry * BLOCK_HEIGHT, BLOCK_WIDTH,
1325 BLOCK_HEIGHT);
1326#endif
1327
1328 /* draw the figure */
1329 for (i = 0; i < 4; i++) {
1330 rx = getRelativeX (rockblox_status.nf, i, 0) + 2;
1331 ry = getRelativeY (rockblox_status.nf, i, 0) + 2;
1332#if LCD_DEPTH >= 2
1333 rb->lcd_set_foreground (figures[rockblox_status.nf].color[1]); /* middle drawing */
1334#endif
1335 rb->lcd_fillrect (PREVIEW_X + rx * BLOCK_WIDTH,
1336 PREVIEW_Y + ry * BLOCK_HEIGHT,
1337 BLOCK_WIDTH, BLOCK_HEIGHT);
1338#if LCD_DEPTH >= 2
1339 rb->lcd_set_foreground (figures[rockblox_status.nf].color[0]); /* light drawing */
1340#endif
1341 rb->lcd_vline (PREVIEW_X + rx * BLOCK_WIDTH,
1342 PREVIEW_Y + ry * BLOCK_HEIGHT,
1343 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 2);
1344 rb->lcd_hline (PREVIEW_X + rx * BLOCK_WIDTH,
1345 PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 2,
1346 PREVIEW_Y + ry * BLOCK_HEIGHT);
1347#if LCD_DEPTH >= 2
1348 rb->lcd_set_foreground (figures[rockblox_status.nf].color[2]); /* shadow drawing */
1349#endif
1350 rb->lcd_vline (PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 1,
1351 PREVIEW_Y + ry * BLOCK_HEIGHT + 1,
1352 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 1);
1353 rb->lcd_hline (PREVIEW_X + rx * BLOCK_WIDTH + 1,
1354 PREVIEW_X + (rx + 1) * BLOCK_WIDTH - 1,
1355 PREVIEW_Y + (ry + 1) * BLOCK_HEIGHT - 1);
1356 }
1357
1358}
1359
1360/* move the block to a relative location */
1361static void move_block (int x, int y, int o)
1362{
1363 if (!rockblox_status.dropped && canMoveTo (rockblox_status.cx + x, rockblox_status.cy + y, o)) {
1364 rockblox_status.cy += y;
1365 rockblox_status.cx += x;
1366 rockblox_status.co = o;
1367 }
1368}
1369
1370/* try to add a new block to play with (return true if gameover) */
1371static void new_block (void)
1372{
1373 rockblox_status.cy = 1;
1374 rockblox_status.cx = 5;
1375 rockblox_status.cf = rockblox_status.nf;
1376 rockblox_status.co = 0; /* start at the same orientation all time */
1377 rockblox_status.nf = t_rand (BLOCKS_NUM);
1378 rockblox_status.gameover = !canMoveTo (rockblox_status.cx,
1379 rockblox_status.cy, rockblox_status.co);
1380 rockblox_status.dropped = false;
1381
1382 draw_next_block ();
1383}
1384
1385
1386/* check for filled rockblox_status.lines and do what necessary */
1387static int check_lines (void)
1388
1389{
1390 int i, j, y;
1391 int rockblox = 0;
1392
1393 for (j = 0; j < BOARD_HEIGHT; j++) {
1394 for (i = 0; ((i < BOARD_WIDTH) &&
1395 (rockblox_status.board[j][i] != EMPTY_BLOCK)); i++);
1396 if (i == BOARD_WIDTH) { /* woo hoo, we have a line */
1397 rockblox++;
1398 for (y = j; y > 0; y--)
1399 {
1400 for (i = 0; i < BOARD_WIDTH; i++)
1401 { /* fall line */
1402 rockblox_status.board[y][i] = rockblox_status.board[y - 1][i];
1403 }
1404 }
1405 }
1406 }
1407
1408 return rockblox;
1409}
1410
1411/* moves down the figure and returns true if gameover */
1412static void move_down (void)
1413{
1414 int l, i, rx, ry;
1415
1416 if (!canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co)) {
1417 /* save figure to board */
1418 for (i = 0; i < 4; i++) {
1419 rx = getRelativeX (rockblox_status.cf, i, rockblox_status.co) + rockblox_status.cx;
1420 ry = getRelativeY (rockblox_status.cf, i, rockblox_status.co) + rockblox_status.cy;
1421 rockblox_status.board[ry][rx] = rockblox_status.cf;
1422 }
1423 /* check if formed some lines */
1424 l = check_lines ();
1425 if (l) {
1426 /* the original scoring from "http://en.wikipedia.org/wiki/Rockblox" */
1427 rockblox_status.score += scoring[l - 1] * rockblox_status.level;
1428 rockblox_status.lines += l;
1429 rockblox_status.level = (int) rockblox_status.lines / 10 + 1;
1430 }
1431
1432 /* show details */
1433 show_details ();
1434
1435 /* generate a new figure */
1436 new_block ();
1437 } else
1438 move_block (0, 1, rockblox_status.co);
1439}
1440
1441static bool rockblox_help(void)
1442{
1443 static char *help_text[] = {
1444 "Rockblox", "", "Aim", "",
1445 "Make", "the", "falling", "blocks", "of",
1446 "different", "shapes", "form", "full", "rows.",
1447 "Whenever", "a", "row", "is", "completed,",
1448 "it", "will", "be", "cleared", "away",
1449 "and", "you", "gain", "points."
1450 };
1451 static struct style_text formation[]={
1452 { 0, TEXT_CENTER|TEXT_UNDERLINE },
1453 { 2, C_RED },
1454 LAST_STYLE_ITEM
1455 };
1456
1457 rb->lcd_setfont(FONT_UI);
1458#ifdef HAVE_LCD_COLOR
1459 rb->lcd_set_background(LCD_BLACK);
1460 rb->lcd_set_foreground(LCD_WHITE);
1461#endif
1462 if (display_text(ARRAYLEN(help_text), help_text, formation, NULL, true))
1463 return true;
1464 rb->lcd_setfont(FONT_SYSFIXED);
1465
1466 return false;
1467}
1468
1469static int rockblox_menu_cb(int action,
1470 const struct menu_item_ex *this_item,
1471 struct gui_synclist *this_list)
1472{
1473 (void)this_list;
1474 int i = ((intptr_t)this_item);
1475 if(action == ACTION_REQUEST_MENUITEM
1476 && !resume && (i==0 || i==5))
1477 return ACTION_EXIT_MENUITEM;
1478 return action;
1479}
1480
1481static int rockblox_menu(void)
1482{
1483 int selected = 0;
1484
1485 MENUITEM_STRINGLIST(main_menu, "Rockblox Menu", rockblox_menu_cb,
1486 "Resume Game", "Start New Game",
1487 "Help", "High Scores", "Playback Control",
1488 "Quit without Saving", "Quit");
1489
1490 rb->button_clear_queue();
1491 while (true) {
1492 switch (rb->do_menu(&main_menu, &selected, NULL, false)) {
1493 case 0:
1494 if(resume_file)
1495 rb->remove(RESUME_FILE);
1496 init_rockblox(true);
1497 return 0;
1498 case 1:
1499 init_rockblox(false);
1500 return 0;
1501 case 2:
1502 if (rockblox_help())
1503 return 1;
1504 break;
1505 case 3:
1506 highscore_show(-1, highscores, NUM_SCORES, true);
1507 break;
1508 case 4:
1509 if (playback_control(NULL))
1510 return 1;
1511 break;
1512 case 5:
1513 return 1;
1514 case 6:
1515 if (resume) {
1516 rb->splash(0, "Saving...");
1517 dump_resume();
1518 rb->lcd_update();
1519 }
1520 return 1;
1521 case MENU_ATTACHED_USB:
1522 return 1;
1523 default:
1524 return 1;
1525 break;
1526 }
1527 }
1528}
1529
1530
1531static int rockblox_loop (void)
1532{
1533 int button;
1534#if defined(ROCKBLOX_OFF_PRE) || defined(ROCKBLOX_DROP_PRE)
1535 int lastbutton = BUTTON_NONE;
1536#endif
1537 long next_down_tick = *rb->current_tick + level_speed(rockblox_status.level);
1538
1539 if (rockblox_menu()) {
1540 return 1;
1541 }
1542 resume = false;
1543 resume_file = false;
1544
1545 while (1) {
1546#ifdef HAS_BUTTON_HOLD
1547 if (rb->button_hold ()) {
1548 /* Turn on backlight timeout (revert to settings) */
1549 backlight_use_settings();
1550 rb->splash(0, "Paused");
1551 while (rb->button_hold ())
1552 rb->sleep(HZ/10);
1553 /* Turn off backlight timeout */
1554 backlight_ignore_timeout();
1555
1556 /* get rid of the splash text */
1557 rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1558 show_details ();
1559#ifdef HIGH_SCORE_Y
1560 show_highscores ();
1561#endif
1562 draw_next_block ();
1563 refresh_board ();
1564 }
1565#endif
1566
1567 button = rb->button_get_w_tmo (MAX(next_down_tick - *rb->current_tick, 1));
1568 switch (button) {
1569#ifdef ROCKBLOX_RC_OFF
1570 case ROCKBLOX_RC_OFF:
1571#endif
1572 case ROCKBLOX_OFF:
1573#ifdef ROCKBLOX_OFF_PRE
1574 if (lastbutton != ROCKBLOX_OFF_PRE)
1575 break;
1576#endif
1577 resume = true;
1578 return 0;
1579 break;
1580
1581#if defined(ROCKBLOX_ROTATE)
1582 case ROCKBLOX_ROTATE:
1583#endif
1584 case ROCKBLOX_ROTATE_CCW:
1585 case ROCKBLOX_ROTATE_CCW | BUTTON_REPEAT:
1586#ifdef HAVE_SCROLLWHEEL
1587 /* if the wheel is disabled, add an event to the stack. */
1588 if(wheel_enabled == false)
1589 wheel_events++;
1590
1591 /* if it's enabled, go ahead and rotate.. */
1592 if(wheel_enabled)
1593#endif
1594#ifdef ROCKBLOX_ROTATE_CCW2
1595 /* fallback */
1596 case ROCKBLOX_ROTATE_CCW2:
1597#endif
1598 move_block (0, 0, (rockblox_status.co + 1) % figures[rockblox_status.cf].max_or);
1599 break;
1600
1601 case ROCKBLOX_ROTATE_CW:
1602 case ROCKBLOX_ROTATE_CW | BUTTON_REPEAT:
1603#ifdef HAVE_SCROLLWHEEL
1604 if(wheel_enabled == false)
1605 wheel_events++;
1606
1607 if(wheel_enabled)
1608#endif
1609#ifdef ROCKBLOX_ROTATE_CW2
1610 /* fallback */
1611 case ROCKBLOX_ROTATE_CW2:
1612#endif
1613 move_block (0, 0,
1614 (rockblox_status.co + figures[rockblox_status.cf].max_or -
1615 1) % figures[rockblox_status.cf].max_or);
1616 break;
1617
1618 case ROCKBLOX_DOWN:
1619 case ROCKBLOX_DOWN | BUTTON_REPEAT:
1620 move_block (0, 1, rockblox_status.co);
1621 break;
1622
1623 case ROCKBLOX_RIGHT:
1624 case ROCKBLOX_RIGHT | BUTTON_REPEAT:
1625 move_block (1, 0, rockblox_status.co);
1626 break;
1627
1628 case ROCKBLOX_LEFT:
1629 case ROCKBLOX_LEFT | BUTTON_REPEAT:
1630 move_block (-1, 0, rockblox_status.co);
1631 break;
1632
1633 case ROCKBLOX_DROP:
1634#ifdef ROCKBLOX_DROP_PRE
1635 if (lastbutton != ROCKBLOX_DROP_PRE)
1636 break;
1637#endif
1638 while (canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co))
1639 move_block (0, 1, rockblox_status.co);
1640 rockblox_status.dropped = true;
1641 break;
1642#ifdef ROCKBLOX_RESTART
1643 case ROCKBLOX_RESTART:
1644 rb->splash (HZ * 1, "Restarting...");
1645 init_rockblox (false);
1646 break;
1647#endif
1648
1649 default:
1650 if (rb->default_event_handler (button) == SYS_USB_CONNECTED)
1651 return PLUGIN_USB_CONNECTED;
1652 break;
1653 }
1654#if defined(ROCKBLOX_OFF_PRE) || defined(ROCKBLOX_DROP_PRE)
1655 if (button != BUTTON_NONE)
1656 lastbutton = button;
1657#endif
1658
1659#ifdef HAVE_SCROLLWHEEL
1660 /* check if we should enable the scroll wheel, if events
1661 * begin to stack up... */
1662 if(wheel_enabled == false)
1663 {
1664 /* stopped rotating the wheel, reset the count */
1665 if(wheel_events == last_wheel_event)
1666 {
1667 last_wheel_event = 0;
1668 wheel_events = 0;
1669 }
1670 /* rotated the wheel a while constantly, enable it. */
1671 else if(wheel_events > 3)
1672 {
1673 wheel_enabled = true;
1674 }
1675
1676 /* this evens out the last event and the "current" event.
1677 * if we get an event next time through button reading, it will
1678 * remain ahead of last_event. if we don't, they'll end up equaling
1679 * each other.. thus, the scroll count will be reset. */
1680 if(wheel_enabled == false && wheel_events > last_wheel_event)
1681 last_wheel_event++;
1682 }
1683#endif
1684
1685 if (TIME_AFTER(*rb->current_tick, next_down_tick)) {
1686 move_down ();
1687 next_down_tick += level_speed(rockblox_status.level);
1688 if (TIME_AFTER(*rb->current_tick, next_down_tick))
1689 /* restart time "raster" when we had to wait longer than usual
1690 * (pause, game restart etc) */
1691 next_down_tick = *rb->current_tick + level_speed(rockblox_status.level);
1692 }
1693
1694 if (rockblox_status.gameover) {
1695#if LCD_DEPTH >= 2
1696 rb->lcd_set_foreground (LCD_BLACK);
1697#endif
1698 show_game_over();
1699 resume = false;
1700 return 0;
1701 }
1702
1703 refresh_board ();
1704 }
1705
1706 return 0;
1707}
1708
1709enum plugin_status plugin_start (const void *parameter)
1710{
1711
1712 (void) parameter;
1713
1714 rb->srand (*rb->current_tick);
1715
1716 /* Load HighScore if any */
1717 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
1718
1719#if LCD_DEPTH > 1
1720 rb->lcd_set_backdrop(NULL);
1721#endif
1722
1723 rb->lcd_setfont (FONT_SYSFIXED);
1724
1725 /* Turn off backlight timeout */
1726 backlight_ignore_timeout();
1727
1728 load_game();
1729 resume_file = resume;
1730
1731#if LCD_DEPTH >= 2
1732 /* precalculate ghost piece colors */
1733
1734#ifdef HAVE_LCD_COLOR
1735 for(int p=0;p<BLOCKS_NUM;++p)
1736 {
1737 for(int i=0;i<3;++i)
1738 {
1739/* find red average */
1740 int red=0;
1741 red+=RGB_UNPACK_RED(figures[p].color[i])/4;
1742 /* green */
1743 int green=0;
1744 green+=RGB_UNPACK_GREEN(figures[p].color[i])/4;
1745 /* blue */
1746 int blue=0;
1747 blue+=RGB_UNPACK_BLUE(figures[p].color[i])/4;
1748 ghost_colors[p][i]=LCD_RGBPACK(red,green,blue);
1749 }
1750 }
1751#else /* greyscale or monochrome */
1752 for(int p=0;p<BLOCKS_NUM;++p)
1753 {
1754 for(int i=0;i<3;++i)
1755 ghost_colors[p][i]=figures[p].color[i]/2;
1756 }
1757#endif
1758#endif /* LCD_DEPTH >= 2 */
1759
1760 while(!rockblox_loop()) {
1761 if(!resume) {
1762 int position = highscore_update(rockblox_status.score,
1763 rockblox_status.level, "",
1764 highscores, NUM_SCORES);
1765 if (position != -1) {
1766 if (position == 0)
1767 rb->splashf(HZ*2, "New High Score: %d", rockblox_status.score);
1768 highscore_show(position, highscores, NUM_SCORES, true);
1769 }
1770 }
1771 }
1772
1773 /* Save user's HighScore */
1774 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
1775
1776 backlight_use_settings();
1777
1778 return PLUGIN_OK;
1779}