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 SCORE_FILE PLUGIN_GAMES_DATA_DIR "/blackjack.score"
33 #define SAVE_FILE PLUGIN_GAMES_DATA_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_QUIT_NAME "OFF"
49 #define BJACK_DOUBLE_NAME "F2"
50 #define BJACK_SELECT BUTTON_PLAY
51 #define BJACK_QUIT BUTTON_OFF
52 #define BJACK_MAX (BUTTON_ON|BUTTON_UP)
53 #define BJACK_MIN (BUTTON_ON|BUTTON_DOWN)
54 #define BJACK_STAY BUTTON_F1
55 #define BJACK_DOUBLEDOWN BUTTON_F2
56 #define BJACK_UP BUTTON_UP
57 #define BJACK_DOWN BUTTON_DOWN
58 #define BJACK_RIGHT BUTTON_RIGHT
59 #define BJACK_LEFT BUTTON_LEFT
61 #elif CONFIG_KEYPAD == ONDIO_PAD
62 #define BJACK_SELECT_NAME "MENU"
63 #define BJACK_STAY_NAME "RIGHT"
64 #define BJACK_QUIT_NAME "OFF"
65 #define BJACK_DOUBLE_NAME "UP"
66 #define BJACK_SELECT BUTTON_MENU
67 #define BJACK_QUIT BUTTON_OFF
68 #define BJACK_STAY BUTTON_RIGHT
69 #define BJACK_DOUBLEDOWN BUTTON_UP
70 #define BJACK_UP BUTTON_UP
71 #define BJACK_DOWN BUTTON_DOWN
72 #define BJACK_RIGHT BUTTON_RIGHT
73 #define BJACK_LEFT BUTTON_LEFT
75 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
76 #define BJACK_SELECT_NAME "PLAY"
77 #define BJACK_STAY_NAME ">>|"
78 #define BJACK_QUIT_NAME "POWER"
79 #define BJACK_DOUBLE_NAME "|<<"
80 #define BJACK_SELECT BUTTON_PLAY
81 #define BJACK_QUIT BUTTON_POWER
82 #define BJACK_STAY BUTTON_FF
83 #define BJACK_DOUBLEDOWN BUTTON_REW
84 #define BJACK_UP BUTTON_SCROLL_UP
85 #define BJACK_DOWN BUTTON_SCROLL_DOWN
86 #define BJACK_RIGHT BUTTON_RIGHT
87 #define BJACK_LEFT BUTTON_LEFT
89 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
90 (CONFIG_KEYPAD == IRIVER_H300_PAD)
91 #define BJACK_SELECT_NAME "ON"
92 #define BJACK_STAY_NAME "REC"
93 #define BJACK_QUIT_NAME "OFF"
94 #define BJACK_DOUBLE_NAME "SELECT"
95 #define BJACK_SELECT BUTTON_ON
96 #define BJACK_QUIT BUTTON_OFF
97 #define BJACK_STAY BUTTON_REC
98 #define BJACK_DOUBLEDOWN BUTTON_SELECT
99 #define BJACK_UP BUTTON_UP
100 #define BJACK_DOWN BUTTON_DOWN
101 #define BJACK_RIGHT BUTTON_RIGHT
102 #define BJACK_LEFT BUTTON_LEFT
104 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
105 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
106 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
107 #define BJACK_SELECT_NAME "SELECT"
108 #define BJACK_STAY_NAME "RIGHT"
109 #define BJACK_RESUME_NAME "PLAY"
110 #define BJACK_QUIT_NAME "MENU"
111 #define BJACK_DOUBLE_NAME "LEFT"
112 #define BJACK_SELECT BUTTON_SELECT
113 #define BJACK_QUIT BUTTON_MENU
114 #define BJACK_STAY BUTTON_RIGHT
115 #define BJACK_DOUBLEDOWN BUTTON_LEFT
116 #define BJACK_UP BUTTON_SCROLL_FWD
117 #define BJACK_DOWN BUTTON_SCROLL_BACK
118 #define BJACK_RIGHT BUTTON_RIGHT
119 #define BJACK_LEFT BUTTON_LEFT
121 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
122 #define BJACK_SELECT_NAME "SELECT"
123 #define BJACK_STAY_NAME "REC"
124 #define BJACK_QUIT_NAME "POWER"
125 #define BJACK_DOUBLE_NAME "PLAY"
126 #define BJACK_SELECT BUTTON_SELECT
127 #define BJACK_QUIT BUTTON_POWER
128 #define BJACK_MAX (BUTTON_PLAY|BUTTON_UP)
129 #define BJACK_MIN (BUTTON_PLAY|BUTTON_DOWN)
130 #define BJACK_STAY BUTTON_REC
131 #define BJACK_DOUBLEDOWN BUTTON_PLAY
132 #define BJACK_UP BUTTON_UP
133 #define BJACK_DOWN BUTTON_DOWN
134 #define BJACK_RIGHT BUTTON_RIGHT
135 #define BJACK_LEFT BUTTON_LEFT
137 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
138 #define BJACK_SELECT_NAME "MODE"
139 #define BJACK_STAY_NAME "MODE"
140 #define BJACK_QUIT_NAME "PLAY"
141 #define BJACK_DOUBLE_NAME "SELECT"
142 #define BJACK_SELECT BUTTON_MODE
143 #define BJACK_QUIT BUTTON_PLAY
144 #define BJACK_MAX (BUTTON_EQ|BUTTON_UP)
145 #define BJACK_MIN (BUTTON_EQ|BUTTON_DOWN)
146 #define BJACK_STAY BUTTON_MODE
147 #define BJACK_DOUBLEDOWN BUTTON_SELECT
148 #define BJACK_UP BUTTON_UP
149 #define BJACK_DOWN BUTTON_DOWN
150 #define BJACK_RIGHT BUTTON_RIGHT
151 #define BJACK_LEFT BUTTON_LEFT
153 #elif CONFIG_KEYPAD == GIGABEAT_PAD
154 #define BJACK_SELECT_NAME "SELECT"
155 #define BJACK_STAY_NAME "VOL-"
156 #define BJACK_QUIT_NAME "POWER"
157 #define BJACK_DOUBLE_NAME "A"
158 #define BJACK_SELECT BUTTON_SELECT
159 #define BJACK_QUIT BUTTON_POWER
160 #define BJACK_MAX BUTTON_VOL_UP
161 #define BJACK_MIN BUTTON_VOL_DOWN
162 #define BJACK_STAY BUTTON_VOL_DOWN
163 #define BJACK_DOUBLEDOWN BUTTON_A
164 #define BJACK_UP BUTTON_UP
165 #define BJACK_DOWN BUTTON_DOWN
166 #define BJACK_RIGHT BUTTON_RIGHT
167 #define BJACK_LEFT BUTTON_LEFT
169 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
170 (CONFIG_KEYPAD == SANSA_CONNECT_PAD)
171 #define BJACK_SELECT_NAME "SELECT"
172 #define BJACK_STAY_NAME "RIGHT"
173 #define BJACK_QUIT_NAME "POWER"
174 #define BJACK_DOUBLE_NAME "LEFT"
175 #define BJACK_SELECT BUTTON_SELECT
176 #define BJACK_QUIT BUTTON_POWER
177 #define BJACK_MAX BUTTON_UP
178 #define BJACK_MIN BUTTON_DOWN
179 #define BJACK_STAY BUTTON_RIGHT
180 #define BJACK_DOUBLEDOWN BUTTON_LEFT
181 #define BJACK_UP BUTTON_SCROLL_FWD
182 #define BJACK_DOWN BUTTON_SCROLL_BACK
183 #define BJACK_RIGHT BUTTON_RIGHT
184 #define BJACK_LEFT BUTTON_LEFT
186 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
187 #define BJACK_SELECT_NAME "SELECT"
188 #define BJACK_STAY_NAME "RIGHT"
189 #define BJACK_QUIT_NAME "HOME"
190 #define BJACK_DOUBLE_NAME "LEFT"
191 #define BJACK_SELECT BUTTON_SELECT
192 #define BJACK_QUIT (BUTTON_HOME|BUTTON_REPEAT)
193 #define BJACK_MAX BUTTON_UP
194 #define BJACK_MIN BUTTON_DOWN
195 #define BJACK_STAY BUTTON_RIGHT
196 #define BJACK_DOUBLEDOWN BUTTON_LEFT
197 #define BJACK_UP BUTTON_SCROLL_FWD
198 #define BJACK_DOWN BUTTON_SCROLL_BACK
199 #define BJACK_RIGHT BUTTON_RIGHT
200 #define BJACK_LEFT BUTTON_LEFT
202 #elif CONFIG_KEYPAD == SANSA_C200_PAD
203 #define BJACK_SELECT_NAME "SELECT"
204 #define BJACK_STAY_NAME "RIGHT"
205 #define BJACK_QUIT_NAME "POWER"
206 #define BJACK_DOUBLE_NAME "LEFT"
207 #define BJACK_SELECT BUTTON_SELECT
208 #define BJACK_QUIT BUTTON_POWER
209 #define BJACK_MAX BUTTON_VOL_UP
210 #define BJACK_MIN BUTTON_VOL_DOWN
211 #define BJACK_STAY BUTTON_RIGHT
212 #define BJACK_DOUBLEDOWN BUTTON_LEFT
213 #define BJACK_UP BUTTON_UP
214 #define BJACK_DOWN BUTTON_DOWN
215 #define BJACK_RIGHT BUTTON_RIGHT
216 #define BJACK_LEFT BUTTON_LEFT
218 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
219 #define BJACK_SELECT_NAME "SELECT"
220 #define BJACK_STAY_NAME "RIGHT"
221 #define BJACK_QUIT_NAME "POWER"
222 #define BJACK_DOUBLE_NAME "LEFT"
223 #define BJACK_SELECT BUTTON_SELECT
224 #define BJACK_QUIT BUTTON_POWER
225 #define BJACK_MAX BUTTON_VOL_UP
226 #define BJACK_MIN BUTTON_VOL_DOWN
227 #define BJACK_STAY BUTTON_RIGHT
228 #define BJACK_DOUBLEDOWN BUTTON_LEFT
229 #define BJACK_UP BUTTON_UP
230 #define BJACK_DOWN BUTTON_DOWN
231 #define BJACK_RIGHT BUTTON_RIGHT
232 #define BJACK_LEFT BUTTON_LEFT
234 #elif CONFIG_KEYPAD == SANSA_M200_PAD
235 #define BJACK_SELECT_NAME "SELECT"
236 #define BJACK_STAY_NAME "RIGHT"
237 #define BJACK_QUIT_NAME "POWER"
238 #define BJACK_DOUBLE_NAME "LEFT"
239 #define BJACK_SELECT (BUTTON_SELECT | BUTTON_REL)
240 #define BJACK_QUIT BUTTON_POWER
241 #define BJACK_MAX BUTTON_VOL_UP
242 #define BJACK_MIN BUTTON_VOL_DOWN
243 #define BJACK_STAY BUTTON_RIGHT
244 #define BJACK_DOUBLEDOWN BUTTON_LEFT
245 #define BJACK_UP BUTTON_UP
246 #define BJACK_DOWN BUTTON_DOWN
247 #define BJACK_RIGHT BUTTON_RIGHT
248 #define BJACK_LEFT BUTTON_LEFT
250 #elif CONFIG_KEYPAD == TATUNG_TPJ1022_PAD
251 #define BJACK_SELECT_NAME "MAIN"
252 #define BJACK_STAY_NAME "MENU"
253 #define BJACK_QUIT_NAME "POWER"
254 #define BJACK_DOUBLE_NAME "DOWN"
255 #define BJACK_SELECT BUTTON_MAIN
256 #define BJACK_QUIT BUTTON_POWER
257 #define BJACK_MAX (BUTTON_REC|BUTTON_UP)
258 #define BJACK_MIN (BUTTON_REC|BUTTON_DOWN)
259 #define BJACK_STAY BUTTON_MENU
260 #define BJACK_DOUBLEDOWN BUTTON_DOWN
261 #define BJACK_UP BUTTON_UP
262 #define BJACK_DOWN BUTTON_DOWN
263 #define BJACK_RIGHT BUTTON_RIGHT
264 #define BJACK_LEFT BUTTON_LEFT
266 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
267 #define BJACK_SELECT_NAME "PLAY"
268 #define BJACK_STAY_NAME "VOL-"
269 #define BJACK_QUIT_NAME "BACK"
270 #define BJACK_DOUBLE_NAME "SELECT"
271 #define BJACK_SELECT BUTTON_PLAY
272 #define BJACK_QUIT BUTTON_BACK
273 #define BJACK_MAX BUTTON_VOL_UP
274 #define BJACK_MIN BUTTON_VOL_DOWN
275 #define BJACK_STAY BUTTON_VOL_DOWN
276 #define BJACK_DOUBLEDOWN BUTTON_SELECT
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 == MROBE100_PAD
283 #define BJACK_SELECT_NAME "SELECT"
284 #define BJACK_STAY_NAME "DISPLAY"
285 #define BJACK_QUIT_NAME "POWER"
286 #define BJACK_DOUBLE_NAME "DOWN"
287 #define BJACK_SELECT BUTTON_SELECT
288 #define BJACK_QUIT BUTTON_POWER
289 #define BJACK_MAX BUTTON_MENU
290 #define BJACK_MIN BUTTON_DISPLAY
291 #define BJACK_STAY BUTTON_DISPLAY
292 #define BJACK_DOUBLEDOWN BUTTON_DOWN
293 #define BJACK_UP BUTTON_UP
294 #define BJACK_DOWN BUTTON_DOWN
295 #define BJACK_RIGHT BUTTON_RIGHT
296 #define BJACK_LEFT BUTTON_LEFT
298 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
299 #define BJACK_SELECT_NAME "RC","PLAY"
300 #define BJACK_STAY_NAME "RC", ">>|"
301 #define BJACK_QUIT_NAME "RC_REC"
302 #define BJACK_DOUBLE_NAME "RC_REW"
303 #define BJACK_SELECT BUTTON_RC_PLAY
304 #define BJACK_QUIT BUTTON_RC_REC
305 #define BJACK_STAY BUTTON_RC_FF
306 #define BJACK_DOUBLEDOWN BUTTON_RC_REW
307 #define BJACK_UP BUTTON_RC_VOL_UP
308 #define BJACK_DOWN BUTTON_RC_VOL_DOWN
309 #define BJACK_RIGHT BUTTON_RC_FF
310 #define BJACK_LEFT BUTTON_RC_REW
312 #elif CONFIG_KEYPAD == COWON_D2_PAD
313 #define BJACK_QUIT_NAME "POWER"
314 #define BJACK_DOUBLE_NAME "-"
315 #define BJACK_QUIT BUTTON_POWER
316 #define BJACK_DOUBLEDOWN BUTTON_MINUS
318 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
319 #define BJACK_SELECT_NAME "SELECT"
320 #define BJACK_STAY_NAME "PLAY"
321 #define BJACK_QUIT_NAME "POWER"
322 #define BJACK_DOUBLE_NAME "CUSTOM"
323 #define BJACK_SELECT BUTTON_SELECT
324 #define BJACK_QUIT BUTTON_POWER
325 #define BJACK_STAY BUTTON_PLAY
326 #define BJACK_MAX (BUTTON_CUSTOM|BUTTON_UP)
327 #define BJACK_MIN (BUTTON_CUSTOM|BUTTON_DOWN)
328 #define BJACK_DOUBLEDOWN BUTTON_CUSTOM
329 #define BJACK_UP BUTTON_UP
330 #define BJACK_DOWN BUTTON_DOWN
331 #define BJACK_RIGHT BUTTON_RIGHT
332 #define BJACK_LEFT BUTTON_LEFT
334 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
335 #define BJACK_SELECT_NAME "SELECT"
336 #define BJACK_STAY_NAME "VOL-"
337 #define BJACK_QUIT_NAME "POWER"
338 #define BJACK_DOUBLE_NAME "MENU"
339 #define BJACK_SELECT BUTTON_SELECT
340 #define BJACK_QUIT BUTTON_POWER
341 #define BJACK_MAX BUTTON_VOL_UP
342 #define BJACK_MIN BUTTON_VOL_DOWN
343 #define BJACK_STAY BUTTON_VOL_DOWN
344 #define BJACK_DOUBLEDOWN BUTTON_MENU
345 #define BJACK_UP BUTTON_UP
346 #define BJACK_DOWN BUTTON_DOWN
347 #define BJACK_RIGHT BUTTON_RIGHT
348 #define BJACK_LEFT BUTTON_LEFT
350 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
351 #define BJACK_SELECT_NAME "PLAY"
352 #define BJACK_STAY_NAME "VOL-"
353 #define BJACK_QUIT_NAME "POWER"
354 #define BJACK_DOUBLE_NAME "MENU"
355 #define BJACK_SELECT BUTTON_PLAY
356 #define BJACK_QUIT BUTTON_POWER
357 #define BJACK_MAX BUTTON_VOL_UP
358 #define BJACK_MIN BUTTON_VOL_DOWN
359 #define BJACK_STAY BUTTON_VOL_DOWN
360 #define BJACK_DOUBLEDOWN BUTTON_MENU
361 #define BJACK_UP BUTTON_UP
362 #define BJACK_DOWN BUTTON_DOWN
363 #define BJACK_RIGHT BUTTON_RIGHT
364 #define BJACK_LEFT BUTTON_LEFT
366 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
367 #define BJACK_SELECT_NAME "MENU"
368 #define BJACK_STAY_NAME "VOL-"
369 #define BJACK_QUIT_NAME "POWER"
370 #define BJACK_DOUBLE_NAME "PLAY"
371 #define BJACK_SELECT BUTTON_MENU
372 #define BJACK_QUIT BUTTON_POWER
373 #define BJACK_MAX BUTTON_VOL_UP
374 #define BJACK_MIN BUTTON_VOL_DOWN
375 #define BJACK_STAY BUTTON_VOL_DOWN
376 #define BJACK_DOUBLEDOWN BUTTON_PLAY
377 #define BJACK_UP BUTTON_UP
378 #define BJACK_DOWN BUTTON_DOWN
379 #define BJACK_RIGHT BUTTON_NEXT
380 #define BJACK_LEFT BUTTON_PREV
382 #elif CONFIG_KEYPAD == ONDAVX747_PAD
383 #define BJACK_QUIT_NAME "POWER"
384 #define BJACK_DOUBLE_NAME "Vol-"
385 #define BJACK_QUIT BUTTON_POWER
386 #define BJACK_DOUBLEDOWN BUTTON_VOL_DOWN
388 #elif CONFIG_KEYPAD == ONDAVX777_PAD
389 #define BJACK_QUIT_NAME "POWER"
390 #define BJACK_QUIT BUTTON_POWER
392 #elif CONFIG_KEYPAD == MROBE500_PAD
393 #define BJACK_QUIT_NAME "POWER"
394 #define BJACK_QUIT BUTTON_POWER
396 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
397 #define BJACK_SELECT_NAME "PLAY"
398 #define BJACK_STAY_NAME "RECORD"
399 #define BJACK_QUIT_NAME "REW"
400 #define BJACK_DOUBLE_NAME "FFWD"
401 #define BJACK_SELECT BUTTON_PLAY
402 #define BJACK_QUIT BUTTON_REW
403 #define BJACK_STAY BUTTON_REC
404 #define BJACK_DOUBLEDOWN BUTTON_FFWD
405 #define BJACK_UP BUTTON_UP
406 #define BJACK_DOWN BUTTON_DOWN
407 #define BJACK_RIGHT BUTTON_RIGHT
408 #define BJACK_LEFT BUTTON_LEFT
410 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
411 #define BJACK_SELECT_NAME "OK"
412 #define BJACK_STAY_NAME "CANCEL"
413 #define BJACK_QUIT_NAME "REC"
414 #define BJACK_DOUBLE_NAME "MENU"
415 #define BJACK_SELECT BUTTON_OK
416 #define BJACK_QUIT BUTTON_REC
417 #define BJACK_STAY BUTTON_CANCEL
418 #define BJACK_DOUBLEDOWN BUTTON_MENU
419 #define BJACK_UP BUTTON_UP
420 #define BJACK_DOWN BUTTON_DOWN
421 #define BJACK_RIGHT BUTTON_NEXT
422 #define BJACK_LEFT BUTTON_PREV
424 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
425 #define BJACK_SELECT_NAME "FUNC"
426 #define BJACK_STAY_NAME "VOL +"
427 #define BJACK_RESUME_NAME "PLAY"
428 #define BJACK_QUIT_NAME "REC+PLAY"
429 #define BJACK_DOUBLE_NAME "VOL -"
430 #define BJACK_SELECT BUTTON_FUNC
431 #define BJACK_QUIT (BUTTON_REC|BUTTON_PLAY)
432 #define BJACK_STAY BUTTON_VOL_UP
433 #define BJACK_DOUBLEDOWN BUTTON_VOL_DOWN
434 #define BJACK_UP BUTTON_REW
435 #define BJACK_DOWN BUTTON_FF
436 #define BJACK_RIGHT BUTTON_VOL_UP
437 #define BJACK_LEFT BUTTON_VOL_DOWN
439 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
440 #define BJACK_SELECT_NAME "FUNC"
441 #define BJACK_STAY_NAME "VOL +"
442 #define BJACK_RESUME_NAME "PLAY"
443 #define BJACK_QUIT_NAME "REC+PLAY"
444 #define BJACK_DOUBLE_NAME "VOL -"
445 #define BJACK_SELECT BUTTON_ENTER
446 #define BJACK_QUIT (BUTTON_REC|BUTTON_REPEAT)
447 #define BJACK_STAY BUTTON_PLAY
448 #define BJACK_DOUBLEDOWN BUTTON_REC
449 #define BJACK_UP BUTTON_UP
450 #define BJACK_DOWN BUTTON_DOWN
451 #define BJACK_RIGHT BUTTON_FF
452 #define BJACK_LEFT BUTTON_REW
454 #elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
455 #define BJACK_SELECT_NAME "SELECT"
456 #define BJACK_STAY_NAME "PLAYPAUSE"
457 #define BJACK_RESUME_NAME ""
458 #define BJACK_QUIT_NAME "POWER"
459 #define BJACK_DOUBLE_NAME "BACK"
460 #define BJACK_SELECT BUTTON_SELECT
461 #define BJACK_QUIT BUTTON_POWER
462 #define BJACK_STAY BUTTON_PLAYPAUSE
463 #define BJACK_DOUBLEDOWN BUTTON_BACK
464 #define BJACK_UP BUTTON_UP
465 #define BJACK_DOWN BUTTON_DOWN
466 #define BJACK_RIGHT BUTTON_RIGHT
467 #define BJACK_LEFT BUTTON_LEFT
469 #elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
470 #define BJACK_SELECT_NAME "SELECT"
471 #define BJACK_STAY_NAME "MENU"
472 #define BJACK_QUIT_NAME "BACK"
473 #define BJACK_DOUBLE_NAME "USER"
474 #define BJACK_SELECT BUTTON_SELECT
475 #define BJACK_QUIT BUTTON_BACK
476 #define BJACK_MAX (BUTTON_LEFT|BUTTON_UP)
477 #define BJACK_MIN (BUTTON_RIGHT|BUTTON_DOWN)
478 #define BJACK_STAY BUTTON_MENU
479 #define BJACK_DOUBLEDOWN BUTTON_USER
480 #define BJACK_UP BUTTON_UP
481 #define BJACK_DOWN BUTTON_DOWN
482 #define BJACK_RIGHT BUTTON_RIGHT
483 #define BJACK_LEFT BUTTON_LEFT
486 #error No keymap defined!
489 #ifdef HAVE_TOUCHSCREEN
490 #ifndef BJACK_DOUBLEDOWN
491 #define BJACK_DOUBLEDOWN BUTTON_MIDLEFT
492 #define BJACK_DOUBLE_NAME "BUTTON_MIDLEFT"
495 #define BJACK_SELECT BUTTON_CENTER
496 #define BJACK_SELECT_NAME "BUTTON_CENTER"
499 #define BJACK_MAX BUTTON_TOPRIGHT
502 #define BJACK_MIN BUTTON_TOPLEFT
505 #define BJACK_STAY BUTTON_BOTTOMLEFT
506 #define BJACK_STAY_NAME "BUTTON_BOTTOMLEFT"
509 #define BJACK_UP BUTTON_TOPMIDDLE
512 #define BJACK_DOWN BUTTON_BOTTOMMIDDLE
515 #define BJACK_RIGHT BUTTON_MIDRIGHT
518 #define BJACK_LEFT BUTTON_MIDLEFT
523 #ifdef HAVE_LCD_COLOR
524 #define BG_COLOR LCD_RGBPACK(0,157,0)
525 #define FG_COLOR LCD_WHITE
527 #define BG_COLOR LCD_WHITE
528 #define FG_COLOR LCD_BLACK
531 #define CARD_WIDTH BMPWIDTH_card_back
532 #define CARD_HEIGHT BMPHEIGHT_card_back
534 /* This is the max amount of cards onscreen before condensing */
535 #define MAX_CARDS LCD_WIDTH/(CARD_WIDTH+4)
537 extern const fb_data card_deck
[];
538 extern const fb_data card_back
[];
540 #define NEXT_CARD bj->player_cards[done][bj->num_player_cards[done]]
542 /* dealer and player card positions */
543 unsigned int dealer_x
, dealer_y
, player_x
, player_y
;
545 typedef struct card
{
546 unsigned int value
; /* Card's value in Blackjack */
547 unsigned int num
; /* Value on card face 0-12 (0=Ace, 1=2, 11=Q) */
548 unsigned int suit
; /* 0:Spades, 1:Hearts, 2: Clubs; 3: Diamonds */
552 typedef struct game_context
{
553 struct card player_cards
[2][22]; /* 22 Cards means the deal was all aces */
554 struct card dealer_cards
[22]; /* That is the worst-case scenario */
555 unsigned int player_total
;
556 unsigned int dealer_total
;
557 signed int player_money
;
558 unsigned int num_player_cards
[2];
559 unsigned int num_dealer_cards
;
560 unsigned int current_bet
;
561 unsigned int split_status
; /* 0 = split hasn't been asked, *
562 * 1 = split did not occur *
563 * 2 = split occurred *
564 * 3 = split occurred and 1st hand done */
567 bool asked_insurance
;
570 static bool resume
= false;
571 static bool resume_file
= false;
572 static struct highscore highscores
[NUM_SCORES
];
574 /*****************************************************************************
575 * blackjack_init() initializes blackjack data structures.
576 ******************************************************************************/
577 static void blackjack_init(struct game_context
* bj
) {
578 /* seed the rand generator */
579 rb
->srand(*rb
->current_tick
);
581 /* reset card positions */
583 dealer_y
= LCD_HEIGHT
/4 - CARD_HEIGHT
/2;
585 player_y
= LCD_HEIGHT
- LCD_HEIGHT
/4 - CARD_HEIGHT
/2;
587 /* check for resumed game */
591 bj
->player_total
= 0;
592 bj
->dealer_total
= 0;
593 bj
->num_player_cards
[0] = 2;
594 bj
->num_player_cards
[1] = 0;
595 bj
->num_dealer_cards
= 2;
596 bj
->end_hand
= false;
597 bj
->split_status
= 0;
598 bj
->is_blackjack
= false;
599 bj
->asked_insurance
= false;
602 /*****************************************************************************
603 * blackjack_drawtable() draws the table and some text.
604 ******************************************************************************/
605 static void blackjack_drawtable(struct game_context
* bj
) {
606 unsigned int w
, h
, y_loc
;
610 rb
->lcd_getstringsize("Bet", &w
, &h
);
611 rb
->lcd_putsxy(LCD_WIDTH
- w
, 2*h
+ 1, "Bet");
612 rb
->snprintf(str
, 9, "$%d", bj
->current_bet
);
613 rb
->lcd_getstringsize(str
, &w
, &h
);
614 rb
->lcd_putsxy(LCD_WIDTH
- w
, 3*h
+ 1, str
);
615 y_loc
= LCD_HEIGHT
/2;
617 rb
->lcd_getstringsize("Bet", &w
, &h
);
618 rb
->lcd_putsxy(LCD_WIDTH
- w
, 5*h
/ 2, "Bet");
619 rb
->snprintf(str
, 9, "$%d", bj
->current_bet
);
620 rb
->lcd_getstringsize(str
, &w
, &h
);
621 rb
->lcd_putsxy(LCD_WIDTH
- w
, 7*h
/ 2, str
);
622 rb
->lcd_hline(0, LCD_WIDTH
, LCD_HEIGHT
/2);
623 y_loc
= LCD_HEIGHT
/2 + h
;
626 rb
->lcd_putsxy(0,0, "Dealer");
627 rb
->lcd_getstringsize("Player", &w
, &h
);
628 rb
->lcd_putsxy(0, y_loc
, "Player");
629 rb
->lcd_getstringsize("Total", &w
, &h
);
630 rb
->lcd_putsxy(LCD_WIDTH
- w
, y_loc
, "Total");
631 rb
->lcd_getstringsize("Money", &w
, &h
);
632 rb
->lcd_putsxy(LCD_WIDTH
- w
, 0, "Money");
633 rb
->snprintf(str
, 9, "$%d", bj
->player_money
- bj
->current_bet
);
634 rb
->lcd_getstringsize(str
, &w
, &h
);
635 rb
->lcd_putsxy(LCD_WIDTH
- w
, h
+ 1, str
);
636 rb
->snprintf(str
, 3, "%d", bj
->player_total
);
637 rb
->lcd_getstringsize(str
, &w
, &h
);
638 rb
->lcd_putsxy(LCD_WIDTH
- w
, y_loc
+ h
, str
);
641 /*****************************************************************************
642 * find_value() is passed a card and returns its blackjack value.
643 ******************************************************************************/
644 static unsigned int find_value(unsigned int number
) {
645 unsigned int thisValue
;
647 thisValue
= 11; /* Aces get a value of 11 at first */
648 else if (number
< 10)
649 thisValue
= number
+ 1;
651 thisValue
= 10; /* Anything 10 or higher gets a value of 10 */
656 /*****************************************************************************
657 * draw_card() draws a card to the screen.
658 ******************************************************************************/
659 static void draw_card(struct card temp_card
, bool shown
,
660 unsigned int x
, unsigned int y
) {
662 rb
->lcd_bitmap_part(card_deck
, CARD_WIDTH
*temp_card
.num
,
663 CARD_HEIGHT
*temp_card
.suit
,
664 STRIDE( SCREEN_MAIN
, BMPWIDTH_card_deck
,
665 BMPHEIGHT_card_deck
),
666 x
+1, y
+1, CARD_WIDTH
, CARD_HEIGHT
);
668 rb
->lcd_bitmap(card_back
, x
+1, y
+1,CARD_WIDTH
, CARD_HEIGHT
);
670 rb
->lcd_set_foreground(LCD_BLACK
);
675 rb
->lcd_hline(x
+2, x
+CARD_WIDTH
-1, y
);
676 rb
->lcd_hline(x
+2, x
+CARD_WIDTH
-1, y
+CARD_HEIGHT
+1);
677 rb
->lcd_vline(x
, y
+2, y
+CARD_HEIGHT
-3);
678 rb
->lcd_vline(x
+CARD_WIDTH
+1, y
+2, y
+CARD_HEIGHT
-1);
679 rb
->lcd_drawpixel(x
+1, y
+1);
680 rb
->lcd_drawpixel(x
+1, y
+CARD_HEIGHT
);
681 rb
->lcd_drawpixel(x
+CARD_WIDTH
, y
+1);
682 rb
->lcd_drawpixel(x
+CARD_WIDTH
, y
+CARD_HEIGHT
);
684 rb
->lcd_hline(x
+1, x
+CARD_WIDTH
, y
);
685 rb
->lcd_hline(x
+1, x
+CARD_WIDTH
, y
+CARD_HEIGHT
+1);
686 rb
->lcd_vline(x
, y
+1, y
+CARD_HEIGHT
);
687 rb
->lcd_vline(x
+CARD_WIDTH
+1, y
+1, y
+CARD_HEIGHT
);
691 rb
->lcd_set_foreground(FG_COLOR
);
695 /*****************************************************************************
696 * new_card() initializes a new card and gives it values.
697 ******************************************************************************/
698 static struct card
new_card(void) {
699 struct card new_card
;
700 new_card
.suit
= rb
->rand()%4; /* Random number 0-3 */
701 new_card
.num
= rb
->rand()%13; /* Random number 0-12 */
702 new_card
.value
= find_value(new_card
.num
);
703 new_card
.is_soft_ace
= (new_card
.num
== 0);
707 /*****************************************************************************
708 * deal_init_card() deals and draws to the screen the player's and dealer's
710 ******************************************************************************/
711 static void deal_init_cards(struct game_context
* bj
) {
712 bj
->dealer_cards
[0] = new_card();
713 bj
->dealer_total
+= bj
->dealer_cards
[0].value
;
715 draw_card(bj
->dealer_cards
[0], false, dealer_x
, dealer_y
);
717 bj
->dealer_cards
[1] = new_card();
718 bj
->dealer_total
+= bj
->dealer_cards
[1].value
;
719 draw_card(bj
->dealer_cards
[1], true, dealer_x
+ CARD_WIDTH
+ 4, dealer_y
);
721 bj
->player_cards
[0][0] = new_card();
722 bj
->player_total
+= bj
->player_cards
[0][0].value
;
723 draw_card(bj
->player_cards
[0][0], true, player_x
, player_y
);
724 player_x
+= CARD_WIDTH
+ 4;
726 bj
->player_cards
[0][1] = new_card();
727 bj
->player_total
+= bj
->player_cards
[0][1].value
;
728 draw_card(bj
->player_cards
[0][1], true, player_x
, player_y
);
729 player_x
+= CARD_WIDTH
+ 4;
732 /*****************************************************************************
733 * redraw_board() redraws all the cards and the board
734 ******************************************************************************/
735 static void redraw_board(struct game_context
* bj
) {
736 unsigned int i
, n
, upper_bound
;
737 rb
->lcd_clear_display();
739 blackjack_drawtable(bj
);
742 upper_bound
= bj
->split_status
> 1 ? 2 : 1;
744 for (i
= 0; i
< bj
->num_dealer_cards
; i
++) {
746 draw_card(bj
->dealer_cards
[0], false, dealer_x
, dealer_y
);
748 /* increment i so the dealer's first card isn't displayed */
750 dealer_x
+= CARD_WIDTH
+ 4;
752 draw_card(bj
->dealer_cards
[i
], true, dealer_x
, dealer_y
);
754 if (bj
->num_dealer_cards
> MAX_CARDS
-1)
757 dealer_x
+= CARD_WIDTH
+ 4;
760 for (n
= 0; n
< upper_bound
; n
++) {
761 for (i
= 0; i
< bj
->num_player_cards
[n
]; i
++) {
762 draw_card(bj
->player_cards
[n
][i
], true, player_x
, player_y
);
763 if (bj
->split_status
>1 || bj
->num_player_cards
[n
]>MAX_CARDS
)
766 player_x
+= CARD_WIDTH
+ 4;
768 if (bj
->split_status
> 1)
769 player_x
= LCD_WIDTH
/2 + 4;
773 /*****************************************************************************
774 * update_total updates the player's total
775 ******************************************************************************/
776 static void update_total(struct game_context
* bj
) {
779 rb
->snprintf(total
, 3, "%d", bj
->player_total
);
780 rb
->lcd_getstringsize(total
, &w
, &h
);
784 rb
->lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 + h
, total
);
785 rb
->lcd_update_rect(LCD_WIDTH
- w
, LCD_HEIGHT
/2 + h
, w
, h
);
789 /*****************************************************************************
790 * check_for_aces() is passed an array of cards and returns where an ace is
791 * located. Otherwise, returns -1.
792 ******************************************************************************/
793 static signed int check_for_aces(struct card temp_cards
[], unsigned int size
) {
795 for(i
= 0; i
< size
; i
++) {
796 if (temp_cards
[i
].is_soft_ace
)
802 /*****************************************************************************
803 * check_totals() compares player and dealer totals.
804 * 0: bust 1: loss, 2: push, 3: win, 4: blackjack, 5: something's not right...
805 ******************************************************************************/
806 static unsigned int check_totals(struct game_context
* bj
) {
808 if (bj
->player_total
> 21)
810 else if (bj
->player_total
== 21 && bj
->is_blackjack
) {
811 if (bj
->dealer_total
== 21 && bj
->num_dealer_cards
== 2)
816 else if (bj
->player_total
== bj
->dealer_total
)
818 else if (bj
->dealer_total
> 21 && bj
->player_total
< 22)
820 else if (bj
->dealer_total
> bj
->player_total
)
822 else if (bj
->player_total
> bj
->dealer_total
)
830 /*****************************************************************************
831 * finish_dealer() draws cards for the dealer until he has 17 or more.
832 ******************************************************************************/
833 static void finish_dealer(struct game_context
* bj
) {
836 if (bj
->dealer_total
> 16 && bj
->dealer_total
< 22)
839 while (bj
->dealer_total
< 17) {
840 bj
->dealer_cards
[bj
->num_dealer_cards
] = new_card();
841 bj
->dealer_total
+= bj
->dealer_cards
[bj
->num_dealer_cards
].value
;
842 bj
->num_dealer_cards
++;
845 while (bj
->dealer_total
> 21) {
846 temp
= check_for_aces(bj
->dealer_cards
, bj
->num_dealer_cards
);
848 bj
->dealer_cards
[temp
].is_soft_ace
= false;
849 bj
->dealer_total
-= 10;
856 /*****************************************************************************
857 * finish_game() completes the game once player's turn is over.
858 ******************************************************************************/
859 static void finish_game(struct game_context
* bj
) {
860 unsigned int rValue
, w
, h
;
865 } while (bj
->dealer_total
< 17);
868 rValue
= check_totals(bj
);
871 rb
->snprintf(str
, sizeof(str
), " Bust! ");
872 bj
->player_money
-= bj
->current_bet
;
874 else if (rValue
== 1) {
875 rb
->snprintf(str
, sizeof(str
), " Sorry, you lost. ");
876 bj
->player_money
-= bj
->current_bet
;
878 else if (rValue
== 2) {
879 rb
->snprintf(str
, sizeof(str
), " Push ");
881 else if (rValue
== 3) {
882 rb
->snprintf(str
, sizeof(str
), " You won! ");
883 bj
->player_money
+= bj
->current_bet
;
886 rb
->snprintf(str
, sizeof(str
), " Blackjack! ");
887 bj
->player_money
+= bj
->current_bet
* 3 / 2;
889 rb
->lcd_getstringsize(str
, &w
, &h
);
892 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
893 rb
->lcd_fillrect(0, LCD_HEIGHT
/2, LCD_WIDTH
, LCD_HEIGHT
/2);
894 rb
->lcd_set_drawmode(DRMODE_SOLID
);
895 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + h
, str
);
896 rb
->snprintf(str
, 12, "You have %d", bj
->player_total
);
897 rb
->lcd_getstringsize(str
, &w
, &h
);
898 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2, str
);
900 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 - h
/2, str
);
905 /*****************************************************************************
906 * blackjack_loadgame() loads the saved game and returns load success.
907 ******************************************************************************/
908 static bool blackjack_loadgame(struct game_context
* bj
) {
913 fd
= rb
->open(SAVE_FILE
, O_RDONLY
);
914 if(fd
< 0) return false;
916 /* read in saved game */
917 if(rb
->read(fd
, bj
, sizeof(struct game_context
))
918 == (long)sizeof(struct game_context
))
928 /*****************************************************************************
929 * blackjack_savegame() saves the current game state.
930 ******************************************************************************/
931 static void blackjack_savegame(struct game_context
* bj
) {
936 /* write out the game state to the save file */
937 fd
= rb
->open(SAVE_FILE
, O_WRONLY
|O_CREAT
, 0666);
940 rb
->write(fd
, bj
, sizeof(struct game_context
));
944 /*****************************************************************************
945 * blackjack_get_yes_no() gets a yes/no answer from the user
946 ******************************************************************************/
947 static unsigned int blackjack_get_yes_no(char message
[20]) {
949 unsigned int w
, h
, b
, choice
= 0;
950 bool breakout
= false;
951 char message_yes
[24], message_no
[24];
953 rb
->strcpy(message_yes
, message
);
954 rb
->strcpy(message_no
, message
);
955 rb
->strcat(message_yes
, " Yes");
956 rb
->strcat(message_no
, " No");
957 rb
->lcd_getstringsize(message_yes
, &w
, &h
);
958 const char *stg
[] = {message_yes
, message_no
};
966 #ifdef HAVE_LCD_COLOR
967 rb
->lcd_fillrect(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + b
, w
+1, h
+3);
968 rb
->lcd_set_foreground(LCD_BLACK
);
969 rb
->lcd_set_background(LCD_WHITE
);
971 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
972 rb
->lcd_fillrect(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + b
, w
+1, h
+3);
973 rb
->lcd_set_drawmode(DRMODE_SOLID
);
975 rb
->lcd_drawrect(LCD_WIDTH
/2 - w
/2 - 1, LCD_HEIGHT
/2 + b
- 1, w
+3, h
+4);
978 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + b
+1, stg
[choice
]);
979 rb
->lcd_update_rect(LCD_WIDTH
/2 - w
/2 - 1, LCD_HEIGHT
/2 + b
-1,
981 button
= rb
->button_get(true);
985 case (BJACK_LEFT
|BUTTON_REPEAT
):
987 case (BJACK_RIGHT
|BUTTON_REPEAT
):
990 case BJACK_SELECT
: breakout
= true;
992 case BJACK_QUIT
: breakout
= true;
999 rb
->lcd_set_foreground(FG_COLOR
);
1000 rb
->lcd_set_background(BG_COLOR
);
1005 /*****************************************************************************
1006 * blackjack_get_amount() gets an amount from the player to be used
1007 ******************************************************************************/
1008 static signed int blackjack_get_amount(char message
[20], signed int lower_limit
,
1009 signed int upper_limit
,
1012 bool breakout
= false, changed
= false;
1016 rb
->lcd_getstringsize("A", &w
, &h
); /* find the size of one character */
1018 if (start
> upper_limit
)
1019 amount
= upper_limit
;
1020 else if (start
< lower_limit
)
1021 amount
= lower_limit
;
1026 rb
->lcd_set_background(LCD_WHITE
);
1027 rb
->lcd_set_foreground(LCD_BLACK
);
1030 #if LCD_HEIGHT <= 64
1031 rb
->lcd_clear_display();
1032 rb
->lcd_puts(0, 1, message
);
1033 rb
->lcd_putsf(0, 2, "$%d", amount
);
1034 rb
->lcd_puts(0, 3, "RIGHT: +1");
1035 rb
->lcd_puts(0, 4, "LEFT: -1");
1036 rb
->lcd_puts(0, 5, "UP: +10");
1037 rb
->lcd_puts(0, 6, "DOWN: -10");
1040 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
1041 rb
->lcd_fillrect(LCD_WIDTH
/2 - 9*w
- 1, LCD_HEIGHT
/2 - 4*h
- 3,
1043 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1044 rb
->lcd_drawrect(LCD_WIDTH
/2 - 9*w
- 1, LCD_HEIGHT
/2 - 4*h
- 3,
1046 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 4*h
- 1, message
);
1047 rb
->lcd_putsxyf(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, "$%d", amount
);
1048 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
1049 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
1050 (CONFIG_KEYPAD == IPOD_1G2G_PAD) || \
1051 (CONFIG_KEYPAD == SANSA_E200_PAD) || \
1052 (CONFIG_KEYPAD == SANSA_FUZE_PAD) || \
1053 (CONFIG_KEYPAD == SANSA_CONNECT_PAD)
1054 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - h
-2, " >>|: +1");
1055 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 1, " |<<: -1");
1056 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + h
, "SCROLL+: +10");
1057 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + 2*h
+ 1, "SCROLL-: -10");
1058 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
1059 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - h
-2, "RIGHT: +1");
1060 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 1, "LEFT: -1");
1061 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + h
, "SCROLL+: +10");
1062 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + 2*h
+ 1, "SCROLL-: -10");
1064 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - h
-2, "RIGHT: +1");
1065 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 1, "LEFT: -1");
1066 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + h
, "UP: +10");
1067 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + 2*h
+ 1, "DOWN: -10");
1069 rb
->lcd_update_rect(LCD_WIDTH
/2 - 9*w
- 1, LCD_HEIGHT
/2 - 4*h
- 3,
1074 button
= rb
->button_get(true);
1078 case (BJACK_UP
|BUTTON_REPEAT
):
1079 if (amount
+ 10 < upper_limit
+ 1) {
1085 case (BJACK_DOWN
|BUTTON_REPEAT
):
1086 if (amount
- 10 > lower_limit
- 1) {
1092 case (BJACK_RIGHT
|BUTTON_REPEAT
):
1093 if (amount
+ 1 < upper_limit
+ 1) {
1099 case (BJACK_LEFT
|BUTTON_REPEAT
):
1100 if (amount
- 1 > lower_limit
- 1) {
1107 amount
= upper_limit
;
1113 amount
= lower_limit
;
1127 #if LCD_HEIGHT <= 64
1128 rb
->lcd_putsf(0, 2, "$%d", amount
);
1131 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
1132 rb
->lcd_fillrect(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, 5*w
, h
);
1133 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1134 rb
->lcd_putsxyf(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, "$%d", amount
);
1135 rb
->lcd_update_rect(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, 5*w
, h
);
1142 rb
->lcd_set_foreground(FG_COLOR
);
1143 rb
->lcd_set_background(BG_COLOR
);
1145 rb
->lcd_clear_display();
1149 /*****************************************************************************
1150 * blackjack_get_bet() gets the player's bet.
1151 ******************************************************************************/
1152 static void blackjack_get_bet(struct game_context
* bj
) {
1153 bj
->current_bet
= blackjack_get_amount("Please enter a bet", 10,
1154 bj
->player_money
, bj
->current_bet
);
1157 /*****************************************************************************
1158 * double_down() returns one final card then finishes the game
1159 ******************************************************************************/
1160 static void double_down(struct game_context
* bj
) {
1161 bj
->current_bet
*= 2;
1162 bj
->player_cards
[0][bj
->num_player_cards
[0]] = new_card();
1163 bj
->player_total
+= bj
->player_cards
[0][bj
->num_player_cards
[0]].value
;
1164 bj
->num_player_cards
[0]++;
1167 /*****************************************************************************
1168 * split() checks if the player wants to split and acts accordingly.
1169 * When bj->split_status is 1, no split occurred. 2 means the player split and 3
1170 * means a split has already occurred and the first hand is done.
1171 ******************************************************************************/
1172 static void split(struct game_context
* bj
) {
1173 if (blackjack_get_yes_no("Split?") != 0)
1174 bj
->split_status
= 1;
1176 bj
->split_status
= 2;
1177 bj
->current_bet
*= 2;
1178 bj
->num_player_cards
[0] = 1;
1179 bj
->num_player_cards
[1] = 1;
1180 bj
->player_cards
[1][0] = bj
->player_cards
[0][1];
1181 bj
->player_total
= bj
->player_cards
[0][0].value
;
1185 /*****************************************************************************
1186 * insurance() see if the player wants to buy insurance and how much.
1187 ******************************************************************************/
1188 static unsigned int insurance(struct game_context
* bj
) {
1189 unsigned int insurance
, max_amount
;
1191 insurance
= blackjack_get_yes_no("Buy Insurance?");
1192 bj
->asked_insurance
= true;
1193 max_amount
= bj
->current_bet
< (unsigned int)bj
->player_money
?
1194 bj
->current_bet
/2 : (unsigned int)bj
->player_money
;
1195 if (insurance
!= 0) return 0;
1197 insurance
= blackjack_get_amount("How much?", 0, max_amount
, 0);
1202 /*****************************************************************************
1203 * play_again() checks to see if the player wants to keep playing.
1204 ******************************************************************************/
1205 static unsigned int play_again(void) {
1206 return blackjack_get_yes_no("Play Again?");
1209 /*****************************************************************************
1210 * blackjack_help() displays help text.
1211 ******************************************************************************/
1212 static bool blackjack_help(void) {
1213 static char *help_text
[] = {
1214 "Blackjack", "", "Aim", "",
1215 "Try", "to", "get", "as", "close", "to", "21", "without", "going",
1216 "over", "or", "simply", "beat", "out", "the", "dealer", "for", "the",
1217 "best", "hand.", "", "",
1219 BJACK_SELECT_NAME
, ":", "hit", "/", "select", "",
1220 BJACK_STAY_NAME
, ":", "stay", "",
1221 BJACK_DOUBLE_NAME
, ":", "double", "down", "",
1222 BJACK_QUIT_NAME
, ":", "go", "to", "menu", "",
1224 static struct style_text formation
[]={
1225 { 0, TEXT_CENTER
|TEXT_UNDERLINE
},
1231 rb
->lcd_setfont(FONT_UI
);
1232 #ifdef HAVE_LCD_COLOR
1233 rb
->lcd_set_background(LCD_BLACK
);
1234 rb
->lcd_set_foreground(LCD_WHITE
);
1236 if (display_text(ARRAYLEN(help_text
), help_text
, formation
, NULL
, true))
1238 rb
->lcd_setfont(FONT_SYSFIXED
);
1243 static int blackjack_menu_cb(int action
, const struct menu_item_ex
*this_item
)
1245 int i
= ((intptr_t)this_item
);
1246 if(action
== ACTION_REQUEST_MENUITEM
1247 && !resume
&& (i
==0 || i
==5))
1248 return ACTION_EXIT_MENUITEM
;
1252 /*****************************************************************************
1253 * blackjack_menu() is the initial menu at the start of the game.
1254 ******************************************************************************/
1255 static unsigned int blackjack_menu(void) {
1257 bool breakout
= false;
1259 MENUITEM_STRINGLIST(menu
, "BlackJack Menu", blackjack_menu_cb
,
1260 "Resume Game", "Start New Game",
1261 "High Scores", "Help",
1263 "Quit without Saving", "Quit");
1266 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1270 rb
->remove(SAVE_FILE
);
1271 resume_file
= false;
1278 highscore_show(-1, highscores
, NUM_SCORES
, false);
1281 if(blackjack_help())
1285 if (playback_control(NULL
))
1289 return BJ_QUIT_WITHOUT_SAVING
;
1294 return BJ_QUIT_WITHOUT_SAVING
;
1296 case MENU_ATTACHED_USB
:
1307 /*****************************************************************************
1308 * blackjack() is the main game subroutine, it returns the final game status.
1309 ******************************************************************************/
1310 static int blackjack(struct game_context
* bj
) {
1312 unsigned int w
, h
, temp_var
, done
= 0, todo
= 1;
1314 bool breakout
= false;
1315 bool dbl_down
= false;
1317 /********************
1319 ********************/
1320 temp_var
= blackjack_menu();
1325 rb
->lcd_set_background(BG_COLOR
);
1326 rb
->lcd_set_foreground(FG_COLOR
);
1329 /********************
1331 ********************/
1334 /********************
1336 ********************/
1338 resume_file
= false;
1339 /* check for resumed game */
1343 if (bj
->split_status
== 2) {
1345 player_x
= bj
->num_player_cards
[0] * 10 + 4;
1347 else if (bj
->split_status
== 3) {
1348 player_x
= bj
->num_player_cards
[1] * 10 + LCD_WIDTH
/2 + 4;
1354 bj
->player_money
= 1000;
1355 bj
->current_bet
= 10;
1356 blackjack_get_bet(bj
);
1357 if (bj
->current_bet
== 0)
1359 rb
->lcd_clear_display();
1360 deal_init_cards(bj
);
1361 blackjack_drawtable(bj
);
1369 if(bj
->player_total
== 21 && bj
->num_player_cards
[0] == 2) {
1370 bj
->is_blackjack
= true;
1371 bj
->end_hand
= true;
1374 else if(bj
->dealer_cards
[1].is_soft_ace
&& !breakout
&&
1375 !bj
->asked_insurance
) {
1376 temp_var
= insurance(bj
);
1377 if (bj
->dealer_total
== 21) {
1378 rb
->splash(HZ
, "Dealer has blackjack");
1379 bj
->player_money
+= temp_var
;
1380 bj
->end_hand
= true;
1386 rb
->splash(HZ
, "Dealer does not have blackjack");
1387 bj
->player_money
-= temp_var
;
1393 if(!bj
->end_hand
&& bj
->split_status
== 0 &&
1394 bj
->player_cards
[0][0].num
== bj
->player_cards
[0][1].num
) {
1397 rb
->lcd_update_rect(0, LCD_HEIGHT
/2, LCD_WIDTH
, LCD_HEIGHT
/2);
1398 if (bj
->split_status
== 2) {
1400 player_x
= bj
->num_player_cards
[0] * 10 + 4;
1404 while(!bj
->end_hand
&& done
< todo
) {
1405 button
= rb
->button_get(true);
1409 NEXT_CARD
= new_card();
1410 bj
->player_total
+= NEXT_CARD
.value
;
1411 draw_card(NEXT_CARD
, true, player_x
, player_y
);
1412 bj
->num_player_cards
[done
]++;
1413 if (bj
->num_player_cards
[done
] == MAX_CARDS
+ 1) {
1415 rb
->lcd_update_rect(0, LCD_HEIGHT
/2, LCD_WIDTH
,
1418 else if (bj
->num_player_cards
[done
]>MAX_CARDS
|| todo
> 1) {
1419 rb
->lcd_update_rect(player_x
, player_y
, CARD_WIDTH
+2,
1424 rb
->lcd_update_rect(player_x
, player_y
, CARD_WIDTH
+2,
1426 player_x
+= CARD_WIDTH
+ 4;
1432 bj
->end_hand
= true;
1434 case BJACK_DOUBLEDOWN
:
1435 if ((signed int)bj
->current_bet
* 2 <
1436 bj
->player_money
+ 1 &&
1437 bj
->num_player_cards
[0]==2 && todo
==1) {
1440 if (bj
->player_total
< 22) {
1441 bj
->end_hand
= true;
1445 else if((signed int)bj
->current_bet
* 2 >
1447 rb
->splash(HZ
, "Not enough money to double down.");
1458 while (bj
->player_total
> 21 && !bj
->end_hand
) {
1459 temp
= check_for_aces(bj
->player_cards
[done
],
1460 bj
->num_player_cards
[done
]);
1462 bj
->player_cards
[done
][temp
].is_soft_ace
= false;
1463 bj
->player_total
-= 10;
1466 bj
->end_hand
= true;
1471 bj
->end_hand
= true;
1478 temp
= bj
->player_total
;
1479 bj
->player_total
= temp_var
;
1482 rb
->lcd_getstringsize(" Split 1 ", &w
, &h
);
1483 rb
->lcd_putsxy(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1485 rb
->lcd_update_rect(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1487 bj
->current_bet
/= 2;
1488 rb
->lcd_update_rect(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1491 bj
->player_total
= temp_var
;
1493 rb
->lcd_getstringsize(" Split 2 ", &w
, &h
);
1494 rb
->lcd_putsxy(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1496 rb
->lcd_update_rect(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1501 bj
->end_hand
= false;
1502 bj
->split_status
= 3;
1503 temp_var
= bj
->player_total
;
1504 bj
->player_total
= bj
->player_cards
[1][0].value
;
1516 if (bj
->player_money
< 10) {
1521 if (bj
->end_hand
) { /* If hand is over */
1522 if (play_again() != 0) /* User wants to quit */
1524 else { /* User keeps playing */
1526 temp
= bj
->current_bet
;
1527 bj
->current_bet
= 0;
1530 bj
->current_bet
= temp
;
1532 bj
->current_bet
/= 2;
1538 blackjack_get_bet(bj
);
1539 if (bj
->current_bet
== 0)
1541 deal_init_cards(bj
);
1542 blackjack_drawtable(bj
);
1551 /*****************************************************************************
1552 * plugin entry point.
1553 ******************************************************************************/
1554 enum plugin_status
plugin_start(const void* parameter
)
1556 struct game_context bj
;
1562 rb
->lcd_set_backdrop(NULL
);
1565 /* load high scores */
1566 highscore_load(SCORE_FILE
, highscores
, NUM_SCORES
);
1567 resume
= blackjack_loadgame(&bj
);
1568 resume_file
= resume
;
1570 rb
->lcd_setfont(FONT_SYSFIXED
);
1573 switch(blackjack(&bj
)){
1575 rb
->splash(HZ
, "Not enough money to continue");
1576 /* fall through to BJ_END */
1579 if(!resume
&& bj
.player_money
> 10) {
1580 /* There is no level, so store -1 to blank column */
1581 int position
= highscore_update(bj
.player_money
, -1, "",
1582 highscores
, NUM_SCORES
);
1586 rb
->splash(HZ
*2, "New High Score");
1587 highscore_show(position
, highscores
, NUM_SCORES
, false);
1593 highscore_save(SCORE_FILE
, highscores
, NUM_SCORES
);
1594 return PLUGIN_USB_CONNECTED
;
1597 rb
->splash(HZ
*1, "Saving game...");
1598 blackjack_savegame(&bj
);
1601 case BJ_QUIT_WITHOUT_SAVING
:
1609 highscore_save(SCORE_FILE
, highscores
, NUM_SCORES
);