| /*************************************************************************** |
| * __________ __ ___. |
| * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| * \/ \/ \/ \/ \/ |
| * $Id$ |
| * |
| * Copyright (C) 2007 Tom Ross |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| ****************************************************************************/ |
| #include "plugin.h" |
| |
| #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110) |
| #include "pegbox_menu_top.h" |
| #include "pegbox_menu_items.h" |
| #include "pegbox_header.h" |
| #endif |
| #include "pegbox_pieces.h" |
| |
| static const struct plugin_api* rb; |
| |
| PLUGIN_HEADER |
| |
| /* final game return status */ |
| #define PB_END 3 |
| #define PB_USB 2 |
| #define PB_QUIT 1 |
| |
| #define DATA_FILE PLUGIN_DIR "/games/pegbox.data" |
| #define SAVE_FILE PLUGIN_DIR "/games/pegbox.save" |
| |
| #define ROWS 8 /* Number of rows on each board */ |
| #define COLS 12 /* Number of columns on each board */ |
| #define NUM_LEVELS 15 /* Number of levels */ |
| |
| #define SPACE 0 |
| #define WALL 1 |
| #define TRIANGLE 2 |
| #define CROSS 3 |
| #define SQUARE 4 |
| #define CIRCLE 5 |
| #define HOLE 6 |
| #define PLAYER 7 |
| |
| #if CONFIG_KEYPAD == RECORDER_PAD |
| #define PEGBOX_SAVE BUTTON_ON |
| #define PEGBOX_QUIT BUTTON_OFF |
| #define PEGBOX_RESTART BUTTON_F2 |
| #define PEGBOX_LVL_UP BUTTON_F1 |
| #define PEGBOX_LVL_DOWN BUTTON_F3 |
| #define PEGBOX_UP BUTTON_UP |
| #define PEGBOX_DOWN BUTTON_DOWN |
| #define PEGBOX_RIGHT BUTTON_RIGHT |
| #define PEGBOX_LEFT BUTTON_LEFT |
| |
| #define SAVE_TEXT "ON" |
| #define QUIT_TEXT "OFF" |
| #define RESTART_TEXT "F2" |
| #define LVL_UP_TEXT "F1" |
| #define LVL_DOWN_TEXT "F3" |
| |
| #elif CONFIG_KEYPAD == ONDIO_PAD |
| #define PEGBOX_SAVE BUTTON_OFF |
| #define PEGBOX_QUIT (BUTTON_MENU | BUTTON_LEFT) |
| #define PEGBOX_RESTART (BUTTON_MENU | BUTTON_RIGHT) |
| #define PEGBOX_LVL_UP (BUTTON_MENU | BUTTON_UP) |
| #define PEGBOX_LVL_DOWN (BUTTON_MENU | BUTTON_DOWN) |
| #define PEGBOX_UP BUTTON_UP |
| #define PEGBOX_DOWN BUTTON_DOWN |
| #define PEGBOX_RIGHT BUTTON_RIGHT |
| #define PEGBOX_LEFT BUTTON_LEFT |
| |
| #define SAVE_TEXT "OFF" |
| #define QUIT_TEXT "M+LEFT" |
| #define RESTART_TEXT "M+RIGHT" |
| #define LVL_UP_TEXT "M+UP" |
| #define LVL_DOWN_TEXT "M+DOWN" |
| |
| #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ |
| (CONFIG_KEYPAD == IRIVER_H300_PAD) |
| #define PEGBOX_SAVE BUTTON_SELECT |
| #define PEGBOX_QUIT BUTTON_OFF |
| #define PEGBOX_RESTART BUTTON_ON |
| #define PEGBOX_LVL_UP BUTTON_MODE |
| #define PEGBOX_LVL_DOWN BUTTON_REC |
| #define PEGBOX_UP BUTTON_UP |
| #define PEGBOX_DOWN BUTTON_DOWN |
| #define PEGBOX_RIGHT BUTTON_RIGHT |
| #define PEGBOX_LEFT BUTTON_LEFT |
| |
| #define SAVE_TEXT "NAVI" |
| #define QUIT_TEXT "OFF" |
| #define RESTART_TEXT "ON" |
| #define LVL_UP_TEXT "AB" |
| #define LVL_DOWN_TEXT "REC" |
| |
| #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ |
| (CONFIG_KEYPAD == IPOD_3G_PAD) || \ |
| (CONFIG_KEYPAD == IPOD_1G2G_PAD) |
| #define PEGBOX_SAVE (BUTTON_SELECT|BUTTON_RIGHT) |
| #define PEGBOX_QUIT (BUTTON_SELECT|BUTTON_PLAY) |
| #define PEGBOX_RESTART (BUTTON_SELECT|BUTTON_LEFT) |
| #define PEGBOX_LVL_UP (BUTTON_SELECT|BUTTON_MENU) |
| #define PEGBOX_UP BUTTON_MENU |
| #define PEGBOX_DOWN BUTTON_PLAY |
| #define PEGBOX_RIGHT BUTTON_RIGHT |
| #define PEGBOX_LEFT BUTTON_LEFT |
| |
| #define SAVE_TEXT "SELECT+RIGHT" |
| #define QUIT_TEXT "SELECT+PLAY" |
| #define RESTART_TEXT "SELECT+LEFT" |
| #define LVL_UP_TEXT "SELECT+MENU" |
| #define LVL_DOWN_TEXT "-" |
| |
| #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD |
| #define PEGBOX_SAVE BUTTON_SELECT |
| #define PEGBOX_QUIT BUTTON_POWER |
| #define PEGBOX_RESTART BUTTON_REC |
| #define PEGBOX_LVL_UP BUTTON_PLAY |
| #define PEGBOX_UP BUTTON_UP |
| #define PEGBOX_DOWN BUTTON_DOWN |
| #define PEGBOX_RIGHT BUTTON_RIGHT |
| #define PEGBOX_LEFT BUTTON_LEFT |
| |
| #define SAVE_TEXT "SELECT" |
| #define QUIT_TEXT "OFF" |
| #define RESTART_TEXT "REC" |
| #define LVL_UP_TEXT "PLAY" |
| #define LVL_DOWN_TEXT "-" |
| |
| #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD |
| #define PEGBOX_SAVE BUTTON_MODE |
| #define PEGBOX_QUIT BUTTON_PLAY |
| #define PEGBOX_RESTART (BUTTON_EQ|BUTTON_MODE) |
| #define PEGBOX_LVL_UP (BUTTON_EQ|BUTTON_UP) |
| #define PEGBOX_LVL_DOWN (BUTTON_EQ|BUTTON_DOWN) |
| #define PEGBOX_UP BUTTON_UP |
| #define PEGBOX_DOWN BUTTON_DOWN |
| #define PEGBOX_RIGHT BUTTON_RIGHT |
| #define PEGBOX_LEFT BUTTON_LEFT |
| |
| #define SAVE_TEXT "MODE" |
| #define QUIT_TEXT "PLAY" |
| #define RESTART_TEXT "EQ+MODE" |
| #define LVL_UP_TEXT "EQ+UP" |
| #define LVL_DOWN_TEXT "EQ+DOWN" |
| |
| #elif CONFIG_KEYPAD == IRIVER_H10_PAD |
| #define PEGBOX_SAVE BUTTON_PLAY |
| #define PEGBOX_QUIT BUTTON_POWER |
| #define PEGBOX_RESTART (BUTTON_FF|BUTTON_REPEAT) |
| #define PEGBOX_LVL_UP (BUTTON_FF|BUTTON_SCROLL_UP) |
| #define PEGBOX_LVL_DOWN (BUTTON_FF|BUTTON_SCROLL_DOWN) |
| #define PEGBOX_UP BUTTON_SCROLL_UP |
| #define PEGBOX_DOWN BUTTON_SCROLL_DOWN |
| #define PEGBOX_RIGHT BUTTON_RIGHT |
| #define PEGBOX_LEFT BUTTON_LEFT |
| |
| #define SAVE_TEXT "PLAY" |
| #define QUIT_TEXT "OFF" |
| #define RESTART_TEXT "LONG FF" |
| #define LVL_UP_TEXT "FF+SCROLL_UP" |
| #define LVL_DOWN_TEXT "FF+SCROLL_DOWN" |
| |
| #elif CONFIG_KEYPAD == SANSA_E200_PAD |
| #define PEGBOX_SAVE BUTTON_SELECT |
| #define PEGBOX_QUIT BUTTON_POWER |
| #define PEGBOX_RESTART BUTTON_REC |
| #define PEGBOX_LVL_UP BUTTON_SCROLL_BACK |
| #define PEGBOX_LVL_DOWN BUTTON_SCROLL_FWD |
| #define PEGBOX_UP BUTTON_UP |
| #define PEGBOX_DOWN BUTTON_DOWN |
| #define PEGBOX_RIGHT BUTTON_RIGHT |
| #define PEGBOX_LEFT BUTTON_LEFT |
| |
| #define SAVE_TEXT "SELECT" |
| #define QUIT_TEXT "POWER" |
| #define RESTART_TEXT "REC" |
| #define LVL_UP_TEXT "SCROLL BACK" |
| #define LVL_DOWN_TEXT "SCROLL FWD" |
| |
| #elif CONFIG_KEYPAD == GIGABEAT_PAD |
| #define PEGBOX_SAVE BUTTON_SELECT |
| #define PEGBOX_QUIT BUTTON_POWER |
| #define PEGBOX_RESTART BUTTON_A |
| #define PEGBOX_LVL_UP BUTTON_VOL_UP |
| #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN |
| #define PEGBOX_UP BUTTON_UP |
| #define PEGBOX_DOWN BUTTON_DOWN |
| #define PEGBOX_RIGHT BUTTON_RIGHT |
| #define PEGBOX_LEFT BUTTON_LEFT |
| |
| #define SAVE_TEXT "SELECT" |
| #define QUIT_TEXT "POWER" |
| #define RESTART_TEXT "A" |
| #define LVL_UP_TEXT "VOL+" |
| #define LVL_DOWN_TEXT "VOL-" |
| |
| #elif CONFIG_KEYPAD == GIGABEAT_S_PAD |
| #define PEGBOX_SAVE BUTTON_SELECT |
| #define PEGBOX_QUIT BUTTON_BACK |
| #define PEGBOX_RESTART BUTTON_MENU |
| #define PEGBOX_LVL_UP BUTTON_VOL_UP |
| #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN |
| #define PEGBOX_UP BUTTON_UP |
| #define PEGBOX_DOWN BUTTON_DOWN |
| #define PEGBOX_RIGHT BUTTON_RIGHT |
| #define PEGBOX_LEFT BUTTON_LEFT |
| |
| #define SAVE_TEXT "SELECT" |
| #define QUIT_TEXT "BACK" |
| #define RESTART_TEXT "MENU" |
| #define LVL_UP_TEXT "VOL+" |
| #define LVL_DOWN_TEXT "VOL-" |
| |
| #elif CONFIG_KEYPAD == MROBE100_PAD |
| #define PEGBOX_SAVE BUTTON_SELECT |
| #define PEGBOX_QUIT BUTTON_POWER |
| #define PEGBOX_RESTART BUTTON_PLAY |
| #define PEGBOX_LVL_UP BUTTON_MENU |
| #define PEGBOX_LVL_DOWN BUTTON_DISPLAY |
| #define PEGBOX_UP BUTTON_UP |
| #define PEGBOX_DOWN BUTTON_DOWN |
| #define PEGBOX_RIGHT BUTTON_RIGHT |
| #define PEGBOX_LEFT BUTTON_LEFT |
| |
| #define SAVE_TEXT "SELECT" |
| #define QUIT_TEXT "POWER" |
| #define RESTART_TEXT "PLAY" |
| #define LVL_UP_TEXT "MENU" |
| #define LVL_DOWN_TEXT "DISPLAY" |
| |
| #elif CONFIG_KEYPAD == SANSA_C200_PAD |
| #define PEGBOX_SAVE BUTTON_SELECT |
| #define PEGBOX_QUIT BUTTON_POWER |
| #define PEGBOX_RESTART BUTTON_REC |
| #define PEGBOX_LVL_UP BUTTON_VOL_UP |
| #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN |
| #define PEGBOX_UP BUTTON_UP |
| #define PEGBOX_DOWN BUTTON_DOWN |
| #define PEGBOX_RIGHT BUTTON_RIGHT |
| #define PEGBOX_LEFT BUTTON_LEFT |
| |
| #define SAVE_TEXT "SELECT" |
| #define QUIT_TEXT "POWER" |
| #define RESTART_TEXT "REC" |
| #define LVL_UP_TEXT "VOL+" |
| #define LVL_DOWN_TEXT "VOL-" |
| |
| #elif CONFIG_KEYPAD == IAUDIO_M3_PAD |
| #define PEGBOX_SAVE BUTTON_RC_PLAY |
| #define PEGBOX_QUIT BUTTON_RC_REC |
| #define PEGBOX_RESTART BUTTON_RC_MODE |
| #define PEGBOX_LVL_UP BUTTON_VOL_UP |
| #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN |
| #define PEGBOX_UP BUTTON_RC_VOL_UP |
| #define PEGBOX_DOWN BUTTON_RC_VOL_DOWN |
| #define PEGBOX_RIGHT BUTTON_RC_FF |
| #define PEGBOX_LEFT BUTTON_RC_REW |
| |
| #define SAVE_TEXT "REM. PLAY" |
| #define QUIT_TEXT "REM. REC" |
| #define RESTART_TEXT "REM. MODE" |
| #define LVL_UP_TEXT "VOL+" |
| #define LVL_DOWN_TEXT "VOL-" |
| |
| #elif CONFIG_KEYPAD == COWOND2_PAD |
| #define PEGBOX_QUIT BUTTON_POWER |
| |
| #define QUIT_TEXT "POWER" |
| #else |
| #error Unsupported keymap! |
| #endif |
| |
| #ifdef HAVE_TOUCHPAD |
| #ifndef PEGBOX_QUIT |
| #define PEGBOX_QUIT BUTTON_TOPLEFT |
| #endif |
| #ifndef PEGBOX_SAVE |
| #define PEGBOX_SAVE BUTTON_CENTER |
| #endif |
| #ifndef PEGBOX_RESTART |
| #define PEGBOX_RESTART BUTTON_TOPRIGHT |
| #endif |
| #ifndef PEGBOX_LVL_UP |
| #define PEGBOX_LVL_UP BUTTON_BOTTOMLEFT |
| #endif |
| #ifndef PEGBOX_LVL_DOWN |
| #define PEGBOX_LVL_DOWN BUTTON_BOTTOMRIGHT |
| #endif |
| #ifndef PEGBOX_UP |
| #define PEGBOX_UP BUTTON_TOPMIDDLE |
| #endif |
| #ifndef PEGBOX_DOWN |
| #define PEGBOX_DOWN BUTTON_BOTTOMMIDDLE |
| #endif |
| #ifndef PEGBOX_RIGHT |
| #define PEGBOX_RIGHT BUTTON_MIDRIGHT |
| #endif |
| #ifndef PEGBOX_LEFT |
| #define PEGBOX_LEFT BUTTON_MIDLEFT |
| #endif |
| #ifndef SAVE_TEXT |
| #define SAVE_TEXT "CENTER" |
| #endif |
| #ifndef QUIT_TEXT |
| #define QUIT_TEXT "TOPLEFT" |
| #endif |
| #ifndef RESTART_TEXT |
| #define RESTART_TEXT "TOPRIGHT" |
| #endif |
| #ifndef LVL_UP_TEXT |
| #define LVL_UP_TEXT "BOTTOMLEFT" |
| #endif |
| #ifndef LVL_DOWN_TEXT |
| #define LVL_DOWN_TEXT "BOTTOMRIGHT" |
| #endif |
| #endif |
| |
| #if (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240) |
| #define LEVEL_TEXT_X 59 |
| #define PEGS_TEXT_X 276 |
| #define TEXT_Y 28 |
| #elif (LCD_WIDTH >= 240) && (LCD_HEIGHT >= 192) |
| #define LEVEL_TEXT_X 59 |
| #define PEGS_TEXT_X 196 |
| #define TEXT_Y 28 |
| #elif (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176) |
| #define LEVEL_TEXT_X 49 |
| #define PEGS_TEXT_X 186 |
| #define TEXT_Y 28 |
| #elif (LCD_WIDTH >= 176) && (LCD_HEIGHT >= 132) |
| #define LEVEL_TEXT_X 38 |
| #define PEGS_TEXT_X 155 |
| #define TEXT_Y 17 |
| #elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) |
| #define LEVEL_TEXT_X 37 |
| #define PEGS_TEXT_X 140 |
| #define TEXT_Y 13 |
| #elif (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110) |
| #define LEVEL_TEXT_X 28 |
| #define PEGS_TEXT_X 119 |
| #define TEXT_Y 15 |
| #elif (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 128) |
| #define LEVEL_TEXT_X 28 |
| #define PEGS_TEXT_X 119 |
| #define TEXT_Y 15 |
| #endif |
| |
| #ifdef HAVE_LCD_COLOR |
| #define BG_COLOR LCD_BLACK |
| #define TEXT_BG LCD_RGBPACK(189,189,189) |
| #endif |
| |
| #define BOARD_X (LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2 |
| |
| #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110) |
| #define BOARD_Y BMPHEIGHT_pegbox_header+2 |
| #else |
| #define BOARD_Y 0 |
| #endif |
| |
| #ifdef HAVE_TOUCHPAD |
| #include "lib/touchscreen.h" |
| |
| static struct ts_mapping main_menu_items[5] = |
| { |
| {(LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, BMPHEIGHT_pegbox_menu_top, BMPWIDTH_pegbox_menu_items, (BMPHEIGHT_pegbox_menu_items/9)}, |
| {(LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, BMPHEIGHT_pegbox_menu_top+(BMPHEIGHT_pegbox_menu_items/9), BMPWIDTH_pegbox_menu_items, (BMPHEIGHT_pegbox_menu_items/9)}, |
| {(LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, BMPHEIGHT_pegbox_menu_top+(BMPHEIGHT_pegbox_menu_items/9)*2, BMPWIDTH_pegbox_menu_items, (BMPHEIGHT_pegbox_menu_items/9)}, |
| {(LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, BMPHEIGHT_pegbox_menu_top+(BMPHEIGHT_pegbox_menu_items/9)*3, BMPWIDTH_pegbox_menu_items, (BMPHEIGHT_pegbox_menu_items/9)}, |
| { |
| #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110) |
| 0, BMPHEIGHT_pegbox_menu_top+4*(BMPHEIGHT_pegbox_menu_items/9)+8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT |
| #elif LCD_WIDTH > 112 |
| 0, LCD_HEIGHT - 8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT |
| #else |
| #error "Touchpad isn't supported on non-bitmap screens!" |
| #endif |
| } |
| |
| }; |
| static struct ts_mappings main_menu = {main_menu_items, 5}; |
| |
| static struct ts_raster pegbox_raster = { BOARD_X, BOARD_Y, COLS*BMPWIDTH_pegbox_pieces, ROWS*BMPWIDTH_pegbox_pieces, BMPWIDTH_pegbox_pieces, BMPWIDTH_pegbox_pieces }; |
| static struct ts_raster_button_mapping pegbox_raster_btn = { &pegbox_raster, false, false, true, false, true, {0, 0}, 0, 0, 0 }; |
| #endif |
| |
| struct game_context { |
| unsigned int level; |
| unsigned int highlevel; |
| signed int player_row; |
| signed int player_col; |
| unsigned int num_left; |
| bool save_exist; |
| unsigned int playboard[ROWS][COLS]; |
| }; |
| |
| char levels[NUM_LEVELS][ROWS][COLS] = { |
| /* Level 1 */ |
| {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}, |
| {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,}, |
| {1, 0, 0, 0, 7, 0, 0, 5, 0, 0, 0, 1,}, |
| {1, 0, 0, 0, 0, 3, 3, 2, 0, 0, 0, 1,}, |
| {1, 0, 0, 0, 4, 6, 0, 5, 0, 0, 0, 1,}, |
| {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,}, |
| {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,}, |
| {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}}, |
| |
| /* Level 2 */ |
| {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}, |
| {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,}, |
| {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,}, |
| {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,}, |
| {7, 0, 0, 0, 2, 2, 5, 5, 0, 0, 0, 1,}, |
| {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,}, |
| {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,}, |
| {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,}}, |
| |
| /* Level 3 */ |
| {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}, |
| {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}, |
| {1, 0, 0, 0, 0, 0, 2, 0, 7, 0, 0, 0,}, |
| {1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 2, 1,}, |
| {1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1,}, |
| {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,}, |
| {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}, |
| {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}}, |
| |
| /* Level 4 */ |
| {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}, |
| {6, 0, 4, 0, 2, 0, 2, 0, 0, 0, 0, 1,}, |
| {6, 0, 3, 0, 5, 0, 2, 0, 0, 0, 0, 1,}, |
| {6, 0, 5, 0, 4, 7, 2, 0, 0, 0, 0, 1,}, |
| {6, 0, 2, 0, 4, 0, 2, 0, 3, 0, 0, 1,}, |
| {6, 0, 4, 0, 5, 0, 2, 0, 0, 0, 0, 1,}, |
| {6, 0, 5, 0, 4, 0, 2, 0, 0, 0, 0, 1,}, |
| {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}}, |
| |
| /* Level 5 */ |
| {{0, 6, 6, 0, 4, 6, 0, 0, 6, 0, 0, 0,}, |
| {0, 6, 6, 0, 4, 4, 0, 0, 6, 0, 0, 2,}, |
| {2, 6, 6, 0, 6, 6, 6, 0, 1, 2, 2, 2,}, |
| {0, 6, 6, 0, 6, 4, 6, 0, 1, 2, 0, 2,}, |
| {0, 6, 6, 0, 6, 7, 6, 5, 6, 0, 0, 0,}, |
| {2, 6, 6, 0, 6, 6, 6, 0, 6, 0, 0, 0,}, |
| {0, 6, 6, 0, 4, 0, 0, 0, 6, 0, 0, 0,}, |
| {0, 6, 6, 0, 0, 5, 0, 0, 6, 5, 5, 0,}}, |
| |
| /* Level 6 */ |
| {{7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, |
| {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,}, |
| {2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0,}, |
| {0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 0,}, |
| {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, |
| {0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1,}, |
| {0, 3, 0, 0, 0, 0, 0, 0, 5, 4, 6, 0,}, |
| {0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1,}}, |
| |
| /* Level 7 */ |
| {{1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,}, |
| {1, 1, 1, 6, 0, 0, 4, 6, 0, 1, 1, 1,}, |
| {1, 1, 1, 1, 0, 1, 5, 1, 0, 1, 1, 1,}, |
| {1, 1, 1, 2, 3, 3, 7, 4, 2, 6, 1, 1,}, |
| {1, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1,}, |
| {1, 1, 1, 1, 0, 0, 5, 0, 0, 1, 0, 1,}, |
| {1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,}, |
| {1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,}}, |
| |
| /* Level 8 */ |
| {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}, |
| {0, 0, 3, 3, 3, 3, 3, 4, 3, 3, 0, 0,}, |
| {0, 0, 3, 3, 3, 2, 3, 3, 5, 3, 0, 0,}, |
| {7, 0, 3, 3, 3, 2, 3, 3, 4, 3, 0, 0,}, |
| {0, 0, 3, 3, 4, 5, 3, 3, 3, 3, 0, 0,}, |
| {0, 0, 3, 3, 5, 2, 3, 3, 3, 3, 0, 0,}, |
| {0, 0, 3, 3, 2, 4, 3, 3, 3, 3, 0, 0,}, |
| {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}}, |
| |
| /* Level 9 */ |
| {{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,}, |
| {0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,}, |
| {0, 0, 0, 0, 2, 4, 4, 3, 0, 1, 1, 0,}, |
| {0, 1, 0, 0, 2, 1, 0, 0, 0, 1, 1, 1,}, |
| {0, 0, 0, 2, 2, 7, 1, 0, 0, 0, 0, 2,}, |
| {0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 1, 1,}, |
| {0, 3, 1, 0, 2, 5, 5, 0, 0, 0, 3, 0,}, |
| {0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0,}}, |
| |
| /* Level 10 */ |
| {{1, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0,}, |
| {1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 7,}, |
| {0, 0, 4, 0, 6, 6, 6, 0, 0, 0, 3, 0,}, |
| {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,}, |
| {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,}, |
| {0, 0, 0, 0, 6, 6, 6, 0, 3, 0, 0, 0,}, |
| {1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0,}, |
| {1, 1, 1, 1, 1, 2, 1, 1, 0, 0, 0, 0,}}, |
| |
| /* Level 11 */ |
| {{1, 7, 1, 0, 1, 1, 6, 0, 0, 1, 1, 0,}, |
| {1, 0, 0, 0, 5, 4, 6, 6, 0, 2, 2, 0,}, |
| {1, 2, 1, 2, 0, 1, 6, 0, 0, 2, 2, 0,}, |
| {1, 0, 0, 2, 0, 1, 0, 0, 0, 3, 3, 0,}, |
| {1, 2, 1, 0, 0, 1, 0, 1, 0, 3, 3, 0,}, |
| {0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0,}, |
| {0, 3, 4, 3, 0, 1, 0, 1, 0, 0, 0, 0,}, |
| {0, 0, 0, 0, 2, 2, 2, 1, 1, 1, 1, 1,}}, |
| |
| /* Level 12 */ |
| {{7, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,}, |
| {1, 2, 1, 2, 1, 2, 1, 1, 0, 0, 0, 1,}, |
| {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,}, |
| {1, 2, 1, 2, 1, 2, 1, 0, 0, 0, 0, 1,}, |
| {0, 0, 0, 0, 0, 0, 1, 1, 5, 5, 6, 1,}, |
| {1, 2, 1, 2, 1, 2, 1, 1, 0, 2, 2, 1,}, |
| {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1,}, |
| {1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,}}, |
| |
| /* Level 13 */ |
| {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}, |
| {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,}, |
| {0, 0, 2, 0, 5, 0, 2, 0, 4, 0, 0, 6,}, |
| {7, 0, 3, 0, 4, 0, 5, 0, 4, 0, 0, 6,}, |
| {0, 0, 5, 0, 4, 0, 2, 0, 4, 0, 0, 6,}, |
| {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,}, |
| {0, 0, 3, 0, 3, 0, 2, 0, 4, 0, 0, 6,}, |
| {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}}, |
| |
| /* Level 14 */ |
| {{1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,}, |
| {1, 1, 0, 2, 0, 0, 4, 0, 0, 2, 0, 1,}, |
| {1, 6, 0, 0, 5, 1, 0, 1, 1, 0, 0, 1,}, |
| {1, 1, 1, 0, 0, 3, 5, 3, 0, 0, 1, 1,}, |
| {1, 1, 0, 0, 1, 1, 0, 1, 5, 0, 0, 6,}, |
| {1, 1, 0, 2, 0, 0, 4, 0, 0, 0, 7, 1,}, |
| {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,}, |
| {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}}, |
| |
| /* Level 15 */ |
| {{0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,}, |
| {0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,}, |
| {0, 3, 4, 6, 0, 6, 0, 6, 0, 6, 0, 2,}, |
| {0, 4, 0, 6, 0, 6, 4, 6, 0, 6, 0, 1,}, |
| {0, 3, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,}, |
| {7, 0, 0, 6, 4, 6, 0, 6, 0, 6, 0, 1,}, |
| {0, 0, 4, 6, 0, 6, 0, 6, 4, 6, 0, 1,}, |
| {0, 0, 4, 6, 0, 6, 0, 6, 0, 6, 0, 1,}} |
| }; |
| |
| |
| /***************************************************************************** |
| * display_text() formats and outputs text. |
| ******************************************************************************/ |
| static void display_text(char *str, bool waitkey) |
| { |
| int chars_by_line; |
| int lines_by_screen; |
| int chars_for_line; |
| int current_line = 0; |
| int char_width, char_height; |
| int first_char_index = 0; |
| char *ptr_char; |
| char *ptr_line; |
| int i; |
| char line[255]; |
| int key; |
| bool go_on; |
| |
| rb->lcd_clear_display(); |
| |
| rb->lcd_getstringsize("a", &char_width, &char_height); |
| |
| chars_by_line = LCD_WIDTH / char_width; |
| lines_by_screen = LCD_HEIGHT / char_height; |
| |
| do |
| { |
| ptr_char = str + first_char_index; |
| chars_for_line = 0; |
| i = 0; |
| ptr_line = line; |
| while (i < chars_by_line) |
| { |
| switch (*ptr_char) |
| { |
| case '\t': |
| case ' ': |
| *(ptr_line++) = ' '; |
| case '\n': |
| case '\0': |
| chars_for_line = i; |
| break; |
| |
| default: |
| *(ptr_line++) = *ptr_char; |
| } |
| if (*ptr_char == '\n' || *ptr_char == '\0') |
| break; |
| ptr_char++; |
| i++; |
| } |
| |
| if (chars_for_line == 0) |
| chars_for_line = i; |
| |
| line[chars_for_line] = '\0'; |
| |
| /* test if we have cut a word. If it is the case we don't have to */ |
| /* skip the space */ |
| if (i == chars_by_line && chars_for_line == chars_by_line) |
| first_char_index += chars_for_line; |
| else |
| first_char_index += chars_for_line + 1; |
| |
| /* print the line on the screen */ |
| rb->lcd_putsxy(0, current_line * char_height, line); |
| |
| /* if the number of line showed on the screen is equals to the */ |
| /* maximum number of line we can show, we wait for a key pressed to */ |
| /* clear and show the remaining text. */ |
| current_line++; |
| if (current_line == lines_by_screen || *ptr_char == '\0') |
| { |
| current_line = 0; |
| rb->lcd_update(); |
| go_on = false; |
| while (waitkey && !go_on) |
| { |
| key = rb->button_get(true); |
| switch (key) |
| { |
| #ifdef HAVE_TOUCHPAD |
| case BUTTON_TOUCHPAD: |
| #endif |
| case PEGBOX_QUIT: |
| case PEGBOX_LEFT: |
| case PEGBOX_DOWN: |
| go_on = true; |
| break; |
| |
| default: |
| /*if (rb->default_event_handler(key) == SYS_USB_CONNECTED) |
| { |
| usb_detected = true; |
| go_on = true; |
| break; |
| }*/ |
| break; |
| } |
| } |
| rb->lcd_clear_display(); |
| } |
| } while (*ptr_char != '\0'); |
| } |
| |
| /***************************************************************************** |
| * draw_board() draws the game's current level. |
| ******************************************************************************/ |
| static void draw_board(struct game_context* pb) { |
| unsigned int r, c, type; |
| pb->num_left = 0; |
| #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110) |
| char str[5]; |
| |
| rb->lcd_clear_display(); |
| rb->lcd_bitmap(pegbox_header,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_header); |
| rb->lcd_drawrect((LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2-2, |
| BMPHEIGHT_pegbox_header, |
| 12*BMPWIDTH_pegbox_pieces+4,8*BMPWIDTH_pegbox_pieces+4); |
| |
| #ifdef HAVE_LCD_COLOR |
| rb->lcd_set_foreground(LCD_WHITE); |
| rb->lcd_fillrect((LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2-1,BMPHEIGHT_pegbox_header+1, |
| 12*BMPWIDTH_pegbox_pieces+2,8*BMPWIDTH_pegbox_pieces+2); |
| rb->lcd_set_foreground(LCD_BLACK); |
| rb->lcd_set_background(TEXT_BG); |
| #endif |
| |
| #else |
| rb->lcd_clear_display(); |
| |
| #ifdef HAVE_LCD_COLOR |
| rb->lcd_set_foreground(LCD_WHITE); |
| rb->lcd_fillrect((LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2-1,0, |
| 12*BMPWIDTH_pegbox_pieces+2,8*BMPWIDTH_pegbox_pieces+1); |
| rb->lcd_set_foreground(LCD_BLACK); |
| rb->lcd_set_background(TEXT_BG); |
| #endif |
| |
| #endif |
| |
| for (r=0 ; r < ROWS ; r++) { |
| for (c = 0 ; c < COLS ; c++) { |
| |
| type = pb->playboard[r][c]; |
| |
| switch(type) { |
| case SPACE: |
| break; |
| |
| default: |
| rb->lcd_bitmap_part(pegbox_pieces, 0, |
| (type-1)*BMPWIDTH_pegbox_pieces, |
| BMPWIDTH_pegbox_pieces, |
| c * BMPWIDTH_pegbox_pieces + BOARD_X, |
| r * BMPWIDTH_pegbox_pieces + BOARD_Y, |
| BMPWIDTH_pegbox_pieces, |
| BMPWIDTH_pegbox_pieces); |
| break; |
| } |
| |
| if(pb->playboard[r][c] == PLAYER) { |
| pb->player_row=r; |
| pb->player_col=c; |
| } |
| else if (type != WALL && type != SPACE && type != HOLE) |
| pb->num_left++; |
| } |
| } |
| #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110) |
| rb->snprintf(str, 3, "%d", pb->level); |
| rb->lcd_putsxy(LEVEL_TEXT_X, TEXT_Y, str); |
| rb->snprintf(str, 3, "%d", pb->num_left); |
| rb->lcd_putsxy(PEGS_TEXT_X, TEXT_Y, str); |
| #endif |
| |
| #ifdef HAVE_LCD_COLOR |
| rb->lcd_set_background(BG_COLOR); |
| rb->lcd_set_foreground(LCD_WHITE); |
| #endif |
| /* print out the screen */ |
| rb->lcd_update(); |
| } |
| |
| /***************************************************************************** |
| * load_level() loads the player's current level from the array and sets the |
| * player's position. |
| ******************************************************************************/ |
| static void load_level(struct game_context* pb) { |
| int r, c; |
| |
| for(r = 0; r < ROWS; r++) |
| for(c = 0; c < COLS; c++) |
| pb->playboard[r][c] = levels[pb->level-1][r][c]; |
| } |
| |
| /***************************************************************************** |
| * new_piece() creates a new piece at a specified location. The player |
| * navigates through the pieces and selects one. |
| ******************************************************************************/ |
| static void new_piece(struct game_context* pb, unsigned int x_loc, |
| unsigned int y_loc) { |
| int button; |
| bool exit = false; |
| |
| pb->playboard[x_loc][y_loc] = TRIANGLE; |
| |
| while (!exit) { |
| draw_board(pb); |
| button = rb->button_get(true); |
| #ifdef HAVE_TOUCHPAD |
| if(button & BUTTON_TOUCHPAD) |
| { |
| pegbox_raster_btn.two_d_from.y = x_loc; |
| pegbox_raster_btn.two_d_from.x = y_loc; |
| |
| struct ts_raster_button_result ret = touchscreen_raster_map_button(&pegbox_raster_btn, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff, button); |
| if(ret.action == TS_ACTION_TWO_D_MOVEMENT) |
| { |
| if(ret.to.x > ret.from.x) |
| button = PEGBOX_UP; |
| else if(ret.to.x < ret.from.x) |
| button = PEGBOX_DOWN; |
| else if(ret.to.y > ret.from.y) |
| button = PEGBOX_LEFT; |
| else if(ret.to.y < ret.from.y) |
| button = PEGBOX_RIGHT; |
| } |
| else if(ret.action == TS_ACTION_CLICK && (unsigned)ret.to.x == y_loc && (unsigned)ret.to.y == x_loc) |
| button = PEGBOX_SAVE; |
| } |
| #endif |
| switch(button){ |
| case PEGBOX_LEFT: |
| case (PEGBOX_LEFT|BUTTON_REPEAT): |
| case PEGBOX_DOWN: |
| case (PEGBOX_DOWN|BUTTON_REPEAT): |
| if (pb->playboard[x_loc][y_loc] < 5) |
| pb->playboard[x_loc][y_loc]++; |
| else |
| pb->playboard[x_loc][y_loc] = TRIANGLE; |
| break; |
| case PEGBOX_RIGHT: |
| case (PEGBOX_RIGHT|BUTTON_REPEAT): |
| case PEGBOX_UP: |
| case (PEGBOX_UP|BUTTON_REPEAT): |
| if (pb->playboard[x_loc][y_loc] > 2) |
| pb->playboard[x_loc][y_loc]--; |
| else |
| pb->playboard[x_loc][y_loc] = CIRCLE; |
| break; |
| case PEGBOX_SAVE: |
| exit = true; |
| break; |
| } |
| } |
| } |
| |
| /***************************************************************************** |
| * move_player() moves the player and pieces and updates the board accordingly. |
| ******************************************************************************/ |
| static void move_player(struct game_context* pb, signed int x_dir, |
| signed int y_dir) { |
| unsigned int type1, type2; |
| signed int r,c; |
| |
| r = pb->player_row+y_dir; |
| c = pb->player_col+x_dir; |
| |
| type1 = pb->playboard[r][c]; |
| type2 = pb->playboard[r+y_dir][c+x_dir]; |
| |
| if (r == ROWS || c == COLS || r < 0 || c < 0 || type1 == WALL) |
| return; |
| else if(type1 != SPACE) { |
| if (type2 == WALL || r+y_dir == ROWS || c+x_dir == COLS || |
| r+y_dir < 0 || c+x_dir < 0) |
| return; |
| } |
| |
| |
| pb->playboard[pb->player_row][pb->player_col] = SPACE; |
| pb->player_row += y_dir; |
| pb->player_col += x_dir; |
| |
| if (type1 == HOLE) { |
| draw_board(pb); |
| rb->splash(HZ*2, "You fell down a hole!"); |
| load_level(pb); |
| } |
| else if (type1 == SPACE) |
| pb->playboard[r][c] = PLAYER; |
| else { |
| pb->playboard[r][c] = PLAYER; |
| if(type1 == type2) { |
| if (type1 == TRIANGLE) |
| pb->playboard[r+y_dir][c+x_dir] = WALL; |
| else if (type1 == CROSS) { |
| pb->playboard[r][c] = SPACE; |
| new_piece(pb, r+y_dir, c+x_dir); |
| pb->playboard[r][c] = PLAYER; |
| } |
| else |
| pb->playboard[r+y_dir][c+x_dir] = SPACE; |
| } |
| else if (type2 == SPACE) |
| pb->playboard[r+y_dir][c+x_dir] = type1; |
| else if (type2 == HOLE) { |
| if (type1 == SQUARE) |
| pb->playboard[r+y_dir][c+x_dir] = SPACE; |
| } |
| else { |
| rb->splash(HZ*2, "Illegal Move!"); |
| load_level(pb); |
| } |
| } |
| |
| draw_board(pb); |
| } |
| |
| /***************************************************************************** |
| * pegbox_loadgame() loads the saved game and returns load success. |
| ******************************************************************************/ |
| static bool pegbox_loadgame(struct game_context* pb) { |
| signed int fd; |
| bool loaded = false; |
| |
| /* open game file */ |
| fd = rb->open(SAVE_FILE, O_RDONLY); |
| if(fd < 0) return loaded; |
| |
| /* read in saved game */ |
| while(true) { |
| if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break; |
| if(rb->read(fd, &pb->playboard, sizeof(pb->playboard)) <= 0) |
| { |
| loaded = true; |
| break; |
| } |
| break; |
| } |
| |
| rb->close(fd); |
| return loaded; |
| } |
| |
| /***************************************************************************** |
| * pegbox_savegame() saves the current game state. |
| ******************************************************************************/ |
| static void pegbox_savegame(struct game_context* pb) { |
| unsigned int fd; |
| |
| /* write out the game state to the save file */ |
| fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT); |
| rb->write(fd, &pb->level, sizeof(pb->level)); |
| rb->write(fd, &pb->playboard, sizeof(pb->playboard)); |
| rb->close(fd); |
| } |
| |
| /***************************************************************************** |
| * pegbox_loaddata() loads the level and highlevel and returns load success. |
| ******************************************************************************/ |
| static void pegbox_loaddata(struct game_context* pb) { |
| signed int fd; |
| |
| /* open game file */ |
| fd = rb->open(DATA_FILE, O_RDONLY); |
| if(fd < 0) { |
| pb->level = 1; |
| pb->highlevel = 1; |
| return; |
| } |
| |
| /* read in saved game */ |
| while(true) { |
| if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break; |
| if(rb->read(fd, &pb->highlevel, sizeof(pb->highlevel)) <= 0) break; |
| break; |
| } |
| |
| rb->close(fd); |
| return; |
| } |
| |
| /***************************************************************************** |
| * pegbox_savedata() saves the level and highlevel. |
| ******************************************************************************/ |
| static void pegbox_savedata(struct game_context* pb) { |
| unsigned int fd; |
| |
| /* write out the game state to the save file */ |
| fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT); |
| rb->write(fd, &pb->level, sizeof(pb->level)); |
| rb->write(fd, &pb->highlevel, sizeof(pb->highlevel)); |
| rb->close(fd); |
| } |
| |
| /***************************************************************************** |
| * pegbox_callback() is the default event handler callback which is called |
| * on usb connect and shutdown. |
| ******************************************************************************/ |
| static void pegbox_callback(void* param) { |
| struct game_context* pb = (struct game_context*) param; |
| rb->splash(HZ, "Saving data..."); |
| pegbox_savedata(pb); |
| } |
| |
| /***************************************************************************** |
| * pegbox_menu() is the initial menu at the start of the game. |
| ******************************************************************************/ |
| static unsigned int pegbox_menu(struct game_context* pb) { |
| int button; |
| char str[30]; |
| unsigned int startlevel = 1, loc = 0; |
| bool breakout = false, can_resume = false; |
| |
| if (pb->num_left > 0 || pb->save_exist) |
| can_resume = true; |
| |
| while(!breakout){ |
| #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110) |
| rb->lcd_clear_display(); |
| rb->lcd_bitmap(pegbox_menu_top,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_menu_top); |
| |
| /* menu bitmaps */ |
| if (loc == 0) { |
| rb->lcd_bitmap_part(pegbox_menu_items, 0, |
| (BMPHEIGHT_pegbox_menu_items/9), |
| BMPWIDTH_pegbox_menu_items, |
| (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, |
| BMPHEIGHT_pegbox_menu_top, |
| BMPWIDTH_pegbox_menu_items, |
| (BMPHEIGHT_pegbox_menu_items/9)); |
| } |
| else { |
| rb->lcd_bitmap_part(pegbox_menu_items, 0, 0, |
| BMPWIDTH_pegbox_menu_items, |
| (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, |
| BMPHEIGHT_pegbox_menu_top, |
| BMPWIDTH_pegbox_menu_items, |
| (BMPHEIGHT_pegbox_menu_items/9)); |
| } |
| if (can_resume) { |
| if (loc == 1) { |
| rb->lcd_bitmap_part(pegbox_menu_items, 0, |
| (BMPHEIGHT_pegbox_menu_items/9)*3, |
| BMPWIDTH_pegbox_menu_items, |
| (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, |
| BMPHEIGHT_pegbox_menu_top+ |
| (BMPHEIGHT_pegbox_menu_items/9), |
| BMPWIDTH_pegbox_menu_items, |
| (BMPHEIGHT_pegbox_menu_items/9)); |
| } |
| else { |
| rb->lcd_bitmap_part(pegbox_menu_items, 0, |
| (BMPHEIGHT_pegbox_menu_items/9)*2, |
| BMPWIDTH_pegbox_menu_items, |
| (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, |
| BMPHEIGHT_pegbox_menu_top+ |
| (BMPHEIGHT_pegbox_menu_items/9), |
| BMPWIDTH_pegbox_menu_items, |
| (BMPHEIGHT_pegbox_menu_items/9)); |
| } |
| } |
| else { |
| rb->lcd_bitmap_part(pegbox_menu_items, 0, |
| (BMPHEIGHT_pegbox_menu_items/9)*4, |
| BMPWIDTH_pegbox_menu_items, |
| (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, |
| BMPHEIGHT_pegbox_menu_top+ |
| (BMPHEIGHT_pegbox_menu_items/9), |
| BMPWIDTH_pegbox_menu_items, |
| (BMPHEIGHT_pegbox_menu_items/9)); |
| } |
| |
| if (loc==2) { |
| rb->lcd_bitmap_part(pegbox_menu_items, 0, |
| (BMPHEIGHT_pegbox_menu_items/9)*6, |
| BMPWIDTH_pegbox_menu_items, |
| (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, |
| BMPHEIGHT_pegbox_menu_top+ |
| (BMPHEIGHT_pegbox_menu_items/9)*2, |
| BMPWIDTH_pegbox_menu_items, |
| (BMPHEIGHT_pegbox_menu_items/9)); |
| } |
| else { |
| rb->lcd_bitmap_part(pegbox_menu_items, 0, |
| (BMPHEIGHT_pegbox_menu_items/9)*5, |
| BMPWIDTH_pegbox_menu_items, |
| (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, |
| BMPHEIGHT_pegbox_menu_top+ |
| (BMPHEIGHT_pegbox_menu_items/9)*2, |
| BMPWIDTH_pegbox_menu_items, |
| (BMPHEIGHT_pegbox_menu_items/9)); |
| } |
| |
| if (loc==3) { |
| rb->lcd_bitmap_part(pegbox_menu_items, 0, |
| (BMPHEIGHT_pegbox_menu_items/9)*8, |
| BMPWIDTH_pegbox_menu_items, |
| (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, |
| BMPHEIGHT_pegbox_menu_top+ |
| (BMPHEIGHT_pegbox_menu_items/9)*3, |
| BMPWIDTH_pegbox_menu_items, |
| (BMPHEIGHT_pegbox_menu_items/9)); |
| } |
| else { |
| rb->lcd_bitmap_part(pegbox_menu_items, 0, |
| (BMPHEIGHT_pegbox_menu_items/9)*7, |
| BMPWIDTH_pegbox_menu_items, |
| (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, |
| BMPHEIGHT_pegbox_menu_top+ |
| (BMPHEIGHT_pegbox_menu_items/9)*3, |
| BMPWIDTH_pegbox_menu_items, |
| (BMPHEIGHT_pegbox_menu_items/9)); |
| } |
| #else |
| unsigned int w,h; |
| rb->lcd_clear_display(); |
| rb->lcd_getstringsize("PegBox", &w, &h); |
| rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, "PegBox"); |
| rb->lcd_putsxy((LCD_WIDTH)/4, 16, "New Game"); |
| rb->lcd_putsxy((LCD_WIDTH)/4, 24, "Resume"); |
| rb->lcd_putsxy((LCD_WIDTH)/4, 32, "Help"); |
| rb->lcd_putsxy((LCD_WIDTH)/4, 40, "Quit"); |
| |
| if(!can_resume) |
| rb->lcd_hline((LCD_WIDTH)/4, (LCD_WIDTH)/4+30, 28); |
| |
| rb->lcd_putsxy((LCD_WIDTH)/4-8, loc*8+16, "*"); |
| |
| |
| #endif |
| rb->snprintf(str, 28, "Start on level %d of %d", startlevel, |
| pb->highlevel); |
| #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110) |
| rb->lcd_putsxy(0, BMPHEIGHT_pegbox_menu_top+4* |
| (BMPHEIGHT_pegbox_menu_items/9)+8, str); |
| #elif LCD_WIDTH > 112 |
| rb->lcd_putsxy(0, LCD_HEIGHT - 8, str); |
| #else |
| rb->lcd_puts_scroll(0, 7, str); |
| #endif |
| rb->lcd_update(); |
| |
| /* handle menu button presses */ |
| button = rb->button_get(true); |
| |
| #ifdef HAVE_TOUCHPAD |
| if(button & BUTTON_TOUCHPAD) |
| { |
| unsigned int result = touchscreen_map(&main_menu, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff); |
| if(result != (unsigned)-1 && button & BUTTON_REL) |
| { |
| if(result == 4) |
| button = PEGBOX_LVL_UP; |
| else |
| { |
| if(loc == result) |
| button = PEGBOX_RIGHT; |
| loc = result; |
| } |
| } |
| } |
| #endif |
| |
| switch(button) { |
| case PEGBOX_SAVE: /* start playing */ |
| case PEGBOX_RIGHT: |
| if (loc == 0) { |
| breakout = true; |
| pb->level = startlevel; |
| load_level(pb); |
| } |
| else if (loc == 1 && can_resume) { |
| if(pb->save_exist) |
| { |
| rb->remove(SAVE_FILE); |
| pb->save_exist = false; |
| } |
| breakout = true; |
| } |
| else if (loc == 2) |
| display_text("How to Play\nTo beat each level, you must " |
| "destroy all of the pegs. If two like pegs are " |
| "pushed into each other they disappear except " |
| "for triangles which form a solid block and " |
| "crosses which allow you to choose a " |
| "replacement block.\n\n" |
| "Controls\n" |
| #if LCD_HEIGHT > 64 |
| RESTART_TEXT " to restart level\n" |
| LVL_UP_TEXT " to go up a level\n" |
| LVL_DOWN_TEXT " to go down a level\n" |
| SAVE_TEXT " to select/save\n" |
| QUIT_TEXT " to quit\n",true); |
| #else |
| RESTART_TEXT ": restart\n" |
| LVL_UP_TEXT ": level up\n" |
| LVL_DOWN_TEXT " level down\n" |
| SAVE_TEXT " select/save\n" |
| QUIT_TEXT " quit\n",true); |
| #endif |
| else if (loc == 3) |
| return PB_QUIT; |
| break; |
| |
| case PEGBOX_QUIT: /* quit program */ |
| return PB_QUIT; |
| |
| case (PEGBOX_UP|BUTTON_REPEAT): |
| case PEGBOX_UP: |
| if (loc <= 0) |
| loc = 3; |
| else |
| loc--; |
| if (!can_resume && loc == 1) { |
| loc = 0; |
| } |
| break; |
| |
| |
| case (PEGBOX_DOWN|BUTTON_REPEAT): |
| case PEGBOX_DOWN: |
| if (loc >= 3) |
| loc = 0; |
| else |
| loc++; |
| if (!can_resume && loc == 1) { |
| loc = 2; |
| } |
| break; |
| |
| case (PEGBOX_LVL_UP|BUTTON_REPEAT): |
| case PEGBOX_LVL_UP: /* increase starting level */ |
| if(startlevel >= pb->highlevel) { |
| startlevel = 1; |
| } else { |
| startlevel++; |
| } |
| break; |
| |
| /* only for targets with enough buttons */ |
| #ifdef PEGBOX_LVL_DOWN |
| case (PEGBOX_LVL_DOWN|BUTTON_REPEAT): |
| case PEGBOX_LVL_DOWN: /* decrease starting level */ |
| if(startlevel <= 1) { |
| startlevel = pb->highlevel; |
| } else { |
| startlevel--; |
| } |
| break; |
| #endif |
| default: |
| if(rb->default_event_handler_ex(button, pegbox_callback, |
| (void*) pb) == SYS_USB_CONNECTED) |
| return PB_USB; |
| break; |
| } |
| |
| } |
| draw_board(pb); |
| |
| return 0; |
| } |
| |
| /***************************************************************************** |
| * pegbox() is the main game subroutine, it returns the final game status. |
| ******************************************************************************/ |
| static int pegbox(struct game_context* pb) { |
| int temp_var; |
| |
| /******************** |
| * menu * |
| ********************/ |
| temp_var = pegbox_menu(pb); |
| if (temp_var == PB_QUIT || temp_var == PB_USB) |
| return temp_var; |
| |
| while (true) { |
| temp_var = rb->button_get(true); |
| #ifdef HAVE_TOUCHPAD |
| if(temp_var & BUTTON_TOUCHPAD) |
| { |
| pegbox_raster_btn.two_d_from.y = pb->player_row; |
| pegbox_raster_btn.two_d_from.x = pb->player_col; |
| |
| struct ts_raster_button_result ret = touchscreen_raster_map_button(&pegbox_raster_btn, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff, temp_var); |
| if(ret.action == TS_ACTION_TWO_D_MOVEMENT) |
| move_player(pb, ret.to.x - ret.from.x, ret.to.y - ret.from.y); |
| } |
| #endif |
| switch(temp_var){ |
| case PEGBOX_LEFT: /* move cursor left */ |
| case (PEGBOX_LEFT|BUTTON_REPEAT): |
| move_player(pb, -1, 0); |
| break; |
| |
| case PEGBOX_RIGHT: /* move cursor right */ |
| case (PEGBOX_RIGHT|BUTTON_REPEAT): |
| move_player(pb, 1, 0); |
| break; |
| |
| case PEGBOX_DOWN: /* move cursor down */ |
| case (PEGBOX_DOWN|BUTTON_REPEAT): |
| move_player(pb, 0, 1); |
| break; |
| |
| case PEGBOX_UP: /* move cursor up */ |
| case (PEGBOX_UP|BUTTON_REPEAT): |
| move_player(pb, 0, -1); |
| break; |
| |
| case PEGBOX_SAVE: /* save and end game */ |
| rb->splash(HZ, "Saving game..."); |
| pegbox_savegame(pb); |
| /* fall through to PEGBOX_QUIT */ |
| |
| case PEGBOX_QUIT: |
| return PB_END; |
| |
| case PEGBOX_RESTART: |
| load_level(pb); |
| draw_board(pb); |
| break; |
| |
| case (PEGBOX_LVL_UP|BUTTON_REPEAT): |
| case PEGBOX_LVL_UP: |
| if(pb->level >= pb->highlevel) { |
| pb->level = 1; |
| } else { |
| pb->level++; |
| } |
| load_level(pb); |
| draw_board(pb); |
| break; |
| |
| /* only for targets with enough buttons */ |
| #ifdef PEGBOX_LVL_DOWN |
| case (PEGBOX_LVL_DOWN|BUTTON_REPEAT): |
| case PEGBOX_LVL_DOWN: |
| if(pb->level <= 1) { |
| pb->level = pb->highlevel; |
| } else { |
| pb->level--; |
| } |
| load_level(pb); |
| draw_board(pb); |
| break; |
| #endif |
| |
| } |
| |
| if(pb->num_left == 0) { |
| rb->splash(HZ*2, "Nice Pegging!"); |
| if(pb->level == NUM_LEVELS) { |
| draw_board(pb); |
| rb->splash(HZ*2, "You Won!"); |
| break; |
| } |
| else { |
| pb->level++; |
| load_level(pb); |
| draw_board(pb); |
| } |
| |
| if(pb->level > pb->highlevel) |
| pb->highlevel = pb->level; |
| |
| } |
| } |
| |
| return PLUGIN_OK; |
| } |
| |
| |
| /***************************************************************************** |
| * plugin entry point. |
| ******************************************************************************/ |
| enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter) { |
| bool exit = false; |
| struct game_context pb; |
| |
| (void)parameter; |
| rb = api; |
| |
| rb->lcd_setfont(FONT_SYSFIXED); |
| #if LCD_DEPTH > 1 |
| rb->lcd_set_backdrop(NULL); |
| #endif |
| #ifdef HAVE_LCD_COLOR |
| rb->lcd_set_foreground(LCD_WHITE); |
| rb->lcd_set_background(BG_COLOR); |
| #endif |
| |
| rb->splash(0, "Loading..."); |
| pegbox_loaddata(&pb); |
| pb.save_exist = pegbox_loadgame(&pb); |
| pb.num_left = 0; |
| |
| rb->lcd_clear_display(); |
| |
| |
| while(!exit) { |
| switch(pegbox(&pb)){ |
| case PB_END: |
| break; |
| |
| case PB_USB: |
| rb->lcd_setfont(FONT_UI); |
| return PLUGIN_USB_CONNECTED; |
| |
| case PB_QUIT: |
| rb->splash(HZ, "Saving data..."); |
| pegbox_savedata(&pb); |
| exit = true; |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| rb->lcd_setfont(FONT_UI); |
| return PLUGIN_OK; |
| } |