From 913fea27fcecd907e9432f6c87970cd08b8aea28 Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Tue, 16 Jan 2007 21:05:15 +0000 Subject: [PATCH] t! Initial version of a Blackjack plugin for bitmap-screen targets. Also includes the changes to the manual. Cross your fingers... git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12030 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/SOURCES | 1 + apps/plugins/blackjack.c | 1442 +++++++++++++++++ manual/plugins/blackjack.tex | 81 + .../plugins/images/ss-blackjack-112x64x1.png | Bin 0 -> 476 bytes .../images/ss-blackjack-128x128x16.png | Bin 0 -> 2047 bytes .../plugins/images/ss-blackjack-138x110x2.png | Bin 0 -> 816 bytes .../images/ss-blackjack-160x128x16.png | Bin 0 -> 2376 bytes .../plugins/images/ss-blackjack-160x128x2.png | Bin 0 -> 871 bytes .../images/ss-blackjack-176x132x16.png | Bin 0 -> 2433 bytes .../images/ss-blackjack-176x220x16.png | Bin 0 -> 2722 bytes .../images/ss-blackjack-220x176x16.png | Bin 0 -> 4134 bytes .../images/ss-blackjack-240x320x16.png | Bin 0 -> 4574 bytes .../images/ss-blackjack-320x240x16.png | Bin 0 -> 8600 bytes manual/plugins/main.tex | 2 + 14 files changed, 1526 insertions(+) create mode 100644 apps/plugins/blackjack.c create mode 100644 manual/plugins/blackjack.tex create mode 100644 manual/plugins/images/ss-blackjack-112x64x1.png create mode 100644 manual/plugins/images/ss-blackjack-128x128x16.png create mode 100644 manual/plugins/images/ss-blackjack-138x110x2.png create mode 100644 manual/plugins/images/ss-blackjack-160x128x16.png create mode 100644 manual/plugins/images/ss-blackjack-160x128x2.png create mode 100644 manual/plugins/images/ss-blackjack-176x132x16.png create mode 100644 manual/plugins/images/ss-blackjack-176x220x16.png create mode 100644 manual/plugins/images/ss-blackjack-220x176x16.png create mode 100644 manual/plugins/images/ss-blackjack-240x320x16.png create mode 100644 manual/plugins/images/ss-blackjack-320x240x16.png diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index f00ac71bed..72fdf7454e 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES @@ -43,6 +43,7 @@ jpeg.c mandelbrot.c plasma.c +blackjack.c bounce.c #ifndef SANSA_E200 bubbles.c diff --git a/apps/plugins/blackjack.c b/apps/plugins/blackjack.c new file mode 100644 index 0000000000..775fc8c834 --- /dev/null +++ b/apps/plugins/blackjack.c @@ -0,0 +1,1442 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: blackjack.c,v 1.6 2006/11/21 20:528:13 midgey34 Exp $ + * + * Copyright (C) 2006 Tom Ross (midgey34@gmail.com) + * + * 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 "solitaire_deck.h" +#include "solitaire_cardback.h" + +PLUGIN_HEADER + +/* save files */ +#define SCORE_FILE PLUGIN_DIR "/blackjack.score" +#define SAVE_FILE PLUGIN_DIR "/blackjack.save" + +#define NUM_SCORES LCD_HEIGHT/8-2 + +/* final game return status */ +#define BJ_END 3 +#define BJ_USB 2 +#define BJ_QUIT 1 +#define BJ_LOSE 0 + +#if CONFIG_KEYPAD == RECORDER_PAD +#define BJACK_START BUTTON_ON +#define BJACK_QUIT BUTTON_OFF +#define BJACK_MAX (BUTTON_ON|BUTTON_UP) +#define BJACK_MIN (BUTTON_ON|BUTTON_DOWN) +#define BJACK_HIT BUTTON_F1 +#define BJACK_STAY BUTTON_F2 +#define BJACK_DOUBLEDOWN BUTTON_F3 +#define BJACK_SCORES BUTTON_RIGHT +#define BJACK_RESUME BUTTON_PLAY +#define BJACK_UP BUTTON_UP +#define BJACK_DOWN BUTTON_DOWN +#define BJACK_RIGHT BUTTON_RIGHT +#define BJACK_LEFT BUTTON_LEFT + +#elif CONFIG_KEYPAD == ONDIO_PAD +#define BJACK_START BUTTON_MENU +#define BJACK_QUIT BUTTON_OFF +#define BJACK_MAX (BUTTON_MENU|BUTTON_UP) +#define BJACK_MIN (BUTTON_MENU|BUTTON_DOWN) +#define BJACK_HIT BUTTON_LEFT +#define BJACK_STAY BUTTON_RIGHT +#define BJACK_DOUBLEDOWN BUTTON_UP +#define BJACK_SCORES BUTTON_UP +#define BJACK_RESUME BUTTON_DOWN +#define BJACK_UP BUTTON_UP +#define BJACK_DOWN BUTTON_DOWN +#define BJACK_RIGHT BUTTON_RIGHT +#define BJACK_LEFT BUTTON_LEFT + +#elif CONFIG_KEYPAD == IRIVER_H10_PAD +#define BJACK_START BUTTON_PLAY +#define BJACK_QUIT BUTTON_POWER +#define BJACK_MAX (BUTTON_PLAY|BUTTON_SCROLL_UP) +#define BJACK_MIN (BUTTON_PLAY|BUTTON_SCROLL_DOWN) +#define BJACK_HIT BUTTON_PLAY +#define BJACK_STAY BUTTON_FF +#define BJACK_DOUBLEDOWN BUTTON_REW +#define BJACK_SCORES BUTTON_LEFT +#define BJACK_RESUME BUTTON_RIGHT +#define BJACK_UP BUTTON_SCROLL_UP +#define BJACK_DOWN BUTTON_SCROLL_DOWN +#define BJACK_RIGHT BUTTON_RIGHT +#define BJACK_LEFT BUTTON_LEFT + +#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H300_PAD) +#define BJACK_START BUTTON_ON +#define BJACK_QUIT BUTTON_OFF +#define BJACK_MAX (BUTTON_ON|BUTTON_UP) +#define BJACK_MIN (BUTTON_ON|BUTTON_DOWN) +#define BJACK_HIT BUTTON_ON +#define BJACK_STAY BUTTON_REC +#define BJACK_DOUBLEDOWN BUTTON_SELECT +#define BJACK_SCORES BUTTON_SELECT +#define BJACK_RESUME BUTTON_MODE +#define BJACK_UP BUTTON_UP +#define BJACK_DOWN BUTTON_DOWN +#define BJACK_RIGHT BUTTON_RIGHT +#define BJACK_LEFT BUTTON_LEFT + +#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || \ + (CONFIG_KEYPAD == IPOD_4G_PAD) +#define BJACK_START BUTTON_SELECT +#define BJACK_QUIT BUTTON_MENU +#define BJACK_MAX (BUTTON_SELECT|BUTTON_SCROLL_FWD) +#define BJACK_MIN (BUTTON_SELECT|BUTTON_SCROLL_BACK) +#define BJACK_HIT BUTTON_SELECT +#define BJACK_STAY BUTTON_RIGHT +#define BJACK_DOUBLEDOWN BUTTON_LEFT +#define BJACK_SCORES BUTTON_RIGHT +#define BJACK_RESUME BUTTON_PLAY +#define BJACK_UP BUTTON_SCROLL_FWD +#define BJACK_DOWN BUTTON_SCROLL_BACK +#define BJACK_RIGHT BUTTON_RIGHT +#define BJACK_LEFT BUTTON_LEFT + +#elif CONFIG_KEYPAD == IAUDIO_X5_PAD +#define BJACK_START BUTTON_PLAY +#define BJACK_QUIT BUTTON_POWER +#define BJACK_MAX (BUTTON_PLAY|BUTTON_UP) +#define BJACK_MIN (BUTTON_PLAY|BUTTON_DOWN) +#define BJACK_HIT BUTTON_SELECT +#define BJACK_STAY BUTTON_REC +#define BJACK_DOUBLEDOWN BUTTON_PLAY +#define BJACK_SCORES BUTTON_RIGHT +#define BJACK_RESUME BUTTON_DOWN +#define BJACK_UP BUTTON_UP +#define BJACK_DOWN BUTTON_DOWN +#define BJACK_RIGHT BUTTON_RIGHT +#define BJACK_LEFT BUTTON_LEFT + +#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD +#define BJACK_START BUTTON_MODE +#define BJACK_QUIT BUTTON_PLAY +#define BJACK_MAX (BUTTON_EQ|BUTTON_UP) +#define BJACK_MIN (BUTTON_EQ|BUTTON_DOWN) +#define BJACK_HIT BUTTON_EQ +#define BJACK_STAY BUTTON_MODE +#define BJACK_DOUBLEDOWN BUTTON_SELECT +#define BJACK_SCORES BUTTON_SELECT +#define BJACK_RESUME (BUTTON_EQ|BUTTON_MODE) +#define BJACK_UP BUTTON_UP +#define BJACK_DOWN BUTTON_DOWN +#define BJACK_RIGHT BUTTON_RIGHT +#define BJACK_LEFT BUTTON_LEFT + +#elif CONFIG_KEYPAD == GIGABEAT_PAD +#define BJACK_START BUTTON_POWER +#define BJACK_QUIT BUTTON_A +#define BJACK_MAX BUTTON_VOL_UP +#define BJACK_MIN BUTTON_VOL_DOWN +#define BJACK_HIT BUTTON_VOL_UP +#define BJACK_STAY BUTTON_VOL_DOWN +#define BJACK_DOUBLEDOWN BUTTON_SELECT +#define BJACK_SCORES BUTTON_RIGHT +#define BJACK_RESUME BUTTON_MENU +#define BJACK_UP BUTTON_UP +#define BJACK_DOWN BUTTON_DOWN +#define BJACK_RIGHT BUTTON_RIGHT +#define BJACK_LEFT BUTTON_LEFT + +#elif CONFIG_KEYPAD == SANSA_E200_PAD +#define BJACK_START BUTTON_SELECT +#define BJACK_QUIT BUTTON_POWER +#define BJACK_MAX (BUTTON_REC|BUTTON_UP) +#define BJACK_MIN (BUTTON_REC|BUTTON_DOWN) +#define BJACK_HIT BUTTON_SELECT +#define BJACK_STAY BUTTON_RIGHT +#define BJACK_DOUBLEDOWN BUTTON_LEFT +#define BJACK_SCORES BUTTON_UP +#define BJACK_RESUME BUTTON_REC +#define BJACK_UP BUTTON_SCROLL_UP +#define BJACK_DOWN BUTTON_SCROLL_DOWN +#define BJACK_RIGHT BUTTON_RIGHT +#define BJACK_LEFT BUTTON_LEFT + +#elif CONFIG_KEYPAD == ELIO_TPJ1022_PAD +#define BJACK_START BUTTON_MAIN +#define BJACK_QUIT BUTTON_POWER +#define BJACK_MAX (BUTTON_REC|BUTTON_UP) +#define BJACK_MIN (BUTTON_REC|BUTTON_DOWN) +#define BJACK_HIT BUTTON_MAIN +#define BJACK_STAY BUTTON_MENU +#define BJACK_DOUBLEDOWN BUTTON_DOWN +#define BJACK_SCORES BUTTON_UP +#define BJACK_RESUME BUTTON_FF +#define BJACK_UP BUTTON_UP +#define BJACK_DOWN BUTTON_DOWN +#define BJACK_RIGHT BUTTON_RIGHT +#define BJACK_LEFT BUTTON_LEFT + +#else + #error BLACKJACK: Unsupported keypad +#endif + +#ifdef HAVE_LCD_COLOR +#define BG_COLOR LCD_RGBPACK(0,157,0) +#define FG_COLOR LCD_WHITE +#elif LCD_DEPTH > 1 +#define BG_COLOR LCD_WHITE +#define FG_COLOR LCD_BLACK +#endif + +#define CARD_WIDTH BMPWIDTH_solitaire_cardback +#define CARD_HEIGHT BMPHEIGHT_solitaire_cardback + +/* This is the max amount of cards onscreen before condensing */ +#define MAX_CARDS LCD_WIDTH/(CARD_WIDTH+4) + +extern const fb_data solitaire_deck[]; +extern const fb_data solitaire_cardback[]; + +#define NEXT_CARD bj->player_cards[done][bj->num_player_cards[done]] + +/* global rockbox api */ +static struct plugin_api* rb; + +/* dealer and player card positions */ +unsigned int dealer_x, dealer_y, player_x, player_y; + +typedef struct card { + unsigned int value; /* Card's value in Blackjack */ + unsigned int num; /* Value on card face 0-12 (0=Ace, 1=2, 11=Q) */ + unsigned int suit; /* 0:Spades, 1:Hearts, 2: Clubs; 3: Diamonds */ + bool is_soft_ace; +} card; + +typedef struct game_context { + struct card player_cards[2][22]; /* 22 Cards means the deal was all aces */ + struct card dealer_cards[22]; /* That is the worst-case scenario */ + unsigned int player_total; + unsigned int dealer_total; + signed int player_money; + unsigned int num_player_cards[2]; + unsigned int num_dealer_cards; + unsigned int current_bet; + unsigned int split_status; /* 0 = split hasn't been asked, * + * 1 = split did not occur * + * 2 = split occurred * + * 3 = split occurred and 1st hand done */ + bool is_blackjack; + bool end_hand; + bool asked_insurance; + signed short highscores[NUM_SCORES]; + bool resume; + bool dirty; +} game_context; + +/***************************************************************************** +* blackjack_init() initializes blackjack data structures. +******************************************************************************/ +static void blackjack_init(struct game_context* bj) { + /* seed the rand generator */ + rb->srand(*rb->current_tick); + + /* reset card positions */ + dealer_x = 4; + dealer_y = LCD_HEIGHT/4 - CARD_HEIGHT/2; + player_x = 4; + player_y = LCD_HEIGHT - LCD_HEIGHT/4 - CARD_HEIGHT/2; + + /* check for resumed game */ + if(bj->resume) return; + + /* reset scoring */ + bj->player_total = 0; + bj->dealer_total = 0; + bj->num_player_cards[0] = 2; + bj->num_player_cards[1] = 0; + bj->num_dealer_cards = 2; + bj->end_hand = false; + bj->split_status = 0; + bj->is_blackjack = false; + bj->asked_insurance = false; +} + +/***************************************************************************** +* blackjack_drawtable() draws the table and some text. +******************************************************************************/ +static void blackjack_drawtable(struct game_context* bj) { + unsigned int w, h, y_loc; + char str[10]; + +#if LCD_HEIGHT <= 64 + rb->lcd_getstringsize("Bet", &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, 2*h + 1, "Bet"); + rb->snprintf(str, 9, "$%d", bj->current_bet); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, 3*h + 1, str); + y_loc = LCD_HEIGHT/2; +#else + rb->lcd_getstringsize("Bet", &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, 5*h / 2, "Bet"); + rb->snprintf(str, 9, "$%d", bj->current_bet); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, 7*h / 2, str); + rb->lcd_hline(0, LCD_WIDTH, LCD_HEIGHT/2); + y_loc = LCD_HEIGHT/2 + h; +#endif + + rb->lcd_putsxy(0,0, "Dealer"); + rb->lcd_getstringsize("Player", &w, &h); + rb->lcd_putsxy(0, y_loc, "Player"); + rb->lcd_getstringsize("Total", &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, y_loc, "Total"); + rb->lcd_getstringsize("Money", &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, 0, "Money"); + rb->snprintf(str, 9, "$%d", bj->player_money - bj->current_bet); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, h + 1, str); + rb->snprintf(str, 3, "%d", bj->player_total); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, y_loc + h, str); +} + +/***************************************************************************** +* find_value() is passed a card and returns its blackjack value. +******************************************************************************/ +static unsigned int find_value(unsigned int number) { + unsigned int thisValue; + if (number == 0) + thisValue = 11; /* Aces get a value of 11 at first */ + else if (number < 10) + thisValue = number + 1; + else + thisValue = 10; /* Anything 10 or higher gets a value of 10 */ + + return thisValue; +} + +/***************************************************************************** +* draw_card() draws a card to the screen. +******************************************************************************/ +static void draw_card(struct card temp_card, bool shown, unsigned int x, + unsigned int y) { + if(shown) + rb->lcd_bitmap_part(solitaire_deck, CARD_WIDTH*temp_card.num, + CARD_HEIGHT*temp_card.suit, BMPWIDTH_solitaire_deck, + x+1, y+1, CARD_WIDTH, CARD_HEIGHT); + else + rb->lcd_bitmap(solitaire_cardback, x+1, y+1,CARD_WIDTH, CARD_HEIGHT); +#if LCD_DEPTH > 1 + rb->lcd_set_foreground(LCD_BLACK); +#endif + + /* Print outlines */ +#if CARD_WIDTH >= 26 + rb->lcd_hline(x+2, x+CARD_WIDTH-1, y); + rb->lcd_hline(x+2, x+CARD_WIDTH-1, y+CARD_HEIGHT+1); + rb->lcd_vline(x, y+2, y+CARD_HEIGHT-3); + rb->lcd_vline(x+CARD_WIDTH+1, y+2, y+CARD_HEIGHT-1); + rb->lcd_drawpixel(x+1, y+1); + rb->lcd_drawpixel(x+1, y+CARD_HEIGHT); + rb->lcd_drawpixel(x+CARD_WIDTH, y+1); + rb->lcd_drawpixel(x+CARD_WIDTH, y+CARD_HEIGHT); +#else + rb->lcd_hline(x+1, x+CARD_WIDTH, y); + rb->lcd_hline(x+1, x+CARD_WIDTH, y+CARD_HEIGHT+1); + rb->lcd_vline(x, y+1, y+CARD_HEIGHT); + rb->lcd_vline(x+CARD_WIDTH+1, y+1, y+CARD_HEIGHT); +#endif + +#if LCD_DEPTH > 1 + rb->lcd_set_foreground(FG_COLOR); +#endif +} + +/***************************************************************************** +* new_card() initializes a new card and gives it values. +******************************************************************************/ +static struct card new_card(void) { + struct card new_card; + new_card.suit = rb->rand()%4; /* Random number 0-3 */ + new_card.num = rb->rand()%13; /* Random number 0-12 */ + new_card.value = find_value(new_card.num); + new_card.is_soft_ace = new_card.num == 0 ? true : false; + return new_card; +} + +/***************************************************************************** +* deal_init_card() deals and draws to the screen the player's and dealer's +* initial cards. +******************************************************************************/ +static void deal_init_cards(struct game_context* bj) { + bj->dealer_cards[0] = new_card(); + bj->dealer_total += bj->dealer_cards[0].value; + + draw_card(bj->dealer_cards[0], false, dealer_x, dealer_y); + + bj->dealer_cards[1] = new_card(); + bj->dealer_total += bj->dealer_cards[1].value; + draw_card(bj->dealer_cards[1], true, dealer_x + CARD_WIDTH + 4, dealer_y); + + bj->player_cards[0][0] = new_card(); + bj->player_total += bj->player_cards[0][0].value; + draw_card(bj->player_cards[0][0], true, player_x, player_y); + player_x += CARD_WIDTH + 4; + + bj->player_cards[0][1] = new_card(); + bj->player_total += bj->player_cards[0][1].value; + draw_card(bj->player_cards[0][1], true, player_x, player_y); + player_x += CARD_WIDTH + 4; +} + +/***************************************************************************** +* redraw_board() redraws all the cards and the board +******************************************************************************/ +static void redraw_board(struct game_context* bj) { + unsigned int i, n, upper_bound; + rb->lcd_clear_display(); + + blackjack_drawtable(bj); + player_x = 4; + dealer_x = 4; + upper_bound = bj->split_status > 1 ? 2 : 1; + + for (i = 0; i < bj->num_dealer_cards; i++) { + if (!bj->end_hand) { + draw_card(bj->dealer_cards[0], false, dealer_x, dealer_y); + + /* increment i so the dealer's first card isn't displayed */ + i++; + dealer_x += CARD_WIDTH + 4; + } + draw_card(bj->dealer_cards[i], true, dealer_x, dealer_y); + + if (bj->num_dealer_cards > MAX_CARDS-1) + dealer_x += 10; + else + dealer_x += CARD_WIDTH + 4; + } + + for (n = 0; n < upper_bound; n++) { + for (i = 0; i < bj->num_player_cards[n]; i++) { + draw_card(bj->player_cards[n][i], true, player_x, player_y); + if (bj->split_status>1 || bj->num_player_cards[n]>MAX_CARDS) + player_x += 10; + else + player_x += CARD_WIDTH + 4; + } + if (bj->split_status > 1) + player_x = LCD_WIDTH/2 + 4; + } +} + +/***************************************************************************** +* update_total updates the player's total +******************************************************************************/ +static void update_total(struct game_context* bj) { + char total[3]; + unsigned int w, h; + rb->snprintf(total, 3, "%d", bj->player_total); + rb->lcd_getstringsize(total, &w, &h); +#if LCD_HEIGHT > 64 + h *= 2; +#endif + rb->lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2 + h, total); + rb->lcd_update_rect(LCD_WIDTH - w, LCD_HEIGHT/2 + h, w, h); +} + + +/***************************************************************************** +* check_for_aces() is passed an array of cards and returns where an ace is +* located. Otherwise, returns -1. +******************************************************************************/ +static signed int check_for_aces(struct card temp_cards[], + unsigned int size) { + unsigned int i; + for(i = 0; i < size; i++) { + if (temp_cards[i].is_soft_ace == true) + return i; + } + return -1; +} + +/***************************************************************************** +* check_totals() compares player and dealer totals. +* 0: bust 1: loss, 2: push, 3: win, 4: blackjack, 5: something's not right... +******************************************************************************/ +static unsigned int check_totals(struct game_context* bj) +{ + unsigned int temp; + if (bj->player_total > 21) + temp = 0; + else if (bj->player_total == 21 && bj->is_blackjack) + if (bj->dealer_total == 21 && bj->num_dealer_cards == 2) + temp = 2; + else + temp = 4; + else if (bj->player_total == bj->dealer_total) + temp = 2; + else if (bj->dealer_total > 21 && bj->player_total < 22) + temp = 3; + else if (bj->dealer_total > bj->player_total) + temp = 1; + else if (bj->player_total > bj->dealer_total) + temp = 3; + else + temp = 5; + + return temp; +} + +/***************************************************************************** +* finish_dealer() draws cards for the dealer until he has 17 or more. +******************************************************************************/ +static void finish_dealer(struct game_context* bj) { + signed int temp = 0; + + if (bj->dealer_total > 16 && bj->dealer_total < 22) + return; + + while (bj->dealer_total < 17) { + bj->dealer_cards[bj->num_dealer_cards] = new_card(); + bj->dealer_total += bj->dealer_cards[bj->num_dealer_cards].value; + bj->num_dealer_cards++; + } + + while (bj->dealer_total > 21) { + temp = check_for_aces(bj->dealer_cards, bj->num_dealer_cards); + if(temp != -1) { + bj->dealer_cards[temp].is_soft_ace = false; + bj->dealer_total -= 10; + } + else + return; + } +} + +/***************************************************************************** +* finish_game() completes the game once player's turn is over. +******************************************************************************/ +static void finish_game(struct game_context* bj) { + unsigned int rValue, w, h; + char str[19]; + + do { + finish_dealer(bj); + } while (bj->dealer_total < 17); + + redraw_board(bj); + rValue = check_totals(bj); + + if (rValue == 0) { + rb->snprintf(str, sizeof(str), " Bust! "); + bj->player_money -= bj->current_bet; + } + else if (rValue == 1) { + rb->snprintf(str, sizeof(str), " Sorry, you lost. "); + bj->player_money -= bj->current_bet; + } + else if (rValue == 2) { + rb->snprintf(str, sizeof(str), " Push "); + } + else if (rValue == 3) { + rb->snprintf(str, sizeof(str), " You won! "); + bj->player_money+= bj->current_bet; + } + else { + rb->snprintf(str, sizeof(str), " Blackjack! "); + bj->player_money += bj->current_bet * 3 / 2; + } + rb->lcd_getstringsize(str, &w, &h); + +#if LCD_HEIGHT <= 64 + rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID); + rb->lcd_fillrect(0, LCD_HEIGHT/2, LCD_WIDTH, LCD_HEIGHT/2); + rb->lcd_set_drawmode(DRMODE_SOLID); + rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + h, str); + rb->snprintf(str, 12, "You have %d", bj->player_total); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2, str); +#else + rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h/2, str); +#endif + rb->lcd_update(); +} + +/***************************************************************************** +* blackjack_recordscore() inserts a high score into the high scores list and +* returns the high score position. +******************************************************************************/ +static unsigned int blackjack_recordscore(struct game_context* bj) { + unsigned int i; + unsigned int position = 0; + signed short current, temp; + + /* calculate total score */ + current = bj->player_money; + if(current <= 10) return 0; + + /* insert the current score into the high scores */ + for(i=0; i= bj->highscores[i]) { + if(!position) { + position = i+1; + bj->dirty = true; + } + temp = bj->highscores[i]; + bj->highscores[i] = current; + current = temp; + } + } + + return position; +} + +/***************************************************************************** +* blackjack_loadscores() loads the high scores saved file. +******************************************************************************/ +static void blackjack_loadscores(struct game_context* bj) { + signed int fd; + + bj->dirty = false; + + /* clear high scores */ + rb->memset(bj->highscores, 0, sizeof(bj->highscores)); + + /* open scores file */ + fd = rb->open(SCORE_FILE, O_RDONLY); + if(fd < 0) return; + + /* read in high scores */ + if(rb->read(fd, bj->highscores, sizeof(bj->highscores)) <= 0) { + /* scores are bad, reset */ + rb->memset(bj->highscores, 0, sizeof(bj->highscores)); + } + + rb->close(fd); +} + +/***************************************************************************** +* blackjack_savescores() saves the high scores saved file. +******************************************************************************/ +static void blackjack_savescores(struct game_context* bj) { + unsigned int fd; + + /* write out the high scores to the save file */ + fd = rb->open(SCORE_FILE, O_WRONLY|O_CREAT); + rb->write(fd, bj->highscores, sizeof(bj->highscores)); + rb->close(fd); + bj->dirty = false; +} + +/***************************************************************************** +* blackjack_loadgame() loads the saved game and returns load success. +******************************************************************************/ +static bool blackjack_loadgame(struct game_context* bj) { + 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, &bj->player_money, sizeof(bj->player_money)) <= 0) break; + if(rb->read(fd, &bj->player_total, sizeof(bj->player_total)) <= 0) break; + if(rb->read(fd, &bj->dealer_total, sizeof(bj->dealer_total)) <= 0) break; + if(rb->read(fd, &bj->num_player_cards, sizeof(bj->num_player_cards))<=0) + break; + if(rb->read(fd, &bj->num_dealer_cards, sizeof(bj->num_dealer_cards))<=0) + break; + if(rb->read(fd, &bj->current_bet, sizeof(bj->current_bet)) <= 0) break; + if(rb->read(fd, &bj->is_blackjack, sizeof(bj->is_blackjack)) <= 0) break; + if(rb->read(fd, &bj->split_status, sizeof(bj->split_status)) <= 0) break; + if(rb->read(fd, &bj->asked_insurance, sizeof(bj->asked_insurance)) <= 0) + break; + if(rb->read(fd, &bj->end_hand, sizeof(bj->end_hand)) <= 0) break; + if(rb->read(fd, &bj->player_cards, sizeof(bj->player_cards)) <= 0) break; + if(rb->read(fd, &bj->dealer_cards, sizeof(bj->dealer_cards)) <= 0) break; + bj->resume = true; + loaded = true; + break; + } + + rb->close(fd); + + /* delete saved file */ + rb->remove(SAVE_FILE); + return loaded; +} + +/***************************************************************************** +* blackjack_savegame() saves the current game state. +******************************************************************************/ +static void blackjack_savegame(struct game_context* bj) { + unsigned int fd; + + /* write out the game state to the save file */ + fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT); + rb->write(fd, &bj->player_money, sizeof(bj->player_money)); + rb->write(fd, &bj->player_total, sizeof(bj->player_total)); + rb->write(fd, &bj->dealer_total, sizeof(bj->dealer_total)); + rb->write(fd, &bj->num_player_cards, sizeof(bj->num_player_cards)); + rb->write(fd, &bj->num_dealer_cards, sizeof(bj->num_dealer_cards)); + rb->write(fd, &bj->current_bet, sizeof(bj->current_bet)); + rb->write(fd, &bj->is_blackjack, sizeof(bj->is_blackjack)); + rb->write(fd, &bj->split_status, sizeof(bj->split_status)); + rb->write(fd, &bj->asked_insurance, sizeof(bj->asked_insurance)); + rb->write(fd, &bj->end_hand, sizeof(bj->end_hand)); + rb->write(fd, &bj->player_cards, sizeof(bj->player_cards)); + rb->write(fd, &bj->dealer_cards, sizeof(bj->dealer_cards)); + rb->close(fd); + + bj->resume = true; +} + +/***************************************************************************** +* blackjack_callback() is the default event handler callback which is called +* on usb connect and shutdown. +******************************************************************************/ +static void blackjack_callback(void* param) { + struct game_context* bj = (struct game_context*) param; + if(bj->dirty) { + rb->splash(HZ, true, "Saving high scores..."); + blackjack_savescores(bj); + } +} + +/***************************************************************************** +* blackjack_get_yes_no() gets a yes/no answer from the user +******************************************************************************/ +static unsigned int blackjack_get_yes_no(char message[20]) { + int button; + unsigned int w, h, b, choice = 0; + bool breakout = false; + char message_yes[24], message_no[24]; + + rb->strcpy(message_yes, message); + rb->strcpy(message_no, message); + rb->strcat(message_yes, " Yes"); + rb->strcat(message_no, " No"); + rb->lcd_getstringsize(message_yes, &w, &h); + const char *stg[] = {message_yes, message_no}; + +#if LCD_HEIGHT <= 64 + b = 2*h+1; +#else + b = h-1; +#endif + +#ifdef HAVE_LCD_COLOR + rb->lcd_fillrect(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b, w+1, h+3); + rb->lcd_set_foreground(LCD_BLACK); + rb->lcd_set_background(LCD_WHITE); +#else + rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID); + rb->lcd_fillrect(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b, w+1, h+3); + rb->lcd_set_drawmode(DRMODE_SOLID); +#endif + rb->lcd_drawrect(LCD_WIDTH/2 - w/2 - 1, LCD_HEIGHT/2 + b - 1, w+3, h+4); + + while(!breakout) { + rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b +1, stg[choice]); + rb->lcd_update_rect(LCD_WIDTH/2 - w/2 - 1, LCD_HEIGHT/2 + b -1, + w+3, h+4); + button = rb->button_get(true); + + switch(button) { + case BJACK_LEFT: + case (BJACK_LEFT|BUTTON_REPEAT): + case BJACK_RIGHT: + case (BJACK_RIGHT|BUTTON_REPEAT): + choice ^= 1; + break; + case BJACK_START: breakout = true; + break; + case BJACK_QUIT: breakout = true; + choice = BJ_QUIT; + break; + } + } + +#if LCD_DEPTH > 1 + rb->lcd_set_foreground(FG_COLOR); + rb->lcd_set_background(BG_COLOR); +#endif + return choice; +} + +/***************************************************************************** +* blackjack_get_amount() gets an amount from the player to be used +******************************************************************************/ +static signed int blackjack_get_amount(char message[20], signed int lower_limit, + signed int upper_limit, + signed int start) { + int button; + char str[6]; + bool changed = false; + unsigned int w, h; + signed int amount; + + rb->lcd_getstringsize("A", &w, &h); /* find the size of one character */ + + if (start > upper_limit) + amount = upper_limit; + else if (start < lower_limit) + amount = lower_limit; + else + amount = start; + +#if LCD_DEPTH > 1 + rb->lcd_set_background(LCD_WHITE); + rb->lcd_set_foreground(LCD_BLACK); +#endif + +#if LCD_HEIGHT <= 64 + rb->lcd_clear_display(); + rb->lcd_puts(0, 1, message); + rb->snprintf(str, 9, "$%d", amount); + rb->lcd_puts(0, 2, str); + rb->lcd_puts(0, 3, "RIGHT: +1"); + rb->lcd_puts(0, 4, "LEFT: -1"); + rb->lcd_puts(0, 5, "UP: +10"); + rb->lcd_puts(0, 6, "DOWN: -10"); + rb->lcd_update(); +#else + rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID); + rb->lcd_fillrect(LCD_WIDTH/2 - 9*w - 1, LCD_HEIGHT/2 - 4*h - 3, 37*w / 2, + 8*h -3); + rb->lcd_set_drawmode(DRMODE_SOLID); + rb->lcd_drawrect(LCD_WIDTH/2 - 9*w - 1, LCD_HEIGHT/2 - 4*h - 3, 37*w / 2, + 8*h -3); + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 4*h - 1, message); + rb->snprintf(str, 9, "$%d", amount); + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, str); +#if (CONFIG_KEY == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, " >>|: +1"); + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, " |<<: -1"); + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "SCROLL+: +10"); + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "SCROLL-: -10"); +#elif CONFIG_KEYPAD == IRIVER_H10_PAD + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, "RIGHT: +1"); + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, "LEFT: -1"); + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "SCROLL+: +10"); + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "SCROLL-: -10"); +#else + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, "RIGHT: +1"); + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, "LEFT: -1"); + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "UP: +10"); + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "DOWN: -10"); +#endif + rb->lcd_update_rect(LCD_WIDTH/2 - 9*w - 2, LCD_HEIGHT/2 - 9*h/2, 37*w/2 + 1, + 8*h-2); +#endif + + while(true) { + button = rb->button_get(true); + + switch(button) { + case BJACK_UP: + case (BJACK_UP|BUTTON_REPEAT): + if (amount + 10 < upper_limit + 1) { + amount += 10; + changed = true; + } + break; + case BJACK_DOWN: + case (BJACK_DOWN|BUTTON_REPEAT): + if (amount - 10 > lower_limit - 1) { + amount -= 10; + changed = true; + } + break; + case BJACK_RIGHT: + case (BJACK_RIGHT|BUTTON_REPEAT): + if (amount + 1 < upper_limit + 1) { + amount++; + changed = true; + } + break; + case BJACK_LEFT: + case (BJACK_LEFT|BUTTON_REPEAT): + if (amount - 1 > lower_limit - 1) { + amount--; + changed = true; + } + break; + case BJACK_MAX : + amount = upper_limit; + changed = true; + break; + case BJACK_MIN : + amount = lower_limit; + changed = true; + break; + case BJACK_QUIT: + return 0; + case BJACK_START: +#if LCD_DEPTH > 1 + rb->lcd_set_foreground(FG_COLOR); + rb->lcd_set_background(BG_COLOR); +#endif + rb->lcd_clear_display(); + return amount; + } + + if(changed) { + rb->snprintf(str, 9, "$%d", amount); +#if LCD_HEIGHT <= 64 + rb->lcd_puts(0, 2, str); + rb->lcd_update(); +#else + rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID); + rb->lcd_fillrect(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, 5*w, h); + rb->lcd_set_drawmode(DRMODE_SOLID); + rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, str); + rb->lcd_update_rect(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, 5*w, h); +#endif + changed = false; + } + } +} + +/***************************************************************************** +* blackjack_get_bet() gets the player's bet. +******************************************************************************/ +static void blackjack_get_bet(struct game_context* bj) { + bj->current_bet = blackjack_get_amount("Please enter a bet", 10, + bj->player_money, bj->current_bet); +} + +/***************************************************************************** +* double_down() returns one final card then finishes the game +******************************************************************************/ +static void double_down(struct game_context* bj) { + bj->current_bet *= 2; + bj->player_cards[0][bj->num_player_cards[0]] = new_card(); + bj->player_total += bj->player_cards[0][bj->num_player_cards[0]].value; + bj->num_player_cards[0]++; +} + +/***************************************************************************** +* split() checks if the player wants to split and acts accordingly. +* When bj->split_status is 1, no split occurred. 2 means the player split and 3 +* means a split has already occurred and the first hand is done. +******************************************************************************/ +static void split(struct game_context* bj) { + if (blackjack_get_yes_no("Split?") == 1) + bj->split_status = 1; + else { + bj->split_status = 2; + bj->current_bet *= 2; + bj->num_player_cards[0] = 1; + bj->num_player_cards[1] = 1; + bj->player_cards[1][0] = bj->player_cards[0][1]; + bj->player_total = bj->player_cards[0][0].value; + } +} + +/***************************************************************************** +* insurance() see if the player wants to buy insurance and how much. +******************************************************************************/ +static unsigned int insurance(struct game_context* bj) { + unsigned int insurance, max_amount; + + insurance = blackjack_get_yes_no("Buy Insurance?"); + bj->asked_insurance = true; + max_amount = bj->current_bet < (unsigned int)bj->player_money ? + bj->current_bet/2 : (unsigned int)bj->player_money; + if (insurance == 1) return 0; + + insurance = blackjack_get_amount("How much?", 0, max_amount, 0); + redraw_board(bj); + return insurance; +} + +/***************************************************************************** +* play_again() checks to see if the player wants to keep playing. +******************************************************************************/ +static unsigned int play_again(void) { + return blackjack_get_yes_no("Play Again?"); +} + +/***************************************************************************** +* blackjack_menu() is the initial menu at the start of the game. +******************************************************************************/ +static unsigned int blackjack_menu(struct game_context* bj) { + int button; + char *title = "Blackjack"; + char str[18]; + unsigned int i, w, h; + bool breakout = false; + bool showscores = false; + + while(true){ +#if LCD_DEPTH > 1 + rb->lcd_set_background(BG_COLOR); + rb->lcd_set_foreground(FG_COLOR); +#endif + rb->lcd_clear_display(); + + if(!showscores) { + /* welcome screen to display key bindings */ + rb->lcd_getstringsize(title, &w, &h); + rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, title); + +#if CONFIG_KEYPAD == RECORDER_PAD + rb->lcd_puts(0, 1, "ON: start"); + rb->lcd_puts(0, 2, "OFF: exit"); + rb->lcd_puts(0, 3, "F1: hit"); + rb->lcd_puts(0, 4, "F2: stay"); + rb->lcd_puts(0, 5, "F3: double down"); + rb->lcd_puts(0, 6, "PLAY: save/resume"); + rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]); + rb->lcd_puts(0, 7, str); +#elif CONFIG_KEYPAD == ONDIO_PAD + rb->lcd_puts(0, 1, "MENU: start"); + rb->lcd_puts(0, 2, "OFF: exit"); + rb->lcd_puts(0, 3, "LEFT: hit"); + rb->lcd_puts(0, 4, "RIGHT: stay"); + rb->lcd_puts(0, 5, "UP: double down"); + rb->lcd_puts(0, 6, "DOWN: save/resume"); + rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]); + rb->lcd_puts(0, 7, str); +#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) + rb->lcd_puts(0, 2, "PLAY to start & to hit"); + rb->lcd_puts(0, 3, "STOP to exit"); + rb->lcd_puts(0, 4, "REC to stay"); + rb->lcd_puts(0, 5, "NAVI to double down "); + rb->lcd_puts(0, 6, " & to view highscores"); + rb->lcd_puts(0, 7, "AB to save/resume"); + rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]); + rb->lcd_puts(0, 8, str); +#elif CONFIG_KEYPAD == IRIVER_H10_PAD + rb->lcd_puts(0, 2, "PLAY to start & hit"); + rb->lcd_puts(0, 3, "POWER to exit"); + rb->lcd_puts(0, 4, ">>| to stay"); + rb->lcd_puts(0, 5, "|<< to double down"); + rb->lcd_puts(0, 6, "LEFT to view scores"); + rb->lcd_puts(0, 7, "RIGHT to save/resume"); + rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]); + rb->lcd_puts(0, 8, str); + +#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) +#if LCD_WIDTH >=176 + rb->lcd_puts(0, 2, "SELECT to start & to hit"); + rb->lcd_puts(0, 3, "MENU to exit"); + rb->lcd_puts(0, 4, ">>| to stay & to view highscores"); + rb->lcd_puts(0, 5, "|<< to double down"); + rb->lcd_puts(0, 6, "PLAY to save/resume"); + rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]); + rb->lcd_puts(0, 7, str); +#else + rb->lcd_puts(0, 2, "SELECT to start & to "); + rb->lcd_puts(0, 3, " hit"); + rb->lcd_puts(0, 4, "MENU to exit"); + rb->lcd_puts(0, 5, ">>| to stay & to view "); + rb->lcd_puts(0, 6, " highscores"); + rb->lcd_puts(0, 7, "|<< to double down"); + rb->lcd_puts(0, 8, "PLAY to save/resume"); + rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]); + rb->lcd_puts(0, 9, str); +#endif +#elif CONFIG_KEYPAD == IAUDIO_X5_PAD + rb->lcd_puts(0, 2, "PLAY to start to hit"); + rb->lcd_puts(0, 3, "POWER to exit"); + rb->lcd_puts(0, 4, "SELECT to hit"); + rb->lcd_puts(0, 5, "REC to stay"); + rb->lcd_puts(0, 6, "PLAY to double down"); + rb->lcd_puts(0, 7, "RIGHT to view highscores "); + rb->lcd_puts(0, 8, "DOWN to save/resume"); + rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]); + rb->lcd_puts(0, 9, str); +#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD + rb->lcd_puts(0, 2, "AB to start & to"); + rb->lcd_puts(0, 3, " stay"); + rb->lcd_puts(0, 4, "EQ to hit"); + rb->lcd_puts(0, 5, "PLAY to exit"); + rb->lcd_puts(0, 6, "CLICK to double down"); + rb->lcd_puts(0, 7, "& to view highscores"); + rb->lcd_puts(0, 8, "AB+EQ to save/resume"); + rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]); + rb->lcd_puts(0, 9, str); +#elif CONFIG_KEYPAD == GIGABEAT_PAD + rb->lcd_puts(0, 2, "POWER to start"); + rb->lcd_puts(0, 3, "A to exit"); + rb->lcd_puts(0, 4, "VOL+ to hit"); + rb->lcd_puts(0, 5, "VOL- to stay"); + rb->lcd_puts(0, 6, "CENTER to double down"); + rb->lcd_puts(0, 6, "RIGHT to view highscores "); + rb->lcd_puts(0, 8, "MENU to save/resume"); + rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]); + rb->lcd_puts(0, 9, str); +#elif (CONFIG_KEYPAD == SANSA_E200_PAD) + rb->lcd_puts(0, 2, "SELECT to start & to hit"); + rb->lcd_puts(0, 3, "POWER to exit"); + rb->lcd_puts(0, 4, "RIGHT to stay"); + rb->lcd_puts(0, 5, "LEFT to double down"); + rb->lcd_puts(0, 6, "REC to save/resume"); + rb->lcd_puts(0, 7, "UP to view scores"); + rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]); + rb->lcd_puts(0, 8, str); + +#endif + } else { + rb->snprintf(str, 12, "%s", "High Scores"); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, str); + + /* print high scores */ + for(i=0; isnprintf(str, 14, "#%02d: $%d", i+1, bj->highscores[i]); + rb->lcd_puts(0, i+1, str); + } + } + + rb->lcd_update(); + + /* handle menu button presses */ + button = rb->button_get(true); + + switch(button) { + case BJACK_START: /* start playing */ + breakout = true; + break; + + case BJACK_QUIT: /* quit program */ + if(showscores) { + showscores = 0; + break; + } + return BJ_QUIT; + + case BJACK_RESUME:/* resume game */ + if(!blackjack_loadgame(bj)) { + rb->splash(HZ*2, true, "Nothing to resume"); + } else { + rb->splash(HZ*2, true, "Loading..."); + breakout = true; + } + break; + + case BJACK_SCORES:/* toggle high scores */ + showscores = !showscores; + break; + + default: + if(rb->default_event_handler_ex(button, blackjack_callback, + (void*) bj) == SYS_USB_CONNECTED) + return BJ_USB; + break; + } + + if(breakout) break; + } + + return(0); +} + +/***************************************************************************** +* blackjack() is the main game subroutine, it returns the final game status. +******************************************************************************/ +static int blackjack(struct game_context* bj) { + int button; + unsigned int w, h, temp_var, done = 0, todo = 1; + signed int temp; + bool breakout = false; + bool dbl_down = false; + + /* don't resume by default */ + bj->resume = false; + + /******************** + * menu * + ********************/ + temp_var = blackjack_menu(bj); + if (temp_var == BJ_QUIT || temp_var == BJ_USB) + return temp_var; + + + /******************** + * init * + ********************/ + blackjack_init(bj); + bj->current_bet=10; + + /******************** + * play * + ********************/ + + /* check for resumed game */ + if(bj->resume) { + bj->resume = false; + redraw_board(bj); + if (bj->split_status == 2) { + todo=2; + player_x = bj->num_player_cards[0] * 10 + 4; + } + else if (bj->split_status == 3) { + player_x = bj->num_player_cards[1] * 10 + LCD_WIDTH/2 + 4; + todo=2; + done=1; + } + + } + else { + bj->player_money = 1000; + blackjack_get_bet(bj); + if (bj->current_bet == 0) + return BJ_QUIT; + rb->lcd_clear_display(); + deal_init_cards(bj); + blackjack_drawtable(bj); + } + + rb->lcd_update(); + + breakout = false; + + while(true){ + if(bj->player_total == 21 && bj->num_player_cards[0] == 2) { + bj->is_blackjack = true; + bj->end_hand = true; + finish_game(bj); + } + else if(bj->dealer_cards[1].is_soft_ace && !breakout && + !bj->asked_insurance) { + temp_var = insurance(bj); + if (bj->dealer_total == 21) { + rb->splash(HZ, true, "Dealer has blackjack"); + bj->player_money += temp_var; + bj->end_hand = true; + breakout = true; + redraw_board(bj); + finish_game(bj); + } + else { + rb->splash(HZ, true, "Dealer does not have blackjack"); + bj->player_money -= temp_var; + breakout = true; + redraw_board(bj); + rb->lcd_update(); + } + } + if(bj->split_status == 0 && + bj->player_cards[0][0].num == bj->player_cards[0][1].num) { + split(bj); + redraw_board(bj); + rb->lcd_update_rect(0, LCD_HEIGHT/2, LCD_WIDTH, LCD_HEIGHT/2); + if (bj->split_status == 2) { + todo++; + player_x = bj->num_player_cards[0] * 10 + 4; + } + } + + while(done < todo) { + button = rb->button_get(true); + + switch(button) { + case BJACK_HIT: + NEXT_CARD = new_card(); + bj->player_total += NEXT_CARD.value; + draw_card(NEXT_CARD, true, player_x, player_y); + bj->num_player_cards[done]++; + if (bj->num_player_cards[done] == MAX_CARDS + 1) { + redraw_board(bj); + rb->lcd_update_rect(0, LCD_HEIGHT/2, LCD_WIDTH, + LCD_HEIGHT/2); + } + else if (bj->num_player_cards[done]>MAX_CARDS || todo > 1) { + rb->lcd_update_rect(player_x, player_y, CARD_WIDTH+2, + CARD_HEIGHT+2); + player_x += 10; + } + else { + rb->lcd_update_rect(player_x, player_y, CARD_WIDTH+2, + CARD_HEIGHT+2); + player_x += CARD_WIDTH + 4; + } + update_total(bj); + + break; + case BJACK_STAY: + bj->end_hand = true; + break; + case BJACK_DOUBLEDOWN: + if ((signed int)bj->current_bet * 2 < bj->player_money + 1 && + bj->num_player_cards[0]==2 && todo==1) { + double_down(bj); + dbl_down = true; + if (bj->player_total < 22) { + bj->end_hand = true; + finish_game(bj); + } + } + else if((signed int)bj->current_bet * 2 > bj->player_money) { + rb->splash(HZ, true, "Not enough money to double down."); + redraw_board(bj); + rb->lcd_update(); + } + break; + case BJACK_RESUME: /* save and end game */ + rb->splash(HZ, true, "Saving game..."); + blackjack_savegame(bj); + /* fall through to BJACK_QUIT */ + + case BJACK_QUIT: + return BJ_END; + } + + while (bj->player_total > 21 && !bj->end_hand) { + temp = check_for_aces(bj->player_cards[done], + bj->num_player_cards[done]); + if(temp != -1) { + bj->player_cards[done][temp].is_soft_ace = false; + bj->player_total -= 10; + update_total(bj); + if (dbl_down) { + bj->end_hand = true; + finish_game(bj); + } + } + else + bj->end_hand = true; + } + + if (bj->end_hand) { + done++; + if(todo > 1) { + if (done == 2) { + temp = bj->player_total; + bj->player_total = temp_var; + temp_var = temp; + finish_game(bj); + rb->lcd_getstringsize(" Split 1 ", &w, &h); + rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, + " Split 1 "); + rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, + w,h); + bj->current_bet /= 2; + rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, + w,h); + rb->sleep(HZ*2); + bj->player_total = temp_var; + finish_game(bj); + rb->lcd_getstringsize(" Split 2 ", &w, &h); + rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, + " Split 2 "); + rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, + w,h); + rb->sleep(HZ*2); + } + else { + bj->end_hand = false; + bj->split_status = 3; + temp_var = bj->player_total; + bj->player_total = bj->player_cards[1][0].value; + update_total(bj); + redraw_board(bj); + player_x += 10; + rb->lcd_update(); + } + } + else + finish_game(bj); + } + } + + if (bj->player_money < 10) { + rb->sleep(HZ); + return BJ_LOSE; + } + + if (bj->end_hand) { /* If hand is over */ + if (play_again() != 0) /* User wants to quit */ + return BJ_END; + else { /* User keeps playing */ + breakout = false; + redraw_board(bj); + if(dbl_down) { + bj->current_bet /= 2; + dbl_down = false; + } + done = 0; + todo = 1; + blackjack_init(bj); + blackjack_get_bet(bj); + if (bj->current_bet == 0) + return BJ_END; + deal_init_cards(bj); + blackjack_drawtable(bj); + rb->lcd_update(); + } + } + } + /* Never reached */ + return PLUGIN_OK; +} + +/***************************************************************************** +* plugin entry point. +******************************************************************************/ +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { + struct game_context bj; + bool exit = false; + unsigned int position; + char str[19]; + + (void)parameter; + rb = api; + + /* load high scores */ + blackjack_loadscores(&bj); + + rb->lcd_setfont(FONT_SYSFIXED); + + while(!exit) { + switch(blackjack(&bj)){ + case BJ_LOSE: + rb->splash(HZ, true, "Not enough money to continue"); + /* fall through to BJ_END */ + + case BJ_END: + if(!bj.resume) { + if((position = blackjack_recordscore(&bj))) { + rb->snprintf(str, 19, "New high score #%d!", position); + rb->splash(HZ*2, true, str); + } + } + break; + + case BJ_USB: + rb->lcd_setfont(FONT_UI); + return PLUGIN_USB_CONNECTED; + + case BJ_QUIT: + if(bj.dirty) { + rb->splash(HZ, true, "Saving high scores..."); + blackjack_savescores(&bj); + } + exit = true; + break; + + default: + break; + } + } + + rb->lcd_setfont(FONT_UI); + return PLUGIN_OK; +} diff --git a/manual/plugins/blackjack.tex b/manual/plugins/blackjack.tex new file mode 100644 index 0000000000..7a7caa491a --- /dev/null +++ b/manual/plugins/blackjack.tex @@ -0,0 +1,81 @@ +\subsection{Blackjack} +\screenshot{plugins/images/ss-blackjack}{Blackjack}{fig:blackjack} + +Blackjack, a game played in casinos around the world, is now available +in the palm of your hand! The rules are simple: try to get as close to 21 +without going over or simply beat out the dealer for the best hand. +Although this may not seem difficult, blackjack is a game renowned for the +strategy involved. This version includes the ability to split, buy insurance, +and double down. + +For the full set of rules to the game, and other facinating information +visit\\ +\url{http://www.blackjackinfo.com/blackjack-rules.php} + +\begin{table} + \begin{btnmap}{}{} + \multicolumn{2}{c}{\textbf{In menu}}\\\hline + \opt{RECORDER_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOn} + \opt{GIGABEAT_PAD}{\ButtonPower} + \opt{IAUDIO_X5_PAD,IRIVER_H10_PAD}{\ButtonPlay} + \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD}{\ButtonSelect} + \opt{ONDIO_PAD}{\ButtonMenu} + & Start new game\\ + \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonMode} + \opt{RECORDER_PAD,IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonPlay} + \opt{ONDIO_PAD,IAUDIO_X5_PAD}{\ButtonDown} + \opt{IRIVER_H10_PAD}{\ButtonRight} + \opt{SANSA_E200_PAD}{\ButtonRec} + \opt{GIGABEAT_PAD}{\ButtonMenu} + & Resume saved game\\ + \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonSelect} + \opt{RECORDER_PAD,IAUDIO_X5_PAD,IPOD_4G_PAD,IPOD_3G_PAD,GIGABEAT_PAD}{\ButtonRight} + \opt{ONDIO_PAD,SANSA_E200_PAD}{\ButtonUp} + \opt{IRIVER_H10_PAD}{\ButtonLeft} + & Show high scores\\ + \opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOff} + \opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu} + \opt{IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD}{\ButtonPower} + \opt{GIGABEAT_PAD}{\ButtonA} + & Quit\\\hline + \multicolumn{2}{c}{\textbf{In game}}\\\hline + \ButtonLeft/\ButtonRight/\\ + \opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,GIGABEAT_PAD} + {\ButtonUp/\ButtonDown} + \opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonScrollFwd/\ButtonScrollBack} + \opt{IRIVER_H10_PAD,SANSA_E200_PAD}{\ButtonScrollUp/\ButtonScrollDown} + & Enter betting amount\\ + \opt{RECORDER_PAD}{\ButtonFOne} + \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOn} + \opt{IRIVER_H10_PAD}{\ButtonPlay} + \opt{IPOD_4G_PAD,IPOD_3G_PAD,IAUDIO_X5_PAD,SANSA_E200_PAD}{\ButtonSelect} + \opt{ONDIO_PAD}{\ButtonLeft} + \opt{GIGABEAT_PAD}{\ButtonVolUp} + & Hit (Draw new card)\\ + \opt{RECORDER_PAD}{\ButtonFTwo} + \opt{IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD}{\ButtonRec} + \opt{IRIVER_H10_PAD}{\ButtonFF} + \opt{ONDIO_PAD,IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD}{\ButtonRight} + \opt{GIGABEAT_PAD}{\ButtonVolDown} + & Stay (End hand)\\ + \opt{RECORDER_PAD}{\ButtonFThree} + \opt{IRIVER_H100_PAD,IRIVER_H300_PAD,GIGABEAT_PAD}{\ButtonSelect} + \opt{IAUDIO_X5_PAD}{\ButtonPlay} + \opt{IRIVER_H10_PAD}{\ButtonRew} + \opt{ONDIO_PAD}{\ButtonUp} + \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD}{\ButtonLeft} + & Double down\\ + \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonMode} + \opt{RECORDER_PAD,IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonPlay} + \opt{ONDIO_PAD,IAUDIO_X5_PAD}{\ButtonDown} + \opt{IRIVER_H10_PAD}{\ButtonRight} + \opt{SANSA_E200_PAD}{\ButtonRec} + \opt{GIGABEAT_PAD}{\ButtonMenu} + & Save game\\ + \opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOff} + \opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu} + \opt{IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD}{\ButtonPower} + \opt{GIGABEAT_PAD}{\ButtonA} + & Return to menu or cancel\\\hline + \end{btnmap} +\end{table} diff --git a/manual/plugins/images/ss-blackjack-112x64x1.png b/manual/plugins/images/ss-blackjack-112x64x1.png new file mode 100644 index 0000000000000000000000000000000000000000..851c80e7c606f89875a0423e1ab38041aee6214c GIT binary patch literal 476 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 literal 0 HcmV?d00001 diff --git a/manual/plugins/images/ss-blackjack-138x110x2.png b/manual/plugins/images/ss-blackjack-138x110x2.png new file mode 100644 index 0000000000000000000000000000000000000000..c1669b354e6afd56b852944f075d9014829655dc GIT binary patch literal 816 zcmV-01JC@4P)r003?T0{{R33VfEs0000mP)t-st=Q&s zkeNA1OaK4?000001ONc|000000000000000000000MGyd0000000000%!p*300009 za7bBm000XU000XU0RWnu7ytkQrb$FWR9J=WmsynKAr?gYtBfO+5En39E(h(WoXVgRSaoO5K#v=D?$ zT@pAMJY37iZplmMeD9pQY6Zv3jlS+$m_1_k}|6^_vZ_G zi88;aMa#vkV@0z1rJI6V-P|mSBf3bH+MZ)C?*{%lE$x0m*q_RtyFy7b?|^oS*n(gc zlXdZ|lxCKO!P(K!Q|Ujo%-tlTgqutgrDG4Cp6`@D7%{)LnUWM<-n zw=n2kj&jIRa#yzVI!NJ+3yWC9+0Q#*kiyx|7J=q2tb=1o(M67~Oj%c{R2Te`+`F`P u?`flOj6f~2f%+$Rz;m8{a zQ|hvu0w z_zu~|0nVyf<+Qgki@ulM)&$LPk#$llqC`n9>aIX*sq zQTIzJi7wdUWmGk3P>1Dqa)K@RI?37d*j)ZBIq-m0RMwG$On7?Pd{p0Wdo4u!VsDAz z%sOi-x&j+q7p_}cT3npkBlfxEiKgYEh{s*CWbT;fo@L1_j*nhL<0^zfS7UFiZaI5$ z_NehDeUa!n%5~^)7?WRj2IFwJLcP1;;ZN|Sp#c8G3OzGbSA|TjkE74?sfwOGZn$bU zX=#MBFKenVXS*^O48ALBFt{Q?66eXk7<4_|M| zeDN$C%c48B)$Rf=vUM6#I#e8${}X@K9!-ysy44OwiKa#qR?RNlFHHZ zj^lQVIQGW8DoUeF5lhTf`L(HY5&*M=6%~t7|T;5E~i> zZMBDNy{c6wMBgO)CIKC$*l0nLXQl${s=!4g4^xhjN0Fr@qnoZnwmm|sb+s{7l-M+@ zu~_@UPd*WnAKC_LU0Lk_KYpt~u(s2QsyZg}6n%A&hbNZrDU^0X^T${h&V0-z#K(r%0SlfzT#Y+0GQ<0DPK))bJjch10@DVD z?29KD_m8dt1%SL*f#)P9dqorZY=Jtso3iPf*$`25wJjiMGkvC3Z=mY4J1`S{njX)?Vn zsH!}<=p$LKl9j@{ivmx(nnhllWc2W-T5-rj<)sLNl5rP45K`03d>&$!VV)%(-NO^5 zUV=-g$~Z3}*=agY1S|wcpt|p?f)(Pl!JvrZTx68_J)D(S2cPCSWJ3=PM%~-no1T6d z%@2%zqd?!GJt(vo74(@IB%l%tKAj^(rN6=|9h~}^i*?d1qBO*Q>vGV_yt`_Uf`sj{ z-f1rq)RKlTrFJIDuySTHGxUEXYM+(h9%S>SRMeRZd|Gh*|3o8`ETA9C0>YbRKidb# zD~FY>lG()yg%{K*!w2L-zo~AzTA5^nWCKLT3Tv;`ea9OMxvJI^3-gmR7vf`mvsdvuIVo2Cf*rf=3Tyce&>p zck4BI#inHap)TQ`bXMiV!6T_uHTy+Ba$;1Nh?{;m8s(s3d>toT9BYMbzqbcCjm)DQ6v z_OoBvo>=p3)Yoj?cYF5thwtq%on#vlS@_;N>Eu7v)FCsoJ7Q}icJ}(Qs;{^YKh~W( waERG!uJr?TIcHDzCCa#u{GZqN?<3ugC;9cnt~8!pX1+!MV*_)2oSrM004jl0{{R3eocQU0000mP)t-st=Q&s zkeNA1OaK4?0001>2LJ#70HALGkN^Mx-2eap00000000000002$KtTXNNF3#~00009 za7bBm000XU000XU0RWnu7ytkQ-AP12RA_g2Sf%^Bexm~zyN^EPr-rS zb~Se#KmhrI0Yqz&o%!#GH(<5sz>uM0nU1alNFR9QP=*e5By$(gMvwlx*R!7ro9+2W z(ix}s5Q%?n+KdpK)44N#-=(2OcETVpgG^d8_P`s@7SDlAHQlRbtZJYA7 z*$OlkKVJ3a^Gt@#)5)?Ta_Hq>QS_UVH}acD=>XOhih;|%$GGoX1twg3ECgLS8Ms8c zHv#Imb#)m+sK9O6BK?VlYk0g~rKighcQS?x(>Apbi@4eq;|$z)ddRMXx?4&I5b8oe zz{nk@M|BEu+ku>5>(ag~1s3JU~zjgIP$pW%G6U>g6T!7)D>0FQP89m({|w@(gfJ>_~A;;mp7XMT#Ftnc;{O zi${0paeiQ6dOlaOuswaCn6cz+sDE4)2*Y(1WURObX( zk3d#WZ0|nYt^oCwRSnuVa-RUDo)|jn*cTX9pw_W%3_E~!y3tzrsjs(f9awf24Jos+qVqJGu>`B}3D95eV++RuX$&8w6b3$P(*-=e++RQZ1E^jGOxf?{+89>*n!o`- zS^0R;(q?jdSyn+PR#|$uV_Ei3Qsa{*rCo1wkQ!gHNXessV&NEIN@=w*O8m{I@$002ovPDHLkV1iJ}e~JJA literal 0 HcmV?d00001 diff --git a/manual/plugins/images/ss-blackjack-176x132x16.png b/manual/plugins/images/ss-blackjack-176x132x16.png new file mode 100644 index 0000000000000000000000000000000000000000..304373306f0cd9fa7e375f1457d8e9c872bea88f GIT binary patch literal 2433 zcma)8XH*kd7LFmyM3g3oB%p+*EW|;;#DEAWK@GhGq)m_#>4O>xgranUG!-K)QbmoS z1`}G4Whfc~VnjlTgn+b52004N;z=C(w=0%SgkLc#;pt`sXkpgLW zM-l*0j*9P#RsS{>u z#;A6)FQS~>q|b$gKUO`h54{_sM5pjp;H&4xX0~GIQ5QjK8#@LZ-Vg=+m-DI@A6u^` zzb`%udL+x%R#nF-wlgc3-0!*`T$vOpMsva# zoSK?3Y#9uP5-fSCfTx=t3t4AfNihckN)K*eiQGz@&-csU&J3IYfB+$|CH6;EKA?5h z%EMmRe@q~fmX&Q=XwO9L6G~X-H4rC5@1zubQb>G=$7iL20cDa4l@}Z(g5BIxyIpBS0 zLw5o#9IoTmYKRon-~3$w59{D zHF|81KD@VUa0?ovEqg?EKrK#>k}GrGDX8o%w&G^w6=g3=d~n12yd5;{G-gQP3Nd$E zD$YumS&0;hM5OJ@>(*`fYtd~!v7f;n5ko z>6Jsd&`jRo#;{m2S*H6HWT^;!eMm7*6W!RKz|irR#|$y5wbJ?;F(p+QK|fei-~Rf- zaQs6y%v2Novz*Uig?G{!%kQnpIuo&&_lOkdDmWBbmO-gEHL3?Xq)$= zK%+>c3#Ic{ho%vqyYquh^#yMgL3on>`;?9y@$Kmtdy}&yO*is2+J5n(f&BI*oW}H3 z6wPELau`||7){F~Oz%J@)KBdS;+!U0KZ!ZAY*8Yg%ekj~sFKBEe0s&8u-0gd`YIOi zxp!8B?qD?yaR2`0z$hN44RE+5|AD0egTrFwdH2ZG&;=J9PK*g!`kV^~DBp+E=+5(F zV`!}a_)qfih|ig-s<|*f`3yXXkpF~eR!Y^kkKn$5|K3ygtcmM9dqQMOgYT~5hq1?4 z^(0WH$Tg53w}s$l5+`;YT6CN6yb@0(NtJc)_?Y9;gL zx^LgL{WmEeLzDYH=}O)^?s%dP>o)7`YBE@bJbt(VL)9+1*d-6Q*UNznTH|XOnFLYm zGehDA7ML5W%UhuJyM|m^N57P>_N}JV_nS~IS^3DFY2uR1Y+RlMx6zT3e&-`Ft2c8lLF0YH1xOwoUu|Aul&kBDL z|H`VUS7eY3Ov>5(o+x}cAgY}jL(c~yVaBIxM&9rP& zsp%Gz{_SJfF4=B=VSJlEr+#~E!(7V0Yv(y^yj!I`;O z!tm^gd)(xyi0Pfz!tr#NewL7(Y%|iGcs#k;##Ip%T+V?_22nE-T{u3BUD4-@CKWiJ zC6=Cf$cRyi5NND(JJ0vqW_tlU_#69hZ=YAu6BB=9e(!4I{p4Td(FUZ-j<~sF>$(Np zj`2(S;gYPhlH&!Xiv_>w+s;PqAsx~}>PPm5^YZ~;XR87Vse6W|?Q_cpf*X;M!`9u! zrP-=-gJ9nC@&@QPY{wT@iGglD#|FUnlS7*;v-mLCFYHMI>zv=)t; ziXrfAHK4`qjR+&;t=){7!H(f{*~Rj$6?M_ta>G*zW8>F_%R3rWF)7ta&2K@@Vs*)Uu`=J6&%~u7%>_s`N}Mde->}!+OPy`nqgI9TRObGB zgIq{bE{>~}jz@qr+^60h5erLF&b(UlF97~6I1rU|7#z?1#|e0eyoPG0RLUz)WX4sJ zrO(XI3!kxRmOjPkdUm<~&FiK~;7j$u^15SFU^kd}G{}?bVt~I?D$q*mNt{AK5DhFdWJ9*Pm)4$Yeie5)Jl#GjO#a2l|oqBX$_5W(+ d|26kP006)X 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 literal 0 HcmV?d00001 diff --git a/manual/plugins/images/ss-blackjack-240x320x16.png b/manual/plugins/images/ss-blackjack-240x320x16.png new file mode 100644 index 0000000000000000000000000000000000000000..7516ed9afc6ccb982f9400443cf7c88878ed4862 GIT binary patch literal 4574 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 aE8fBkSO;9+JNd8y7~VG1FW3F!&wl`++q%{O literal 0 HcmV?d00001 diff --git a/manual/plugins/images/ss-blackjack-320x240x16.png b/manual/plugins/images/ss-blackjack-320x240x16.png new file mode 100644 index 0000000000000000000000000000000000000000..c26e4866b1b7d1719a44e6d2ce1c9a645b6b9d64 GIT binary patch literal 8600 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 Lr&gz8^YT9cZAr21 literal 0 HcmV?d00001 diff --git a/manual/plugins/main.tex b/manual/plugins/main.tex index a92c3e2a8c..2d10ffe81b 100644 --- a/manual/plugins/main.tex +++ b/manual/plugins/main.tex @@ -18,6 +18,8 @@ text files, chip8 games), or from the \setting{Open with} option on the \opt{recorder,recorderv2fm,h1xx,h300,ipodcolor,ipodvideo,sansa} {and Rockboy in \reference{ref:Rockboy}}.} +\opt{HAVE_LCD_BITMAP}{\input{plugins/blackjack.tex}} + \opt{HAVE_LCD_BITMAP}{\input{plugins/brickmania.tex}} \opt{HAVE_LCD_BITMAP}{\input{plugins/bubbles.tex}}