1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 Tom Ross
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 #include "pluginbitmaps/card_deck.h"
24 #include "pluginbitmaps/card_back.h"
25 #include "lib/display_text.h"
26 #include "lib/highscore.h"
27 #include "lib/playback_control.h"
32 #define HIGH_SCORE PLUGIN_GAMES_DIR "/blackjack.score"
33 #define SAVE_FILE PLUGIN_GAMES_DIR "/blackjack.save"
36 /* final game return status */
39 BJ_QUIT_WITHOUT_SAVING
,
45 #if CONFIG_KEYPAD == RECORDER_PAD
46 #define BJACK_SELECT_NAME "PLAY"
47 #define BJACK_STAY_NAME "F1"
48 #define BJACK_RESUME_NAME "F3"
49 #define BJACK_QUIT_NAME "OFF"
50 #define BJACK_DOUBLE_NAME "F2"
51 #define BJACK_SELECT BUTTON_PLAY
52 #define BJACK_QUIT BUTTON_OFF
53 #define BJACK_MAX (BUTTON_ON|BUTTON_UP)
54 #define BJACK_MIN (BUTTON_ON|BUTTON_DOWN)
55 #define BJACK_STAY BUTTON_F1
56 #define BJACK_DOUBLEDOWN BUTTON_F2
57 #define BJACK_RESUME BUTTON_F3
58 #define BJACK_UP BUTTON_UP
59 #define BJACK_DOWN BUTTON_DOWN
60 #define BJACK_RIGHT BUTTON_RIGHT
61 #define BJACK_LEFT BUTTON_LEFT
63 #elif CONFIG_KEYPAD == ONDIO_PAD
64 #define BJACK_SELECT_NAME "MENU"
65 #define BJACK_STAY_NAME "RIGHT"
66 #define BJACK_RESUME_NAME "DOWN"
67 #define BJACK_QUIT_NAME "OFF"
68 #define BJACK_DOUBLE_NAME "UP"
69 #define BJACK_SELECT BUTTON_MENU
70 #define BJACK_QUIT BUTTON_OFF
71 #define BJACK_MAX (BUTTON_MENU|BUTTON_UP)
72 #define BJACK_MIN (BUTTON_MENU|BUTTON_DOWN)
73 #define BJACK_STAY BUTTON_RIGHT
74 #define BJACK_DOUBLEDOWN BUTTON_UP
75 #define BJACK_RESUME BUTTON_DOWN
76 #define BJACK_UP BUTTON_UP
77 #define BJACK_DOWN BUTTON_DOWN
78 #define BJACK_RIGHT BUTTON_RIGHT
79 #define BJACK_LEFT BUTTON_LEFT
81 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
82 #define BJACK_SELECT_NAME "PLAY"
83 #define BJACK_STAY_NAME ">>|"
84 #define BJACK_RESUME_NAME "RIGHT"
85 #define BJACK_QUIT_NAME "POWER"
86 #define BJACK_DOUBLE_NAME "|<<"
87 #define BJACK_SELECT BUTTON_PLAY
88 #define BJACK_QUIT BUTTON_POWER
89 #define BJACK_MAX (BUTTON_PLAY|BUTTON_SCROLL_UP)
90 #define BJACK_MIN (BUTTON_PLAY|BUTTON_SCROLL_DOWN)
91 #define BJACK_STAY BUTTON_FF
92 #define BJACK_DOUBLEDOWN BUTTON_REW
93 #define BJACK_RESUME BUTTON_RIGHT
94 #define BJACK_UP BUTTON_SCROLL_UP
95 #define BJACK_DOWN BUTTON_SCROLL_DOWN
96 #define BJACK_RIGHT BUTTON_RIGHT
97 #define BJACK_LEFT BUTTON_LEFT
99 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
100 (CONFIG_KEYPAD == IRIVER_H300_PAD)
101 #define BJACK_SELECT_NAME "ON"
102 #define BJACK_STAY_NAME "REC"
103 #define BJACK_RESUME_NAME "MODE"
104 #define BJACK_QUIT_NAME "OFF"
105 #define BJACK_DOUBLE_NAME "SELECT"
106 #define BJACK_SELECT BUTTON_ON
107 #define BJACK_QUIT BUTTON_OFF
108 #define BJACK_MAX (BUTTON_ON|BUTTON_UP)
109 #define BJACK_MIN (BUTTON_ON|BUTTON_DOWN)
110 #define BJACK_STAY BUTTON_REC
111 #define BJACK_DOUBLEDOWN BUTTON_SELECT
112 #define BJACK_RESUME BUTTON_MODE
113 #define BJACK_UP BUTTON_UP
114 #define BJACK_DOWN BUTTON_DOWN
115 #define BJACK_RIGHT BUTTON_RIGHT
116 #define BJACK_LEFT BUTTON_LEFT
118 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
119 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
120 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
121 #define BJACK_SELECT_NAME "SELECT"
122 #define BJACK_STAY_NAME "RIGHT"
123 #define BJACK_RESUME_NAME "PLAY"
124 #define BJACK_QUIT_NAME "MENU"
125 #define BJACK_DOUBLE_NAME "LEFT"
126 #define BJACK_SELECT BUTTON_SELECT
127 #define BJACK_QUIT BUTTON_MENU
128 #define BJACK_MAX (BUTTON_SELECT|BUTTON_SCROLL_FWD)
129 #define BJACK_MIN (BUTTON_SELECT|BUTTON_SCROLL_BACK)
130 #define BJACK_STAY BUTTON_RIGHT
131 #define BJACK_DOUBLEDOWN BUTTON_LEFT
132 #define BJACK_RESUME BUTTON_PLAY
133 #define BJACK_UP BUTTON_SCROLL_FWD
134 #define BJACK_DOWN BUTTON_SCROLL_BACK
135 #define BJACK_RIGHT BUTTON_RIGHT
136 #define BJACK_LEFT BUTTON_LEFT
138 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
139 #define BJACK_SELECT_NAME "PLAY"
140 #define BJACK_STAY_NAME "REC"
141 #define BJACK_RESUME_NAME "DOWN"
142 #define BJACK_QUIT_NAME "POWER"
143 #define BJACK_DOUBLE_NAME "PLAY"
144 #define BJACK_SELECT BUTTON_SELECT
145 #define BJACK_QUIT BUTTON_POWER
146 #define BJACK_MAX (BUTTON_PLAY|BUTTON_UP)
147 #define BJACK_MIN (BUTTON_PLAY|BUTTON_DOWN)
148 #define BJACK_STAY BUTTON_REC
149 #define BJACK_DOUBLEDOWN BUTTON_PLAY
150 #define BJACK_RESUME BUTTON_DOWN
151 #define BJACK_UP BUTTON_UP
152 #define BJACK_DOWN BUTTON_DOWN
153 #define BJACK_RIGHT BUTTON_RIGHT
154 #define BJACK_LEFT BUTTON_LEFT
156 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
157 #define BJACK_SELECT_NAME "MODE"
158 #define BJACK_STAY_NAME "MODE"
159 #define BJACK_RESUME_NAME "EQ+MODE"
160 #define BJACK_QUIT_NAME "PLAY"
161 #define BJACK_DOUBLE_NAME "SELECT"
162 #define BJACK_SELECT BUTTON_MODE
163 #define BJACK_QUIT BUTTON_PLAY
164 #define BJACK_MAX (BUTTON_EQ|BUTTON_UP)
165 #define BJACK_MIN (BUTTON_EQ|BUTTON_DOWN)
166 #define BJACK_STAY BUTTON_MODE
167 #define BJACK_DOUBLEDOWN BUTTON_SELECT
168 #define BJACK_RESUME (BUTTON_EQ|BUTTON_MODE)
169 #define BJACK_UP BUTTON_UP
170 #define BJACK_DOWN BUTTON_DOWN
171 #define BJACK_RIGHT BUTTON_RIGHT
172 #define BJACK_LEFT BUTTON_LEFT
174 #elif CONFIG_KEYPAD == GIGABEAT_PAD
175 #define BJACK_SELECT_NAME "SELECT"
176 #define BJACK_STAY_NAME "VOL-"
177 #define BJACK_RESUME_NAME "MENU"
178 #define BJACK_QUIT_NAME "POWER"
179 #define BJACK_DOUBLE_NAME "A"
180 #define BJACK_SELECT BUTTON_SELECT
181 #define BJACK_QUIT BUTTON_POWER
182 #define BJACK_MAX BUTTON_VOL_UP
183 #define BJACK_MIN BUTTON_VOL_DOWN
184 #define BJACK_STAY BUTTON_VOL_DOWN
185 #define BJACK_DOUBLEDOWN BUTTON_A
186 #define BJACK_RESUME BUTTON_MENU
187 #define BJACK_UP BUTTON_UP
188 #define BJACK_DOWN BUTTON_DOWN
189 #define BJACK_RIGHT BUTTON_RIGHT
190 #define BJACK_LEFT BUTTON_LEFT
192 #elif CONFIG_KEYPAD == SANSA_E200_PAD
193 #define BJACK_SELECT_NAME "SELECT"
194 #define BJACK_STAY_NAME "RIGHT"
195 #define BJACK_RESUME_NAME "DOWN"
196 #define BJACK_QUIT_NAME "POWER"
197 #define BJACK_DOUBLE_NAME "LEFT"
198 #define BJACK_SELECT BUTTON_SELECT
199 #define BJACK_QUIT BUTTON_POWER
200 #define BJACK_MAX (BUTTON_REC|BUTTON_UP)
201 #define BJACK_MIN (BUTTON_REC|BUTTON_DOWN)
202 #define BJACK_STAY BUTTON_RIGHT
203 #define BJACK_DOUBLEDOWN BUTTON_LEFT
204 #define BJACK_RESUME BUTTON_DOWN
205 #define BJACK_UP BUTTON_SCROLL_FWD
206 #define BJACK_DOWN BUTTON_SCROLL_BACK
207 #define BJACK_RIGHT BUTTON_RIGHT
208 #define BJACK_LEFT BUTTON_LEFT
210 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
211 #define BJACK_SELECT_NAME "SELECT"
212 #define BJACK_STAY_NAME "RIGHT"
213 #define BJACK_RESUME_NAME "UP"
214 #define BJACK_QUIT_NAME "HOME"
215 #define BJACK_DOUBLE_NAME "LEFT"
216 #define BJACK_SELECT BUTTON_SELECT
217 #define BJACK_QUIT (BUTTON_HOME|BUTTON_REPEAT)
218 #define BJACK_MAX (BUTTON_SELECT|BUTTON_UP)
219 #define BJACK_MIN (BUTTON_SELECT|BUTTON_DOWN)
220 #define BJACK_STAY BUTTON_RIGHT
221 #define BJACK_DOUBLEDOWN BUTTON_LEFT
222 #define BJACK_RESUME BUTTON_UP
223 #define BJACK_UP BUTTON_SCROLL_FWD
224 #define BJACK_DOWN BUTTON_SCROLL_BACK
225 #define BJACK_RIGHT BUTTON_RIGHT
226 #define BJACK_LEFT BUTTON_LEFT
228 #elif CONFIG_KEYPAD == SANSA_C200_PAD
229 #define BJACK_SELECT_NAME "SELECT"
230 #define BJACK_STAY_NAME "RIGHT"
231 #define BJACK_RESUME_NAME "DOWN"
232 #define BJACK_QUIT_NAME "POWER"
233 #define BJACK_DOUBLE_NAME "LEFT"
234 #define BJACK_SELECT BUTTON_SELECT
235 #define BJACK_QUIT BUTTON_POWER
236 #define BJACK_MAX BUTTON_VOL_UP
237 #define BJACK_MIN BUTTON_VOL_DOWN
238 #define BJACK_STAY BUTTON_RIGHT
239 #define BJACK_DOUBLEDOWN BUTTON_LEFT
240 #define BJACK_RESUME BUTTON_DOWN
241 #define BJACK_UP BUTTON_UP
242 #define BJACK_DOWN BUTTON_DOWN
243 #define BJACK_RIGHT BUTTON_RIGHT
244 #define BJACK_LEFT BUTTON_LEFT
246 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
247 #define BJACK_SELECT_NAME "SELECT"
248 #define BJACK_STAY_NAME "RIGHT"
249 #define BJACK_RESUME_NAME "DOWN"
250 #define BJACK_QUIT_NAME "POWER"
251 #define BJACK_DOUBLE_NAME "LEFT"
252 #define BJACK_SELECT BUTTON_SELECT
253 #define BJACK_QUIT BUTTON_POWER
254 #define BJACK_MAX BUTTON_VOL_UP
255 #define BJACK_MIN BUTTON_VOL_DOWN
256 #define BJACK_STAY BUTTON_RIGHT
257 #define BJACK_DOUBLEDOWN BUTTON_LEFT
258 #define BJACK_RESUME BUTTON_DOWN
259 #define BJACK_UP BUTTON_UP
260 #define BJACK_DOWN BUTTON_DOWN
261 #define BJACK_RIGHT BUTTON_RIGHT
262 #define BJACK_LEFT BUTTON_LEFT
264 #elif CONFIG_KEYPAD == SANSA_M200_PAD
265 #define BJACK_SELECT_NAME "SELECT"
266 #define BJACK_STAY_NAME "RIGHT"
267 #define BJACK_RESUME_NAME "DOWN"
268 #define BJACK_QUIT_NAME "POWER"
269 #define BJACK_DOUBLE_NAME "LEFT"
270 #define BJACK_SELECT (BUTTON_SELECT | BUTTON_REL)
271 #define BJACK_QUIT BUTTON_POWER
272 #define BJACK_MAX BUTTON_VOL_UP
273 #define BJACK_MIN BUTTON_VOL_DOWN
274 #define BJACK_STAY BUTTON_RIGHT
275 #define BJACK_DOUBLEDOWN BUTTON_LEFT
276 #define BJACK_RESUME BUTTON_DOWN
277 #define BJACK_UP BUTTON_UP
278 #define BJACK_DOWN BUTTON_DOWN
279 #define BJACK_RIGHT BUTTON_RIGHT
280 #define BJACK_LEFT BUTTON_LEFT
282 #elif CONFIG_KEYPAD == ELIO_TPJ1022_PAD
283 #define BJACK_SELECT_NAME "MAIN"
284 #define BJACK_STAY_NAME "MENU"
285 #define BJACK_RESUME_NAME ">>|"
286 #define BJACK_QUIT_NAME "POWER"
287 #define BJACK_DOUBLE_NAME "DOWN"
288 #define BJACK_SELECT BUTTON_MAIN
289 #define BJACK_QUIT BUTTON_POWER
290 #define BJACK_MAX (BUTTON_REC|BUTTON_UP)
291 #define BJACK_MIN (BUTTON_REC|BUTTON_DOWN)
292 #define BJACK_STAY BUTTON_MENU
293 #define BJACK_DOUBLEDOWN BUTTON_DOWN
294 #define BJACK_RESUME BUTTON_FF
295 #define BJACK_UP BUTTON_UP
296 #define BJACK_DOWN BUTTON_DOWN
297 #define BJACK_RIGHT BUTTON_RIGHT
298 #define BJACK_LEFT BUTTON_LEFT
300 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
301 #define BJACK_SELECT_NAME "PLAY"
302 #define BJACK_STAY_NAME "VOL-"
303 #define BJACK_RESUME_NAME "MENU"
304 #define BJACK_QUIT_NAME "BACK"
305 #define BJACK_DOUBLE_NAME "SELECT"
306 #define BJACK_SELECT BUTTON_PLAY
307 #define BJACK_QUIT BUTTON_BACK
308 #define BJACK_MAX BUTTON_VOL_UP
309 #define BJACK_MIN BUTTON_VOL_DOWN
310 #define BJACK_STAY BUTTON_VOL_DOWN
311 #define BJACK_DOUBLEDOWN BUTTON_SELECT
312 #define BJACK_RESUME BUTTON_MENU
313 #define BJACK_UP BUTTON_UP
314 #define BJACK_DOWN BUTTON_DOWN
315 #define BJACK_RIGHT BUTTON_RIGHT
316 #define BJACK_LEFT BUTTON_LEFT
318 #elif CONFIG_KEYPAD == MROBE100_PAD
319 #define BJACK_SELECT_NAME "SELECT"
320 #define BJACK_STAY_NAME "DISPLAY"
321 #define BJACK_RESUME_NAME "PLAY"
322 #define BJACK_QUIT_NAME "POWER"
323 #define BJACK_DOUBLE_NAME "DOWN"
324 #define BJACK_SELECT BUTTON_SELECT
325 #define BJACK_QUIT BUTTON_POWER
326 #define BJACK_MAX BUTTON_MENU
327 #define BJACK_MIN BUTTON_DISPLAY
328 #define BJACK_STAY BUTTON_DISPLAY
329 #define BJACK_DOUBLEDOWN BUTTON_DOWN
330 #define BJACK_RESUME BUTTON_PLAY
331 #define BJACK_UP BUTTON_UP
332 #define BJACK_DOWN BUTTON_DOWN
333 #define BJACK_RIGHT BUTTON_RIGHT
334 #define BJACK_LEFT BUTTON_LEFT
336 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
337 #define BJACK_SELECT_NAME "RC","PLAY"
338 #define BJACK_STAY_NAME "RC", ">>|"
339 #define BJACK_RESUME_NAME "RC_MODE"
340 #define BJACK_QUIT_NAME "RC_REC"
341 #define BJACK_DOUBLE_NAME "RC_REW"
342 #define BJACK_SELECT BUTTON_RC_PLAY
343 #define BJACK_QUIT BUTTON_RC_REC
344 #define BJACK_MAX (BUTTON_RC_PLAY|BUTTON_RC_VOL_UP)
345 #define BJACK_MIN (BUTTON_RC_PLAY|BUTTON_RC_VOL_DOWN)
346 #define BJACK_STAY BUTTON_RC_FF
347 #define BJACK_DOUBLEDOWN BUTTON_RC_REW
348 #define BJACK_RESUME BUTTON_RC_MODE
349 #define BJACK_UP BUTTON_RC_VOL_UP
350 #define BJACK_DOWN BUTTON_RC_VOL_DOWN
351 #define BJACK_RIGHT BUTTON_RC_FF
352 #define BJACK_LEFT BUTTON_RC_REW
354 #elif CONFIG_KEYPAD == COWOND2_PAD
355 #define BJACK_QUIT_NAME "POWER"
356 #define BJACK_DOUBLE_NAME "-"
357 #define BJACK_QUIT BUTTON_POWER
358 #define BJACK_DOUBLEDOWN BUTTON_MINUS
360 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
361 #define BJACK_SELECT_NAME "SELECT"
362 #define BJACK_STAY_NAME "PLAY"
363 #define BJACK_RESUME_NAME "MENU"
364 #define BJACK_QUIT_NAME "POWER"
365 #define BJACK_DOUBLE_NAME "CUSTOM"
366 #define BJACK_SELECT BUTTON_SELECT
367 #define BJACK_QUIT BUTTON_POWER
368 #define BJACK_STAY BUTTON_PLAY
369 #define BJACK_MAX (BUTTON_CUSTOM|BUTTON_UP)
370 #define BJACK_MIN (BUTTON_CUSTOM|BUTTON_DOWN)
371 #define BJACK_DOUBLEDOWN BUTTON_CUSTOM
372 #define BJACK_RESUME BUTTON_MENU
373 #define BJACK_UP BUTTON_UP
374 #define BJACK_DOWN BUTTON_DOWN
375 #define BJACK_RIGHT BUTTON_RIGHT
376 #define BJACK_LEFT BUTTON_LEFT
378 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
379 #define BJACK_SELECT_NAME "MENU"
380 #define BJACK_STAY_NAME "VOL-"
381 #define BJACK_RESUME_NAME "VIEW"
382 #define BJACK_QUIT_NAME "POWER"
383 #define BJACK_DOUBLE_NAME "SELECT"
384 #define BJACK_SELECT BUTTON_MENU
385 #define BJACK_QUIT BUTTON_POWER
386 #define BJACK_MAX BUTTON_VOL_UP
387 #define BJACK_MIN BUTTON_VOL_DOWN
388 #define BJACK_STAY BUTTON_VOL_DOWN
389 #define BJACK_DOUBLEDOWN BUTTON_SELECT
390 #define BJACK_RESUME BUTTON_VIEW
391 #define BJACK_UP BUTTON_UP
392 #define BJACK_DOWN BUTTON_DOWN
393 #define BJACK_RIGHT BUTTON_RIGHT
394 #define BJACK_LEFT BUTTON_LEFT
396 #elif CONFIG_KEYPAD == ONDAVX747_PAD
397 #define BJACK_QUIT_NAME "POWER"
398 #define BJACK_DOUBLE_NAME "Vol-"
399 #define BJACK_QUIT BUTTON_POWER
400 #define BJACK_DOUBLEDOWN BUTTON_VOL_DOWN
402 #elif CONFIG_KEYPAD == ONDAVX777_PAD
403 #define BJACK_QUIT_NAME "POWER"
404 #define BJACK_QUIT BUTTON_POWER
406 #elif CONFIG_KEYPAD == MROBE500_PAD
407 #define BJACK_QUIT_NAME "POWER"
408 #define BJACK_QUIT BUTTON_POWER
410 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
411 #define BJACK_SELECT_NAME ""
412 #define BJACK_STAY_NAME "RECORD"
413 #define BJACK_RESUME_NAME "PREVIOUS"
414 #define BJACK_QUIT_NAME "PLAY+LEFT"
415 #define BJACK_DOUBLE_NAME "FFWD"
416 #define BJACK_SELECT BUTTON_PLAY
417 #define BJACK_QUIT (BUTTON_PLAY|BUTTON_LEFT)
418 #define BJACK_MAX (BUTTON_PLAY|BUTTON_UP)
419 #define BJACK_MIN (BUTTON_PLAY|BUTTON_DOWN)
420 #define BJACK_STAY BUTTON_REC
421 #define BJACK_DOUBLEDOWN BUTTON_FFWD
422 #define BJACK_RESUME BUTTON_REW
423 #define BJACK_UP BUTTON_UP
424 #define BJACK_DOWN BUTTON_DOWN
425 #define BJACK_RIGHT BUTTON_RIGHT
426 #define BJACK_LEFT BUTTON_LEFT
429 #error No keymap defined!
432 #ifdef HAVE_TOUCHSCREEN
433 #ifndef BJACK_DOUBLEDOWN
434 #define BJACK_DOUBLEDOWN BUTTON_MIDLEFT
435 #define BJACK_DOUBLE_NAME "BUTTON_MIDLEFT"
438 #define BJACK_SELECT BUTTON_CENTER
439 #define BJACK_SELECT_NAME "BUTTON_CENTER"
442 #define BJACK_MAX BUTTON_TOPRIGHT
445 #define BJACK_MIN BUTTON_TOPLEFT
448 #define BJACK_RESUME BUTTON_BOTTOMRIGHT
449 #define BJACK_RESUME_NAME "BUTTON_BOTTOMRIGHT"
452 #define BJACK_STAY BUTTON_BOTTOMLEFT
453 #define BJACK_STAY_NAME "BUTTON_BOTTOMLEFT"
456 #define BJACK_UP BUTTON_TOPMIDDLE
459 #define BJACK_DOWN BUTTON_BOTTOMMIDDLE
462 #define BJACK_RIGHT BUTTON_MIDRIGHT
465 #define BJACK_LEFT BUTTON_MIDLEFT
470 #ifdef HAVE_LCD_COLOR
471 #define BG_COLOR LCD_RGBPACK(0,157,0)
472 #define FG_COLOR LCD_WHITE
474 #define BG_COLOR LCD_WHITE
475 #define FG_COLOR LCD_BLACK
478 #define CARD_WIDTH BMPWIDTH_card_back
479 #define CARD_HEIGHT BMPHEIGHT_card_back
481 /* This is the max amount of cards onscreen before condensing */
482 #define MAX_CARDS LCD_WIDTH/(CARD_WIDTH+4)
484 extern const fb_data card_deck
[];
485 extern const fb_data card_back
[];
487 #define NEXT_CARD bj->player_cards[done][bj->num_player_cards[done]]
489 /* dealer and player card positions */
490 unsigned int dealer_x
, dealer_y
, player_x
, player_y
;
492 typedef struct card
{
493 unsigned int value
; /* Card's value in Blackjack */
494 unsigned int num
; /* Value on card face 0-12 (0=Ace, 1=2, 11=Q) */
495 unsigned int suit
; /* 0:Spades, 1:Hearts, 2: Clubs; 3: Diamonds */
499 typedef struct game_context
{
500 struct card player_cards
[2][22]; /* 22 Cards means the deal was all aces */
501 struct card dealer_cards
[22]; /* That is the worst-case scenario */
502 unsigned int player_total
;
503 unsigned int dealer_total
;
504 signed int player_money
;
505 unsigned int num_player_cards
[2];
506 unsigned int num_dealer_cards
;
507 unsigned int current_bet
;
508 unsigned int split_status
; /* 0 = split hasn't been asked, *
509 * 1 = split did not occur *
510 * 2 = split occurred *
511 * 3 = split occurred and 1st hand done */
514 bool asked_insurance
;
517 static bool resume
= false;
518 static bool resume_file
= false;
519 static struct highscore highest
[NUM_SCORES
];
521 /*****************************************************************************
522 * blackjack_init() initializes blackjack data structures.
523 ******************************************************************************/
524 static void blackjack_init(struct game_context
* bj
) {
525 /* seed the rand generator */
526 rb
->srand(*rb
->current_tick
);
528 /* reset card positions */
530 dealer_y
= LCD_HEIGHT
/4 - CARD_HEIGHT
/2;
532 player_y
= LCD_HEIGHT
- LCD_HEIGHT
/4 - CARD_HEIGHT
/2;
534 /* check for resumed game */
538 bj
->player_total
= 0;
539 bj
->dealer_total
= 0;
540 bj
->num_player_cards
[0] = 2;
541 bj
->num_player_cards
[1] = 0;
542 bj
->num_dealer_cards
= 2;
543 bj
->end_hand
= false;
544 bj
->split_status
= 0;
545 bj
->is_blackjack
= false;
546 bj
->asked_insurance
= false;
549 /*****************************************************************************
550 * blackjack_drawtable() draws the table and some text.
551 ******************************************************************************/
552 static void blackjack_drawtable(struct game_context
* bj
) {
553 unsigned int w
, h
, y_loc
;
557 rb
->lcd_getstringsize("Bet", &w
, &h
);
558 rb
->lcd_putsxy(LCD_WIDTH
- w
, 2*h
+ 1, "Bet");
559 rb
->snprintf(str
, 9, "$%d", bj
->current_bet
);
560 rb
->lcd_getstringsize(str
, &w
, &h
);
561 rb
->lcd_putsxy(LCD_WIDTH
- w
, 3*h
+ 1, str
);
562 y_loc
= LCD_HEIGHT
/2;
564 rb
->lcd_getstringsize("Bet", &w
, &h
);
565 rb
->lcd_putsxy(LCD_WIDTH
- w
, 5*h
/ 2, "Bet");
566 rb
->snprintf(str
, 9, "$%d", bj
->current_bet
);
567 rb
->lcd_getstringsize(str
, &w
, &h
);
568 rb
->lcd_putsxy(LCD_WIDTH
- w
, 7*h
/ 2, str
);
569 rb
->lcd_hline(0, LCD_WIDTH
, LCD_HEIGHT
/2);
570 y_loc
= LCD_HEIGHT
/2 + h
;
573 rb
->lcd_putsxy(0,0, "Dealer");
574 rb
->lcd_getstringsize("Player", &w
, &h
);
575 rb
->lcd_putsxy(0, y_loc
, "Player");
576 rb
->lcd_getstringsize("Total", &w
, &h
);
577 rb
->lcd_putsxy(LCD_WIDTH
- w
, y_loc
, "Total");
578 rb
->lcd_getstringsize("Money", &w
, &h
);
579 rb
->lcd_putsxy(LCD_WIDTH
- w
, 0, "Money");
580 rb
->snprintf(str
, 9, "$%d", bj
->player_money
- bj
->current_bet
);
581 rb
->lcd_getstringsize(str
, &w
, &h
);
582 rb
->lcd_putsxy(LCD_WIDTH
- w
, h
+ 1, str
);
583 rb
->snprintf(str
, 3, "%d", bj
->player_total
);
584 rb
->lcd_getstringsize(str
, &w
, &h
);
585 rb
->lcd_putsxy(LCD_WIDTH
- w
, y_loc
+ h
, str
);
588 /*****************************************************************************
589 * find_value() is passed a card and returns its blackjack value.
590 ******************************************************************************/
591 static unsigned int find_value(unsigned int number
) {
592 unsigned int thisValue
;
594 thisValue
= 11; /* Aces get a value of 11 at first */
595 else if (number
< 10)
596 thisValue
= number
+ 1;
598 thisValue
= 10; /* Anything 10 or higher gets a value of 10 */
603 /*****************************************************************************
604 * draw_card() draws a card to the screen.
605 ******************************************************************************/
606 static void draw_card(struct card temp_card
, bool shown
,
607 unsigned int x
, unsigned int y
) {
609 rb
->lcd_bitmap_part(card_deck
, CARD_WIDTH
*temp_card
.num
,
610 CARD_HEIGHT
*temp_card
.suit
,
611 STRIDE( SCREEN_MAIN
, BMPWIDTH_card_deck
,
612 BMPHEIGHT_card_deck
),
613 x
+1, y
+1, CARD_WIDTH
, CARD_HEIGHT
);
615 rb
->lcd_bitmap(card_back
, x
+1, y
+1,CARD_WIDTH
, CARD_HEIGHT
);
617 rb
->lcd_set_foreground(LCD_BLACK
);
622 rb
->lcd_hline(x
+2, x
+CARD_WIDTH
-1, y
);
623 rb
->lcd_hline(x
+2, x
+CARD_WIDTH
-1, y
+CARD_HEIGHT
+1);
624 rb
->lcd_vline(x
, y
+2, y
+CARD_HEIGHT
-3);
625 rb
->lcd_vline(x
+CARD_WIDTH
+1, y
+2, y
+CARD_HEIGHT
-1);
626 rb
->lcd_drawpixel(x
+1, y
+1);
627 rb
->lcd_drawpixel(x
+1, y
+CARD_HEIGHT
);
628 rb
->lcd_drawpixel(x
+CARD_WIDTH
, y
+1);
629 rb
->lcd_drawpixel(x
+CARD_WIDTH
, y
+CARD_HEIGHT
);
631 rb
->lcd_hline(x
+1, x
+CARD_WIDTH
, y
);
632 rb
->lcd_hline(x
+1, x
+CARD_WIDTH
, y
+CARD_HEIGHT
+1);
633 rb
->lcd_vline(x
, y
+1, y
+CARD_HEIGHT
);
634 rb
->lcd_vline(x
+CARD_WIDTH
+1, y
+1, y
+CARD_HEIGHT
);
638 rb
->lcd_set_foreground(FG_COLOR
);
642 /*****************************************************************************
643 * new_card() initializes a new card and gives it values.
644 ******************************************************************************/
645 static struct card
new_card(void) {
646 struct card new_card
;
647 new_card
.suit
= rb
->rand()%4; /* Random number 0-3 */
648 new_card
.num
= rb
->rand()%13; /* Random number 0-12 */
649 new_card
.value
= find_value(new_card
.num
);
650 new_card
.is_soft_ace
= new_card
.num
== 0 ? true : false;
654 /*****************************************************************************
655 * deal_init_card() deals and draws to the screen the player's and dealer's
657 ******************************************************************************/
658 static void deal_init_cards(struct game_context
* bj
) {
659 bj
->dealer_cards
[0] = new_card();
660 bj
->dealer_total
+= bj
->dealer_cards
[0].value
;
662 draw_card(bj
->dealer_cards
[0], false, dealer_x
, dealer_y
);
664 bj
->dealer_cards
[1] = new_card();
665 bj
->dealer_total
+= bj
->dealer_cards
[1].value
;
666 draw_card(bj
->dealer_cards
[1], true, dealer_x
+ CARD_WIDTH
+ 4, dealer_y
);
668 bj
->player_cards
[0][0] = new_card();
669 bj
->player_total
+= bj
->player_cards
[0][0].value
;
670 draw_card(bj
->player_cards
[0][0], true, player_x
, player_y
);
671 player_x
+= CARD_WIDTH
+ 4;
673 bj
->player_cards
[0][1] = new_card();
674 bj
->player_total
+= bj
->player_cards
[0][1].value
;
675 draw_card(bj
->player_cards
[0][1], true, player_x
, player_y
);
676 player_x
+= CARD_WIDTH
+ 4;
679 /*****************************************************************************
680 * redraw_board() redraws all the cards and the board
681 ******************************************************************************/
682 static void redraw_board(struct game_context
* bj
) {
683 unsigned int i
, n
, upper_bound
;
684 rb
->lcd_clear_display();
686 blackjack_drawtable(bj
);
689 upper_bound
= bj
->split_status
> 1 ? 2 : 1;
691 for (i
= 0; i
< bj
->num_dealer_cards
; i
++) {
693 draw_card(bj
->dealer_cards
[0], false, dealer_x
, dealer_y
);
695 /* increment i so the dealer's first card isn't displayed */
697 dealer_x
+= CARD_WIDTH
+ 4;
699 draw_card(bj
->dealer_cards
[i
], true, dealer_x
, dealer_y
);
701 if (bj
->num_dealer_cards
> MAX_CARDS
-1)
704 dealer_x
+= CARD_WIDTH
+ 4;
707 for (n
= 0; n
< upper_bound
; n
++) {
708 for (i
= 0; i
< bj
->num_player_cards
[n
]; i
++) {
709 draw_card(bj
->player_cards
[n
][i
], true, player_x
, player_y
);
710 if (bj
->split_status
>1 || bj
->num_player_cards
[n
]>MAX_CARDS
)
713 player_x
+= CARD_WIDTH
+ 4;
715 if (bj
->split_status
> 1)
716 player_x
= LCD_WIDTH
/2 + 4;
720 /*****************************************************************************
721 * update_total updates the player's total
722 ******************************************************************************/
723 static void update_total(struct game_context
* bj
) {
726 rb
->snprintf(total
, 3, "%d", bj
->player_total
);
727 rb
->lcd_getstringsize(total
, &w
, &h
);
731 rb
->lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 + h
, total
);
732 rb
->lcd_update_rect(LCD_WIDTH
- w
, LCD_HEIGHT
/2 + h
, w
, h
);
736 /*****************************************************************************
737 * check_for_aces() is passed an array of cards and returns where an ace is
738 * located. Otherwise, returns -1.
739 ******************************************************************************/
740 static signed int check_for_aces(struct card temp_cards
[], unsigned int size
) {
742 for(i
= 0; i
< size
; i
++) {
743 if (temp_cards
[i
].is_soft_ace
== true)
749 /*****************************************************************************
750 * check_totals() compares player and dealer totals.
751 * 0: bust 1: loss, 2: push, 3: win, 4: blackjack, 5: something's not right...
752 ******************************************************************************/
753 static unsigned int check_totals(struct game_context
* bj
) {
755 if (bj
->player_total
> 21)
757 else if (bj
->player_total
== 21 && bj
->is_blackjack
) {
758 if (bj
->dealer_total
== 21 && bj
->num_dealer_cards
== 2)
763 else if (bj
->player_total
== bj
->dealer_total
)
765 else if (bj
->dealer_total
> 21 && bj
->player_total
< 22)
767 else if (bj
->dealer_total
> bj
->player_total
)
769 else if (bj
->player_total
> bj
->dealer_total
)
777 /*****************************************************************************
778 * finish_dealer() draws cards for the dealer until he has 17 or more.
779 ******************************************************************************/
780 static void finish_dealer(struct game_context
* bj
) {
783 if (bj
->dealer_total
> 16 && bj
->dealer_total
< 22)
786 while (bj
->dealer_total
< 17) {
787 bj
->dealer_cards
[bj
->num_dealer_cards
] = new_card();
788 bj
->dealer_total
+= bj
->dealer_cards
[bj
->num_dealer_cards
].value
;
789 bj
->num_dealer_cards
++;
792 while (bj
->dealer_total
> 21) {
793 temp
= check_for_aces(bj
->dealer_cards
, bj
->num_dealer_cards
);
795 bj
->dealer_cards
[temp
].is_soft_ace
= false;
796 bj
->dealer_total
-= 10;
803 /*****************************************************************************
804 * finish_game() completes the game once player's turn is over.
805 ******************************************************************************/
806 static void finish_game(struct game_context
* bj
) {
807 unsigned int rValue
, w
, h
;
812 } while (bj
->dealer_total
< 17);
815 rValue
= check_totals(bj
);
818 rb
->snprintf(str
, sizeof(str
), " Bust! ");
819 bj
->player_money
-= bj
->current_bet
;
821 else if (rValue
== 1) {
822 rb
->snprintf(str
, sizeof(str
), " Sorry, you lost. ");
823 bj
->player_money
-= bj
->current_bet
;
825 else if (rValue
== 2) {
826 rb
->snprintf(str
, sizeof(str
), " Push ");
828 else if (rValue
== 3) {
829 rb
->snprintf(str
, sizeof(str
), " You won! ");
830 bj
->player_money
+= bj
->current_bet
;
833 rb
->snprintf(str
, sizeof(str
), " Blackjack! ");
834 bj
->player_money
+= bj
->current_bet
* 3 / 2;
836 rb
->lcd_getstringsize(str
, &w
, &h
);
839 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
840 rb
->lcd_fillrect(0, LCD_HEIGHT
/2, LCD_WIDTH
, LCD_HEIGHT
/2);
841 rb
->lcd_set_drawmode(DRMODE_SOLID
);
842 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + h
, str
);
843 rb
->snprintf(str
, 12, "You have %d", bj
->player_total
);
844 rb
->lcd_getstringsize(str
, &w
, &h
);
845 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2, str
);
847 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 - h
/2, str
);
852 /*****************************************************************************
853 * blackjack_loadgame() loads the saved game and returns load success.
854 ******************************************************************************/
855 static bool blackjack_loadgame(struct game_context
* bj
) {
860 fd
= rb
->open(SAVE_FILE
, O_RDONLY
);
861 if(fd
< 0) return false;
863 /* read in saved game */
864 if(rb
->read(fd
, bj
, sizeof(struct game_context
))
865 == (long)sizeof(struct game_context
))
875 /*****************************************************************************
876 * blackjack_savegame() saves the current game state.
877 ******************************************************************************/
878 static void blackjack_savegame(struct game_context
* bj
) {
883 /* write out the game state to the save file */
884 fd
= rb
->open(SAVE_FILE
, O_WRONLY
|O_CREAT
);
887 rb
->write(fd
, bj
, sizeof(struct game_context
));
891 /*****************************************************************************
892 * blackjack_get_yes_no() gets a yes/no answer from the user
893 ******************************************************************************/
894 static unsigned int blackjack_get_yes_no(char message
[20]) {
896 unsigned int w
, h
, b
, choice
= 0;
897 bool breakout
= false;
898 char message_yes
[24], message_no
[24];
900 rb
->strcpy(message_yes
, message
);
901 rb
->strcpy(message_no
, message
);
902 rb
->strcat(message_yes
, " Yes");
903 rb
->strcat(message_no
, " No");
904 rb
->lcd_getstringsize(message_yes
, &w
, &h
);
905 const char *stg
[] = {message_yes
, message_no
};
913 #ifdef HAVE_LCD_COLOR
914 rb
->lcd_fillrect(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + b
, w
+1, h
+3);
915 rb
->lcd_set_foreground(LCD_BLACK
);
916 rb
->lcd_set_background(LCD_WHITE
);
918 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
919 rb
->lcd_fillrect(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + b
, w
+1, h
+3);
920 rb
->lcd_set_drawmode(DRMODE_SOLID
);
922 rb
->lcd_drawrect(LCD_WIDTH
/2 - w
/2 - 1, LCD_HEIGHT
/2 + b
- 1, w
+3, h
+4);
925 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + b
+1, stg
[choice
]);
926 rb
->lcd_update_rect(LCD_WIDTH
/2 - w
/2 - 1, LCD_HEIGHT
/2 + b
-1,
928 button
= rb
->button_get(true);
932 case (BJACK_LEFT
|BUTTON_REPEAT
):
934 case (BJACK_RIGHT
|BUTTON_REPEAT
):
937 case BJACK_SELECT
: breakout
= true;
939 case BJACK_QUIT
: breakout
= true;
946 rb
->lcd_set_foreground(FG_COLOR
);
947 rb
->lcd_set_background(BG_COLOR
);
952 /*****************************************************************************
953 * blackjack_get_amount() gets an amount from the player to be used
954 ******************************************************************************/
955 static signed int blackjack_get_amount(char message
[20], signed int lower_limit
,
956 signed int upper_limit
,
960 bool changed
= false;
964 rb
->lcd_getstringsize("A", &w
, &h
); /* find the size of one character */
966 if (start
> upper_limit
)
967 amount
= upper_limit
;
968 else if (start
< lower_limit
)
969 amount
= lower_limit
;
974 rb
->lcd_set_background(LCD_WHITE
);
975 rb
->lcd_set_foreground(LCD_BLACK
);
979 rb
->lcd_clear_display();
980 rb
->lcd_puts(0, 1, message
);
981 rb
->snprintf(str
, 9, "$%d", amount
);
982 rb
->lcd_puts(0, 2, str
);
983 rb
->lcd_puts(0, 3, "RIGHT: +1");
984 rb
->lcd_puts(0, 4, "LEFT: -1");
985 rb
->lcd_puts(0, 5, "UP: +10");
986 rb
->lcd_puts(0, 6, "DOWN: -10");
989 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
990 rb
->lcd_fillrect(LCD_WIDTH
/2 - 9*w
- 1, LCD_HEIGHT
/2 - 4*h
- 3,
992 rb
->lcd_set_drawmode(DRMODE_SOLID
);
993 rb
->lcd_drawrect(LCD_WIDTH
/2 - 9*w
- 1, LCD_HEIGHT
/2 - 4*h
- 3,
995 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 4*h
- 1, message
);
996 rb
->snprintf(str
, 9, "$%d", amount
);
997 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, str
);
998 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
999 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
1000 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
1001 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - h
-2, " >>|: +1");
1002 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 1, " |<<: -1");
1003 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + h
, "SCROLL+: +10");
1004 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + 2*h
+ 1, "SCROLL-: -10");
1005 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
1006 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - h
-2, "RIGHT: +1");
1007 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 1, "LEFT: -1");
1008 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + h
, "SCROLL+: +10");
1009 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + 2*h
+ 1, "SCROLL-: -10");
1011 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - h
-2, "RIGHT: +1");
1012 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 1, "LEFT: -1");
1013 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + h
, "UP: +10");
1014 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + 2*h
+ 1, "DOWN: -10");
1016 rb
->lcd_update_rect(LCD_WIDTH
/2 - 9*w
- 1, LCD_HEIGHT
/2 - 4*h
- 3,
1021 button
= rb
->button_get(true);
1025 case (BJACK_UP
|BUTTON_REPEAT
):
1026 if (amount
+ 10 < upper_limit
+ 1) {
1032 case (BJACK_DOWN
|BUTTON_REPEAT
):
1033 if (amount
- 10 > lower_limit
- 1) {
1039 case (BJACK_RIGHT
|BUTTON_REPEAT
):
1040 if (amount
+ 1 < upper_limit
+ 1) {
1046 case (BJACK_LEFT
|BUTTON_REPEAT
):
1047 if (amount
- 1 > lower_limit
- 1) {
1053 amount
= upper_limit
;
1057 amount
= lower_limit
;
1064 rb
->lcd_set_foreground(FG_COLOR
);
1065 rb
->lcd_set_background(BG_COLOR
);
1067 rb
->lcd_clear_display();
1072 rb
->snprintf(str
, 9, "$%d", amount
);
1073 #if LCD_HEIGHT <= 64
1074 rb
->lcd_puts(0, 2, str
);
1077 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
1078 rb
->lcd_fillrect(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, 5*w
, h
);
1079 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1080 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, str
);
1081 rb
->lcd_update_rect(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, 5*w
, h
);
1088 /*****************************************************************************
1089 * blackjack_get_bet() gets the player's bet.
1090 ******************************************************************************/
1091 static void blackjack_get_bet(struct game_context
* bj
) {
1092 bj
->current_bet
= blackjack_get_amount("Please enter a bet", 10,
1093 bj
->player_money
, bj
->current_bet
);
1096 /*****************************************************************************
1097 * double_down() returns one final card then finishes the game
1098 ******************************************************************************/
1099 static void double_down(struct game_context
* bj
) {
1100 bj
->current_bet
*= 2;
1101 bj
->player_cards
[0][bj
->num_player_cards
[0]] = new_card();
1102 bj
->player_total
+= bj
->player_cards
[0][bj
->num_player_cards
[0]].value
;
1103 bj
->num_player_cards
[0]++;
1106 /*****************************************************************************
1107 * split() checks if the player wants to split and acts accordingly.
1108 * When bj->split_status is 1, no split occurred. 2 means the player split and 3
1109 * means a split has already occurred and the first hand is done.
1110 ******************************************************************************/
1111 static void split(struct game_context
* bj
) {
1112 if (blackjack_get_yes_no("Split?") == 1)
1113 bj
->split_status
= 1;
1115 bj
->split_status
= 2;
1116 bj
->current_bet
*= 2;
1117 bj
->num_player_cards
[0] = 1;
1118 bj
->num_player_cards
[1] = 1;
1119 bj
->player_cards
[1][0] = bj
->player_cards
[0][1];
1120 bj
->player_total
= bj
->player_cards
[0][0].value
;
1124 /*****************************************************************************
1125 * insurance() see if the player wants to buy insurance and how much.
1126 ******************************************************************************/
1127 static unsigned int insurance(struct game_context
* bj
) {
1128 unsigned int insurance
, max_amount
;
1130 insurance
= blackjack_get_yes_no("Buy Insurance?");
1131 bj
->asked_insurance
= true;
1132 max_amount
= bj
->current_bet
< (unsigned int)bj
->player_money
?
1133 bj
->current_bet
/2 : (unsigned int)bj
->player_money
;
1134 if (insurance
== 1) return 0;
1136 insurance
= blackjack_get_amount("How much?", 0, max_amount
, 0);
1141 /*****************************************************************************
1142 * play_again() checks to see if the player wants to keep playing.
1143 ******************************************************************************/
1144 static unsigned int play_again(void) {
1145 return blackjack_get_yes_no("Play Again?");
1148 /*****************************************************************************
1149 * blackjack_help() displays help text.
1150 ******************************************************************************/
1151 static bool blackjack_help(void) {
1152 #define WORDS (sizeof help_text / sizeof (char*))
1153 static char *help_text
[] = {
1155 "The", "goal", "is", "to", "get", "21.", "", "",
1157 BJACK_SELECT_NAME
, ":", "hit", "/", "select", "",
1158 BJACK_STAY_NAME
, ":", "stay", "",
1159 BJACK_DOUBLE_NAME
, ":", "double", "down", "",
1160 BJACK_QUIT_NAME
, ":", "End", "game", "and", "go", "to", "menu", "",
1161 BJACK_RESUME_NAME
, ":", "Go", "to", "menu", "without", "end", "game",
1163 static struct style_text formation
[]={
1164 { 0, TEXT_CENTER
|TEXT_UNDERLINE
},
1165 { 12, C_RED
}, /* Hit/Select */
1166 { 18, C_RED
}, /* Stay */
1167 { 22, C_RED
}, /* Double Down */
1168 { 27, C_RED
}, /* Quit */
1169 { 36, C_RED
}, /* Menu */
1174 rb
->lcd_setfont(FONT_UI
);
1175 #ifdef HAVE_LCD_COLOR
1176 rb
->lcd_set_background(LCD_BLACK
);
1177 rb
->lcd_set_foreground(LCD_WHITE
);
1180 if (display_text(WORDS
, help_text
, formation
, NULL
))
1183 button
= rb
->button_get(true);
1184 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
) {
1187 } while( ( button
== BUTTON_NONE
)
1188 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
1189 rb
->lcd_setfont(FONT_SYSFIXED
);
1193 /*****************************************************************************
1194 * blackjack_menu() is the initial menu at the start of the game.
1195 ******************************************************************************/
1196 static unsigned int blackjack_menu(struct game_context
* bj
) {
1197 int selection
= resume
?0:1;
1198 bool breakout
= false;
1201 MENUITEM_STRINGLIST(menu
, "BlackJack Menu", NULL
,
1202 "Resume Game", "Start New Game",
1203 "High Scores", "Help",
1205 "Quit without Saving", "Quit");
1208 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1211 rb
->splash(HZ
*2, "Nothing to resume");
1215 rb
->remove(SAVE_FILE
);
1223 highscore_show(NUM_SCORES
, highest
, NUM_SCORES
, false);
1226 if(blackjack_help())
1230 if (playback_control(NULL
))
1234 return BJ_QUIT_WITHOUT_SAVING
;
1238 case MENU_ATTACHED_USB
:
1249 /*****************************************************************************
1250 * blackjack() is the main game subroutine, it returns the final game status.
1251 ******************************************************************************/
1252 static int blackjack(struct game_context
* bj
) {
1254 unsigned int w
, h
, temp_var
, done
= 0, todo
= 1;
1256 bool breakout
= false;
1257 bool dbl_down
= false;
1260 rb
->lcd_set_background(BG_COLOR
);
1261 rb
->lcd_set_foreground(FG_COLOR
);
1264 /********************
1266 ********************/
1267 temp_var
= blackjack_menu(bj
);
1272 /********************
1274 ********************/
1277 /********************
1279 ********************/
1281 resume_file
= false;
1282 /* check for resumed game */
1286 if (bj
->split_status
== 2) {
1288 player_x
= bj
->num_player_cards
[0] * 10 + 4;
1290 else if (bj
->split_status
== 3) {
1291 player_x
= bj
->num_player_cards
[1] * 10 + LCD_WIDTH
/2 + 4;
1297 bj
->player_money
= 1000;
1298 bj
->current_bet
= 10;
1299 blackjack_get_bet(bj
);
1300 if (bj
->current_bet
== 0)
1302 rb
->lcd_clear_display();
1303 deal_init_cards(bj
);
1304 blackjack_drawtable(bj
);
1312 if(bj
->player_total
== 21 && bj
->num_player_cards
[0] == 2) {
1313 bj
->is_blackjack
= true;
1314 bj
->end_hand
= true;
1317 else if(bj
->dealer_cards
[1].is_soft_ace
&& !breakout
&&
1318 !bj
->asked_insurance
) {
1319 temp_var
= insurance(bj
);
1320 if (bj
->dealer_total
== 21) {
1321 rb
->splash(HZ
, "Dealer has blackjack");
1322 bj
->player_money
+= temp_var
;
1323 bj
->end_hand
= true;
1329 rb
->splash(HZ
, "Dealer does not have blackjack");
1330 bj
->player_money
-= temp_var
;
1336 if(!bj
->end_hand
&& bj
->split_status
== 0 &&
1337 bj
->player_cards
[0][0].num
== bj
->player_cards
[0][1].num
) {
1340 rb
->lcd_update_rect(0, LCD_HEIGHT
/2, LCD_WIDTH
, LCD_HEIGHT
/2);
1341 if (bj
->split_status
== 2) {
1343 player_x
= bj
->num_player_cards
[0] * 10 + 4;
1347 while(!bj
->end_hand
&& done
< todo
) {
1348 button
= rb
->button_get(true);
1352 NEXT_CARD
= new_card();
1353 bj
->player_total
+= NEXT_CARD
.value
;
1354 draw_card(NEXT_CARD
, true, player_x
, player_y
);
1355 bj
->num_player_cards
[done
]++;
1356 if (bj
->num_player_cards
[done
] == MAX_CARDS
+ 1) {
1358 rb
->lcd_update_rect(0, LCD_HEIGHT
/2, LCD_WIDTH
,
1361 else if (bj
->num_player_cards
[done
]>MAX_CARDS
|| todo
> 1) {
1362 rb
->lcd_update_rect(player_x
, player_y
, CARD_WIDTH
+2,
1367 rb
->lcd_update_rect(player_x
, player_y
, CARD_WIDTH
+2,
1369 player_x
+= CARD_WIDTH
+ 4;
1375 bj
->end_hand
= true;
1377 case BJACK_DOUBLEDOWN
:
1378 if ((signed int)bj
->current_bet
* 2 <
1379 bj
->player_money
+ 1 &&
1380 bj
->num_player_cards
[0]==2 && todo
==1) {
1383 if (bj
->player_total
< 22) {
1384 bj
->end_hand
= true;
1388 else if((signed int)bj
->current_bet
* 2 >
1390 rb
->splash(HZ
, "Not enough money to double down.");
1395 case BJACK_RESUME
: /* save and end game */
1403 while (bj
->player_total
> 21 && !bj
->end_hand
) {
1404 temp
= check_for_aces(bj
->player_cards
[done
],
1405 bj
->num_player_cards
[done
]);
1407 bj
->player_cards
[done
][temp
].is_soft_ace
= false;
1408 bj
->player_total
-= 10;
1411 bj
->end_hand
= true;
1416 bj
->end_hand
= true;
1423 temp
= bj
->player_total
;
1424 bj
->player_total
= temp_var
;
1427 rb
->lcd_getstringsize(" Split 1 ", &w
, &h
);
1428 rb
->lcd_putsxy(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1430 rb
->lcd_update_rect(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1432 bj
->current_bet
/= 2;
1433 rb
->lcd_update_rect(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1436 bj
->player_total
= temp_var
;
1438 rb
->lcd_getstringsize(" Split 2 ", &w
, &h
);
1439 rb
->lcd_putsxy(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1441 rb
->lcd_update_rect(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1446 bj
->end_hand
= false;
1447 bj
->split_status
= 3;
1448 temp_var
= bj
->player_total
;
1449 bj
->player_total
= bj
->player_cards
[1][0].value
;
1461 if (bj
->player_money
< 10) {
1466 if (bj
->end_hand
) { /* If hand is over */
1467 if (play_again() != 0) /* User wants to quit */
1469 else { /* User keeps playing */
1471 temp
= bj
->current_bet
;
1472 bj
->current_bet
= 0;
1475 bj
->current_bet
= temp
;
1477 bj
->current_bet
/= 2;
1483 blackjack_get_bet(bj
);
1484 if (bj
->current_bet
== 0)
1486 deal_init_cards(bj
);
1487 blackjack_drawtable(bj
);
1496 /*****************************************************************************
1497 * plugin entry point.
1498 ******************************************************************************/
1499 enum plugin_status
plugin_start(const void* parameter
)
1501 struct game_context bj
;
1507 rb
->lcd_set_backdrop(NULL
);
1510 /* load high scores */
1511 highscore_load(HIGH_SCORE
,highest
,NUM_SCORES
);
1512 resume
= blackjack_loadgame(&bj
);
1513 resume_file
= resume
;
1515 rb
->lcd_setfont(FONT_SYSFIXED
);
1518 switch(blackjack(&bj
)){
1520 rb
->splash(HZ
, "Not enough money to continue");
1521 /* fall through to BJ_END */
1524 if(!resume
&& bj
.player_money
> 10) {
1525 /* There is no level, so store -1 to blank column */
1526 int position
= highscore_update(bj
.player_money
, -1, "",
1527 highest
, NUM_SCORES
);
1528 if (position
!= -1) {
1529 if (position
== 0) {
1530 rb
->splash(HZ
*2, "New High Score");
1532 highscore_show(position
, highest
, NUM_SCORES
, false);
1538 rb
->lcd_setfont(FONT_UI
);
1539 highscore_save(HIGH_SCORE
,highest
,NUM_SCORES
);
1540 return PLUGIN_USB_CONNECTED
;
1543 rb
->splash(HZ
/5, "Saving Game and Scores...");
1544 blackjack_savegame(&bj
);
1545 highscore_save(HIGH_SCORE
,highest
,NUM_SCORES
);
1548 case BJ_QUIT_WITHOUT_SAVING
:
1557 rb
->lcd_setfont(FONT_UI
);