Index: apps/plugins/bitmaps/native/SOURCES
===================================================================
--- apps/plugins/bitmaps/native/SOURCES	(revision 12138)
+++ apps/plugins/bitmaps/native/SOURCES	(working copy)
@@ -365,4 +366,10 @@
 minesweeper_tiles.8x8x1.bmp
 #endif
 
+/* Spider solitaire */
+#if (LCD_WIDTH > 210)
+spider_deck.234x92x16.bmp
+spider_back.19x33x16.bmp
+#endif
+
 #endif /* HAVE_LCD_BITMAP */
Index: apps/plugins/SOURCES
===================================================================
--- apps/plugins/SOURCES	(revision 12138)
+++ apps/plugins/SOURCES	(working copy)
@@ -85,6 +85,12 @@
 #endif
 #endif
 
+/* not support models with lcd width small than 210 
+   because of the card width */
+#if (LCD_WIDTH > 210)
+spider.c
+#endif
+
 /* not support recorder models for now */
 #if (LCD_WIDTH > 112) && (LCD_HEIGHT > 64)
 fireworks.c
Index: apps/plugins/spider.c
===================================================================
--- apps/plugins/spider.c	(revision 0)
+++ apps/plugins/spider.c	(revision 0)
@@ -0,0 +1,824 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   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 "configfile.h"
+
+
+#ifdef HAVE_LCD_BITMAP
+
+PLUGIN_HEADER
+
+static struct plugin_api* rb;
+
+#include "spider_deck.h"
+#include "spider_back.h"
+
+
+#if (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)
+
+#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
+
+#endif
+
+#ifdef HAVE_LCD_COLOR
+#define BACKGROUND_COLOR LCD_RGBPACK(47, 98, 149)
+#define CARD_COLOR LCD_WHITE
+#define TEXT_COLOR LCD_WHITE
+#endif
+
+#define CONFIG_FILENAME "spider.cfg"
+
+int cfg_play_animation, cfg_show_text;
+static struct configdata config[] = {
+   {TYPE_INT, 0, 1, &cfg_play_animation, "play_animation", NULL, NULL},
+   {TYPE_INT, 0, 1, &cfg_show_text, "show_text", NULL, 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 21
+#define CARD_HEIGHT 35
+
+#define CARD_PIC_WIDTH 16
+#define CARD_PIC_HEIGHT 8
+
+#define CYCLETIME 75
+
+#define X_MARGIN 1
+#define Y_MARGIN 2
+
+
+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 game {
+    struct board_cards board[COL_NUM][32];
+    int rem[REM_STACK][COL_NUM];
+    int card[CARDS_NUM];
+    int rem_cards_pos;
+    int cur_col;
+    int cur_row;
+    int sel_col;
+    int sel_row;
+    bool select;
+    int completed_suits;
+    bool play_animation;
+    bool show_text;
+    bool in_game;
+};
+
+bool is_movable (struct game *sp, int last_in_col);
+bool is_removable (struct game *sp, int col, int last_in_col);
+void spider_unhide_card (struct game *sp, int col, int row);
+void first_and_last (struct game *sp, int *first_in_col, int *last_in_col, int col);
+void spider_draw_card (struct game *sp, int col, int row, int last_in_col);
+int spider_remove_suit (struct game *sp, int col, int last_in_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);
+
+bool is_movable (struct game *sp, int last_in_col)
+{
+    int i;
+    bool ret;
+    
+    ret = true;
+    
+    i = sp->sel_row;
+    while (sp->board[sp->sel_col][i].card != NOT_A_CARD) {
+        if (sp->card[sp->board[sp->sel_col][i].card] != (sp->card[sp->board[sp->sel_col][i + 1].card] + 1)
+            && sp->board[sp->sel_col][i + 1].known) {
+            ret = false;
+            break;
+        }
+        i++;
+    }
+
+    if (ret && sp->card[sp->board[sp->cur_col][sp->cur_row].card] != 
+        (sp->card[sp->board[sp->sel_col][sp->sel_row].card] + 1) && last_in_col >= 0)
+       ret = false;
+    
+    return ret;
+}
+
+bool is_removable (struct game *sp, int col, int last_in_col)
+{
+    int i, j;
+    bool ret;
+    
+    ret = false;
+    
+    //DEBUGF("%d\n", sp->card[sp->board[col][last_in_col].card]);
+    if (sp->card[sp->board[col][last_in_col].card] == 1) {
+        i = last_in_col;
+        j = 1;
+        while (i != 0 && sp->board[col][i].card != NOT_A_CARD) {
+            //DEBUGF("removable %d %d %d\n", i, j, sp->card[sp->board[col][i].card]);
+            if (sp->card[sp->board[col][i].card] == (sp->card[sp->board[col][i - 1].card] - 1))
+                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;
+}
+
+
+/* check the location of the first and the last rows in a col */
+void first_and_last (struct game *sp, int *first_in_col, int *last_in_col, int col)
+{
+    int i; 
+    i = 0;
+    *first_in_col = -1;
+    while (sp->board[col][i].card != NOT_A_CARD) {
+        //DEBUGF("UP %d - %d\n", j, sp->board[sp->cur_col][j].known);
+        if (sp->board[col][i].known == true &&
+            *first_in_col == -1)
+            *first_in_col = i;
+        i++;
+    }
+    *last_in_col = i - 1;
+}
+
+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;
+    while (cards_to_deal < CARDS_NUM) {
+        rand = rb->rand() % 13 + 1;
+        /* if (++rand > 13)
+            rand = 1; */
+        if (all_cards[rand - 1] >= 0) {
+            //DEBUGF("%d\n",all_cards[rand]);
+            sp->card[cards_to_deal] = rand;
+            all_cards[rand - 1]--;
+            cards_to_deal++;
+        } else
+            continue;
+     }
+     
+                 
+}
+
+void spider_draw_card (struct game *sp, int col, int row, int last_in_col)
+{
+    int y_cor, x_cor;
+    int y_multi, x_multi, num;
+    
+    num = NOT_A_CARD;    
+    y_multi = 8;
+    if ((Y_MARGIN + last_in_col * y_multi + CARD_HEIGHT) > LCD_HEIGHT)
+        y_multi = (LCD_HEIGHT - Y_MARGIN - CARD_HEIGHT) / last_in_col;
+    
+    x_multi = LCD_WIDTH / COL_NUM - CARD_WIDTH;
+    
+    row = row == -1 ? 0 : row;
+    
+    if (last_in_col > sp->cur_row && ((sp->cur_row + 1) == row || row > sp->cur_row) && sp->cur_col == col)
+        y_cor = Y_MARGIN + row * y_multi + 3;
+    else
+        y_cor = Y_MARGIN + row * y_multi;
+
+    x_cor = X_MARGIN + x_multi * col + col * CARD_WIDTH;
+    
+    if (sp->board[col][row].card != NOT_A_CARD) {
+        num = sp->card[sp->board[col][row].card];
+#ifdef HAVE_LCD_COLOR
+        if (sp->board[col][row].known == true) {
+            rb->lcd_set_foreground(CARD_COLOR);
+            rb->lcd_fillrect(x_cor + 1, y_cor + 1, CARD_WIDTH - 2, CARD_HEIGHT - 2);
+        } else {
+            rb->lcd_bitmap_part(spider_back, 0, 0 , BMPWIDTH_spider_back,
+                                x_cor + 1, y_cor + 1, CARD_WIDTH - 2, 
+                                CARD_HEIGHT - 2);
+        }
+#endif
+    }
+    
+#ifdef HAVE_LCD_COLOR    
+    rb->lcd_set_foreground(LCD_BLACK);
+#endif
+
+    rb->lcd_vline(x_cor, y_cor + 1, y_cor + CARD_HEIGHT - 2);
+    rb->lcd_vline(x_cor + CARD_WIDTH - 1, y_cor + 1, y_cor + CARD_HEIGHT - 2);
+    rb->lcd_hline(x_cor + 1, x_cor + CARD_WIDTH - 2, y_cor);
+    rb->lcd_hline(x_cor + 1, x_cor + CARD_WIDTH - 2, y_cor + CARD_HEIGHT - 1);
+
+    if (sp->board[col][row].known == true) {
+        rb->lcd_bitmap_part(spider_deck, 1 + CARD_PIC_WIDTH * (num - 1) + 
+                            2 * (num - 1), 1 , BMPWIDTH_spider_deck,
+                            x_cor + 2, y_cor + 1, CARD_PIC_WIDTH, CARD_PIC_HEIGHT);
+    }
+
+    /* draw the cursor if the card is focused */
+    if (sp->cur_col == col && (sp->cur_row == row || (sp->cur_row == -1 &&
+                                                      sp->cur_row + 1 == row))) {
+        rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
+        rb->lcd_fillrect(x_cor + 1, y_cor + 1, CARD_WIDTH - 2, CARD_HEIGHT - 2);
+        rb->lcd_set_drawmode(DRMODE_SOLID);
+    }
+
+    /* select the selected card */
+    if (sp->select && col ==  sp->sel_col && row == sp->sel_row) {
+        rb->lcd_drawrect(x_cor + 1, y_cor + 1, CARD_WIDTH - 2, CARD_HEIGHT - 2);
+    }
+    //DEBUGF("%d %d == %d %d\n", sp->cur_col, sp->cur_row, row, col);
+
+}
+
+int spider_remove_suit (struct game *sp, int col, int last_in_col)
+{
+    int i, j, ret;
+    int end;
+
+    end = 0;
+    
+#ifdef HAVE_LCD_COLOR
+    rb->lcd_set_foreground(BACKGROUND_COLOR);
+#endif
+    rb->lcd_fillrect(X_MARGIN + sp->sel_col + sp->sel_col * CARD_WIDTH, 0, CARD_WIDTH, LCD_HEIGHT);   
+    for (j = 0; j < 32; j++) {
+        if (sp->board[sp->sel_col][j].card == NOT_A_CARD)
+            break;
+        spider_draw_card (sp, sp->sel_col, j, last_in_col + 1);
+    }
+    rb->lcd_update_rect(X_MARGIN + sp->sel_col + sp->sel_col * CARD_WIDTH, 0, CARD_WIDTH, LCD_HEIGHT);
+    //DEBUGF("iii %d\n", last_in_col);
+    
+    for (i = last_in_col + 1; i > (last_in_col - 13); 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);
+#endif
+        if (sp->play_animation) {
+            /* clear the area */
+            rb->lcd_fillrect(X_MARGIN + col + col * CARD_WIDTH, 0, CARD_WIDTH, LCD_HEIGHT);
+    
+            for (j = 0; j < 32; j++) {
+                if (sp->board[col][j].card == NOT_A_CARD)
+                    break;
+                spider_draw_card (sp, col, j, i);
+            }
+            
+            rb->lcd_update_rect(X_MARGIN + col + col * CARD_WIDTH, 0, CARD_WIDTH, LCD_HEIGHT);
+            
+            if (end > *rb->current_tick)
+                rb->sleep(end-*rb->current_tick);
+            else
+                rb->yield();
+        }
+        
+    }
+
+    if (--i > 0)
+        ret = 0;
+    else
+        ret = i;
+    
+    sp->completed_suits++;
+
+    return ret;
+}
+
+
+void spider_deal_new_row (struct game *sp)
+{
+    int i, first_in_col, last_in_col;
+    int last[COL_NUM];
+    int end;
+    
+    end = 0;
+    
+    for (i = 0; i < COL_NUM; i++)
+        if (sp->board[i][0].card == NOT_A_CARD) {
+            rb->splash( HZ, true, "There are empty slots!" );
+            return;
+        }
+
+    for (i = 0; i < COL_NUM; i++) {
+        
+        if (sp->play_animation)
+            end = *rb->current_tick + (CYCLETIME * HZ) / 1000;
+        
+        first_and_last (sp, &first_in_col, &last_in_col, i);
+        sp->board[i][last_in_col + 1].card = sp->rem[sp->rem_cards_pos][i];
+        sp->board[i][last_in_col + 1].known = true;
+        last[i] = last_in_col + 1;
+
+        spider_draw_card (sp, i, last_in_col + 1, last_in_col + 1);
+
+        if (sp->play_animation) {
+            rb->lcd_update_rect(X_MARGIN + i + i * CARD_WIDTH, 0, CARD_WIDTH, LCD_HEIGHT);
+    
+            if (end > *rb->current_tick)
+                rb->sleep(end-*rb->current_tick);
+            else
+                rb->yield();
+        }
+
+    }
+
+    for (i = 0; i < COL_NUM; i++) {
+        if (is_removable(sp, i, last[i])) {
+            last_in_col = spider_remove_suit (sp, i, last[i]);
+            spider_unhide_card (sp, i, last[i]);
+        }
+    }
+
+    if (sp->rem_cards_pos < REM_STACK)
+        sp->rem_cards_pos++;
+
+}
+
+
+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;
+    int first_in_col, last_in_col;
+    
+#ifdef HAVE_LCD_COLOR
+    rb->lcd_set_background(BACKGROUND_COLOR);
+    rb->lcd_set_foreground(LCD_BLACK);
+#endif
+    rb->lcd_clear_display();
+
+    for (i = 0; i < COL_NUM; i++) {
+        first_and_last (sp, &first_in_col, &last_in_col, i);    
+        for (j = 0; j < 32; j++) {
+            if (sp->board[i][j].card == NOT_A_CARD && j != 0)
+                break;
+            spider_draw_card (sp, i, j, last_in_col);
+        }
+    }
+}
+
+/* initialize the game */
+void spider_init(struct game *sp)
+{
+    int i, j;
+    int card_num;
+    
+    sp->rem_cards_pos = 0;
+    sp->completed_suits = 0;
+    
+    sp->sel_col = 0;
+    sp->sel_row = 0;
+    
+    sp->select = false;
+    sp->in_game = false;
+    
+    deal_cards(sp);
+    /* 44 cards are drawn reversed */
+    for (j = 0; j < 32; j++) {
+        for (i = 0; i < COL_NUM; i++) {
+            if (j * 10 + i < 44)
+                sp->board[i][j].card = j * 10 + i;
+            else
+                sp->board[i][j].card = NOT_A_CARD;
+            sp->board[i][j].known = false;
+        }
+    }
+    
+    /* start to fill the remains from card 45 */
+    card_num = 44;
+    for (j = 0; j < REM_STACK; j++) {
+        for (i = 0; i < COL_NUM; i++) {
+            sp->rem[j][i] = card_num;
+            card_num++;
+        }
+    }
+
+    j = 0;
+    sp->cur_col = 0;
+
+}
+
+int spider_menu(struct game *sp)
+{
+    int m;
+    int result = -1;
+    int i = 0;
+    char menu_play_animation[22], menu_show_text[22];    
+    
+    struct menu_item items[5];
+
+#ifdef HAVE_LCD_COLOR
+    rb->lcd_set_foreground(rb->global_settings->fg_color);
+    rb->lcd_set_background(rb->global_settings->bg_color);
+#endif
+
+    if (sp->in_game) {
+        items[i++].desc = "Resume Game";
+        items[i++].desc = "Restart Game";
+    } else {
+        items[i++].desc = "Start Game";
+        items[i++].desc = "";
+    }
+    items[i++].desc = menu_show_text;
+    items[i++].desc = menu_play_animation;
+    items[i++].desc = "Quit";
+
+
+    if (sp->play_animation) 
+        rb->strcpy(menu_play_animation, "Play animation: Yes");
+    else
+        rb->strcpy(menu_play_animation, "Play animation: No");
+        
+    if (sp->show_text) 
+        rb->strcpy(menu_show_text, "Show text: Yes");
+    else
+        rb->strcpy(menu_show_text, "Show text: No");
+
+    m = rb->menu_init(items, i, NULL, NULL, NULL, NULL);
+
+    while (result < 0)
+    {
+        switch (rb->menu_show(m))
+        {
+            case MENU_ATTACHED_USB:
+                result = MENU_USB;
+                break;
+
+            case MENU_SELECTED_EXIT:
+            case 0:
+                if (sp->in_game)
+                    result = MENU_RESUME;
+                else
+                    result = MENU_NEW_GAME;
+                break;
+                
+            case 1:
+                spider_init (sp);
+                result = MENU_NEW_GAME;
+                break;
+                
+            case 2:
+                sp->show_text = !sp->show_text;
+                if (sp->show_text) 
+                    rb->strcpy(menu_show_text, "Show text: Yes");
+                else
+                    rb->strcpy(menu_show_text, "Show text: No");
+                break;
+            case 3:
+                sp->play_animation = !sp->play_animation;
+                if (sp->play_animation) 
+                    rb->strcpy(menu_play_animation, "Play animation: Yes");
+                else
+                    rb->strcpy(menu_play_animation, "Play animation: No");
+
+                break;
+
+            case 4:
+                result = MENU_QUIT;
+                break;
+        }
+    }
+    rb->menu_exit(m);
+    rb->lcd_setmargins(0, 0);
+    return result;
+}
+
+int main_game_loop (struct game *sp)
+{
+    int button;
+    int i = 0, j = 0;
+    int first_in_col, last_in_col;
+    
+    spider_init (sp);
+    
+    switch (spider_menu (sp)) {
+        case MENU_USB:
+             return SPIDER_USB;
+             
+        case MENU_QUIT:
+             return SPIDER_QUIT;
+        
+        case MENU_NEW_GAME:
+            sp->in_game = true;
+            
+            spider_draw_board (sp);
+            spider_put_text (sp);
+            
+            rb->lcd_update();
+               
+            spider_deal_new_row (sp);
+            
+            first_and_last (sp, &first_in_col, &last_in_col, sp->cur_col);
+            sp->cur_row = last_in_col;;
+            
+            break;
+    }
+    
+
+    while (sp->completed_suits != SUITS) {
+
+        spider_draw_board (sp);
+        spider_put_text (sp);
+        
+        rb->lcd_update();
+
+        first_and_last (sp, &first_in_col, &last_in_col, sp->cur_col);
+
+        /* what to do when a key is pressed ... */
+        button = rb->button_get( true );
+        switch( button )
+        {
+            case SPIDER_OFF:
+                switch (spider_menu (sp)) {
+                    case MENU_USB:
+                         return SPIDER_USB;
+                         
+                    case MENU_QUIT:
+                         return SPIDER_QUIT;
+                         
+                    case MENU_NEW_GAME:
+                        sp->in_game = true;
+                        spider_draw_board (sp);
+                        spider_put_text (sp);
+                        
+                        rb->lcd_update();
+                           
+                        spider_deal_new_row (sp);
+                        
+                        first_and_last (sp, &first_in_col, &last_in_col, sp->cur_col);
+                        sp->cur_row = last_in_col;
+                        
+                        break;
+                }
+                        
+      
+            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, last_in_col) && last_in_col == sp->cur_row) {
+                    if (last_in_col >= 0) {
+                        sp->select = false;
+                        
+                        spider_unhide_card (sp, sp->sel_col, sp->sel_row - 1);
+                        
+                        j = sp->sel_row;
+                        while (sp->board[sp->sel_col][j].card != NOT_A_CARD) {
+                            i = j - sp->sel_row + 1;
+                            
+                            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;
+                            //DEBUGF("%d %d -- %d %d\n", sp->cur_col, sp->cur_row + i, sp->sel_col, j);
+                            
+                            sp->board[sp->sel_col][j].card = NOT_A_CARD;
+                            sp->board[sp->sel_col][j].known = false;
+    
+                            j++;
+                        }
+                        
+                        last_in_col = sp->cur_row + i;
+                        sp->cur_row = last_in_col;
+                        if (is_removable(sp, sp->cur_col, last_in_col)) {
+                            spider_remove_suit (sp, sp->cur_col, last_in_col);
+                            spider_unhide_card (sp, sp->cur_col, last_in_col - 13);
+                            sp->cur_row = last_in_col - 13;
+                        }
+                    } else {
+                        sp->select = false;
+                        
+                        j = sp->sel_row;
+                        
+                        while (sp->board[sp->sel_col][j].card != NOT_A_CARD) {
+                            i = j - sp->sel_row + 1;
+                            
+                            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;
+                            DEBUGF("%d %d -- %d %d\n", sp->cur_col, sp->cur_row + i, sp->sel_col, j);
+                            
+                            sp->board[sp->sel_col][j].card = NOT_A_CARD;
+                            sp->board[sp->sel_col][j].known = false;
+    
+                            j++;
+                        }
+                        sp->cur_row += i;
+                        spider_unhide_card (sp, sp->sel_col, sp->sel_row - 1);
+                    }
+                    
+                } else if (sp->select && sp->cur_col == sp->sel_col && 
+                           sp->cur_row == sp->sel_row) {
+                    sp->select = false;
+                } else if (sp->cur_row > -1) {
+                    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 = COL_NUM - 1;
+                j = 0;
+                while (sp->board[sp->cur_col][j].card != NOT_A_CARD)
+                    j++;
+                sp->cur_row = j - 1;
+            break;
+            
+            case SPIDER_RIGHT:
+                if (++sp->cur_col == COL_NUM)
+                    sp->cur_col = 0;
+                j = 0;
+                while (sp->board[sp->cur_col][j].card != NOT_A_CARD)
+                    j++;
+                sp->cur_row = j - 1;
+            break;
+            
+            case SPIDER_DOWN:
+                //DEBUGF("DOWN FIRST: %d LAST: %d\n", first_in_col, last_in_col);
+                if (++sp->cur_row > last_in_col)
+                    sp->cur_row = first_in_col;
+            break;
+            
+            case SPIDER_UP:
+                if (--sp->cur_row < first_in_col)
+                    sp->cur_row = last_in_col;
+            break;
+            
+            default:
+                if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
+                    return SPIDER_USB;
+            break;
+        }
+
+    }
+    rb->splash(HZ, true, "You Won! :)");
+    sp->in_game = false;
+    return SPIDER_WIN;
+}
+
+
+enum plugin_status plugin_start( struct plugin_api* api, void* parameter )
+{
+    int ret;
+
+    (void)parameter;
+    rb = api;
+
+    struct game spider;
+    
+    rb->srand (*rb->current_tick);
+    
+#if LCD_DEPTH > 1
+    rb->lcd_set_backdrop(NULL);
+#endif
+    
+    rb->lcd_setfont(FONT_SYSFIXED);
+
+    configfile_init(rb);
+    configfile_load(CONFIG_FILENAME, config, 2, 0);
+                    
+    spider.play_animation = cfg_play_animation;
+    spider.show_text = 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, true, "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
