A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1779 lines 53 kB view raw
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}