A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1713 lines 58 kB view raw
1/*************************************************************************** 2* __________ __ ___. 3* Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7* \/ \/ \/ \/ \/ 8* $Id$ 9* 10* Copyright (C) 2005 Adam Boot 11* 12* Color graphics from Gweled (http://sebdelestaing.free.fr/gweled/) 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 24#include "plugin.h" 25#include "lib/display_text.h" 26#include "lib/highscore.h" 27#include "lib/playback_control.h" 28#include "pluginbitmaps/jewels.h" 29 30/* button definitions */ 31#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) 32#define JEWELS_UP BUTTON_UP 33#define JEWELS_DOWN BUTTON_DOWN 34#define JEWELS_LEFT BUTTON_LEFT 35#define JEWELS_RIGHT BUTTON_RIGHT 36#define JEWELS_SELECT BUTTON_SELECT 37#define JEWELS_CANCEL BUTTON_OFF 38#define JEWELS_RC_CANCEL BUTTON_RC_STOP 39#define HK_SELECT "SELECT" 40#define HK_CANCEL "OFF" 41 42#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ 43 (CONFIG_KEYPAD == IPOD_1G2G_PAD) 44#define JEWELS_SCROLLWHEEL 45#define JEWELS_UP BUTTON_MENU 46#define JEWELS_DOWN BUTTON_PLAY 47#define JEWELS_LEFT BUTTON_LEFT 48#define JEWELS_RIGHT BUTTON_RIGHT 49#define JEWELS_PREV BUTTON_SCROLL_BACK 50#define JEWELS_NEXT BUTTON_SCROLL_FWD 51#define JEWELS_SELECT BUTTON_SELECT 52#define JEWELS_CANCEL (BUTTON_SELECT | BUTTON_REPEAT) 53#define HK_SELECT "SELECT" 54#define HK_CANCEL "Long SELECT" 55 56#elif (CONFIG_KEYPAD == IPOD_3G_PAD) 57#define JEWELS_LEFT BUTTON_LEFT 58#define JEWELS_RIGHT BUTTON_RIGHT 59#define JEWELS_UP BUTTON_SCROLL_BACK 60#define JEWELS_DOWN BUTTON_SCROLL_FWD 61#define JEWELS_SELECT BUTTON_SELECT 62#define JEWELS_CANCEL BUTTON_MENU 63#define HK_SELECT "SELECT" 64#define HK_CANCEL "MENU" 65 66#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD 67#define JEWELS_UP BUTTON_UP 68#define JEWELS_DOWN BUTTON_DOWN 69#define JEWELS_LEFT BUTTON_LEFT 70#define JEWELS_RIGHT BUTTON_RIGHT 71#define JEWELS_SELECT BUTTON_SELECT 72#define JEWELS_CANCEL BUTTON_POWER 73#define HK_SELECT "SELECT" 74#define HK_CANCEL "POWER" 75 76#elif CONFIG_KEYPAD == GIGABEAT_PAD 77#define JEWELS_UP BUTTON_UP 78#define JEWELS_DOWN BUTTON_DOWN 79#define JEWELS_LEFT BUTTON_LEFT 80#define JEWELS_RIGHT BUTTON_RIGHT 81#define JEWELS_SELECT BUTTON_SELECT 82#define JEWELS_CANCEL BUTTON_POWER 83#define HK_SELECT "SELECT" 84#define HK_CANCEL "POWER" 85 86 87#elif CONFIG_KEYPAD == SONY_NWZ_PAD 88#define JEWELS_UP BUTTON_UP 89#define JEWELS_DOWN BUTTON_DOWN 90#define JEWELS_LEFT BUTTON_LEFT 91#define JEWELS_RIGHT BUTTON_RIGHT 92#define JEWELS_SELECT BUTTON_PLAY 93#define JEWELS_CANCEL BUTTON_BACK 94#define HK_SELECT "PLAY" 95#define HK_CANCEL "BACK" 96 97#elif CONFIG_KEYPAD == CREATIVE_ZEN_PAD 98#define JEWELS_UP BUTTON_UP 99#define JEWELS_DOWN BUTTON_DOWN 100#define JEWELS_LEFT BUTTON_LEFT 101#define JEWELS_RIGHT BUTTON_RIGHT 102#define JEWELS_SELECT BUTTON_SELECT 103#define JEWELS_CANCEL BUTTON_BACK 104#define HK_SELECT "SELECT" 105#define HK_CANCEL "BACK" 106 107 108#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \ 109 (CONFIG_KEYPAD == SANSA_CONNECT_PAD) 110#define JEWELS_SCROLLWHEEL 111#define JEWELS_UP BUTTON_UP 112#define JEWELS_DOWN BUTTON_DOWN 113#define JEWELS_LEFT BUTTON_LEFT 114#define JEWELS_RIGHT BUTTON_RIGHT 115#define JEWELS_PREV BUTTON_SCROLL_BACK 116#define JEWELS_NEXT BUTTON_SCROLL_FWD 117#define JEWELS_SELECT BUTTON_SELECT 118#define JEWELS_CANCEL BUTTON_POWER 119#define HK_SELECT "SELECT" 120#define HK_CANCEL "POWER" 121 122#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD) 123#define JEWELS_SCROLLWHEEL 124#define JEWELS_UP BUTTON_UP 125#define JEWELS_DOWN BUTTON_DOWN 126#define JEWELS_LEFT BUTTON_LEFT 127#define JEWELS_RIGHT BUTTON_RIGHT 128#define JEWELS_PREV BUTTON_SCROLL_BACK 129#define JEWELS_NEXT BUTTON_SCROLL_FWD 130#define JEWELS_SELECT BUTTON_SELECT 131#define JEWELS_CANCEL (BUTTON_HOME|BUTTON_REPEAT) 132#define HK_SELECT "SELECT" 133#define HK_CANCEL "HOME" 134 135#elif CONFIG_KEYPAD == SANSA_C200_PAD || \ 136CONFIG_KEYPAD == SANSA_CLIP_PAD || \ 137CONFIG_KEYPAD == SANSA_M200_PAD 138#define JEWELS_UP BUTTON_UP 139#define JEWELS_DOWN BUTTON_DOWN 140#define JEWELS_LEFT BUTTON_LEFT 141#define JEWELS_RIGHT BUTTON_RIGHT 142#define JEWELS_SELECT BUTTON_SELECT 143#define JEWELS_CANCEL BUTTON_POWER 144#define HK_SELECT "SELECT" 145#define HK_CANCEL "POWER" 146 147#elif CONFIG_KEYPAD == IRIVER_H10_PAD 148#define JEWELS_UP BUTTON_SCROLL_UP 149#define JEWELS_DOWN BUTTON_SCROLL_DOWN 150#define JEWELS_LEFT BUTTON_LEFT 151#define JEWELS_RIGHT BUTTON_RIGHT 152#define JEWELS_SELECT BUTTON_PLAY 153#define JEWELS_CANCEL BUTTON_POWER 154#define HK_SELECT "PLAY" 155#define HK_CANCEL "POWER" 156 157#elif CONFIG_KEYPAD == GIGABEAT_S_PAD || \ 158 CONFIG_KEYPAD == SAMSUNG_YPR0_PAD 159#define JEWELS_UP BUTTON_UP 160#define JEWELS_DOWN BUTTON_DOWN 161#define JEWELS_LEFT BUTTON_LEFT 162#define JEWELS_RIGHT BUTTON_RIGHT 163#define JEWELS_SELECT BUTTON_SELECT 164#define JEWELS_CANCEL BUTTON_BACK 165#define HK_SELECT "SELECT" 166#define HK_CANCEL "BACK" 167 168#elif CONFIG_KEYPAD == MROBE100_PAD 169#define JEWELS_UP BUTTON_UP 170#define JEWELS_DOWN BUTTON_DOWN 171#define JEWELS_LEFT BUTTON_LEFT 172#define JEWELS_RIGHT BUTTON_RIGHT 173#define JEWELS_SELECT BUTTON_SELECT 174#define JEWELS_CANCEL BUTTON_POWER 175#define HK_SELECT "SELECT" 176#define HK_CANCEL "POWER" 177 178#elif CONFIG_KEYPAD == IAUDIO_M3_PAD 179#define JEWELS_UP BUTTON_RC_VOL_UP 180#define JEWELS_DOWN BUTTON_RC_VOL_DOWN 181#define JEWELS_LEFT BUTTON_RC_REW 182#define JEWELS_RIGHT BUTTON_RC_FF 183#define JEWELS_SELECT BUTTON_RC_PLAY 184#define JEWELS_CANCEL BUTTON_RC_REC 185#define HK_SELECT "PLAY" 186#define HK_CANCEL "REC" 187 188#define JEWELS_RC_CANCEL BUTTON_REC 189 190#elif CONFIG_KEYPAD == COWON_D2_PAD 191#define JEWELS_CANCEL BUTTON_POWER 192#define HK_CANCEL "POWER" 193 194#elif CONFIG_KEYPAD == CREATIVEZVM_PAD 195#define JEWELS_UP BUTTON_UP 196#define JEWELS_DOWN BUTTON_DOWN 197#define JEWELS_LEFT BUTTON_LEFT 198#define JEWELS_RIGHT BUTTON_RIGHT 199#define JEWELS_SELECT BUTTON_SELECT 200#define JEWELS_CANCEL BUTTON_BACK 201#define HK_SELECT "MIDDLE" 202#define HK_CANCEL "BACK" 203 204#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD 205#define JEWELS_UP BUTTON_UP 206#define JEWELS_DOWN BUTTON_DOWN 207#define JEWELS_LEFT BUTTON_BACK 208#define JEWELS_RIGHT BUTTON_MENU 209#define JEWELS_SELECT BUTTON_VOL_UP 210#define JEWELS_CANCEL BUTTON_VOL_DOWN 211#define HK_SELECT "VOL+" 212#define HK_CANCEL "VOL-" 213 214#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD 215#define JEWELS_UP BUTTON_UP 216#define JEWELS_DOWN BUTTON_DOWN 217#define JEWELS_LEFT BUTTON_LEFT 218#define JEWELS_RIGHT BUTTON_RIGHT 219#define JEWELS_SELECT BUTTON_SELECT 220#define JEWELS_CANCEL BUTTON_POWER 221#define HK_SELECT "SELECT" 222#define HK_CANCEL "POWER" 223 224#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD 225#define JEWELS_UP BUTTON_UP 226#define JEWELS_DOWN BUTTON_DOWN 227#define JEWELS_LEFT BUTTON_LEFT 228#define JEWELS_RIGHT BUTTON_RIGHT 229#define JEWELS_SELECT BUTTON_PLAY 230#define JEWELS_CANCEL BUTTON_POWER 231#define HK_SELECT "PLAY" 232#define HK_CANCEL "POWER" 233 234#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD 235#define JEWELS_UP BUTTON_UP 236#define JEWELS_DOWN BUTTON_DOWN 237#define JEWELS_LEFT BUTTON_PREV 238#define JEWELS_RIGHT BUTTON_NEXT 239#define JEWELS_SELECT BUTTON_PLAY 240#define JEWELS_CANCEL BUTTON_POWER 241#define HK_SELECT "PLAY" 242#define HK_CANCEL "POWER" 243 244#elif CONFIG_KEYPAD == ONDAVX747_PAD || \ 245CONFIG_KEYPAD == ONDAVX777_PAD || \ 246CONFIG_KEYPAD == MROBE500_PAD 247#define JEWELS_CANCEL BUTTON_POWER 248#define HK_CANCEL "POWER" 249 250#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \ 251 (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD) 252#define JEWELS_UP BUTTON_UP 253#define JEWELS_DOWN BUTTON_DOWN 254#define JEWELS_LEFT BUTTON_LEFT 255#define JEWELS_RIGHT BUTTON_RIGHT 256#define JEWELS_SELECT BUTTON_PLAY 257#define JEWELS_CANCEL BUTTON_REW 258#define HK_SELECT "PLAY" 259#define HK_CANCEL "REWIND" 260 261#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD 262#define JEWELS_UP BUTTON_UP 263#define JEWELS_DOWN BUTTON_DOWN 264#define JEWELS_LEFT BUTTON_PREV 265#define JEWELS_RIGHT BUTTON_NEXT 266#define JEWELS_SELECT BUTTON_OK 267#define JEWELS_CANCEL BUTTON_REC 268#define HK_SELECT "OK" 269#define HK_CANCEL "REC" 270 271#elif CONFIG_KEYPAD == MPIO_HD200_PAD 272#define JEWELS_LEFT BUTTON_VOL_DOWN 273#define JEWELS_RIGHT BUTTON_VOL_UP 274#define JEWELS_UP BUTTON_REW 275#define JEWELS_DOWN BUTTON_FF 276#define JEWELS_SELECT BUTTON_FUNC 277#define JEWELS_CANCEL BUTTON_REC 278#define HK_SELECT "FUNC" 279#define HK_CANCEL "REC" 280 281#elif CONFIG_KEYPAD == MPIO_HD300_PAD 282#define JEWELS_LEFT BUTTON_REW 283#define JEWELS_RIGHT BUTTON_FF 284#define JEWELS_UP BUTTON_UP 285#define JEWELS_DOWN BUTTON_DOWN 286#define JEWELS_SELECT BUTTON_ENTER 287#define JEWELS_CANCEL BUTTON_MENU 288#define HK_SELECT "ENTER" 289#define HK_CANCEL "MENU" 290 291#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD 292#define JEWELS_LEFT BUTTON_LEFT 293#define JEWELS_RIGHT BUTTON_RIGHT 294#define JEWELS_UP BUTTON_UP 295#define JEWELS_DOWN BUTTON_DOWN 296#define JEWELS_SELECT BUTTON_SELECT 297#define JEWELS_CANCEL BUTTON_POWER 298#define HK_SELECT "SELECT" 299#define HK_CANCEL "POWER" 300 301#elif CONFIG_KEYPAD == AGPTEK_ROCKER_PAD 302#define JEWELS_LEFT BUTTON_LEFT 303#define JEWELS_RIGHT BUTTON_RIGHT 304#define JEWELS_UP BUTTON_UP 305#define JEWELS_DOWN BUTTON_DOWN 306#define JEWELS_SELECT BUTTON_SELECT 307#define JEWELS_CANCEL BUTTON_POWER 308#define HK_SELECT "SELECT" 309#define HK_CANCEL "POWER" 310 311#elif (CONFIG_KEYPAD == HM60X_PAD) || \ 312 (CONFIG_KEYPAD == HM801_PAD) 313#define JEWELS_LEFT BUTTON_LEFT 314#define JEWELS_RIGHT BUTTON_RIGHT 315#define JEWELS_UP BUTTON_UP 316#define JEWELS_DOWN BUTTON_DOWN 317#define JEWELS_SELECT BUTTON_SELECT 318#define JEWELS_CANCEL BUTTON_POWER 319#define HK_SELECT "SELECT" 320#define HK_CANCEL "POWER" 321 322#elif CONFIG_KEYPAD == DX50_PAD 323#define JEWELS_CANCEL BUTTON_POWER 324#define HK_CANCEL "Power" 325 326#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD 327#define JEWELS_CANCEL BUTTON_POWER 328#define HK_CANCEL "Power" 329 330#elif CONFIG_KEYPAD == XDUOO_X3_PAD || CONFIG_KEYPAD == XDUOO_X3II_PAD || CONFIG_KEYPAD == XDUOO_X20_PAD 331#define JEWELS_UP BUTTON_HOME 332#define JEWELS_DOWN BUTTON_OPTION 333#define JEWELS_LEFT BUTTON_PREV 334#define JEWELS_RIGHT BUTTON_NEXT 335#define JEWELS_SELECT BUTTON_PLAY 336#define JEWELS_CANCEL BUTTON_POWER 337#define HK_SELECT "PLAY" 338#define HK_CANCEL "POWER" 339 340#elif CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD 341#define JEWELS_UP BUTTON_HOME 342#define JEWELS_DOWN BUTTON_OPTION 343#define JEWELS_LEFT BUTTON_PREV 344#define JEWELS_RIGHT BUTTON_NEXT 345#define JEWELS_SELECT BUTTON_PLAY 346#define JEWELS_CANCEL BUTTON_POWER 347#define HK_SELECT "PLAY" 348#define HK_CANCEL "POWER" 349 350#elif CONFIG_KEYPAD == IHIFI_770_PAD || CONFIG_KEYPAD == IHIFI_800_PAD 351#define JEWELS_UP BUTTON_PREV 352#define JEWELS_DOWN BUTTON_NEXT 353#define JEWELS_LEFT BUTTON_HOME 354#define JEWELS_RIGHT BUTTON_VOL_DOWN 355#define JEWELS_SELECT BUTTON_PLAY 356#define JEWELS_CANCEL BUTTON_POWER 357#define HK_SELECT "PLAY" 358#define HK_CANCEL "POWER" 359 360#elif CONFIG_KEYPAD == EROSQ_PAD 361#define JEWELS_UP BUTTON_PREV 362#define JEWELS_DOWN BUTTON_NEXT 363#define JEWELS_LEFT BUTTON_SCROLL_BACK 364#define JEWELS_RIGHT BUTTON_SCROLL_FWD 365#define JEWELS_SELECT BUTTON_PLAY 366#define JEWELS_CANCEL BUTTON_BACK 367#define HK_SELECT "PLAY" 368#define HK_CANCEL "BACK" 369 370#elif CONFIG_KEYPAD == FIIO_M3K_PAD 371#define JEWELS_UP BUTTON_UP 372#define JEWELS_DOWN BUTTON_DOWN 373#define JEWELS_LEFT BUTTON_LEFT 374#define JEWELS_RIGHT BUTTON_RIGHT 375#define JEWELS_SELECT BUTTON_SELECT 376#define JEWELS_CANCEL BUTTON_BACK 377#define HK_SELECT "SELECT" 378#define HK_CANCEL "BACK" 379 380#elif CONFIG_KEYPAD == SHANLING_Q1_PAD 381/* use touchscreen */ 382 383#elif CONFIG_KEYPAD == SDL_PAD 384/* use touchscreen */ 385#elif CONFIG_KEYPAD == MA_PAD 386#define JEWELS_UP BUTTON_UP 387#define JEWELS_DOWN BUTTON_DOWN 388#define JEWELS_LEFT BUTTON_LEFT 389#define JEWELS_RIGHT BUTTON_RIGHT 390#define JEWELS_SELECT BUTTON_PLAY 391#define JEWELS_CANCEL BUTTON_BACK 392#define HK_SELECT "PLAY" 393#define HK_CANCEL "BACK" 394 395#elif CONFIG_KEYPAD == RG_NANO_PAD 396#define JEWELS_UP BUTTON_UP 397#define JEWELS_DOWN BUTTON_DOWN 398#define JEWELS_LEFT BUTTON_LEFT 399#define JEWELS_RIGHT BUTTON_RIGHT 400#define JEWELS_SELECT BUTTON_A 401#define JEWELS_CANCEL BUTTON_START 402#define HK_SELECT "A" 403#define HK_CANCEL "START" 404 405#else 406#error No keymap defined! 407#endif 408 409#ifdef HAVE_TOUCHSCREEN 410#ifndef JEWELS_UP 411#define JEWELS_UP BUTTON_TOPMIDDLE 412#endif 413#ifndef JEWELS_DOWN 414#define JEWELS_DOWN BUTTON_BOTTOMMIDDLE 415#endif 416#ifndef JEWELS_LEFT 417#define JEWELS_LEFT BUTTON_MIDLEFT 418#endif 419#ifndef JEWELS_RIGHT 420#define JEWELS_RIGHT BUTTON_MIDRIGHT 421#endif 422#ifndef JEWELS_SELECT 423#define JEWELS_SELECT BUTTON_CENTER 424#define HK_SELECT "CENTER" 425#endif 426#ifndef JEWELS_CANCEL 427#define JEWELS_CANCEL BUTTON_TOPLEFT 428#define HK_CANCEL "TOPLEFT" 429#endif 430#endif 431 432#define TILE_WIDTH BMPWIDTH_jewels 433#define TILE_HEIGHT (BMPHEIGHT_jewels/23) 434 435#if LCD_HEIGHT < LCD_WIDTH 436/* This calculation assumes integer division w/ LCD_HEIGHT/TILE_HEIGHT */ 437#define YOFS LCD_HEIGHT-((LCD_HEIGHT/TILE_HEIGHT)*TILE_HEIGHT) 438#else 439#define YOFS 0 440#endif 441 442#define NUM_SCORES 5 443 444/* swap directions */ 445#define SWAP_UP 0 446#define SWAP_RIGHT 1 447#define SWAP_DOWN 2 448#define SWAP_LEFT 3 449 450/* play board dimension */ 451#define BJ_HEIGHT 9 452#define BJ_WIDTH 8 453 454/* next level threshold */ 455#define LEVEL_PTS 100 456 457/* animation frame rate */ 458#define MAX_FPS 20 459 460/* text margin */ 461#define MARGIN 5 462 463/* Game types */ 464enum game_type { 465 GAME_TYPE_NORMAL, 466 GAME_TYPE_PUZZLE 467}; 468 469/* external bitmaps */ 470extern const fb_data jewels[]; 471 472/* tile background colors */ 473#ifdef HAVE_LCD_COLOR 474static const unsigned jewels_bkgd[2] = { 475 LCD_RGBPACK(104, 63, 63), 476 LCD_RGBPACK(83, 44, 44) 477}; 478#endif 479 480/* the tile struct 481 * type is the jewel number 0-7 482 * falling if the jewel is falling 483 * delete marks the jewel for deletion 484 */ 485struct tile { 486 int type; 487 bool falling; 488 bool delete; 489}; 490 491/* the game context struct 492 * score is the current level score 493 * segments is the number of cleared segments in the current run 494 * level is the current level 495 * tmp_type is the select type in the menu 496 * type is the game type (normal or puzzle) 497 * playboard is the game playing board (first row is hidden) 498 * num_jewels is the number of different jewels to use 499 */ 500struct game_context { 501 unsigned int score; 502 unsigned int segments; 503 unsigned int level; 504 unsigned int type; 505 unsigned int tmp_type; 506 struct tile playboard[BJ_HEIGHT][BJ_WIDTH]; 507 unsigned int num_jewels; 508}; 509 510#define MAX_NUM_JEWELS 7 511 512#define MAX_PUZZLE_TILES 4 513#define NUM_PUZZLE_LEVELS 10 514 515struct puzzle_tile { 516 int x; 517 int y; 518 int tile_type; 519}; 520 521struct puzzle_level { 522 unsigned int num_jewels; 523 unsigned int num_tiles; 524 struct puzzle_tile tiles[MAX_PUZZLE_TILES]; 525}; 526 527#define PUZZLE_TILE_UP 1 528#define PUZZLE_TILE_DOWN 2 529#define PUZZLE_TILE_LEFT 4 530#define PUZZLE_TILE_RIGHT 8 531 532struct puzzle_level puzzle_levels[NUM_PUZZLE_LEVELS] = { 533 { 5, 2, { {3, 3, PUZZLE_TILE_RIGHT}, 534 {4, 2, PUZZLE_TILE_LEFT} } }, 535 { 5, 2, { {3, 2, PUZZLE_TILE_DOWN}, 536 {3, 4, PUZZLE_TILE_UP} } }, 537 { 6, 3, { {3, 2, PUZZLE_TILE_DOWN}, 538 {3, 4, PUZZLE_TILE_UP|PUZZLE_TILE_DOWN}, 539 {3, 6, PUZZLE_TILE_UP} } }, 540 { 6, 3, { {3, 2, PUZZLE_TILE_RIGHT}, 541 {4, 3, PUZZLE_TILE_LEFT|PUZZLE_TILE_RIGHT}, 542 {5, 4, PUZZLE_TILE_LEFT} } }, 543 { 6, 2, { {3, 4, PUZZLE_TILE_RIGHT}, 544 {4, 2, PUZZLE_TILE_LEFT} } }, 545 { 6, 2, { {3, 2, PUZZLE_TILE_DOWN}, 546 {4, 4, PUZZLE_TILE_UP} } }, 547 { 7, 4, { {3, 2, PUZZLE_TILE_RIGHT|PUZZLE_TILE_DOWN}, 548 {4, 3, PUZZLE_TILE_LEFT|PUZZLE_TILE_DOWN}, 549 {3, 4, PUZZLE_TILE_RIGHT|PUZZLE_TILE_UP}, 550 {4, 4, PUZZLE_TILE_LEFT|PUZZLE_TILE_UP} } }, 551 { 6, 3, { {3, 2, PUZZLE_TILE_DOWN}, 552 {4, 4, PUZZLE_TILE_UP|PUZZLE_TILE_DOWN}, 553 {3, 6, PUZZLE_TILE_UP} } }, 554 { 7, 3, { {2, 2, PUZZLE_TILE_RIGHT}, 555 {4, 1, PUZZLE_TILE_LEFT|PUZZLE_TILE_RIGHT}, 556 {5, 4, PUZZLE_TILE_LEFT} } }, 557 { 7, 4, { {3, 0, PUZZLE_TILE_RIGHT|PUZZLE_TILE_DOWN}, 558 {5, 0, PUZZLE_TILE_LEFT|PUZZLE_TILE_DOWN}, 559 {2, 7, PUZZLE_TILE_RIGHT|PUZZLE_TILE_UP}, 560 {4, 7, PUZZLE_TILE_LEFT|PUZZLE_TILE_UP} } }, 561}; 562 563#define SAVE_FILE PLUGIN_GAMES_DATA_DIR "/jewels.save" 564#define SCORE_FILE PLUGIN_GAMES_DATA_DIR "/jewels.score" 565struct highscore highscores[NUM_SCORES]; 566 567static bool resume_file = false; 568 569/***************************************************************************** 570* jewels_setcolors() set the foreground and background colors. 571******************************************************************************/ 572static inline void jewels_setcolors(void) { 573#ifdef HAVE_LCD_COLOR 574 rb->lcd_set_background(LCD_RGBPACK(49, 26, 26)); 575 rb->lcd_set_foreground(LCD_RGBPACK(210, 181, 181)); 576#endif 577} 578 579/***************************************************************************** 580* jewels_loadgame() loads the saved game and returns load success. 581******************************************************************************/ 582static bool jewels_loadgame(struct game_context* bj) 583{ 584 int fd; 585 bool loaded = false; 586 587 /* open game file */ 588 fd = rb->open(SAVE_FILE, O_RDONLY); 589 if(fd < 0) return loaded; 590 591 /* read in saved game */ 592 while(true) { 593 if(rb->read(fd, &bj->tmp_type, sizeof(bj->tmp_type)) <= 0) break; 594 if(rb->read(fd, &bj->type, sizeof(bj->type)) <= 0) break; 595 if(rb->read(fd, &bj->score, sizeof(bj->score)) <= 0) break; 596 if(rb->read(fd, &bj->level, sizeof(bj->level)) <= 0) break; 597 if(rb->read(fd, &bj->segments, sizeof(bj->segments)) <= 0) break; 598 if(rb->read(fd, &bj->num_jewels, sizeof(bj->num_jewels)) <= 0) break; 599 if(rb->read(fd, bj->playboard, sizeof(bj->playboard)) <= 0) break; 600 loaded = true; 601 break; 602 } 603 604 rb->close(fd); 605 606 return loaded; 607} 608 609/***************************************************************************** 610* jewels_savegame() saves the current game state. 611******************************************************************************/ 612static void jewels_savegame(struct game_context* bj) 613{ 614 int fd; 615 /* write out the game state to the save file */ 616 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT, 0666); 617 if(fd < 0) return; 618 619 rb->write(fd, &bj->tmp_type, sizeof(bj->tmp_type)); 620 rb->write(fd, &bj->type, sizeof(bj->type)); 621 rb->write(fd, &bj->score, sizeof(bj->score)); 622 rb->write(fd, &bj->level, sizeof(bj->level)); 623 rb->write(fd, &bj->segments, sizeof(bj->segments)); 624 rb->write(fd, &bj->num_jewels, sizeof(bj->num_jewels)); 625 rb->write(fd, bj->playboard, sizeof(bj->playboard)); 626 rb->close(fd); 627} 628 629/***************************************************************************** 630* jewels_drawboard() redraws the entire game board. 631******************************************************************************/ 632static void jewels_drawboard(struct game_context* bj) { 633 int i, j; 634 int w, h; 635 unsigned int tempscore; 636 unsigned int size; 637 char *title = "Level"; 638 char str[10]; 639 640 if (bj->type == GAME_TYPE_NORMAL) { 641 tempscore = (bj->score>LEVEL_PTS ? LEVEL_PTS : bj->score); 642 size = LEVEL_PTS; 643 } else { 644 tempscore = (bj->level>NUM_PUZZLE_LEVELS ? NUM_PUZZLE_LEVELS : bj->level); 645 size = NUM_PUZZLE_LEVELS; 646 } 647 648 /* clear screen */ 649 rb->lcd_clear_display(); 650 651 /* dispay playing board */ 652 for(i=0; i<BJ_HEIGHT-1; i++){ 653 for(j=0; j<BJ_WIDTH; j++){ 654#ifdef HAVE_LCD_COLOR 655 rb->lcd_set_foreground(jewels_bkgd[(i+j)%2]); 656 rb->lcd_fillrect(j*TILE_WIDTH, i*TILE_HEIGHT+YOFS, 657 TILE_WIDTH, TILE_HEIGHT); 658 rb->lcd_bitmap_transparent_part(jewels, 659 0, TILE_HEIGHT*(bj->playboard[i+1][j].type), 660 STRIDE( SCREEN_MAIN, 661 BMPWIDTH_jewels, BMPHEIGHT_jewels), 662 j*TILE_WIDTH, i*TILE_HEIGHT+YOFS, 663 TILE_WIDTH, TILE_HEIGHT); 664#else 665 rb->lcd_bitmap_part(jewels, 666 0, TILE_HEIGHT*(bj->playboard[i+1][j].type), 667 STRIDE( SCREEN_MAIN, 668 BMPWIDTH_jewels, BMPHEIGHT_jewels), 669 j*TILE_WIDTH, i*TILE_HEIGHT+YOFS, 670 TILE_WIDTH, TILE_HEIGHT); 671#endif 672 } 673 } 674 675#if LCD_WIDTH > LCD_HEIGHT /* horizontal layout */ 676 677 /* draw separator lines */ 678 jewels_setcolors(); 679 rb->lcd_vline(BJ_WIDTH*TILE_WIDTH, 0, LCD_HEIGHT-1); 680 681 rb->lcd_hline(BJ_WIDTH*TILE_WIDTH, LCD_WIDTH-1, 18); 682 rb->lcd_hline(BJ_WIDTH*TILE_WIDTH, LCD_WIDTH-1, LCD_HEIGHT-10); 683 684 /* draw progress bar */ 685#ifdef HAVE_LCD_COLOR 686 rb->lcd_set_foreground(LCD_RGBPACK(104, 63, 63)); 687#endif 688 rb->lcd_fillrect(BJ_WIDTH*TILE_WIDTH+(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/4, 689 (LCD_HEIGHT-10)-(((LCD_HEIGHT-10)-18)* 690 tempscore/size), 691 (LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2, 692 ((LCD_HEIGHT-10)-18)*tempscore/size); 693#ifdef HAVE_LCD_COLOR 694 rb->lcd_set_foreground(LCD_RGBPACK(83, 44, 44)); 695 rb->lcd_drawrect(BJ_WIDTH*TILE_WIDTH+(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/4+1, 696 (LCD_HEIGHT-10)-(((LCD_HEIGHT-10)-18)* 697 tempscore/size)+1, 698 (LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2-2, 699 ((LCD_HEIGHT-10)-18)*tempscore/size-1); 700 jewels_setcolors(); 701 rb->lcd_drawrect(BJ_WIDTH*TILE_WIDTH+(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/4, 702 (LCD_HEIGHT-10)-(((LCD_HEIGHT-10)-18)*tempscore/size), 703 (LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2, 704 ((LCD_HEIGHT-10)-18)*tempscore/size+1); 705#endif 706 707 /* print text */ 708 rb->lcd_getstringsize(title, &w, &h); 709 rb->lcd_putsxy(LCD_WIDTH-(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2-w/2, 1, title); 710 rb->snprintf(str, 4, "%d", bj->level); 711 rb->lcd_getstringsize(str, &w, &h); 712 rb->lcd_putsxy(LCD_WIDTH-(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2-w/2, 10, str); 713 714 if (bj->type == GAME_TYPE_NORMAL) { 715 rb->snprintf(str, 6, "%d", (bj->level-1)*LEVEL_PTS+bj->score); 716 rb->lcd_getstringsize(str, &w, &h); 717 rb->lcd_putsxy(LCD_WIDTH-(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2-w/2, 718 LCD_HEIGHT-8, str); 719 } 720 721#elif LCD_WIDTH < LCD_HEIGHT /* vertical layout */ 722 723 /* draw separator lines */ 724 jewels_setcolors(); 725 rb->lcd_hline(0, LCD_WIDTH-1, 8*TILE_HEIGHT+YOFS); 726 rb->lcd_hline(0, LCD_WIDTH-1, LCD_HEIGHT-14); 727 rb->lcd_vline(LCD_WIDTH/2, LCD_HEIGHT-14, LCD_HEIGHT-1); 728 729 /* draw progress bar */ 730#ifdef HAVE_LCD_COLOR 731 rb->lcd_set_foreground(LCD_RGBPACK(104, 63, 63)); 732#endif 733 rb->lcd_fillrect(0, (8*TILE_HEIGHT+YOFS) 734 +(LCD_HEIGHT-14-(8*TILE_HEIGHT+YOFS))/4, 735 LCD_WIDTH*tempscore/size, 736 (LCD_HEIGHT-14-(8*TILE_HEIGHT+YOFS))/2); 737#ifdef HAVE_LCD_COLOR 738 rb->lcd_set_foreground(LCD_RGBPACK(83, 44, 44)); 739 rb->lcd_drawrect(1, (8*TILE_HEIGHT+YOFS) 740 +(LCD_HEIGHT-14-(8*TILE_HEIGHT+YOFS))/4+1, 741 LCD_WIDTH*tempscore/size-1, 742 (LCD_HEIGHT-14-(8*TILE_HEIGHT+YOFS))/2-2); 743 jewels_setcolors(); 744 rb->lcd_drawrect(0, (8*TILE_HEIGHT+YOFS) 745 +(LCD_HEIGHT-14-(8*TILE_HEIGHT+YOFS))/4, 746 LCD_WIDTH*tempscore/size+1, 747 (LCD_HEIGHT-14-(8*TILE_HEIGHT+YOFS))/2); 748#endif 749 750 /* print text */ 751 rb->lcd_putsxyf(1, LCD_HEIGHT-10, "%s %d", title, bj->level); 752 753 if (bj->type == GAME_TYPE_NORMAL) { 754 rb->snprintf(str, 6, "%d", (bj->level-1)*LEVEL_PTS+bj->score); 755 rb->lcd_getstringsize(str, &w, &h); 756 rb->lcd_putsxy((LCD_WIDTH-2)-w, LCD_HEIGHT-10, str); 757 } 758 759 760#else /* square layout */ 761 762 /* draw separator lines */ 763 jewels_setcolors(); 764 rb->lcd_hline(0, LCD_WIDTH-1, 8*TILE_HEIGHT+YOFS); 765 rb->lcd_vline(BJ_WIDTH*TILE_WIDTH, 0, 8*TILE_HEIGHT+YOFS); 766 rb->lcd_vline(LCD_WIDTH/2, 8*TILE_HEIGHT+YOFS, LCD_HEIGHT-1); 767 768 /* draw progress bar */ 769#ifdef HAVE_LCD_COLOR 770 rb->lcd_set_foreground(LCD_RGBPACK(104, 63, 63)); 771#endif 772 rb->lcd_fillrect(BJ_WIDTH*TILE_WIDTH+(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/4, 773 (8*TILE_HEIGHT+YOFS)-(8*TILE_HEIGHT+YOFS)*tempscore/size, 774 (LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2, 775 (8*TILE_HEIGHT+YOFS)*tempscore/size); 776#ifdef HAVE_LCD_COLOR 777 rb->lcd_set_foreground(LCD_RGBPACK(83, 44, 44)); 778 rb->lcd_drawrect(BJ_WIDTH*TILE_WIDTH+(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/4+1, 779 (8*TILE_HEIGHT+YOFS)-(8*TILE_HEIGHT+YOFS) 780 *tempscore/size+1, 781 (LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2-2, 782 (8*TILE_HEIGHT+YOFS)*tempscore/size-1); 783 jewels_setcolors(); 784 rb->lcd_drawrect(BJ_WIDTH*TILE_WIDTH+(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/4, 785 (8*TILE_HEIGHT+YOFS)-(8*TILE_HEIGHT+YOFS) 786 *tempscore/size, 787 (LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2, 788 (8*TILE_HEIGHT+YOFS)*tempscore/size+1); 789#endif 790 791 /* print text */ 792 rb->lcd_putsxyf(1, LCD_HEIGHT-(LCD_HEIGHT-(8*TILE_HEIGHT+YOFS))/2-3,"%s %d", 793 title, bj->level); 794 795 if (bj->type == GAME_TYPE_NORMAL) { 796 rb->snprintf(str, 6, "%d", (bj->level-1)*LEVEL_PTS+bj->score); 797 rb->lcd_getstringsize(str, &w, &h); 798 rb->lcd_putsxy((LCD_WIDTH-2)-w, 799 LCD_HEIGHT-(LCD_HEIGHT-(8*TILE_HEIGHT+YOFS))/2-3, str); 800 } 801 802#endif /* layout */ 803 804 rb->lcd_update(); 805} 806 807/***************************************************************************** 808* jewels_putjewels() makes the jewels fall to fill empty spots and adds 809* new random jewels at the empty spots at the top of each row. 810******************************************************************************/ 811static void jewels_putjewels(struct game_context* bj){ 812 int i, j, k; 813 bool mark, done; 814 long lasttick, currenttick; 815 816 /* loop to make all the jewels fall */ 817 while(true) { 818 /* mark falling jewels and add new jewels to hidden top row*/ 819 mark = false; 820 done = true; 821 for(j=0; j<BJ_WIDTH; j++) { 822 if(bj->playboard[1][j].type == 0) { 823 bj->playboard[0][j].type = rb->rand()%bj->num_jewels+1; 824 } 825 for(i=BJ_HEIGHT-2; i>=0; i--) { 826 if(!mark && bj->playboard[i+1][j].type == 0) { 827 mark = true; 828 done = false; 829 } 830 if(mark) bj->playboard[i][j].falling = true; 831 } 832 /*if(bj->playboard[1][j].falling) { 833 bj->playboard[0][j].type = rb->rand()%bj->num_jewels+1; 834 bj->playboard[0][j].falling = true; 835 }*/ 836 mark = false; 837 } 838 839 /* break if there are no falling jewels */ 840 if(done) break; 841 842 /* animate falling jewels */ 843 lasttick = *rb->current_tick; 844 845 for(k=1; k<=8; k++) { 846 for(i=BJ_HEIGHT-2; i>=0; i--) { 847 for(j=0; j<BJ_WIDTH; j++) { 848 if(bj->playboard[i][j].falling && 849 bj->playboard[i][j].type != 0) { 850 /* clear old position */ 851#ifdef HAVE_LCD_COLOR 852 if(i == 0 && YOFS) { 853 rb->lcd_set_foreground(rb->lcd_get_background()); 854 } else { 855 rb->lcd_set_foreground(jewels_bkgd[(i-1+j)%2]); 856 } 857 rb->lcd_fillrect(j*TILE_WIDTH, (i-1)*TILE_HEIGHT+YOFS, 858 TILE_WIDTH, TILE_HEIGHT); 859 if(bj->playboard[i+1][j].type == 0) { 860 rb->lcd_set_foreground(jewels_bkgd[(i+j)%2]); 861 rb->lcd_fillrect(j*TILE_WIDTH, i*TILE_HEIGHT+YOFS, 862 TILE_WIDTH, TILE_HEIGHT); 863 } 864#else 865 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 866 rb->lcd_fillrect(j*TILE_WIDTH, (i-1)*TILE_HEIGHT+YOFS, 867 TILE_WIDTH, TILE_HEIGHT); 868 if(bj->playboard[i+1][j].type == 0) { 869 rb->lcd_fillrect(j*TILE_WIDTH, i*TILE_HEIGHT+YOFS, 870 TILE_WIDTH, TILE_HEIGHT); 871 } 872 rb->lcd_set_drawmode(DRMODE_SOLID); 873#endif 874 875 /* draw new position */ 876#ifdef HAVE_LCD_COLOR 877 rb->lcd_bitmap_transparent_part(jewels, 0, 878 TILE_HEIGHT*(bj->playboard[i][j].type), 879 STRIDE( SCREEN_MAIN, 880 BMPWIDTH_jewels, 881 BMPHEIGHT_jewels), 882 j*TILE_WIDTH, 883 (i-1)*TILE_HEIGHT+YOFS+ 884 ((((TILE_HEIGHT<<10)*k)/8)>>10), 885 TILE_WIDTH, TILE_HEIGHT); 886#else 887 rb->lcd_bitmap_part(jewels, 0, 888 TILE_HEIGHT*(bj->playboard[i][j].type), 889 STRIDE( SCREEN_MAIN, 890 BMPWIDTH_jewels, 891 BMPHEIGHT_jewels), 892 j*TILE_WIDTH, 893 (i-1)*TILE_HEIGHT+YOFS+ 894 ((((TILE_HEIGHT<<10)*k)/8)>>10), 895 TILE_WIDTH, TILE_HEIGHT); 896#endif 897 } 898 } 899 } 900 901 rb->lcd_update_rect(0, 0, TILE_WIDTH*8, LCD_HEIGHT); 902 jewels_setcolors(); 903 904 /* framerate limiting */ 905 currenttick = *rb->current_tick; 906 if(currenttick-lasttick < HZ/MAX_FPS) { 907 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick)); 908 } else { 909 rb->yield(); 910 } 911 lasttick = currenttick; 912 } 913 914 /* shift jewels down */ 915 for(j=0; j<BJ_WIDTH; j++) { 916 for(i=BJ_HEIGHT-1; i>=1; i--) { 917 if(bj->playboard[i-1][j].falling) { 918 bj->playboard[i][j].type = bj->playboard[i-1][j].type; 919 } 920 } 921 } 922 923 /* clear out top row */ 924 for(j=0; j<BJ_WIDTH; j++) { 925 bj->playboard[0][j].type = 0; 926 } 927 928 /* mark everything not falling */ 929 for(i=0; i<BJ_HEIGHT; i++) { 930 for(j=0; j<BJ_WIDTH; j++) { 931 bj->playboard[i][j].falling = false; 932 } 933 } 934 } 935} 936 937/***************************************************************************** 938* jewels_clearjewels() finds all the connected rows and columns and 939* calculates and returns the points earned. 940******************************************************************************/ 941static unsigned int jewels_clearjewels(struct game_context* bj) { 942 int i, j; 943 int last, run; 944 unsigned int points = 0; 945 946 /* check for connected rows */ 947 for(i=1; i<BJ_HEIGHT; i++) { 948 last = 0; 949 run = 1; 950 for(j=0; j<BJ_WIDTH; j++) { 951 if(bj->playboard[i][j].type == last && 952 bj->playboard[i][j].type != 0 && 953 bj->playboard[i][j].type <= MAX_NUM_JEWELS) { 954 run++; 955 956 if(run == 3) { 957 bj->segments++; 958 points += bj->segments; 959 bj->playboard[i][j].delete = true; 960 bj->playboard[i][j-1].delete = true; 961 bj->playboard[i][j-2].delete = true; 962 } else if(run > 3) { 963 points++; 964 bj->playboard[i][j].delete = true; 965 } 966 } else { 967 run = 1; 968 last = bj->playboard[i][j].type; 969 } 970 } 971 } 972 973 /* check for connected columns */ 974 for(j=0; j<BJ_WIDTH; j++) { 975 last = 0; 976 run = 1; 977 for(i=1; i<BJ_HEIGHT; i++) { 978 if(bj->playboard[i][j].type != 0 && 979 bj->playboard[i][j].type == last && 980 bj->playboard[i][j].type <= MAX_NUM_JEWELS) { 981 run++; 982 983 if(run == 3) { 984 bj->segments++; 985 points += bj->segments; 986 bj->playboard[i][j].delete = true; 987 bj->playboard[i-1][j].delete = true; 988 bj->playboard[i-2][j].delete = true; 989 } else if(run > 3) { 990 points++; 991 bj->playboard[i][j].delete = true; 992 } 993 } else { 994 run = 1; 995 last = bj->playboard[i][j].type; 996 } 997 } 998 } 999 1000 /* clear deleted jewels */ 1001 for(i=1; i<BJ_HEIGHT; i++) { 1002 for(j=0; j<BJ_WIDTH; j++) { 1003 if(bj->playboard[i][j].delete) { 1004 bj->playboard[i][j].delete = false; 1005 bj->playboard[i][j].type = 0; 1006 } 1007 } 1008 } 1009 1010 return points; 1011} 1012 1013/***************************************************************************** 1014* jewels_runboard() runs the board until it settles in a fixed state and 1015* returns points earned. 1016******************************************************************************/ 1017static unsigned int jewels_runboard(struct game_context* bj) { 1018 unsigned int points = 0; 1019 unsigned int ret; 1020 1021 bj->segments = 0; 1022 1023 while((ret = jewels_clearjewels(bj)) > 0) { 1024 points += ret; 1025 jewels_drawboard(bj); 1026 jewels_putjewels(bj); 1027 } 1028 1029 return points; 1030} 1031 1032/***************************************************************************** 1033* jewels_swapjewels() swaps two jewels as long as it results in points and 1034* returns points earned. 1035******************************************************************************/ 1036static unsigned int jewels_swapjewels(struct game_context* bj, 1037 int x, int y, int direc) { 1038 int k; 1039 int horzmod, vertmod; 1040 int movelen = 0; 1041 bool undo = false; 1042 unsigned int points = 0; 1043 long lasttick, currenttick; 1044 1045 /* check for invalid parameters */ 1046 if(x < 0 || x >= BJ_WIDTH || y < 0 || y >= BJ_HEIGHT-1 || 1047 direc < SWAP_UP || direc > SWAP_LEFT) { 1048 return 0; 1049 } 1050 1051 /* check for invalid directions */ 1052 if((x == 0 && direc == SWAP_LEFT) || 1053 (x == BJ_WIDTH-1 && direc == SWAP_RIGHT) || 1054 (y == 0 && direc == SWAP_UP) || 1055 (y == BJ_HEIGHT-2 && direc == SWAP_DOWN)) { 1056 return 0; 1057 } 1058 1059 /* set direction variables */ 1060 horzmod = 0; 1061 vertmod = 0; 1062 switch(direc) { 1063 case SWAP_UP: 1064 vertmod = -1; 1065 movelen = TILE_HEIGHT; 1066 break; 1067 case SWAP_RIGHT: 1068 horzmod = 1; 1069 movelen = TILE_WIDTH; 1070 break; 1071 case SWAP_DOWN: 1072 vertmod = 1; 1073 movelen = TILE_HEIGHT; 1074 break; 1075 case SWAP_LEFT: 1076 horzmod = -1; 1077 movelen = TILE_WIDTH; 1078 break; 1079 } 1080 1081 while(true) { 1082 lasttick = *rb->current_tick; 1083 1084 /* animate swapping jewels */ 1085 for(k=0; k<=8; k++) { 1086 /* clear old position */ 1087#ifdef HAVE_LCD_COLOR 1088 rb->lcd_set_foreground(jewels_bkgd[(x+y)%2]); 1089 rb->lcd_fillrect(x*TILE_WIDTH, 1090 y*TILE_HEIGHT+YOFS, 1091 TILE_WIDTH, TILE_HEIGHT); 1092 rb->lcd_set_foreground(jewels_bkgd[(x+horzmod+y+vertmod)%2]); 1093 rb->lcd_fillrect((x+horzmod)*TILE_WIDTH, 1094 (y+vertmod)*TILE_HEIGHT+YOFS, 1095 TILE_WIDTH, TILE_HEIGHT); 1096#else 1097 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 1098 rb->lcd_fillrect(x*TILE_WIDTH, 1099 y*TILE_HEIGHT+YOFS, 1100 TILE_WIDTH, TILE_HEIGHT); 1101 rb->lcd_fillrect((x+horzmod)*TILE_WIDTH, 1102 (y+vertmod)*TILE_HEIGHT+YOFS, 1103 TILE_WIDTH, TILE_HEIGHT); 1104 rb->lcd_set_drawmode(DRMODE_SOLID); 1105#endif 1106 /* draw new position */ 1107#ifdef HAVE_LCD_COLOR 1108 rb->lcd_bitmap_transparent_part(jewels, 1109 0, TILE_HEIGHT*(bj->playboard 1110 [y+1+vertmod][x+horzmod].type), 1111 STRIDE( SCREEN_MAIN, 1112 BMPWIDTH_jewels, BMPHEIGHT_jewels), 1113 (x+horzmod)*TILE_WIDTH-horzmod* 1114 ((((movelen<<10)*k)/8)>>10), 1115 (y+vertmod)*TILE_HEIGHT-vertmod* 1116 ((((movelen<<10)*k)/8)>>10)+YOFS, 1117 TILE_WIDTH, TILE_HEIGHT); 1118 rb->lcd_bitmap_transparent_part(jewels, 1119 0, TILE_HEIGHT*(bj->playboard[y+1][x].type), 1120 STRIDE( SCREEN_MAIN, 1121 BMPWIDTH_jewels, BMPHEIGHT_jewels), 1122 x*TILE_WIDTH+horzmod* 1123 ((((movelen<<10)*k)/8)>>10), 1124 y*TILE_HEIGHT+vertmod* 1125 ((((movelen<<10)*k)/8)>>10)+YOFS, 1126 TILE_WIDTH, TILE_HEIGHT); 1127#else 1128 rb->lcd_bitmap_part(jewels, 1129 0, TILE_HEIGHT*(bj->playboard 1130 [y+1+vertmod][x+horzmod].type), 1131 STRIDE( SCREEN_MAIN, 1132 BMPWIDTH_jewels, BMPHEIGHT_jewels), 1133 (x+horzmod)*TILE_WIDTH-horzmod* 1134 ((((movelen<<10)*k)/8)>>10), 1135 (y+vertmod)*TILE_HEIGHT-vertmod* 1136 ((((movelen<<10)*k)/8)>>10)+YOFS, 1137 TILE_WIDTH, TILE_HEIGHT); 1138 rb->lcd_set_drawmode(DRMODE_FG); 1139 rb->lcd_bitmap_part(jewels, 1140 0, TILE_HEIGHT*(bj->playboard[y+1][x].type), 1141 STRIDE( SCREEN_MAIN, 1142 BMPWIDTH_jewels, BMPHEIGHT_jewels), 1143 x*TILE_WIDTH+horzmod* 1144 ((((movelen<<10)*k)/8)>>10), 1145 y*TILE_HEIGHT+vertmod* 1146 ((((movelen<<10)*k)/8)>>10)+YOFS, 1147 TILE_WIDTH, TILE_HEIGHT); 1148 rb->lcd_set_drawmode(DRMODE_SOLID); 1149#endif 1150 1151 rb->lcd_update_rect(0, 0, TILE_WIDTH*8, LCD_HEIGHT); 1152 jewels_setcolors(); 1153 1154 /* framerate limiting */ 1155 currenttick = *rb->current_tick; 1156 if(currenttick-lasttick < HZ/MAX_FPS) { 1157 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick)); 1158 } else { 1159 rb->yield(); 1160 } 1161 lasttick = currenttick; 1162 } 1163 1164 /* swap jewels */ 1165 int temp = bj->playboard[y+1][x].type; 1166 bj->playboard[y+1][x].type = 1167 bj->playboard[y+1+vertmod][x+horzmod].type; 1168 bj->playboard[y+1+vertmod][x+horzmod].type = temp; 1169 1170 if(undo) break; 1171 1172 points = jewels_runboard(bj); 1173 if(points == 0) { 1174 undo = true; 1175 } else { 1176 break; 1177 } 1178 } 1179 1180 return points; 1181} 1182 1183/***************************************************************************** 1184* jewels_movesavail() uses pattern matching to see if there are any 1185* available move left. 1186******************************************************************************/ 1187static bool jewels_movesavail(struct game_context* bj) { 1188 int i, j; 1189 bool moves = false; 1190 int mytype; 1191 1192 for(i=1; i<BJ_HEIGHT; i++) { 1193 for(j=0; j<BJ_WIDTH; j++) { 1194 mytype = bj->playboard[i][j].type; 1195 if(mytype == 0 || mytype > MAX_NUM_JEWELS) continue; 1196 1197 /* check horizontal patterns */ 1198 if(j <= BJ_WIDTH-3) { 1199 if(i > 1) { 1200 if(bj->playboard[i-1][j+1].type == mytype) { 1201 if(bj->playboard[i-1][j+2].type == mytype) 1202 {moves = true; break;} 1203 if(bj->playboard[i][j+2].type == mytype) 1204 {moves = true; break;} 1205 } 1206 if(bj->playboard[i][j+1].type == mytype) { 1207 if(bj->playboard[i-1][j+2].type == mytype) 1208 {moves = true; break;} 1209 } 1210 } 1211 1212 if(j <= BJ_WIDTH-4) { 1213 if(bj->playboard[i][j+3].type == mytype) { 1214 if(bj->playboard[i][j+1].type == mytype) 1215 {moves = true; break;} 1216 if(bj->playboard[i][j+2].type == mytype) 1217 {moves = true; break;} 1218 } 1219 } 1220 1221 if(i < BJ_HEIGHT-1) { 1222 if(bj->playboard[i][j+1].type == mytype) { 1223 if(bj->playboard[i+1][j+2].type == mytype) 1224 {moves = true; break;} 1225 } 1226 if(bj->playboard[i+1][j+1].type == mytype) { 1227 if(bj->playboard[i][j+2].type == mytype) 1228 {moves = true; break;} 1229 if(bj->playboard[i+1][j+2].type == mytype) 1230 {moves = true; break;} 1231 } 1232 } 1233 } 1234 1235 /* check vertical patterns */ 1236 if(i <= BJ_HEIGHT-3) { 1237 if(j > 0) { 1238 if(bj->playboard[i+1][j-1].type == mytype) { 1239 if(bj->playboard[i+2][j-1].type == mytype) 1240 {moves = true; break;} 1241 if(bj->playboard[i+2][j].type == mytype) 1242 {moves = true; break;} 1243 } 1244 if(bj->playboard[i+1][j].type == mytype) { 1245 if(bj->playboard[i+2][j-1].type == mytype) 1246 {moves = true; break;} 1247 } 1248 } 1249 1250 if(i <= BJ_HEIGHT-4) { 1251 if(bj->playboard[i+3][j].type == mytype) { 1252 if(bj->playboard[i+1][j].type == mytype) 1253 {moves = true; break;} 1254 if(bj->playboard[i+2][j].type == mytype) 1255 {moves = true; break;} 1256 } 1257 } 1258 1259 if(j < BJ_WIDTH-1) { 1260 if(bj->playboard[i+1][j].type == mytype) { 1261 if(bj->playboard[i+2][j+1].type == mytype) 1262 {moves = true; break;} 1263 } 1264 if(bj->playboard[i+1][j+1].type == mytype) { 1265 if(bj->playboard[i+2][j].type == mytype) 1266 {moves = true; break;} 1267 if (bj->playboard[i+2][j+1].type == mytype) 1268 {moves = true; break;} 1269 } 1270 } 1271 } 1272 } 1273 if(moves) break; 1274 } 1275 return moves; 1276} 1277 1278/***************************************************************************** 1279* jewels_puzzle_is_finished() checks if the puzzle is finished. 1280******************************************************************************/ 1281static bool jewels_puzzle_is_finished(struct game_context* bj) { 1282 unsigned int i, j; 1283 for(i=0; i<BJ_HEIGHT; i++) { 1284 for(j=0; j<BJ_WIDTH; j++) { 1285 int mytype = bj->playboard[i][j].type; 1286 if(mytype>MAX_NUM_JEWELS) { 1287 mytype -= MAX_NUM_JEWELS; 1288 if(mytype&PUZZLE_TILE_UP) { 1289 if(i==0 || bj->playboard[i-1][j].type<=MAX_NUM_JEWELS || 1290 !((bj->playboard[i-1][j].type-MAX_NUM_JEWELS) 1291 &PUZZLE_TILE_DOWN)) 1292 return false; 1293 } 1294 if(mytype&PUZZLE_TILE_DOWN) { 1295 if(i==BJ_HEIGHT-1 || 1296 bj->playboard[i+1][j].type<=MAX_NUM_JEWELS || 1297 !((bj->playboard[i+1][j].type-MAX_NUM_JEWELS) 1298 &PUZZLE_TILE_UP)) 1299 return false; 1300 } 1301 if(mytype&PUZZLE_TILE_LEFT) { 1302 if(j==0 || bj->playboard[i][j-1].type<=MAX_NUM_JEWELS || 1303 !((bj->playboard[i][j-1].type-MAX_NUM_JEWELS) 1304 &PUZZLE_TILE_RIGHT)) 1305 return false; 1306 } 1307 if(mytype&PUZZLE_TILE_RIGHT) { 1308 if(j==BJ_WIDTH-1 || 1309 bj->playboard[i][j+1].type<=MAX_NUM_JEWELS || 1310 !((bj->playboard[i][j+1].type-MAX_NUM_JEWELS) 1311 &PUZZLE_TILE_LEFT)) 1312 return false; 1313 } 1314 } 1315 } 1316 } 1317 return true; 1318} 1319 1320/***************************************************************************** 1321* jewels_initlevel() initialises a level. 1322******************************************************************************/ 1323static unsigned int jewels_initlevel(struct game_context* bj) { 1324 unsigned int points = 0; 1325 1326 switch(bj->type) { 1327 case GAME_TYPE_NORMAL: 1328 bj->num_jewels = MAX_NUM_JEWELS; 1329 break; 1330 1331 case GAME_TYPE_PUZZLE: 1332 { 1333 unsigned int i, j; 1334 struct puzzle_tile *tile; 1335 1336 bj->num_jewels = puzzle_levels[bj->level-1].num_jewels; 1337 1338 for(i=0; i<BJ_HEIGHT; i++) { 1339 for(j=0; j<BJ_WIDTH; j++) { 1340 bj->playboard[i][j].type = (rb->rand()%bj->num_jewels)+1; 1341 bj->playboard[i][j].falling = false; 1342 bj->playboard[i][j].delete = false; 1343 } 1344 } 1345 jewels_runboard(bj); 1346 tile = puzzle_levels[bj->level-1].tiles; 1347 for(i=0; i<puzzle_levels[bj->level-1].num_tiles; i++, tile++) { 1348 bj->playboard[tile->y+1][tile->x].type = MAX_NUM_JEWELS 1349 +tile->tile_type; 1350 } 1351 } 1352 break; 1353 } 1354 1355 jewels_drawboard(bj); 1356 1357 /* run the play board */ 1358 jewels_putjewels(bj); 1359 points += jewels_runboard(bj); 1360 return points; 1361} 1362 1363/***************************************************************************** 1364* jewels_init() initializes jewels data structures. 1365******************************************************************************/ 1366static void jewels_init(struct game_context* bj) { 1367 /* seed the rand generator */ 1368 rb->srand(*rb->current_tick); 1369 1370 bj->type = bj->tmp_type; 1371 bj->level = 1; 1372 bj->score = 0; 1373 bj->segments = 0; 1374 1375 jewels_setcolors(); 1376 1377 /* clear playing board */ 1378 rb->memset(bj->playboard, 0, sizeof(bj->playboard)); 1379 do { 1380 bj->score += jewels_initlevel(bj); 1381 } while(!jewels_movesavail(bj)); 1382} 1383 1384/***************************************************************************** 1385* jewels_nextlevel() advances the game to the next bj->level and returns 1386* points earned. 1387******************************************************************************/ 1388static void jewels_nextlevel(struct game_context* bj) { 1389 int i, x, y; 1390 unsigned int points = 0; 1391 1392 switch(bj->type) { 1393 case GAME_TYPE_NORMAL: 1394 /* roll over score, change and display level */ 1395 while(bj->score >= LEVEL_PTS) { 1396 bj->score -= LEVEL_PTS; 1397 bj->level++; 1398 rb->splashf(HZ*2, "Level %d", bj->level); 1399 jewels_drawboard(bj); 1400 } 1401 1402 /* randomly clear some jewels */ 1403 for(i=0; i<16; i++) { 1404 x = rb->rand()%8; 1405 y = rb->rand()%8; 1406 1407 if(bj->playboard[y][x].type != 0) { 1408 points++; 1409 bj->playboard[y][x].type = 0; 1410 } 1411 } 1412 break; 1413 1414 case GAME_TYPE_PUZZLE: 1415 bj->level++; 1416 rb->splashf(HZ*2, "Level %d", bj->level); 1417 break; 1418 } 1419 1420 points += jewels_initlevel(bj); 1421 bj->score += points; 1422} 1423 1424static bool jewels_help(void) 1425{ 1426 static char *help_text[] = { 1427 "Jewels", "", "Aim", "", 1428 "Swap", "pairs", "of", "jewels", "to", "form", "connected", 1429 "segments", "of", "three", "or", "more", "of", "the", "same", 1430 "type.", "", 1431 "The", "goal", "of", "the", "game", "is", "to", "score", "as", "many", 1432 "points", "as", "possible", "before", "running", "out", "of", 1433 "available", "moves.", "", "", 1434 "Controls", "", 1435 "Directions", 1436#ifdef JEWELS_SCROLLWHEEL 1437 "or", "scroll", 1438#endif 1439 "to", "move", "", 1440 HK_SELECT, "to", "select", "", 1441 HK_CANCEL, "to", "go", "to", "menu" 1442 }; 1443 static struct style_text formation[]={ 1444 { 0, TEXT_CENTER|TEXT_UNDERLINE }, 1445 { 2, C_RED }, 1446 { 42, C_RED }, 1447 LAST_STYLE_ITEM 1448 }; 1449 1450 rb->lcd_setfont(FONT_UI); 1451 if (display_text(ARRAYLEN(help_text), help_text, formation, NULL, true)) 1452 return true; 1453 rb->lcd_setfont(FONT_SYSFIXED); 1454 1455 return false; 1456} 1457 1458static bool _ingame; 1459static int jewels_menu_cb(int action, 1460 const struct menu_item_ex *this_item, 1461 struct gui_synclist *this_list) 1462{ 1463 (void)this_list; 1464 int i = ((intptr_t)this_item); 1465 if(action == ACTION_REQUEST_MENUITEM 1466 && !_ingame && (i==0 || i==6)) 1467 return ACTION_EXIT_MENUITEM; 1468 return action; 1469} 1470/***************************************************************************** 1471* jewels_game_menu() shows the game menu. 1472******************************************************************************/ 1473static int jewels_game_menu(struct game_context* bj, bool ingame) 1474{ 1475 rb->button_clear_queue(); 1476 int choice = 0; 1477 1478 _ingame = ingame; 1479 1480 static struct opt_items mode[] = { 1481 { "Normal", -1 }, 1482 { "Puzzle", -1 }, 1483 }; 1484 1485 MENUITEM_STRINGLIST (main_menu, "Jewels Menu", jewels_menu_cb, 1486 "Resume Game", 1487 "Start New Game", 1488 "Mode", 1489 "Help", 1490 "High Scores", 1491 "Playback Control", 1492 "Quit without Saving", 1493 "Quit"); 1494 1495 while (1) { 1496 switch (rb->do_menu(&main_menu, &choice, NULL, false)) { 1497 case 0: 1498 jewels_setcolors(); 1499 if(resume_file) 1500 rb->remove(SAVE_FILE); 1501 return 0; 1502 case 1: 1503 jewels_init(bj); 1504 return 0; 1505 case 2: 1506 rb->set_option("Mode", &bj->tmp_type, RB_INT, mode, 2, NULL); 1507 break; 1508 case 3: 1509 if(jewels_help()) 1510 return 1; 1511 break; 1512 case 4: 1513 highscore_show(-1, highscores, NUM_SCORES, true); 1514 break; 1515 case 5: 1516 playback_control(NULL); 1517 break; 1518 case 6: 1519 return 1; 1520 case 7: 1521 if (ingame) { 1522 rb->splash(HZ*1, "Saving game ..."); 1523 jewels_savegame(bj); 1524 } 1525 return 1; 1526 case MENU_ATTACHED_USB: 1527 return 1; 1528 default: 1529 break; 1530 } 1531 } 1532} 1533 1534static int jewels_main(struct game_context* bj) { 1535 int button; 1536 int position; 1537 bool selected = false; 1538 int x=0, y=0; 1539 1540 bool loaded = jewels_loadgame(bj); 1541 resume_file = loaded; 1542 if (jewels_game_menu(bj, loaded)!=0) 1543 return 0; 1544 1545 resume_file = false; 1546 while(true) { 1547 /* refresh the board */ 1548 jewels_drawboard(bj); 1549 1550 /* display the cursor */ 1551 if(selected) { 1552 rb->lcd_set_drawmode(DRMODE_COMPLEMENT); 1553 rb->lcd_fillrect(x*TILE_WIDTH, y*TILE_HEIGHT+YOFS, 1554 TILE_WIDTH, TILE_HEIGHT); 1555 rb->lcd_set_drawmode(DRMODE_SOLID); 1556 } else { 1557 rb->lcd_drawrect(x*TILE_WIDTH, y*TILE_HEIGHT+YOFS, 1558 TILE_WIDTH, TILE_HEIGHT); 1559 } 1560 rb->lcd_update_rect(x*TILE_WIDTH, y*TILE_HEIGHT+YOFS, 1561 TILE_WIDTH, TILE_HEIGHT); 1562 1563 /* handle game button presses */ 1564 rb->yield(); 1565 button = rb->button_get(true); 1566 switch(button){ 1567 case JEWELS_LEFT: /* move cursor left */ 1568 case (JEWELS_LEFT|BUTTON_REPEAT): 1569 if(selected) { 1570 bj->score += jewels_swapjewels(bj, x, y, SWAP_LEFT); 1571 selected = false; 1572 } else { 1573 x = (x+BJ_WIDTH-1)%BJ_WIDTH; 1574 } 1575 break; 1576 1577 case JEWELS_RIGHT: /* move cursor right */ 1578 case (JEWELS_RIGHT|BUTTON_REPEAT): 1579 if(selected) { 1580 bj->score += jewels_swapjewels(bj, x, y, SWAP_RIGHT); 1581 selected = false; 1582 } else { 1583 x = (x+1)%BJ_WIDTH; 1584 } 1585 break; 1586 1587 case JEWELS_DOWN: /* move cursor down */ 1588 case (JEWELS_DOWN|BUTTON_REPEAT): 1589 if(selected) { 1590 bj->score += jewels_swapjewels(bj, x, y, SWAP_DOWN); 1591 selected = false; 1592 } else { 1593 y = (y+1)%(BJ_HEIGHT-1); 1594 } 1595 break; 1596 1597 case JEWELS_UP: /* move cursor up */ 1598 case (JEWELS_UP|BUTTON_REPEAT): 1599 if(selected) { 1600 bj->score += jewels_swapjewels(bj, x, y, SWAP_UP); 1601 selected = false; 1602 } else { 1603 y = (y+(BJ_HEIGHT-1)-1)%(BJ_HEIGHT-1); 1604 } 1605 break; 1606 1607#ifdef JEWELS_SCROLLWHEEL 1608 case JEWELS_PREV: /* scroll backwards */ 1609 case (JEWELS_PREV|BUTTON_REPEAT): 1610 if(!selected) { 1611 if(x == 0) { 1612 y = (y+(BJ_HEIGHT-1)-1)%(BJ_HEIGHT-1); 1613 } 1614 x = (x+BJ_WIDTH-1)%BJ_WIDTH; 1615 } 1616 break; 1617 1618 case JEWELS_NEXT: /* scroll forwards */ 1619 case (JEWELS_NEXT|BUTTON_REPEAT): 1620 if(!selected) { 1621 if(x == BJ_WIDTH-1) { 1622 y = (y+1)%(BJ_HEIGHT-1); 1623 } 1624 x = (x+1)%BJ_WIDTH; 1625 } 1626 break; 1627#endif 1628 1629 case JEWELS_SELECT: /* toggle selected */ 1630 selected = !selected; 1631 break; 1632 1633#ifdef JEWELS_RC_CANCEL 1634 case JEWELS_RC_CANCEL: 1635#endif 1636 case JEWELS_CANCEL: /* end game */ 1637 if (jewels_game_menu(bj, true)!=0) 1638 return 0; 1639 break; 1640 1641 default: 1642 if (rb->default_event_handler (button) == SYS_USB_CONNECTED) 1643 return PLUGIN_USB_CONNECTED; 1644 break; 1645 } 1646 1647 switch(bj->type) { 1648 case GAME_TYPE_NORMAL: 1649 if(bj->score >= LEVEL_PTS) 1650 jewels_nextlevel(bj); 1651 break; 1652 case GAME_TYPE_PUZZLE: 1653 if (jewels_puzzle_is_finished(bj)) { 1654 if (bj->level < NUM_PUZZLE_LEVELS) { 1655 jewels_nextlevel(bj); 1656 } else { 1657 rb->splash(2*HZ, "Congratulations!"); 1658 rb->splash(2*HZ, "You have finished the game!"); 1659 if (jewels_game_menu(bj, false)!=0) { 1660 return 0; 1661 } 1662 } 1663 break; 1664 } 1665 } 1666 1667 if (!jewels_movesavail(bj)) { 1668 switch(bj->type) { 1669 case GAME_TYPE_NORMAL: 1670 rb->splash(HZ*2, "Game Over!"); 1671 rb->lcd_clear_display(); 1672 bj->score += (bj->level-1)*LEVEL_PTS; 1673 position=highscore_update(bj->score, bj->level, "", 1674 highscores, NUM_SCORES); 1675 if (position != -1) 1676 { 1677 if (position == 0) 1678 rb->splash(HZ*2, "New High Score"); 1679 highscore_show(position, highscores, NUM_SCORES, true); 1680 } 1681 break; 1682 case GAME_TYPE_PUZZLE: 1683 rb->splash(2*HZ, "Game Over"); 1684 break; 1685 } 1686 if (jewels_game_menu(bj, false)!=0) { 1687 return 0; 1688 } 1689 } 1690 } 1691} 1692 1693/* this is the plugin entry point */ 1694enum plugin_status plugin_start(const void* parameter) 1695{ 1696 (void)parameter; 1697 1698 /* load high scores */ 1699 highscore_load(SCORE_FILE, highscores, NUM_SCORES); 1700 1701 rb->lcd_setfont(FONT_SYSFIXED); 1702#if LCD_DEPTH > 1 1703 rb->lcd_set_backdrop(NULL); 1704#endif 1705 1706 struct game_context bj; 1707 bj.tmp_type = GAME_TYPE_NORMAL; 1708 jewels_main(&bj); 1709 highscore_save(SCORE_FILE, highscores, NUM_SCORES); 1710 rb->lcd_setfont(FONT_UI); 1711 1712 return PLUGIN_OK; 1713}