Index: apps/plugins/spiderbox.c =================================================================== --- apps/plugins/spiderbox.c (revision 0) +++ apps/plugins/spiderbox.c (revision 0) @@ -0,0 +1,1040 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 by Ben Basha. + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "plugin.h" +#include "lib/playback_control.h" +#include "lib/configfile.h" +#include "lib/display_text.h" +#include "button.h" +#include "lcd.h" + + +#ifdef HAVE_LCD_BITMAP + +PLUGIN_HEADER + + +#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H300_PAD) + +#define SPIDER_OFF BUTTON_OFF +#define SPIDER_UP BUTTON_UP +#define SPIDER_DOWN BUTTON_DOWN +#define SPIDER_LEFT BUTTON_LEFT +#define SPIDER_RIGHT BUTTON_RIGHT +#define SPIDER_DEAL BUTTON_MODE +#define SPIDER_SELECT BUTTON_SELECT + +#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ + (CONFIG_KEYPAD == IPOD_3G_PAD) || \ + (CONFIG_KEYPAD == IPOD_1G2G_PAD) + +#define SPIDER_OFF BUTTON_MENU +#define SPIDER_UP BUTTON_SCROLL_BACK +#define SPIDER_DOWN BUTTON_SCROLL_FWD +#define SPIDER_LEFT BUTTON_LEFT +#define SPIDER_RIGHT BUTTON_RIGHT +#define SPIDER_DEAL BUTTON_PLAY +#define SPIDER_SELECT BUTTON_SELECT + +#elif (CONFIG_KEYPAD == GIGABEAT_PAD) +#define SPIDER_OFF BUTTON_MENU +#define SPIDER_UP BUTTON_UP +#define SPIDER_DOWN BUTTON_DOWN +#define SPIDER_LEFT BUTTON_LEFT +#define SPIDER_RIGHT BUTTON_RIGHT +#define SPIDER_DEAL BUTTON_A +#define SPIDER_SELECT BUTTON_SELECT + +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) +#define SPIDER_OFF BUTTON_BACK +#define SPIDER_UP BUTTON_UP +#define SPIDER_DOWN BUTTON_DOWN +#define SPIDER_LEFT BUTTON_LEFT +#define SPIDER_RIGHT BUTTON_RIGHT +#define SPIDER_DEAL BUTTON_MENU +#define SPIDER_SELECT BUTTON_SELECT + +#elif (CONFIG_KEYPAD == MROBE100_PAD) +#define SPIDER_OFF BUTTON_POWER +#define SPIDER_UP BUTTON_UP +#define SPIDER_DOWN BUTTON_DOWN +#define SPIDER_LEFT BUTTON_LEFT +#define SPIDER_RIGHT BUTTON_RIGHT +#define SPIDER_DEAL BUTTON_MENU +#define SPIDER_SELECT BUTTON_SELECT + +#elif (CONFIG_KEYPAD == SANSA_E200_PAD) +#define SPIDER_OFF BUTTON_POWER +#define SPIDER_UP BUTTON_UP +#define SPIDER_DOWN BUTTON_DOWN +#define SPIDER_LEFT BUTTON_SCROLL_BACK +#define SPIDER_RIGHT BUTTON_SCROLL_FWD +#define SPIDER_DEAL BUTTON_REC +#define SPIDER_SELECT BUTTON_SELECT + +#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD) +#define SPIDER_OFF BUTTON_HOME +#define SPIDER_UP BUTTON_UP +#define SPIDER_DOWN BUTTON_DOWN +#define SPIDER_LEFT BUTTON_SCROLL_BACK +#define SPIDER_RIGHT BUTTON_SCROLL_FWD +#define SPIDER_DEAL BUTTON_LEFT +#define SPIDER_SELECT BUTTON_SELECT + +#elif (CONFIG_KEYPAD == SANSA_C200_PAD) +#define SPIDER_OFF BUTTON_POWER +#define SPIDER_UP BUTTON_UP +#define SPIDER_DOWN BUTTON_DOWN +#define SPIDER_LEFT BUTTON_LEFT +#define SPIDER_RIGHT BUTTON_RIGHT +#define SPIDER_DEAL BUTTON_REC +#define SPIDER_SELECT BUTTON_SELECT + +#elif CONFIG_KEYPAD == IRIVER_H10_PAD +#define SPIDER_OFF BUTTON_POWER +#define SPIDER_UP BUTTON_SCROLL_UP +#define SPIDER_DOWN BUTTON_SCROLL_DOWN +#define SPIDER_LEFT BUTTON_LEFT +#define SPIDER_RIGHT BUTTON_RIGHT +#define SPIDER_DEAL BUTTON_FF +#define SPIDER_SELECT BUTTON_PLAY + +#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) +#define SPIDER_OFF BUTTON_POWER +#define SPIDER_UP BUTTON_UP +#define SPIDER_DOWN BUTTON_DOWN +#define SPIDER_LEFT BUTTON_LEFT +#define SPIDER_RIGHT BUTTON_RIGHT +#define SPIDER_DEAL BUTTON_PLAY +#define SPIDER_SELECT BUTTON_SELECT + +#elif (CONFIG_KEYPAD == IAUDIO_M3_PAD) +#define SPIDER_OFF BUTTON_RC_REC +#define SPIDER_UP BUTTON_RC_VOL_UP +#define SPIDER_DOWN BUTTON_RC_VOL_DOWN +#define SPIDER_LEFT BUTTON_RC_REW +#define SPIDER_RIGHT BUTTON_RC_FF +#define SPIDER_DEAL BUTTON_RC_MENU +#define SPIDER_SELECT BUTTON_RC_MODE + +#else +#error No keymap defined! +#endif + +#ifdef HAVE_LCD_COLOR +#define BACKGROUND_COLOR LCD_RGBPACK(47, 98, 149) +#define TEXT_COLOR LCD_WHITE +#endif + +#define CONFIG_FILENAME "spider.cfg" + +#include "pluginbitmaps/card_back.h" +#include "pluginbitmaps/card_deck.h" + +int cfg_play_animation = 0, cfg_show_text = 0; +static struct configdata config[] = { + { TYPE_INT, 0, 1, { .int_p = &cfg_play_animation}, "play_animation", NULL }, + { TYPE_INT, 0, 1, { .int_p = &cfg_show_text}, "show_text", NULL } +}; + +#define NOT_A_CARD -1 + +#define CARDS_PER_SUIT 13 +#define SUITS 8 +#define CARDS_NUM (CARDS_PER_SUIT * SUITS) + +#define COL_NUM 10 +#define REM_STACK 6 + +#define CARD_WIDTH (BMPWIDTH_card_back + 2) +#define CARD_HEIGHT (BMPHEIGHT_card_back + 2) + +#define CARD_PIC_WIDTH BMPWIDTH_card_back +#define CARD_PIC_HEIGHT BMPHEIGHT_card_back + +#define REV_CARD_HEIGHT 10 + +#define CYCLETIME 75 + +#define X_MARGIN 3 +#define Y_MARGIN 2 +#define BETWEEN_CARDS_X 2 +#define BETWEEN_CARDS_Y 10 + +#define FAKE_LCD_WIDTH (X_MARGIN + (COL_NUM - 1) * (CARD_WIDTH + BETWEEN_CARDS_X) + CARD_WIDTH + X_MARGIN) + +#define SPIDER_LCD_STEPS ((FAKE_LCD_WIDTH - LCD_WIDTH) / (COL_NUM/2 -1)) + +enum { + MENU_USB, + MENU_QUIT, + MENU_RESUME, + MENU_NEW_GAME, +}; + +enum { + SPIDER_WIN, + SPIDER_USB, + SPIDER_QUIT, +}; + +struct board_cards { + bool known; + int card; +}; + +struct board_choose { + int col; + int row; +}; + +/* NOT_A_CARD when NO cards in column */ +struct first_last { + int first_known, last_known; +}; + +struct game { + struct board_cards board[COL_NUM][32]; + int rem[REM_STACK][COL_NUM]; + int rem_cards_pos; /* reminnig suits to deal */ + struct first_last fl[COL_NUM]; + struct board_choose cur; + struct board_choose sel; + bool select; + int completed_suits; /* cleared suits */ + bool play_animation; + bool show_text; + bool in_game; + int lcd_x_margin; +}; + +struct draw_card { + int col, row, x, y; +}; + +bool is_movable (struct game *sp); +void check_lcd_margins (struct game *sp, int direction); +bool is_removable (struct game *sp, int col); +void spider_unhide_card (struct game *sp, int col, int row); +void spider_draw_card (struct game *sp, struct draw_card card); +void spider_remove_suit (struct game *sp, int col); +void spider_deal_new_row (struct game *sp); +void deal_cards(struct game *sp); +void spider_put_text (struct game *sp); +void spider_draw_board (struct game *sp); +void spider_init(struct game *sp); +int spider_menu(struct game *sp); +int main_game_loop (struct game *sp); +void draw_tringale (int direction, int size); + +bool is_movable (struct game *sp) +{ + int i; + bool ret; + + ret = true; + + i = sp->sel.row; + while (sp->board[sp->sel.col][i].card != NOT_A_CARD) { + if (sp->board[sp->sel.col][i].card != (sp->board[sp->sel.col][i + 1].card + 1) + && sp->board[sp->sel.col][i + 1].card != NOT_A_CARD) { + ret = false; + break; + } + i++; + } + + if (ret && (sp->board[sp->cur.col][sp->cur.row].card != + (sp->board[sp->sel.col][sp->sel.row].card + 1)) && (sp->board[sp->cur.col][sp->cur.row].card != NOT_A_CARD)) + ret = false; + + return ret; +} +/* check if thereis 1-13 */ +bool is_removable (struct game *sp, int col) +{ + int i, j; + bool ret; + + ret = false; + + if (sp->board[col][sp->fl[col].last_known].card == 1) { + i = sp->fl[col].last_known; + j = 1; + while (i != 0 && sp->board[col][i].card != NOT_A_CARD) { + if (sp->board[col][i].card == (sp->board[col][i - 1].card - 1) && sp->board[col][i - 1].known == true) + j++; + else { + ret = false; + break; + } + i--; + } + + if (j == 13) + ret = true; + } + + return ret; +} + +void spider_unhide_card (struct game *sp, int col, int row) +{ + if (sp->board[col][row].card != NOT_A_CARD) + sp->board[col][row].known = true; +} + +/* deal the cards and put them on the board */ +void deal_cards(struct game *sp) +{ + int all_cards[CARDS_PER_SUIT]; + int i, cards_to_deal; + int rand; + + for (i = 0; i < CARDS_PER_SUIT; i++) { + all_cards[i] = 7; + } + + cards_to_deal = 0; + rand = 0; + /* all the cards in board */ + while (cards_to_deal < COL_NUM * 32) { + if (cards_to_deal < CARDS_NUM) { + rand = rb->rand() % 13 + 1; + /* if (++rand > 13) + rand = 1; */ + if (all_cards[rand - 1] >= 0) { + + all_cards[rand - 1]--; + + /* 44 cards are drawn reversed */ + if (cards_to_deal < 44) { + sp->board[cards_to_deal % 10][cards_to_deal / 10].card = rand; + } else { + /* 45+ get the number from the remains stuck */ + sp->board[cards_to_deal % 10][cards_to_deal / 10].card = NOT_A_CARD; + sp->rem[(cards_to_deal-44) / 10][(cards_to_deal-44) % 10] = rand; + } + sp->board[cards_to_deal % 10][cards_to_deal / 10].known = false; + + + } else + continue; + } else + sp->board[cards_to_deal % 10][cards_to_deal / 10].card = NOT_A_CARD; + + cards_to_deal++; + } + + +} + + +void spider_draw_card (struct game *sp, struct draw_card card) +{ + +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground(LCD_BLACK); +#endif + rb->lcd_set_drawmode(DRMODE_SOLID); + + /* card margins */ + rb->lcd_vline(card.x, card.y + 1, card.y + CARD_HEIGHT - 2); + rb->lcd_vline(card.x + CARD_WIDTH - 1, card.y + 1, card.y + CARD_HEIGHT - 2); + rb->lcd_hline(card.x + 1, card.x + CARD_WIDTH - 2, card.y); + rb->lcd_hline(card.x + 1, card.x + CARD_WIDTH - 2, card.y + CARD_HEIGHT - 1); + + /* card front */ + if (sp->board[card.col][card.row].known == true) + rb->lcd_bitmap_part(card_deck, CARD_PIC_WIDTH * (sp->board[card.col][card.row].card - 1), + 0, STRIDE(SCREEN_MAIN, BMPWIDTH_card_deck, BMPHEIGHT_card_deck), + card.x + 1, card.y + 1, CARD_PIC_WIDTH, CARD_PIC_HEIGHT); + /* card back */ + else if (sp->board[card.col][card.row].card != NOT_A_CARD) + rb->lcd_bitmap_part(card_back, 0, 0 , STRIDE(SCREEN_MAIN, BMPWIDTH_card_back, BMPHEIGHT_card_back), + card.x + 1, card.y + 1, CARD_PIC_WIDTH, + CARD_PIC_HEIGHT); + + + /* draw the cursor if the card is focused */ + if (sp->cur.col == card.col && (sp->cur.row == card.row || (sp->cur.row == -1 && + sp->cur.row + 1 == card.row))) { + rb->lcd_set_drawmode(DRMODE_COMPLEMENT); + rb->lcd_fillrect(card.x + 1, card.y + 1, CARD_WIDTH - 2, CARD_HEIGHT - 2); + rb->lcd_set_drawmode(DRMODE_SOLID); + } + + /* select the focused card */ + if (sp->select && card.col == sp->sel.col && card.row == sp->sel.row) { + rb->lcd_drawrect(card.x + 1, card.y + 1, CARD_WIDTH - 2, CARD_HEIGHT - 2); + } + +} + +void spider_remove_suit (struct game *sp, int col) +{ + int i; + int end; + struct draw_card cur_card; + end = 0; + + for (i = sp->fl[col].last_known; i >= (sp->fl[col].last_known - 12); i--) { + + if (sp->play_animation) + end = *rb->current_tick + (CYCLETIME * HZ) / 1000; + + sp->board[col][i].card = NOT_A_CARD; + sp->board[col][i].known = false; + +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground(BACKGROUND_COLOR); +#else + rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); +#endif + if (sp->play_animation) { + /* clear the area */ + cur_card.col = col; + cur_card.row = i - 1; + cur_card.x = sp->lcd_x_margin + X_MARGIN + col * BETWEEN_CARDS_X + col * CARD_WIDTH; + cur_card.y = Y_MARGIN + ((cur_card.row < sp->fl[col].first_known?cur_card.row: + (sp->fl[col].first_known==NOT_A_CARD?0:sp->fl[col].first_known)) + * (BETWEEN_CARDS_Y / 2)); + if ((Y_MARGIN + sp->fl[col].last_known * BETWEEN_CARDS_Y + CARD_HEIGHT) < LCD_HEIGHT) + cur_card.y += (cur_card.row < sp->fl[col].first_known?0:(cur_card.row + - (sp->fl[col].first_known==NOT_A_CARD?0:sp->fl[col].first_known))) + * BETWEEN_CARDS_Y; + else + cur_card.y += (cur_card.row < sp->fl[col].first_known?0:(cur_card.row + - (sp->fl[col].first_known==NOT_A_CARD?0:sp->fl[col].first_known))) + * ((LCD_HEIGHT - Y_MARGIN - CARD_HEIGHT) / sp->fl[col].last_known); + if (i == 0) + rb->lcd_fillrect(cur_card.x, cur_card.y, CARD_WIDTH, CARD_HEIGHT + BETWEEN_CARDS_Y); + else { + if ((Y_MARGIN + sp->fl[col].last_known * BETWEEN_CARDS_Y + CARD_HEIGHT) < LCD_HEIGHT) + rb->lcd_fillrect(cur_card.x, cur_card.y + BETWEEN_CARDS_Y, CARD_WIDTH, CARD_HEIGHT); + else + rb->lcd_fillrect(cur_card.x, cur_card.y + ((LCD_HEIGHT - Y_MARGIN - CARD_HEIGHT) / + sp->fl[col].last_known), CARD_WIDTH, CARD_HEIGHT); + } + /* draw the previous card */ + spider_draw_card (sp, cur_card); + + if ((Y_MARGIN + sp->fl[col].last_known * BETWEEN_CARDS_Y + CARD_HEIGHT) < LCD_HEIGHT) + rb->lcd_update_rect(cur_card.x, cur_card.y, CARD_WIDTH, CARD_HEIGHT + BETWEEN_CARDS_Y); + else + rb->lcd_update_rect(cur_card.x, cur_card.y, CARD_WIDTH, CARD_HEIGHT + + ((LCD_HEIGHT - Y_MARGIN - CARD_HEIGHT) / sp->fl[col].last_known)); + + if (end > *rb->current_tick) + rb->sleep(end-*rb->current_tick); + else + rb->yield(); + } + + } + + if (i < 0) { + sp->fl[col].last_known = NOT_A_CARD; + sp->fl[col].first_known = NOT_A_CARD; + if (col == sp->cur.col) + sp->cur.row = 0; + } else { + sp->fl[col].last_known = i; + spider_unhide_card (sp, col, i); + if (col == sp->cur.col) + sp->cur.row = i; + } + sp->completed_suits++; + +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground(LCD_BLACK); +#else + rb->lcd_set_drawmode(DRMODE_SOLID); +#endif + +} + + +void spider_deal_new_row (struct game *sp) +{ + int i, cur_row; + int end; + struct draw_card cur_card; + + end = 0; + + for (i = 0; i < COL_NUM; i++) + if (sp->board[i][0].card == NOT_A_CARD) { + rb->splash( HZ, "There are empty slots!" ); + return; + } + + cur_card.x = 0; + + /* nothing is selected */ + sp->sel.col = 0; + sp->sel.row = 0; + sp->select = false; + + /* un mark the cur card */ + cur_row = sp->cur.row; + if (sp->rem_cards_pos > 0) + sp->cur.row = sp->fl[sp->cur.col].last_known + 1; + + /* equal spaces between all cards */ + cur_card.col = sp->cur.col; + for (i = cur_row; i <= sp->fl[sp->cur.col].last_known; i++) { + cur_card.row = i; + cur_card.x = sp->lcd_x_margin + X_MARGIN + sp->cur.col * BETWEEN_CARDS_X + sp->cur.col * CARD_WIDTH; + cur_card.y = Y_MARGIN + ((sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known) + * (BETWEEN_CARDS_Y / 2)); + + if ((Y_MARGIN + sp->fl[sp->cur.col].last_known * BETWEEN_CARDS_Y + CARD_HEIGHT) < LCD_HEIGHT) + cur_card.y += (i - (sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known)) + * BETWEEN_CARDS_Y; + else + cur_card.y += (i - (sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known)) + * ((LCD_HEIGHT - Y_MARGIN - CARD_HEIGHT) / sp->fl[sp->cur.col].last_known); + + spider_draw_card (sp, cur_card); + } + +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground(BACKGROUND_COLOR); +#else + rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); +#endif + if ((Y_MARGIN + sp->fl[sp->cur.col].last_known * BETWEEN_CARDS_Y + CARD_HEIGHT) < LCD_HEIGHT) { + rb->lcd_fillrect(cur_card.x,Y_MARGIN + ((sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known) + * (BETWEEN_CARDS_Y / 2)) + ((sp->fl[sp->cur.col].last_known - + (sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known)) + * BETWEEN_CARDS_Y) + CARD_HEIGHT, CARD_WIDTH, BETWEEN_CARDS_Y + 3); + rb->lcd_update_rect(cur_card.x, Y_MARGIN + + ((sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known) + * (BETWEEN_CARDS_Y / 2)), CARD_WIDTH, Y_MARGIN + + ((sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known) + * (BETWEEN_CARDS_Y / 2)) + ((sp->fl[sp->cur.col].last_known - + (sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known)) + * BETWEEN_CARDS_Y + CARD_HEIGHT) + BETWEEN_CARDS_Y + 3); + } else { + rb->lcd_fillrect(cur_card.x,Y_MARGIN + ((sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known) + * (BETWEEN_CARDS_Y / 2)) + ((sp->fl[sp->cur.col].last_known - + (sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known)) + * ((LCD_HEIGHT - Y_MARGIN - CARD_HEIGHT) / sp->fl[sp->cur.col].last_known)) + CARD_HEIGHT, CARD_WIDTH, + ((LCD_HEIGHT - Y_MARGIN - CARD_HEIGHT) / sp->fl[sp->cur.col].last_known) + 3); + rb->lcd_update_rect(cur_card.x, Y_MARGIN + ((sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known) + * (BETWEEN_CARDS_Y / 2)), CARD_WIDTH, Y_MARGIN + + ((sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known) + * (BETWEEN_CARDS_Y / 2)) + ((sp->fl[sp->cur.col].last_known - + (sp->fl[sp->cur.col].first_known==NOT_A_CARD?0:sp->fl[sp->cur.col].first_known)) + * ((LCD_HEIGHT - Y_MARGIN - CARD_HEIGHT) / sp->fl[sp->cur.col].last_known) + CARD_HEIGHT) + + ((LCD_HEIGHT - Y_MARGIN - CARD_HEIGHT) / sp->fl[sp->cur.col].last_known) + 3); + } + + /* deal new cards */ + for (i = 0; i < COL_NUM; i++) { + + if (sp->play_animation) + end = *rb->current_tick + (CYCLETIME * HZ) / 1000; + + if (sp->rem_cards_pos > 0) + sp->fl[i].last_known++; + + sp->board[i][sp->fl[i].last_known].card = sp->rem[sp->rem_cards_pos][i]; + sp->board[i][sp->fl[i].last_known].known = true; + + if (sp->play_animation) { + cur_card.col = i; + cur_card.row = sp->fl[i].last_known; + cur_card.x = sp->lcd_x_margin + X_MARGIN + i * BETWEEN_CARDS_X + i * CARD_WIDTH; + cur_card.y = Y_MARGIN + ((sp->fl[i].first_known==NOT_A_CARD?0:sp->fl[i].first_known) * (BETWEEN_CARDS_Y / 2)); + if ((Y_MARGIN + sp->fl[i].last_known * BETWEEN_CARDS_Y + CARD_HEIGHT) < LCD_HEIGHT) + cur_card.y += (sp->fl[i].last_known - (sp->fl[i].first_known==NOT_A_CARD?0:sp->fl[i].first_known)) + * BETWEEN_CARDS_Y; + else + cur_card.y += ((sp->fl[i].last_known - (sp->fl[i].first_known==NOT_A_CARD?0:sp->fl[i].first_known)) + * ((LCD_HEIGHT - Y_MARGIN - CARD_HEIGHT) / (sp->fl[i].last_known - 1))); + + spider_draw_card (sp, cur_card); + + if (cur_card.x < 0) + rb->lcd_update_rect(0, cur_card.y, CARD_WIDTH - cur_card.x, CARD_HEIGHT); + else + rb->lcd_update_rect(cur_card.x, cur_card.y, CARD_WIDTH, CARD_HEIGHT); + + if (end > *rb->current_tick) + rb->sleep(end-*rb->current_tick); + else + rb->yield(); + } + + } + + if (sp->rem_cards_pos > 0) + sp->cur.row = sp->fl[sp->cur.col].last_known; + + if (sp->rem_cards_pos < REM_STACK) + sp->rem_cards_pos++; + +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground(LCD_BLACK); +#else + rb->lcd_set_drawmode(DRMODE_SOLID); +#endif + +} + + +void spider_put_text (struct game *sp) +{ + int h, w; + char str[12]; + +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground(TEXT_COLOR); +#endif + if (sp->show_text) { + rb->snprintf(str, sizeof(str), "Remain: %d", REM_STACK - sp->rem_cards_pos); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w - 1, LCD_HEIGHT - h - 1, str); + + /* suits that have been cleared from the screen */ + rb->snprintf(str, sizeof(str), "Clear: %d", sp->completed_suits); + rb->lcd_putsxy(1, LCD_HEIGHT - h - 1, str); + } + +} + +/* draw the cards on the board + draw the cursor + selected card */ +void spider_draw_board (struct game *sp) +{ + int i, j; + struct draw_card cur_card; + bool new_margin; + + for (i = 0; i < COL_NUM; i++) { + cur_card.col = i; + cur_card.x = sp->lcd_x_margin + X_MARGIN + BETWEEN_CARDS_X * i + i * CARD_WIDTH; + cur_card.y = Y_MARGIN; + + if (sp->rem_cards_pos > 0) { + sp->fl[i].first_known = NOT_A_CARD; + } + //DEBUGF("col %d -- ", i==sp->cur.col?1000+i:i); /* Board checking */ + /* check if the draw > LCD_HEIGHT */ + if ((Y_MARGIN + sp->fl[i].last_known * BETWEEN_CARDS_Y + CARD_HEIGHT) > LCD_HEIGHT) + new_margin = true; + else + new_margin = false; + + for (j = 0; j < 32; j++) { + /* take last known */ + if (sp->board[i][j].card == NOT_A_CARD) { + if (sp->rem_cards_pos > 0) + sp->fl[i].last_known = j - 1; + if (j != 0) + break; + } + /* take first known */ + if (sp->board[i][j].known == true && + sp->fl[i].first_known == NOT_A_CARD && sp->rem_cards_pos > 0) + sp->fl[i].first_known = j; + + cur_card.row = j; + spider_draw_card (sp, cur_card); + if (sp->board[i][j+1].known && j == sp->cur.row && sp->cur.col == i) + cur_card.y += BETWEEN_CARDS_Y + 3; + else if (new_margin && sp->board[i][j].known) + cur_card.y += (LCD_HEIGHT - Y_MARGIN - CARD_HEIGHT) / sp->fl[i].last_known; + else if (!sp->board[i][j].known) + cur_card.y += BETWEEN_CARDS_Y / 2; + else + cur_card.y += BETWEEN_CARDS_Y; + + //DEBUGF("%d ", sp->board[i][j].card); /* Board checking */ + + /* break after draw blank col */ + if (sp->board[i][j].card == NOT_A_CARD && j == 0) + break; + } + //DEBUGF("\n"); /* Board checking */ + } + //DEBUGF("#################################\n"); /* Board checking */ +} + + + +void draw_tringale (int direction, int size) +{ + int x,y,h; + rb->lcd_getstringsize("A" , NULL, &h); + y = LCD_HEIGHT - h - size * 2; + +#ifdef HAVE_LCD_COLOR + rb->lcd_set_background(BACKGROUND_COLOR); + rb->lcd_set_foreground(LCD_BLACK); +#endif + rb->lcd_set_drawmode(DRMODE_SOLID); + + if (direction == SPIDER_LEFT) { + x = X_MARGIN; + rb->lcd_drawline(x, y + size / 2, x + size, y); + rb->lcd_drawline(x, y + size / 2, x + size, y + size); + rb->lcd_vline(x + size, y, y + size); + } else { + x = LCD_WIDTH - (X_MARGIN + size); + rb->lcd_drawline(x, y, x + size, y + size / 2); + rb->lcd_drawline(x, y + size, x + size, y + size / 2); + rb->lcd_vline(x, y, y + size); + } + + +} + +void check_lcd_margins (struct game *sp, int direction) +{ + if ((sp->cur.col < (COL_NUM / 2 - 1)) && (direction == SPIDER_LEFT) && (sp->lcd_x_margin < 0) + && (((sp->cur.col)* SPIDER_LCD_STEPS) <= abs(sp->lcd_x_margin))) + sp->lcd_x_margin += SPIDER_LCD_STEPS; + else if ((sp->cur.col > (COL_NUM / 2)) && (direction == SPIDER_RIGHT) + && ((-sp->lcd_x_margin + LCD_WIDTH) < FAKE_LCD_WIDTH) + && (-((sp->cur.col - COL_NUM / 2)* SPIDER_LCD_STEPS) < sp->lcd_x_margin)) + sp->lcd_x_margin -= SPIDER_LCD_STEPS; + +} + +/* initialize the game */ +void spider_init(struct game *sp) +{ + int i; + sp->rem_cards_pos = 0; + sp->completed_suits = 0; + sp->sel.col = 0; + sp->sel.row = 0; + sp->select = false; + sp->in_game = false; + sp->lcd_x_margin = 0; + sp->cur.col = 0; + sp->cur.row = -2; + + for (i = 0; i < COL_NUM; i++) { + if (i < 4) + sp->fl[i].last_known = sp->fl[i].first_known = 5; + else + sp->fl[i].last_known = sp->fl[i].first_known = 4; + } + + deal_cards(sp); +} + +/* menu */ + +static const struct opt_items yesno[2] = { + { "No", 0 }, + { "Yes", 1 }, +}; + +int resume; + +static int spider_menu_cb(int action, const struct menu_item_ex *this_item) +{ + int i = ((intptr_t)this_item); + if(action == ACTION_REQUEST_MENUITEM + && !resume && i==0) + return ACTION_EXIT_MENUITEM; + return action; +} + +int spider_menu(struct game *sp) +{ + int selected = 0; + int selected2 = 0; + + resume = sp->in_game; + + MENUITEM_STRINGLIST(main_menu, "Spiderbox Menu", spider_menu_cb, + "Resume Game", "Start New Game", + "Settings", + "Playback Control", "Quit"); + + MENUITEM_STRINGLIST(settings_menu, "Settings", NULL, + "Show text", "Play animation"); + while (true) + { + switch (rb->do_menu(&main_menu, &selected, NULL, false)) + { + case 0: + return -1; + break; + + case 1: + spider_init (sp); + sp->in_game = true; + + rb->lcd_set_drawmode(DRMODE_SOLID); +#ifdef HAVE_LCD_COLOR + rb->lcd_set_background(BACKGROUND_COLOR); + rb->lcd_set_foreground(LCD_BLACK); +#endif + + rb->lcd_clear_display(); + + spider_put_text (sp); + spider_draw_board (sp); + + + /* draw left and right tringales */ + if ((sp->lcd_x_margin != 0) && (abs(sp->lcd_x_margin) <= SPIDER_LCD_STEPS*3)) { + draw_tringale(SPIDER_LEFT, 6); + draw_tringale(SPIDER_RIGHT, 6); + } else if (sp->lcd_x_margin == 0) + draw_tringale(SPIDER_RIGHT, 6); + else + draw_tringale(SPIDER_LEFT, 6); + + rb->lcd_update(); + + sp->cur.row = sp->fl[sp->cur.col].last_known; + spider_deal_new_row (sp); + + return -1; + break; + + case 2: + + switch (rb->do_menu(&settings_menu, &selected2, NULL, false)) + { + case 0: + rb->set_option("Show text", &sp->show_text, BOOL, yesno, 2, NULL); + break; + case 1: + rb->set_option("Play animation", &sp->play_animation, BOOL, yesno, 2, NULL); + break; + } + break; + case 3: + playback_control(NULL); + break; + case 4: + return SPIDER_QUIT; + break; + case MENU_ATTACHED_USB: + return SPIDER_USB; + default: + break; + } + } + + return SPIDER_QUIT; +} + +int main_game_loop (struct game *sp) +{ + int button, menu; + int i = 0, j = 0; + + sp->in_game = false; + + /* first - start with the menu */ + menu = spider_menu (sp); + if (menu != -1) + return menu; + + while (sp->completed_suits != SUITS) { + + rb->lcd_set_drawmode(DRMODE_SOLID); +#ifdef HAVE_LCD_COLOR + rb->lcd_set_background(BACKGROUND_COLOR); + rb->lcd_set_foreground(LCD_BLACK); +#endif + rb->lcd_clear_display(); + + spider_put_text (sp); + spider_draw_board (sp); + + /* DEBUGF("cur_col=%d cur_row=%d first_known=%d last_known=%d\nsel_col=%d sel_row=%d is_movable=%d\ncur_board=%d sel_board=%d\n", + sp->cur.col, sp->cur.row, sp->fl[sp->cur.col].first_known, sp->fl[sp->cur.col].last_known, + sp->sel.col, sp->sel.row, is_movable(sp), + sp->board[sp->cur.col][sp->cur.row].card, sp->board[sp->sel.col][sp->sel.row].card); */ /* global variabels check*/ + + /* draw left and right tringales */ + if ((sp->lcd_x_margin != 0) && (abs(sp->lcd_x_margin) < SPIDER_LCD_STEPS*3)) { + draw_tringale(SPIDER_LEFT, 6); + draw_tringale(SPIDER_RIGHT, 6); + } else if (sp->lcd_x_margin == 0) + draw_tringale(SPIDER_RIGHT, 6); + else + draw_tringale(SPIDER_LEFT, 6); + + rb->lcd_update(); + + /* check if thereis a suit to remove */ + for (i = 0; i < COL_NUM; i++) + if (is_removable(sp, i)) + spider_remove_suit (sp, i); + + button = rb->button_get( true ); +#if (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_FUZE_PAD) + if (button & (BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD)) + button = button & (~BUTTON_REPEAT); +#endif + /* what to do when a key is pressed ... */ + switch( button ) + { + case SPIDER_OFF: + menu = spider_menu (sp); + if (menu != -1) + return menu; + break; + + case SPIDER_DEAL: + if (sp->rem_cards_pos < REM_STACK) + spider_deal_new_row (sp); + + + break; + + case SPIDER_SELECT: + + if (sp->select && is_movable(sp) && ((sp->fl[sp->cur.col].last_known == sp->cur.row) + || (sp->fl[sp->cur.col].last_known == NOT_A_CARD))) { + + sp->select = false; + + spider_unhide_card (sp, sp->sel.col, sp->sel.row - 1); + + j = sp->sel.row; + + if (sp->board[sp->cur.col][sp->cur.row].card == NOT_A_CARD) + i = 0; + else + i = 1; + + while (sp->board[sp->sel.col][j].card != NOT_A_CARD) { + + sp->board[sp->cur.col][sp->cur.row + i].card = + sp->board[sp->sel.col][j].card; + sp->board[sp->cur.col][sp->cur.row + i].known = true; + + sp->board[sp->sel.col][j].card = NOT_A_CARD; + sp->board[sp->sel.col][j].known = false; + + j++; + i++; + } + + sp->fl[sp->cur.col].last_known = sp->cur.row + i - 1; + sp->cur.row = sp->fl[sp->cur.col].last_known; + + } else if (sp->select && sp->cur.col == sp->sel.col && + sp->cur.row == sp->sel.row) { + sp->select = false; + } else if (sp->cur.row >= 0 && sp->board[sp->cur.col][sp->cur.row].card != NOT_A_CARD) { + sp->sel.col = sp->cur.col; + sp->sel.row = sp->cur.row; + sp->select = true; + } + + break; + case SPIDER_LEFT: + if (--sp->cur.col < 0) + sp->cur.col = 0;//COL_NUM - 1; + sp->cur.row = sp->fl[sp->cur.col].last_known<0?0:sp->fl[sp->cur.col].last_known; + + check_lcd_margins(sp, SPIDER_LEFT); + break; + + case SPIDER_RIGHT: + if (++sp->cur.col == COL_NUM) + sp->cur.col = COL_NUM-1; //0; + + sp->cur.row = sp->fl[sp->cur.col].last_known<0?0:sp->fl[sp->cur.col].last_known; + + check_lcd_margins(sp, SPIDER_RIGHT); + break; + + case SPIDER_DOWN: + if (++sp->cur.row > sp->fl[sp->cur.col].last_known) + sp->cur.row = sp->fl[sp->cur.col].first_known<0?0:sp->fl[sp->cur.col].first_known; + break; + + case SPIDER_UP: + if (--sp->cur.row < sp->fl[sp->cur.col].first_known) + sp->cur.row = sp->fl[sp->cur.col].last_known<0?0:sp->fl[sp->cur.col].last_known; + break; + + default: + if (rb->default_event_handler(button) == SYS_USB_CONNECTED) + return SPIDER_USB; + break; + } + + rb->yield(); + } + rb->splash(HZ, "You Won! :)"); + sp->in_game = false; + return SPIDER_WIN; +} + + +enum plugin_status plugin_start(const void* parameter ) +{ + int ret; + + (void)parameter; + + struct game spider; + + rb->srand (*rb->current_tick); + +#if LCD_DEPTH > 1 + rb->lcd_set_backdrop(NULL); +#endif + + rb->lcd_setfont(FONT_SYSFIXED); + + configfile_load(CONFIG_FILENAME, config, 2, 0); + + spider.play_animation = !cfg_play_animation?1:cfg_play_animation; + spider.show_text = !cfg_show_text?1:cfg_show_text; + + while ((ret = main_game_loop (&spider)) == SPIDER_WIN); + + rb->lcd_setfont(FONT_UI); + + cfg_play_animation = spider.play_animation; + cfg_show_text = spider.show_text; + + rb->splash(0, "Saving data..."); + configfile_save(CONFIG_FILENAME, config, 2, 0); + + switch (ret) { + case SPIDER_USB: + return PLUGIN_USB_CONNECTED; + break; + case SPIDER_QUIT: + return PLUGIN_OK; + break; + } + + return PLUGIN_OK; +} + +#endif Index: apps/plugins/CATEGORIES =================================================================== --- apps/plugins/CATEGORIES (revision 22819) +++ apps/plugins/CATEGORIES (working copy) @@ -87,6 +87,7 @@ solitaire,games sort,viewers spacerocks,games +spiderbox,games splitedit,apps star,games starfield,demos Index: apps/plugins/bitmaps/native/SOURCES =================================================================== --- apps/plugins/bitmaps/native/SOURCES (revision 22819) +++ apps/plugins/bitmaps/native/SOURCES (working copy) @@ -588,7 +588,7 @@ #endif /* tilesize */ #endif /* HAVE_COLOR */ -/* Solitaire and Blackjack */ +/* Solitaire, Blackjack and Spiderbox */ #ifdef HAVE_LCD_COLOR #if LCD_WIDTH >= 640 card_back.74x98x16.bmp Index: apps/plugins/SOURCES =================================================================== --- apps/plugins/SOURCES (revision 22819) +++ apps/plugins/SOURCES (working copy) @@ -53,6 +53,7 @@ #ifdef HAVE_LCD_BITMAP /* Not for the Player */ rockblox1d.c brickmania.c +spiderbox.c maze.c mazezam.c text_editor.c