A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1689 lines 44 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2003 Mat Holton 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21 22/* 23Snake2! 24 25Board consists of a WIDTHxHEIGHT grid. If board element is 0 then nothing is 26there otherwise it is part of the snake or a wall. 27 28Head and Tail are stored 29 30*/ 31 32#include "plugin.h" 33 34#include "lib/highscore.h" 35#include "lib/playback_control.h" 36 37 38 39#define WIDTH 28 40#define HEIGHT 16 41 42#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) \ 43 || (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 96) && (LCD_DEPTH >= 16) 44#include "pluginbitmaps/snake2_header1.h" 45#include "pluginbitmaps/snake2_header2.h" 46#include "pluginbitmaps/snake2_left.h" 47#include "pluginbitmaps/snake2_right.h" 48#include "pluginbitmaps/snake2_bottom.h" 49#define BMPHEIGHT_snake2_header BMPHEIGHT_snake2_header1 50#define BMPWIDTH_snake2_header BMPWIDTH_snake2_header1 51#endif 52 53#if (LCD_WIDTH >= 640) && (LCD_HEIGHT >= 480) 54 #define MULTIPLIER 20 /*Modifier for porting on other screens*/ 55 #define MODIFIER_1 20 56 #define MODIFIER_2 16 57 #define CENTER_X 40 58 #define CENTER_Y 110 59 #define TOP_X1 68 /* x-coord of the upperleft item (game type) */ 60 #define TOP_X2 562 /* x-coord of the upperright item (maze type) */ 61 #define TOP_X3 84 /* x-coord of the lowerleft item (speed) */ 62 #define TOP_X4 548 /* x-coord of the lowerright item (hi-score) */ 63 #define TOP_Y1 8 /* y-coord of the top row of items */ 64 #define TOP_Y2 50 /* y-coord of the bottom row of items */ 65#elif (LCD_WIDTH >= 360) && (LCD_HEIGHT >= 400) 66 #define MULTIPLIER 12 /*Modifier for porting on other screens*/ 67 #define MODIFIER_1 12 68 #define MODIFIER_2 10 69 #define CENTER_X 12 70 #define CENTER_Y 40 71 #define TOP_X1 34 /* x-coord of the upperleft item (game type) */ 72 #define TOP_X2 320 /* x-coord of the upperright item (maze type) */ 73 #define TOP_X3 42 /* x-coord of the lowerleft item (speed) */ 74 #define TOP_X4 314 /* x-coord of the lowerright item (hi-score) */ 75 #define TOP_Y1 4 /* y-coord of the top row of items */ 76 #define TOP_Y2 25 /* y-coord of the bottom row of items */ 77#elif (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240) 78 #define MULTIPLIER 10 /*Modifier for porting on other screens*/ 79 #define MODIFIER_1 10 80 #define MODIFIER_2 8 81 #define CENTER_X 20 82 #define CENTER_Y 55 83 #define TOP_X1 34 /* x-coord of the upperleft item (game type) */ 84 #define TOP_X2 281 /* x-coord of the upperright item (maze type) */ 85 #define TOP_X3 42 /* x-coord of the lowerleft item (speed) */ 86 #define TOP_X4 274 /* x-coord of the lowerright item (hi-score) */ 87 #define TOP_Y1 4 /* y-coord of the top row of items */ 88 #define TOP_Y2 25 /* y-coord of the bottom row of items */ 89#elif (LCD_WIDTH >= 240) && (LCD_HEIGHT >= 168) 90 #define MULTIPLIER 8 91 #define MODIFIER_1 8 92 #define MODIFIER_2 6 93 #define CENTER_X 8 94 #define CENTER_Y 34 95 #define TOP_X1 34 96 #define TOP_X2 201 97 #define TOP_X3 42 98 #define TOP_X4 194 99 #define TOP_Y1 4 100 #define TOP_Y2 25 101#elif (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176) 102 #define MULTIPLIER 7 103 #define MODIFIER_1 7 104 #define MODIFIER_2 5 105 #define CENTER_X 12 106 #define CENTER_Y 46 107 #define TOP_X1 34 108 #define TOP_X2 181 109 #define TOP_X3 42 110 #define TOP_X4 174 111 #define TOP_Y1 4 112 #define TOP_Y2 25 113#elif (LCD_WIDTH >= 176) && (LCD_HEIGHT >= 132) 114 #define MULTIPLIER 5 115 #define MODIFIER_1 5 116 #define MODIFIER_2 3 117 #define CENTER_X 18 118 #define CENTER_Y 40 119 #define TOP_X1 34 120 #define TOP_X2 137 121 #define TOP_X3 42 122 #define TOP_X4 130 123 #define TOP_Y1 4 124 #define TOP_Y2 25 125#elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) 126 #define MULTIPLIER 5 127 #define MODIFIER_1 5 128 #define MODIFIER_2 3 129 #define CENTER_X 10 130 #define CENTER_Y 38 131 #define TOP_X1 34 132 #define TOP_X2 121 133 #define TOP_X3 42 134 #define TOP_X4 114 135 #define TOP_Y1 4 136 #define TOP_Y2 25 137#elif (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 96) && (LCD_DEPTH >= 16) 138 #define MULTIPLIER 4 139 #define MODIFIER_1 4 140 #define MODIFIER_2 2 141 #define CENTER_X 8 142 #define CENTER_Y 24 143 #define TOP_X1 28 144 #define TOP_X2 96 145 #define TOP_X3 44 146 #define TOP_X4 83 147 #define TOP_Y1 2 148 #define TOP_Y2 13 149#elif (LCD_WIDTH == 96) && (LCD_HEIGHT == 96) 150 #define MULTIPLIER 3 151 #define MODIFIER_1 4 152 #define MODIFIER_2 2 153 #define CENTER_X 6 154 #define CENTER_Y 12 155#else 156 #define MULTIPLIER 4 157 #define MODIFIER_1 4 158 #define MODIFIER_2 2 159 #define CENTER_X 0 160 #define CENTER_Y 0 161 162#endif 163 164/* variable button definitions */ 165#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 166 (CONFIG_KEYPAD == IRIVER_H300_PAD) 167#define SNAKE2_LEFT BUTTON_LEFT 168#define SNAKE2_RIGHT BUTTON_RIGHT 169#define SNAKE2_UP BUTTON_UP 170#define SNAKE2_DOWN BUTTON_DOWN 171#define SNAKE2_QUIT BUTTON_OFF 172#define SNAKE2_PLAYPAUSE BUTTON_ON 173#define SNAKE2_PLAYPAUSE_TEXT "Play" 174 175#define SNAKE2_RC_QUIT BUTTON_RC_STOP 176 177#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ 178 (CONFIG_KEYPAD == IPOD_3G_PAD) || \ 179 (CONFIG_KEYPAD == IPOD_1G2G_PAD) 180#define SNAKE2_LEFT BUTTON_LEFT 181#define SNAKE2_RIGHT BUTTON_RIGHT 182#define SNAKE2_UP BUTTON_MENU 183#define SNAKE2_DOWN BUTTON_PLAY 184#define SNAKE2_QUIT (BUTTON_SELECT | BUTTON_REPEAT) 185#define SNAKE2_PLAYPAUSE (BUTTON_SELECT | BUTTON_REL) 186#define SNAKE2_PLAYPAUSE_TEXT "Select" 187 188#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) 189#define SNAKE2_LEFT BUTTON_LEFT 190#define SNAKE2_RIGHT BUTTON_RIGHT 191#define SNAKE2_UP BUTTON_UP 192#define SNAKE2_DOWN BUTTON_DOWN 193#define SNAKE2_QUIT BUTTON_POWER 194#define SNAKE2_PLAYPAUSE BUTTON_SELECT 195#define SNAKE2_PLAYPAUSE_TEXT "Select" 196 197#elif (CONFIG_KEYPAD == GIGABEAT_PAD) 198#define SNAKE2_LEFT BUTTON_LEFT 199#define SNAKE2_RIGHT BUTTON_RIGHT 200#define SNAKE2_UP BUTTON_UP 201#define SNAKE2_DOWN BUTTON_DOWN 202#define SNAKE2_QUIT BUTTON_POWER 203#define SNAKE2_PLAYPAUSE BUTTON_SELECT 204#define SNAKE2_PLAYPAUSE_TEXT "Select" 205 206#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \ 207(CONFIG_KEYPAD == SANSA_C200_PAD) || \ 208(CONFIG_KEYPAD == SANSA_CONNECT_PAD) || \ 209(CONFIG_KEYPAD == SANSA_CLIP_PAD) || \ 210(CONFIG_KEYPAD == SANSA_M200_PAD) 211#define SNAKE2_LEFT BUTTON_LEFT 212#define SNAKE2_RIGHT BUTTON_RIGHT 213#define SNAKE2_UP BUTTON_UP 214#define SNAKE2_DOWN BUTTON_DOWN 215#define SNAKE2_QUIT BUTTON_POWER 216#define SNAKE2_PLAYPAUSE BUTTON_SELECT 217#define SNAKE2_PLAYPAUSE_TEXT "Select" 218 219#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD) 220#define SNAKE2_LEFT BUTTON_LEFT 221#define SNAKE2_RIGHT BUTTON_RIGHT 222#define SNAKE2_UP BUTTON_UP 223#define SNAKE2_DOWN BUTTON_DOWN 224#define SNAKE2_QUIT (BUTTON_HOME|BUTTON_REPEAT) 225#define SNAKE2_PLAYPAUSE BUTTON_SELECT 226#define SNAKE2_PLAYPAUSE_TEXT "Select" 227 228#elif (CONFIG_KEYPAD == IRIVER_H10_PAD) 229#define SNAKE2_LEFT BUTTON_LEFT 230#define SNAKE2_RIGHT BUTTON_RIGHT 231#define SNAKE2_UP BUTTON_SCROLL_UP 232#define SNAKE2_DOWN BUTTON_SCROLL_DOWN 233#define SNAKE2_QUIT BUTTON_POWER 234#define SNAKE2_PLAYPAUSE BUTTON_FF 235#define SNAKE2_PLAYPAUSE_TEXT "FF" 236 237#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ 238 (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) 239#define SNAKE2_LEFT BUTTON_LEFT 240#define SNAKE2_RIGHT BUTTON_RIGHT 241#define SNAKE2_UP BUTTON_UP 242#define SNAKE2_DOWN BUTTON_DOWN 243#define SNAKE2_QUIT BUTTON_BACK 244#define SNAKE2_PLAYPAUSE BUTTON_SELECT 245#define SNAKE2_PLAYPAUSE_TEXT "Select" 246 247#elif (CONFIG_KEYPAD == MROBE100_PAD) 248#define SNAKE2_LEFT BUTTON_LEFT 249#define SNAKE2_RIGHT BUTTON_RIGHT 250#define SNAKE2_UP BUTTON_UP 251#define SNAKE2_DOWN BUTTON_DOWN 252#define SNAKE2_QUIT BUTTON_POWER 253#define SNAKE2_PLAYPAUSE BUTTON_SELECT 254#define SNAKE2_PLAYPAUSE_TEXT "Select" 255 256#elif CONFIG_KEYPAD == IAUDIO_M3_PAD 257#define SNAKE2_LEFT BUTTON_RC_REW 258#define SNAKE2_RIGHT BUTTON_RC_FF 259#define SNAKE2_UP BUTTON_RC_VOL_UP 260#define SNAKE2_DOWN BUTTON_RC_VOL_DOWN 261#define SNAKE2_QUIT BUTTON_RC_REC 262#define SNAKE2_PLAYPAUSE BUTTON_RC_PLAY 263#define SNAKE2_PLAYPAUSE_TEXT "Play" 264 265#elif (CONFIG_KEYPAD == COWON_D2_PAD) 266#define SNAKE2_QUIT BUTTON_POWER 267 268#elif CONFIG_KEYPAD == CREATIVEZVM_PAD 269#define SNAKE2_LEFT BUTTON_LEFT 270#define SNAKE2_RIGHT BUTTON_RIGHT 271#define SNAKE2_UP BUTTON_UP 272#define SNAKE2_DOWN BUTTON_DOWN 273#define SNAKE2_QUIT BUTTON_BACK 274#define SNAKE2_PLAYPAUSE BUTTON_PLAY 275#define SNAKE2_PLAYPAUSE_TEXT "Play" 276 277#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD 278#define SNAKE2_LEFT BUTTON_BACK 279#define SNAKE2_RIGHT BUTTON_MENU 280#define SNAKE2_UP BUTTON_UP 281#define SNAKE2_DOWN BUTTON_DOWN 282#define SNAKE2_QUIT BUTTON_POWER 283#define SNAKE2_PLAYPAUSE (BUTTON_PLAY|BUTTON_REL) 284#define SNAKE2_PLAYPAUSE_TEXT "Play" 285 286#elif (CONFIG_KEYPAD == PHILIPS_HDD1630_PAD) || \ 287 (CONFIG_KEYPAD == PHILIPS_HDD6330_PAD) 288#define SNAKE2_LEFT BUTTON_LEFT 289#define SNAKE2_RIGHT BUTTON_RIGHT 290#define SNAKE2_UP BUTTON_UP 291#define SNAKE2_DOWN BUTTON_DOWN 292#define SNAKE2_QUIT BUTTON_POWER 293#define SNAKE2_PLAYPAUSE BUTTON_VIEW 294#define SNAKE2_PLAYPAUSE_TEXT "View" 295 296#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD 297#define SNAKE2_LEFT BUTTON_PREV 298#define SNAKE2_RIGHT BUTTON_NEXT 299#define SNAKE2_UP BUTTON_UP 300#define SNAKE2_DOWN BUTTON_DOWN 301#define SNAKE2_QUIT BUTTON_POWER 302#define SNAKE2_PLAYPAUSE BUTTON_RIGHT 303#define SNAKE2_PLAYPAUSE_TEXT "Right" 304 305#elif (CONFIG_KEYPAD == ONDAVX747_PAD) || \ 306(CONFIG_KEYPAD == ONDAVX777_PAD) || \ 307CONFIG_KEYPAD == MROBE500_PAD 308#define SNAKE2_QUIT BUTTON_POWER 309 310#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \ 311 (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD) 312#define SNAKE2_LEFT BUTTON_LEFT 313#define SNAKE2_RIGHT BUTTON_RIGHT 314#define SNAKE2_UP BUTTON_UP 315#define SNAKE2_DOWN BUTTON_DOWN 316#define SNAKE2_QUIT BUTTON_REW 317#define SNAKE2_PLAYPAUSE BUTTON_PLAY 318#define SNAKE2_PLAYPAUSE_TEXT "Play" 319 320#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD 321#define SNAKE2_LEFT BUTTON_PREV 322#define SNAKE2_RIGHT BUTTON_NEXT 323#define SNAKE2_UP BUTTON_UP 324#define SNAKE2_DOWN BUTTON_DOWN 325#define SNAKE2_QUIT BUTTON_REC 326#define SNAKE2_PLAYPAUSE BUTTON_PLAY 327#define SNAKE2_PLAYPAUSE_TEXT "Play" 328 329#elif CONFIG_KEYPAD == MPIO_HD200_PAD 330#define SNAKE2_LEFT BUTTON_VOL_DOWN 331#define SNAKE2_RIGHT BUTTON_VOL_UP 332#define SNAKE2_UP BUTTON_REW 333#define SNAKE2_DOWN BUTTON_FF 334#define SNAKE2_QUIT (BUTTON_REC | BUTTON_PLAY) 335#define SNAKE2_PLAYPAUSE BUTTON_PLAY 336#define SNAKE2_PLAYPAUSE_TEXT "Play" 337 338#elif CONFIG_KEYPAD == MPIO_HD300_PAD 339#define SNAKE2_LEFT BUTTON_REW 340#define SNAKE2_RIGHT BUTTON_FF 341#define SNAKE2_UP BUTTON_UP 342#define SNAKE2_DOWN BUTTON_DOWN 343#define SNAKE2_QUIT (BUTTON_MENU|BUTTON_REPEAT) 344#define SNAKE2_PLAYPAUSE BUTTON_PLAY 345#define SNAKE2_PLAYPAUSE_TEXT "Play" 346 347#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD 348#define SNAKE2_LEFT BUTTON_LEFT 349#define SNAKE2_RIGHT BUTTON_RIGHT 350#define SNAKE2_UP BUTTON_UP 351#define SNAKE2_DOWN BUTTON_DOWN 352#define SNAKE2_QUIT BUTTON_POWER 353#define SNAKE2_PLAYPAUSE BUTTON_PLAYPAUSE 354#define SNAKE2_PLAYPAUSE_TEXT "Play-Pause" 355 356#elif (CONFIG_KEYPAD == HM60X_PAD) || \ 357 (CONFIG_KEYPAD == HM801_PAD) 358#define SNAKE2_LEFT BUTTON_LEFT 359#define SNAKE2_RIGHT BUTTON_RIGHT 360#define SNAKE2_UP BUTTON_UP 361#define SNAKE2_DOWN BUTTON_DOWN 362#define SNAKE2_QUIT BUTTON_POWER 363#define SNAKE2_PLAYPAUSE BUTTON_SELECT 364#define SNAKE2_PLAYPAUSE_TEXT "Select" 365 366#elif CONFIG_KEYPAD == SONY_NWZ_PAD 367#define SNAKE2_LEFT BUTTON_LEFT 368#define SNAKE2_RIGHT BUTTON_RIGHT 369#define SNAKE2_UP BUTTON_UP 370#define SNAKE2_DOWN BUTTON_DOWN 371#define SNAKE2_QUIT BUTTON_BACK 372#define SNAKE2_PLAYPAUSE BUTTON_PLAY 373#define SNAKE2_PLAYPAUSE_TEXT "Play" 374 375#elif CONFIG_KEYPAD == CREATIVE_ZEN_PAD 376#define SNAKE2_LEFT BUTTON_LEFT 377#define SNAKE2_RIGHT BUTTON_RIGHT 378#define SNAKE2_UP BUTTON_UP 379#define SNAKE2_DOWN BUTTON_DOWN 380#define SNAKE2_QUIT BUTTON_BACK 381#define SNAKE2_PLAYPAUSE BUTTON_PLAYPAUSE 382#define SNAKE2_PLAYPAUSE_TEXT "Play/Pause" 383 384#elif (CONFIG_KEYPAD == DX50_PAD) 385#define SNAKE2_QUIT (BUTTON_POWER|BUTTON_REL) 386#define SNAKE2_LEFT BUTTON_LEFT 387#define SNAKE2_RIGHT BUTTON_PLAY 388#define SNAKE2_UP BUTTON_VOL_UP 389#define SNAKE2_DOWN BUTTON_VOL_DOWN 390#define SNAKE2_PLAYPAUSE BUTTON_RIGHT 391#define SNAKE2_PLAYPAUSE_TEXT "Right" 392 393#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD 394#define SNAKE2_QUIT BUTTON_POWER 395#define SNAKE2_PLAYPAUSE BUTTON_MENU 396#define SNAKE2_PLAYPAUSE_TEXT "Menu" 397 398#elif CONFIG_KEYPAD == AGPTEK_ROCKER_PAD 399#define SNAKE2_LEFT BUTTON_LEFT 400#define SNAKE2_RIGHT BUTTON_RIGHT 401#define SNAKE2_UP BUTTON_UP 402#define SNAKE2_DOWN BUTTON_DOWN 403#define SNAKE2_QUIT BUTTON_POWER 404#define SNAKE2_PLAYPAUSE BUTTON_SELECT 405#define SNAKE2_PLAYPAUSE_TEXT "Select" 406 407#elif (CONFIG_KEYPAD == XDUOO_X3_PAD) 408#define SNAKE2_LEFT BUTTON_PREV 409#define SNAKE2_RIGHT BUTTON_NEXT 410#define SNAKE2_UP BUTTON_HOME 411#define SNAKE2_DOWN BUTTON_OPTION 412#define SNAKE2_QUIT BUTTON_POWER 413#define SNAKE2_PLAYPAUSE BUTTON_PLAY 414#define SNAKE2_PLAYPAUSE_TEXT "PLAY" 415 416#elif (CONFIG_KEYPAD == XDUOO_X3II_PAD) || (CONFIG_KEYPAD == XDUOO_X20_PAD) 417#define SNAKE2_LEFT BUTTON_PREV 418#define SNAKE2_RIGHT BUTTON_NEXT 419#define SNAKE2_UP BUTTON_HOME 420#define SNAKE2_DOWN BUTTON_OPTION 421#define SNAKE2_QUIT BUTTON_POWER 422#define SNAKE2_PLAYPAUSE BUTTON_PLAY 423#define SNAKE2_PLAYPAUSE_TEXT "PLAY" 424 425#elif (CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD) 426#define SNAKE2_LEFT BUTTON_PREV 427#define SNAKE2_RIGHT BUTTON_NEXT 428#define SNAKE2_UP BUTTON_HOME 429#define SNAKE2_DOWN BUTTON_OPTION 430#define SNAKE2_QUIT BUTTON_POWER 431#define SNAKE2_PLAYPAUSE BUTTON_PLAY 432#define SNAKE2_PLAYPAUSE_TEXT "PLAY" 433 434#elif (CONFIG_KEYPAD == IHIFI_770_PAD) || (CONFIG_KEYPAD == IHIFI_800_PAD) 435#define SNAKE2_LEFT BUTTON_HOME 436#define SNAKE2_RIGHT BUTTON_VOL_DOWN 437#define SNAKE2_UP BUTTON_PREV 438#define SNAKE2_DOWN BUTTON_NEXT 439#define SNAKE2_QUIT BUTTON_POWER 440#define SNAKE2_PLAYPAUSE BUTTON_PLAY 441#define SNAKE2_PLAYPAUSE_TEXT "PLAY" 442 443#elif (CONFIG_KEYPAD == EROSQ_PAD) 444#define SNAKE2_LEFT BUTTON_SCROLL_BACK 445#define SNAKE2_RIGHT BUTTON_SCROLL_FWD 446#define SNAKE2_UP BUTTON_PREV 447#define SNAKE2_DOWN BUTTON_NEXT 448#define SNAKE2_QUIT BUTTON_POWER 449#define SNAKE2_PLAYPAUSE BUTTON_PLAY 450#define SNAKE2_PLAYPAUSE_TEXT "PLAY" 451 452#elif CONFIG_KEYPAD == FIIO_M3K_PAD 453#define SNAKE2_LEFT BUTTON_LEFT 454#define SNAKE2_RIGHT BUTTON_RIGHT 455#define SNAKE2_UP BUTTON_UP 456#define SNAKE2_DOWN BUTTON_DOWN 457#define SNAKE2_QUIT BUTTON_POWER 458#define SNAKE2_PLAYPAUSE BUTTON_PLAY 459#define SNAKE2_PLAYPAUSE_TEXT "PLAY" 460 461#elif CONFIG_KEYPAD == SDL_PAD 462/* use touchscreen */ 463 464#elif CONFIG_KEYPAD == SHANLING_Q1_PAD 465/* use touchscreen */ 466 467#elif CONFIG_KEYPAD == MA_PAD 468#define SNAKE2_LEFT BUTTON_LEFT 469#define SNAKE2_RIGHT BUTTON_RIGHT 470#define SNAKE2_UP BUTTON_UP 471#define SNAKE2_DOWN BUTTON_DOWN 472#define SNAKE2_QUIT BUTTON_BACK 473#define SNAKE2_PLAYPAUSE BUTTON_PLAY 474#define SNAKE2_PLAYPAUSE_TEXT "PLAY" 475 476#elif (CONFIG_KEYPAD == RG_NANO_PAD) 477#define SNAKE2_LEFT BUTTON_LEFT 478#define SNAKE2_RIGHT BUTTON_RIGHT 479#define SNAKE2_UP BUTTON_UP 480#define SNAKE2_DOWN BUTTON_DOWN 481#define SNAKE2_QUIT BUTTON_START 482#define SNAKE2_PLAYPAUSE BUTTON_A 483#define SNAKE2_PLAYPAUSE_TEXT "A" 484 485#else 486#error No keymap defined! 487#endif 488 489#ifdef HAVE_TOUCHSCREEN 490#ifndef SNAKE2_LEFT 491#define SNAKE2_LEFT BUTTON_MIDLEFT 492#endif 493#ifndef SNAKE2_RIGHT 494#define SNAKE2_RIGHT BUTTON_MIDRIGHT 495#endif 496#ifndef SNAKE2_UP 497#define SNAKE2_UP BUTTON_TOPMIDDLE 498#endif 499#ifndef SNAKE2_DOWN 500#define SNAKE2_DOWN BUTTON_BOTTOMMIDDLE 501#endif 502#ifndef SNAKE2_QUIT 503#define SNAKE2_QUIT BUTTON_TOPLEFT 504#endif 505#ifndef SNAKE2_PLAYPAUSE 506#define SNAKE2_PLAYPAUSE BUTTON_CENTER 507#endif 508#ifndef SNAKE2_PLAYPAUSE_TEXT 509#define SNAKE2_PLAYPAUSE_TEXT "CENTER" 510#endif 511#endif 512 513static int max_levels = 0; 514static char (*level_cache)[HEIGHT][WIDTH]; 515 516/*Board itself - 2D int array*/ 517static int board[WIDTH][HEIGHT]; 518/* 519 Buffer for sorting movement (in case user presses two movements during a 520 single frame 521*/ 522static int ardirectionbuffer[2]; 523static int score; 524static int applex; 525static int appley; 526static int dir; 527static int frames; 528static int apple; 529static int level = 4, speed = 5,dead = 0, quit = 0; 530static int sillydir = 0, num_levels = 0; 531static int level_from_file = 0; 532static int headx, heady, tailx, taily, applecountdown = 5; 533static int game_type = 0; 534static int num_apples_to_get=1; 535static int num_apples_to_got=0; 536static int game_b_level=0; 537static int applecount=0; 538/* used for string width, height for orientation purposes */ 539static int strwdt, strhgt; 540static char strbuf[32]; 541 542#define NUM_SCORES 5 543static struct highscore highscores[NUM_SCORES]; 544 545#define NORTH 1 546#define EAST 2 547#define SOUTH 4 548#define WEST 8 549#define HEAD 16 550 551#define EAST_NORTH 32 552#define EAST_SOUTH 64 553#define WEST_NORTH 128 554#define WEST_SOUTH 256 555 556#define NORTH_EAST 512 557#define NORTH_WEST 1024 558#define SOUTH_EAST 2048 559#define SOUTH_WEST 4096 560 561#define LEVELS_FILE PLUGIN_GAMES_DIR "/snake2.levels" 562#define SCORE_FILE PLUGIN_GAMES_DATA_DIR "/snake2.score" 563 564static int load_all_levels(void) 565{ 566 int linecnt = 0; 567 int fd; 568 size_t size; 569 char buf[64]; /* Larger than WIDTH, to allow for whitespace after the 570 lines */ 571 572 /* Init the level_cache pointer and 573 calculate how many levels that will fit */ 574 level_cache = rb->plugin_get_buffer(&size); 575 max_levels = size / (HEIGHT*WIDTH); 576 577 num_levels = 0; 578 579 /* open file */ 580 if ((fd = rb->open(LEVELS_FILE, O_RDONLY)) < 0) 581 { 582 return -1; 583 } 584 585 while(rb->read_line(fd, buf, 64) > 0) 586 { 587 if(rb->strlen(buf) == 0) /* Separator? */ 588 { 589 num_levels++; 590 if(num_levels > max_levels) 591 { 592 rb->splash(HZ, "Too many levels in file"); 593 break; 594 } 595 continue; 596 } 597 598 rb->memcpy(level_cache[num_levels][linecnt], buf, WIDTH); 599 linecnt++; 600 if(linecnt == HEIGHT) 601 { 602 linecnt = 0; 603 } 604 } 605 606 rb->close(fd); 607 return 0; 608} 609 610/* 611** Completely clear the board of walls and/or snake 612*/ 613 614static void clear_board( void) 615{ 616 int x,y; 617 618 for (x = 0; x < WIDTH; x++) 619 { 620 for (y = 0; y < HEIGHT; y++) 621 { 622 board[x][y] = 0; 623 } 624 } 625} 626 627static int load_level( int level_number ) 628{ 629 int x,y; 630 clear_board(); 631 for(y = 0;y < HEIGHT;y++) 632 { 633 for(x = 0;x < WIDTH;x++) 634 { 635 switch(level_cache[level_number][y][x]) 636 { 637 case '|': 638 board[x][y] = NORTH; 639 break; 640 641 case '-': 642 board[x][y] = EAST; 643 break; 644 645 case '+': 646 board[x][y] = HEAD; 647 break; 648 } 649 } 650 } 651 return 1; 652} 653 654/* 655** Gets the currently chosen direction from the first place 656** in the direction buffer. If there is something in the 657** next part of the buffer then that is moved to the first place 658*/ 659static void get_direction( void ) 660{ 661 /*if 1st place is empty*/ 662 if(ardirectionbuffer[0] != -1) 663 { 664 /*return this direction*/ 665 dir = ardirectionbuffer[0]; 666 ardirectionbuffer[0]=-1; 667 /*now see if one needs moving:*/ 668 if(ardirectionbuffer[1] != -1) 669 { 670 /*there's a move waiting to be done 671 so move it into the space:*/ 672 ardirectionbuffer[0] = ardirectionbuffer[1]; 673 ardirectionbuffer[1] = -1; 674 } 675 } 676} 677 678/* 679** Sets the direction 680*/ 681static void set_direction(int newdir) 682{ 683 if(ardirectionbuffer[0] != newdir) 684 { 685 /*if 1st place is empty*/ 686 if(ardirectionbuffer[0] == -1) 687 { 688 /*use 1st space:*/ 689 ardirectionbuffer[0] = newdir; 690 } 691 else 692 { 693 /*use 2nd space:*/ 694 if(ardirectionbuffer[0] != newdir) ardirectionbuffer[1] = newdir; 695 } 696 697 if(frames < 0) ardirectionbuffer[0] = newdir; 698 } 699} 700 701static void new_level(int level) 702{ 703 load_level(level); 704 705 ardirectionbuffer[0] = -1; 706 ardirectionbuffer[1] = -1; 707 dir = EAST; 708 headx = WIDTH/2; 709 heady = HEIGHT/2; 710 tailx = headx - 4; 711 taily = heady; 712 applecountdown = 0; 713 /*Create a small snake to start off with*/ 714 board[headx][heady] = dir; 715 board[headx-1][heady] = dir; 716 board[headx-2][heady] = dir; 717 board[headx-3][heady] = dir; 718 board[headx-4][heady] = dir; 719 num_apples_to_got=0; 720} 721 722static void init_snake(void) 723{ 724 num_apples_to_get=1; 725 if(game_type == 1) 726 level_from_file = 1; 727 game_b_level=1; 728 new_level(level_from_file); 729} 730 731#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) \ 732 || (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 96) && (LCD_DEPTH >= 16) 733static void draw_frame_bitmap(int header_type) 734{ 735 rb->lcd_bitmap(header_type==1? snake2_header1: snake2_header2, 0, 0, 736 BMPWIDTH_snake2_header, BMPHEIGHT_snake2_header); 737 rb->lcd_bitmap(snake2_left, 0, BMPHEIGHT_snake2_header, 738 BMPWIDTH_snake2_left, BMPHEIGHT_snake2_left); 739 rb->lcd_bitmap(snake2_right, 740 LCD_WIDTH - BMPWIDTH_snake2_right, BMPHEIGHT_snake2_header, 741 BMPWIDTH_snake2_right, BMPHEIGHT_snake2_right); 742 rb->lcd_bitmap(snake2_bottom, 743 0, BMPHEIGHT_snake2_header + BMPHEIGHT_snake2_left, 744 BMPWIDTH_snake2_bottom, BMPHEIGHT_snake2_bottom); 745} 746#endif 747 748/* 749** Draws the apple. If it doesn't exist then 750** a new one get's created. 751*/ 752static void draw_apple_bit(int x, int y) 753{ 754 rb->lcd_fillrect((CENTER_X+x*MULTIPLIER)+1, CENTER_Y+y*MULTIPLIER, 755 MODIFIER_2, MODIFIER_1); 756 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER, (CENTER_Y+y*MULTIPLIER)+1, 757 MODIFIER_1, MODIFIER_2); 758} 759 760static void draw_apple( void ) 761{ 762 int x,y; 763 764#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) \ 765 || (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 96) && (LCD_DEPTH >= 16) 766 draw_frame_bitmap(2); 767 768 rb->snprintf(strbuf, sizeof(strbuf), "%d", applecount); 769 rb->lcd_getstringsize(strbuf, &strwdt, &strhgt); 770 rb->lcd_putsxy(TOP_X3 - strwdt/2, TOP_Y2, strbuf); 771 772 rb->snprintf(strbuf, sizeof(strbuf), "%d", score); 773 rb->lcd_getstringsize(strbuf, &strwdt, &strhgt); 774 rb->lcd_putsxy(TOP_X4 - strwdt/2, TOP_Y2, strbuf); 775#endif 776 777 if (!apple) 778 { 779 do 780 { 781 x = (rb->rand() % (WIDTH-1))+1; 782 y = (rb->rand() % (HEIGHT-1))+1; 783 } while (board[x][y]); 784 apple = 1; 785 board[x][y] = -1; 786 applex = x;appley = y; 787 } 788 draw_apple_bit(applex, appley); 789} 790 791/* 792 * x x * 793 * x x * 794 * x x * 795 * x x * 796*/ 797static void draw_vertical_bit(int x, int y) 798{ 799 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+1, CENTER_Y+y*MULTIPLIER, 800 MODIFIER_2, MODIFIER_1); 801} 802 803/* 804 * * * * 805 X X X X 806 X X X X 807 * * * * 808*/ 809static void draw_horizontal_bit(int x, int y) 810{ 811 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER, CENTER_Y+y*MULTIPLIER+1, 812 MODIFIER_1, MODIFIER_2); 813} 814 815/* 816 * * * * 817 * * X X 818 * X X X 819 * X X * 820*/ 821static void draw_n_to_e_bit(int x, int y) 822{ 823 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+1, CENTER_Y+y*MULTIPLIER+2, 824 MODIFIER_2, MODIFIER_2); 825 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+2, CENTER_Y+y*MULTIPLIER+1, 826 MODIFIER_2, MODIFIER_2); 827} 828 829/* 830 * * * * 831 * * X X 832 * X X X 833 * X X * 834*/ 835static void draw_w_to_s_bit(int x, int y) 836{ 837 draw_n_to_e_bit(x,y); 838} 839 840/* 841 * * * * 842 X X * * 843 X X X * 844 * X X * 845*/ 846static void draw_n_to_w_bit(int x, int y) 847{ 848 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER, CENTER_Y+y*MULTIPLIER+1, 849 MODIFIER_2, MODIFIER_2); 850 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+1, CENTER_Y+y*MULTIPLIER+2, 851 MODIFIER_2, MODIFIER_2); 852} 853 854/* 855 * * * * 856 X X * * 857 X X X * 858 * X X * 859*/ 860static void draw_e_to_s_bit(int x, int y) 861{ 862 draw_n_to_w_bit(x, y); 863} 864 865/* 866 * X X * 867 * X X X 868 * * X X 869 * * * * 870*/ 871static void draw_s_to_e_bit(int x, int y) 872{ 873 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+1, CENTER_Y+y*MULTIPLIER, 874 MODIFIER_2, MODIFIER_2); 875 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+2, CENTER_Y+y*MULTIPLIER+1, 876 MODIFIER_2, MODIFIER_2); 877} 878 879/* 880 * X X * 881 * X X X 882 * * X X 883 * * * * 884*/ 885static void draw_w_to_n_bit(int x, int y) 886{ 887 draw_s_to_e_bit(x,y); 888} 889 890/* 891 * X X * 892 X X X * 893 X X * * 894 * * * * 895*/ 896static void draw_e_to_n_bit(int x, int y) 897{ 898 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+1, CENTER_Y+y*MULTIPLIER, 899 MODIFIER_2, MODIFIER_2); 900 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER, CENTER_Y+y*MULTIPLIER+1, 901 MODIFIER_2, MODIFIER_2); 902} 903 904/* 905 * X X * 906 X X X * 907 X X * * 908 * * * * 909*/ 910static void draw_s_to_w_bit(int x, int y) 911{ 912 draw_e_to_n_bit(x, y); 913} 914 915static void draw_head_bit(int x, int y) 916{ 917 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER, CENTER_Y+y*MULTIPLIER, 918 MODIFIER_1, MODIFIER_1); 919} 920 921#if 0 /* unused */ 922/* 923** Draws a wall/obsticals 924*/ 925static void draw_boundary ( void ) 926{ 927 int x, y; 928 929 /*TODO: Load levels from file!*/ 930 931 /*top and bottom line*/ 932 for(x=0; x < WIDTH; x++) 933 { 934 board[x][0] = EAST; 935 board[x][HEIGHT-1] = WEST; 936 } 937 938 /*left and right lines*/ 939 for(y=0; y < HEIGHT; y++) 940 { 941 board[0][y] = NORTH; 942 board[WIDTH-1][y] = SOUTH; 943 } 944 945 /*corners:*/ 946 board[0][0] = NORTH_EAST; 947 board[WIDTH-1][0] = EAST_SOUTH; 948 board[0][HEIGHT-1] = SOUTH_EAST; 949 board[WIDTH-1][HEIGHT-1] = EAST_NORTH; 950} 951#endif 952 953/* 954** Redraw the entire board 955*/ 956static void redraw (void) 957{ 958 int x,y; 959 960#ifdef HAVE_LCD_COLOR 961 rb->lcd_set_foreground(LCD_BLACK); 962 rb->lcd_set_background(LCD_WHITE); 963#endif 964 965 rb->lcd_clear_display(); 966 967 for (x = 0; x < WIDTH; x++) 968 { 969 for (y = 0; y < HEIGHT; y++) 970 { 971 switch (board[x][y]) 972 { 973 case -1: 974 draw_apple_bit(x, y); 975 break; 976 case 0: 977 break; 978 979 case NORTH: 980 case SOUTH: 981 draw_vertical_bit(x,y); 982 break; 983 984 case EAST: 985 case WEST: 986 draw_horizontal_bit(x,y); 987 break; 988 989 default: 990 draw_head_bit(x, y); 991 break; 992 } 993 } 994 } 995 996#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) \ 997 || (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 96) && (LCD_DEPTH >= 16) 998 draw_frame_bitmap(2); 999 1000 rb->snprintf(strbuf, sizeof(strbuf), "%d", applecount); 1001 rb->lcd_getstringsize(strbuf, &strwdt, &strhgt); 1002 rb->lcd_putsxy(TOP_X3 - strwdt/2, TOP_Y2, strbuf); 1003 1004 rb->snprintf(strbuf, sizeof(strbuf), "%d", score); 1005 rb->lcd_getstringsize(strbuf, &strwdt, &strhgt); 1006 rb->lcd_putsxy(TOP_X4 - strwdt/2, TOP_Y2, strbuf); 1007#endif 1008} 1009 1010/* 1011** Draws the snake bit described by nCurrentBit at position x/y 1012** deciding whether it's a corner bit by examing the nPrevious bit 1013*/ 1014static void draw_snake_bit(int currentbit, int previousbit, int x, int y) 1015{ 1016 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 1017 draw_head_bit(x, y); 1018 rb->lcd_set_drawmode(DRMODE_SOLID); 1019 1020 switch(currentbit) 1021 { 1022 case(NORTH): 1023 switch(previousbit) 1024 { 1025 case(SOUTH): 1026 case(NORTH): 1027 draw_vertical_bit(x,y); 1028 break; 1029 1030 case(EAST): 1031 draw_e_to_n_bit(x,y); 1032 break; 1033 1034 case(WEST): 1035 draw_w_to_n_bit(x,y); 1036 break; 1037 } 1038 break; 1039 1040 case(EAST): 1041 switch(previousbit) 1042 { 1043 case(WEST): 1044 case(EAST): 1045 draw_horizontal_bit(x,y); 1046 break; 1047 1048 case(NORTH): 1049 draw_n_to_e_bit(x,y); 1050 break; 1051 1052 case(SOUTH): 1053 draw_s_to_e_bit(x,y); 1054 break; 1055 } 1056 break; 1057 1058 case(SOUTH): 1059 switch(previousbit) 1060 { 1061 case(SOUTH): 1062 case(NORTH): 1063 draw_vertical_bit(x,y); 1064 break; 1065 1066 case(EAST): 1067 draw_e_to_s_bit(x,y); 1068 break; 1069 1070 case(WEST): 1071 draw_w_to_s_bit(x,y); 1072 break; 1073 } 1074 break; 1075 1076 case(WEST): 1077 switch(previousbit) 1078 { 1079 case(EAST): 1080 case(WEST): 1081 draw_horizontal_bit(x,y); 1082 break; 1083 1084 case(SOUTH): 1085 draw_s_to_w_bit(x,y); 1086 break; 1087 1088 case(NORTH): 1089 draw_n_to_w_bit(x,y); 1090 break; 1091 } 1092 break; 1093 } 1094} 1095 1096static void redraw_snake(void) 1097{ 1098 int x = tailx, y = taily; 1099 int olddir, newdir = board[x][y]; 1100 1101 while (x != headx || y != heady) 1102 { 1103 olddir = newdir; 1104 1105 switch (olddir) 1106 { 1107 case(NORTH): 1108 y--; 1109 break; 1110 1111 case(EAST): 1112 x++; 1113 break; 1114 1115 case(SOUTH): 1116 y++; 1117 break; 1118 1119 case(WEST): 1120 x--; 1121 break; 1122 } 1123 1124 if(x == WIDTH) 1125 x = 0; 1126 else if(x < 0) 1127 x = WIDTH-1; 1128 1129 if(y == HEIGHT) 1130 y = 0; 1131 else if(y < 0) 1132 y = HEIGHT-1; 1133 1134 newdir = board[x][y]; 1135 if(olddir != newdir) 1136 draw_snake_bit(newdir, olddir, x, y); 1137 } 1138} 1139 1140/* 1141** Death 'sequence' and end game stuff. 1142*/ 1143static void die (void) 1144{ 1145 int button; 1146 bool done=false; 1147 1148 rb->splash(HZ*2, "Oops!"); 1149 1150 rb->lcd_clear_display(); 1151 1152 applecount=0; 1153 1154 rb->lcd_getstringsize("You died!",&strwdt,&strhgt); 1155 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt,"You died!"); 1156 1157 rb->snprintf(strbuf, sizeof(strbuf), "Your score: %d", score); 1158 rb->lcd_getstringsize(strbuf, &strwdt, &strhgt); 1159 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2, strhgt * 2 + 2, strbuf); 1160 1161 if (highscore_update(score, level_from_file, game_type==0?"Type A":"Type B", 1162 highscores, NUM_SCORES) == 0) 1163 { 1164 rb->lcd_getstringsize("New high score!",&strwdt,&strhgt); 1165 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt * 4 + 2,"New high score!"); 1166 } 1167 else 1168 { 1169 rb->snprintf(strbuf, sizeof(strbuf), "High score: %d", highscores[0].score); 1170 rb->lcd_getstringsize(strbuf, &strwdt, &strhgt); 1171 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2, strhgt * 5, strbuf); 1172 } 1173 1174 rb->snprintf(strbuf, sizeof(strbuf), "Press %s...", SNAKE2_PLAYPAUSE_TEXT); 1175 rb->lcd_getstringsize(strbuf, &strwdt, &strhgt); 1176 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2, strhgt * 7, strbuf); 1177 1178 rb->lcd_update(); 1179 1180 while(!done) 1181 { 1182 button=rb->button_get(true); 1183 switch(button) 1184 { 1185 case SNAKE2_PLAYPAUSE: 1186 done = true; 1187 break; 1188 } 1189 } 1190 1191 dead=1; 1192} 1193 1194/* 1195** Check for collision. TODO: Currently this 1196** sets of the death sequence. What we want is it to only return a true/false 1197** depending on whether a collision occured. 1198*/ 1199static void collision ( int x, int y ) 1200{ 1201 int bdeath=0; 1202 1203 1204 switch (board[x][y]) 1205 { 1206 case 0: 1207 1208 break; 1209 case -1: 1210 score = score + (1 * level); 1211 apple=0; 1212 applecountdown=2; 1213 applecount++; 1214 1215 if(game_type==1) 1216 { 1217 if(num_apples_to_get == num_apples_to_got) 1218 { 1219 level_from_file++; 1220 if(level_from_file >= num_levels) 1221 { 1222 level_from_file = 1; 1223 /*and increase the number of apples to pick up 1224 before level changes*/ 1225 num_apples_to_get+=2; 1226 game_b_level++; 1227 } 1228 rb->splash(HZ, "Level Completed!"); 1229 new_level(level_from_file); 1230 redraw(); 1231 rb->lcd_update(); 1232 } 1233 else 1234 num_apples_to_got++; 1235 } 1236 break; 1237 default: 1238 bdeath=1; 1239 break; 1240 } 1241 1242 if(bdeath==1) 1243 { 1244 die(); 1245 sillydir = dir; 1246 frames = -110; 1247 } 1248} 1249 1250static void move( void ) 1251{ 1252 int taildir; 1253 /*this actually sets the dir variable.*/ 1254 get_direction(); 1255 /*draw head*/ 1256 switch (dir) 1257 { 1258 case (NORTH): 1259 board[headx][heady]=NORTH; 1260 heady--; 1261 break; 1262 case (EAST): 1263 board[headx][heady]=EAST; 1264 headx++; 1265 break; 1266 case (SOUTH): 1267 board[headx][heady]=SOUTH; 1268 heady++; 1269 break; 1270 case (WEST): 1271 board[headx][heady]=WEST; 1272 headx--; 1273 break; 1274 } 1275 1276 if(headx == WIDTH) 1277 headx = 0; 1278 else if(headx < 0) 1279 headx = WIDTH-1; 1280 1281 if(heady == HEIGHT) 1282 heady = 0; 1283 else if(heady < 0) 1284 heady = HEIGHT-1; 1285 1286 draw_head_bit(headx, heady); 1287 1288 /*clear tail*/ 1289 if(applecountdown <= 0) 1290 { 1291 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 1292 draw_head_bit(tailx, taily); 1293 rb->lcd_set_drawmode(DRMODE_SOLID); 1294 1295 taildir = board[tailx][taily]; 1296 board[tailx][taily] = 0; 1297 1298 switch (taildir) 1299 { 1300 case(NORTH): 1301 taily--; 1302 break; 1303 1304 case(EAST): 1305 tailx++; 1306 break; 1307 1308 case(SOUTH): 1309 taily++; 1310 break; 1311 1312 case(WEST): 1313 tailx--; 1314 break; 1315 } 1316 1317 if(tailx == WIDTH) 1318 tailx = 0; 1319 else if(tailx < 0) 1320 tailx = WIDTH-1; 1321 1322 if(taily == HEIGHT) 1323 taily = 0; 1324 else if(taily < 0) 1325 taily = HEIGHT-1; 1326 } 1327 else 1328 applecountdown--; 1329} 1330 1331static void frame (void) 1332{ 1333 int olddir, noldx, noldy, temp; 1334 noldx = headx; 1335 noldy = heady; 1336 olddir = 0; 1337 switch(dir) 1338 { 1339 case(NORTH): 1340 if(heady == HEIGHT-1) 1341 temp = 0; 1342 else 1343 temp = heady + 1; 1344 1345 olddir = board[headx][temp]; 1346 break; 1347 1348 case(EAST): 1349 if(headx == 0) 1350 temp = WIDTH-1; 1351 else 1352 temp = headx - 1; 1353 1354 olddir = board[temp][heady]; 1355 break; 1356 1357 case(SOUTH): 1358 if(heady == 0) 1359 temp = HEIGHT-1; 1360 else 1361 temp = heady - 1; 1362 1363 olddir = board[headx][temp]; 1364 break; 1365 1366 case(WEST): 1367 if(headx == WIDTH-1) 1368 temp = 0; 1369 else 1370 temp = headx + 1; 1371 1372 olddir = board[temp][heady]; 1373 break; 1374 } 1375 1376 move(); 1377 1378 /* 1379 now redraw the bit that was 1380 the tail, to something snake-like: 1381 */ 1382 draw_snake_bit(dir, olddir, noldx, noldy); 1383 1384 collision(headx, heady); 1385 1386 rb->lcd_update(); 1387} 1388 1389static void game_pause (void) 1390{ 1391 int button; 1392 1393 rb->lcd_clear_display(); 1394 rb->lcd_getstringsize("Paused",&strwdt,&strhgt); 1395 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,LCD_HEIGHT/2,"Paused"); 1396 1397 rb->lcd_update(); 1398 while (1) 1399 { 1400 button = rb->button_get(true); 1401 switch (button) 1402 { 1403 case SNAKE2_PLAYPAUSE: 1404 redraw(); 1405 redraw_snake(); 1406 draw_head_bit(headx, heady); 1407 rb->lcd_update(); 1408 rb->sleep(HZ/2); 1409 return; 1410 1411#ifdef SNAKE2_RC_QUIT 1412 case SNAKE2_RC_QUIT: 1413#endif 1414 case SNAKE2_QUIT: 1415 dead = 1; 1416 quit = 1; 1417 return; 1418 1419 default: 1420 if (rb->default_event_handler(button)==SYS_USB_CONNECTED) { 1421 dead = 1; 1422 quit = 2; 1423 return; 1424 } 1425 break; 1426 } 1427 } 1428} 1429 1430static void game (void) 1431{ 1432 int button; 1433 1434 redraw(); 1435 rb->lcd_update(); 1436 /*main loop:*/ 1437 while (1) 1438 { 1439 if(frames==5) 1440 { 1441 frame(); 1442 if(frames > 0) frames = 0; 1443 } 1444 frames++; 1445 1446 if(frames == 0) 1447 { 1448 die(); 1449 } 1450 else 1451 { 1452 if(frames < 0) 1453 { 1454 if(sillydir != dir) 1455 { 1456 /*it has, great set frames to a positive value again:*/ 1457 frames = 1; 1458 } 1459 } 1460 } 1461 1462 if (dead) return; 1463 1464 draw_apple(); 1465 1466 rb->sleep(HZ/speed); 1467 1468 button = rb->button_get(false); 1469 1470#ifdef HAS_BUTTON_HOLD 1471 if (rb->button_hold()) 1472 button = SNAKE2_PLAYPAUSE; 1473#endif 1474 1475 switch (button) 1476 { 1477 case SNAKE2_UP: 1478 case SNAKE2_UP | BUTTON_REPEAT: 1479 if (dir != SOUTH) set_direction(NORTH); 1480 break; 1481 1482 case SNAKE2_RIGHT: 1483 case SNAKE2_RIGHT | BUTTON_REPEAT: 1484 if (dir != WEST) set_direction(EAST); 1485 break; 1486 1487 case SNAKE2_DOWN: 1488 case SNAKE2_DOWN | BUTTON_REPEAT: 1489 if (dir != NORTH) set_direction(SOUTH); 1490 break; 1491 1492 case SNAKE2_LEFT: 1493 case SNAKE2_LEFT | BUTTON_REPEAT: 1494 if (dir != EAST) set_direction(WEST); 1495 break; 1496 1497#ifdef SNAKE2_RC_QUIT 1498 case SNAKE2_RC_QUIT: 1499#endif 1500 case SNAKE2_QUIT: 1501 quit = 1; 1502 return; 1503 1504 case SNAKE2_PLAYPAUSE: 1505 game_pause(); 1506 break; 1507 1508 default: 1509 if (rb->default_event_handler(button)==SYS_USB_CONNECTED) { 1510 quit = 2; 1511 return; 1512 } 1513 break; 1514 } 1515 } 1516 1517} 1518 1519static void select_maze(void) 1520{ 1521 int button; 1522 1523 clear_board(); 1524 load_level( level_from_file ); 1525 redraw(); 1526 rb->lcd_update(); 1527 1528 while (1) 1529 { 1530#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) \ 1531 || (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 96) && (LCD_DEPTH >= 16) 1532 draw_frame_bitmap(1); 1533 1534 rb->snprintf(strbuf, sizeof(strbuf), "%d", level); 1535 rb->lcd_getstringsize(strbuf, &strwdt, &strhgt); 1536 rb->lcd_putsxy(TOP_X3 - strwdt/2, TOP_Y2, strbuf); 1537 1538 rb->snprintf(strbuf, sizeof(strbuf), "%d", level_from_file); 1539 rb->lcd_getstringsize(strbuf, &strwdt, &strhgt); 1540 rb->lcd_putsxy(TOP_X2 - strwdt/2, TOP_Y1, strbuf); 1541 1542 rb->strcpy(strbuf, game_type==0? "A": "B"); 1543 rb->lcd_getstringsize(strbuf, &strwdt, &strhgt); 1544 rb->lcd_putsxy(TOP_X1, TOP_Y1, strbuf); 1545 1546 rb->snprintf(strbuf, sizeof(strbuf), "%d", highscores[0].score); 1547 rb->lcd_getstringsize(strbuf, &strwdt, &strhgt); 1548 rb->lcd_putsxy(TOP_X4 - strwdt/2, TOP_Y2, strbuf); 1549 1550#else 1551 rb->snprintf(strbuf, sizeof(strbuf), "Maze: %d", level_from_file); 1552 rb->lcd_getstringsize(strbuf, &strwdt, &strhgt); 1553 rb->lcd_putsxy((WIDTH*MULTIPLIER - strwdt)/2, 1554 (HEIGHT*MULTIPLIER - strhgt)/2, strbuf); 1555#endif 1556 1557 rb->lcd_update(); 1558 1559 button = rb->button_get(true); 1560 switch (button) 1561 { 1562 case SNAKE2_QUIT: 1563 case SNAKE2_PLAYPAUSE: 1564 return; 1565 break; 1566 case SNAKE2_UP: 1567 case SNAKE2_RIGHT: 1568 if(level_from_file < num_levels) 1569 level_from_file++; 1570 else 1571 level_from_file = 0; 1572 load_level( level_from_file ); 1573 redraw(); 1574 break; 1575 case SNAKE2_DOWN: 1576 case SNAKE2_LEFT: 1577 if(level_from_file > 0) 1578 level_from_file--; 1579 else 1580 level_from_file = num_levels; 1581 load_level( level_from_file ); 1582 redraw(); 1583 break; 1584 default: 1585 if (rb->default_event_handler(button)==SYS_USB_CONNECTED) { 1586 quit = 2; 1587 return; 1588 } 1589 break; 1590 } 1591 } 1592 1593} 1594 1595static void game_init(void) 1596{ 1597 int selection = 0; 1598 1599 static const struct opt_items type_options[] = { 1600 { "Type A", -1 }, 1601 { "Type B", -1 }, 1602 }; 1603 1604 MENUITEM_STRINGLIST(menu, "Snake2 Menu", NULL, 1605 "Start New Game", 1606 "Game Type", "Select Maze", "Speed", 1607 "High Scores", 1608 "Playback Control", "Quit"); 1609 1610 rb->button_clear_queue(); 1611 1612 dead = 0; 1613 apple = 0; 1614 score = 0; 1615 applecount = 0; 1616 1617 while (1) { 1618 switch (rb->do_menu(&menu, &selection, NULL, false)) { 1619 case 0: 1620 speed = level*20; 1621 return; 1622 case 1: 1623 rb->set_option("Game Type", &game_type, RB_INT, 1624 type_options, 2, NULL); 1625 break; 1626 case 2: 1627 select_maze(); 1628 if(quit) return; 1629 break; 1630 case 3: 1631 rb->set_int("Speed", "", UNIT_INT, &level, 1632 NULL, 1, 1, 10, NULL); 1633 break; 1634 case 4: 1635 highscore_show(-1, highscores, NUM_SCORES, true); 1636 break; 1637 case 5: 1638 playback_control(NULL); 1639 break; 1640 case 6: 1641 quit = 1; 1642 return; 1643 case MENU_ATTACHED_USB: 1644 quit = 2; 1645 return; 1646 default: 1647 break; 1648 } 1649 } 1650} 1651 1652enum plugin_status plugin_start(const void* parameter) 1653{ 1654 (void)(parameter); 1655 1656 /* Lets use the default font */ 1657 rb->lcd_setfont(FONT_SYSFIXED); 1658#if LCD_DEPTH > 1 1659 rb->lcd_set_backdrop(NULL); 1660#endif 1661 1662 load_all_levels(); 1663 1664 if (num_levels == 0) { 1665 rb->splash(HZ*2, "Failed loading levels!"); 1666 return PLUGIN_OK; 1667 } 1668 1669 highscore_load(SCORE_FILE, highscores, NUM_SCORES); 1670 1671 while(quit==0) 1672 { 1673 game_init(); 1674 if(quit) 1675 break; 1676 1677 rb->lcd_clear_display(); 1678 frames=1; 1679 1680 init_snake(); 1681 1682 /*Start Game:*/ 1683 game(); 1684 } 1685 1686 highscore_save(SCORE_FILE, highscores, NUM_SCORES); 1687 1688 return (quit==1) ? PLUGIN_OK : PLUGIN_USB_CONNECTED; 1689}