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 || CONFIG_KEYPAD == SANSA_CLIP_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_M200_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 | BUTTON_REL)
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 == TATUNG_TPJ1022_PAD
235 #define BJACK_SELECT_NAME "MAIN"
236 #define BJACK_STAY_NAME "MENU"
237 #define BJACK_QUIT_NAME "POWER"
238 #define BJACK_DOUBLE_NAME "DOWN"
239 #define BJACK_SELECT BUTTON_MAIN
240 #define BJACK_QUIT BUTTON_POWER
241 #define BJACK_MAX (BUTTON_REC|BUTTON_UP)
242 #define BJACK_MIN (BUTTON_REC|BUTTON_DOWN)
243 #define BJACK_STAY BUTTON_MENU
244 #define BJACK_DOUBLEDOWN BUTTON_DOWN
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 == GIGABEAT_S_PAD
251 #define BJACK_SELECT_NAME "PLAY"
252 #define BJACK_STAY_NAME "VOL-"
253 #define BJACK_QUIT_NAME "BACK"
254 #define BJACK_DOUBLE_NAME "SELECT"
255 #define BJACK_SELECT BUTTON_PLAY
256 #define BJACK_QUIT BUTTON_BACK
257 #define BJACK_MAX BUTTON_VOL_UP
258 #define BJACK_MIN BUTTON_VOL_DOWN
259 #define BJACK_STAY BUTTON_VOL_DOWN
260 #define BJACK_DOUBLEDOWN BUTTON_SELECT
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 == MROBE100_PAD
267 #define BJACK_SELECT_NAME "SELECT"
268 #define BJACK_STAY_NAME "DISPLAY"
269 #define BJACK_QUIT_NAME "POWER"
270 #define BJACK_DOUBLE_NAME "DOWN"
271 #define BJACK_SELECT BUTTON_SELECT
272 #define BJACK_QUIT BUTTON_POWER
273 #define BJACK_MAX BUTTON_MENU
274 #define BJACK_MIN BUTTON_DISPLAY
275 #define BJACK_STAY BUTTON_DISPLAY
276 #define BJACK_DOUBLEDOWN 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 == IAUDIO_M3_PAD
283 #define BJACK_SELECT_NAME "RC","PLAY"
284 #define BJACK_STAY_NAME "RC", ">>|"
285 #define BJACK_QUIT_NAME "RC_REC"
286 #define BJACK_DOUBLE_NAME "RC_REW"
287 #define BJACK_SELECT BUTTON_RC_PLAY
288 #define BJACK_QUIT BUTTON_RC_REC
289 #define BJACK_STAY BUTTON_RC_FF
290 #define BJACK_DOUBLEDOWN BUTTON_RC_REW
291 #define BJACK_UP BUTTON_RC_VOL_UP
292 #define BJACK_DOWN BUTTON_RC_VOL_DOWN
293 #define BJACK_RIGHT BUTTON_RC_FF
294 #define BJACK_LEFT BUTTON_RC_REW
296 #elif CONFIG_KEYPAD == COWON_D2_PAD
297 #define BJACK_QUIT_NAME "POWER"
298 #define BJACK_DOUBLE_NAME "-"
299 #define BJACK_QUIT BUTTON_POWER
300 #define BJACK_DOUBLEDOWN BUTTON_MINUS
302 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
303 #define BJACK_SELECT_NAME "SELECT"
304 #define BJACK_STAY_NAME "PLAY"
305 #define BJACK_QUIT_NAME "POWER"
306 #define BJACK_DOUBLE_NAME "CUSTOM"
307 #define BJACK_SELECT BUTTON_SELECT
308 #define BJACK_QUIT BUTTON_POWER
309 #define BJACK_STAY BUTTON_PLAY
310 #define BJACK_MAX (BUTTON_CUSTOM|BUTTON_UP)
311 #define BJACK_MIN (BUTTON_CUSTOM|BUTTON_DOWN)
312 #define BJACK_DOUBLEDOWN BUTTON_CUSTOM
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 == PHILIPS_HDD1630_PAD
319 #define BJACK_SELECT_NAME "SELECT"
320 #define BJACK_STAY_NAME "VOL-"
321 #define BJACK_QUIT_NAME "POWER"
322 #define BJACK_DOUBLE_NAME "MENU"
323 #define BJACK_SELECT BUTTON_SELECT
324 #define BJACK_QUIT BUTTON_POWER
325 #define BJACK_MAX BUTTON_VOL_UP
326 #define BJACK_MIN BUTTON_VOL_DOWN
327 #define BJACK_STAY BUTTON_VOL_DOWN
328 #define BJACK_DOUBLEDOWN BUTTON_MENU
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_HDD6330_PAD
335 #define BJACK_SELECT_NAME "PLAY"
336 #define BJACK_STAY_NAME "VOL-"
337 #define BJACK_QUIT_NAME "POWER"
338 #define BJACK_DOUBLE_NAME "MENU"
339 #define BJACK_SELECT BUTTON_PLAY
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_SA9200_PAD
351 #define BJACK_SELECT_NAME "MENU"
352 #define BJACK_STAY_NAME "VOL-"
353 #define BJACK_QUIT_NAME "POWER"
354 #define BJACK_DOUBLE_NAME "PLAY"
355 #define BJACK_SELECT BUTTON_MENU
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_PLAY
361 #define BJACK_UP BUTTON_UP
362 #define BJACK_DOWN BUTTON_DOWN
363 #define BJACK_RIGHT BUTTON_NEXT
364 #define BJACK_LEFT BUTTON_PREV
366 #elif CONFIG_KEYPAD == ONDAVX747_PAD
367 #define BJACK_QUIT_NAME "POWER"
368 #define BJACK_DOUBLE_NAME "Vol-"
369 #define BJACK_QUIT BUTTON_POWER
370 #define BJACK_DOUBLEDOWN BUTTON_VOL_DOWN
372 #elif CONFIG_KEYPAD == ONDAVX777_PAD
373 #define BJACK_QUIT_NAME "POWER"
374 #define BJACK_QUIT BUTTON_POWER
376 #elif CONFIG_KEYPAD == MROBE500_PAD
377 #define BJACK_QUIT_NAME "POWER"
378 #define BJACK_QUIT BUTTON_POWER
380 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
381 #define BJACK_SELECT_NAME "PLAY"
382 #define BJACK_STAY_NAME "RECORD"
383 #define BJACK_QUIT_NAME "REW"
384 #define BJACK_DOUBLE_NAME "FFWD"
385 #define BJACK_SELECT BUTTON_PLAY
386 #define BJACK_QUIT BUTTON_REW
387 #define BJACK_STAY BUTTON_REC
388 #define BJACK_DOUBLEDOWN BUTTON_FFWD
389 #define BJACK_UP BUTTON_UP
390 #define BJACK_DOWN BUTTON_DOWN
391 #define BJACK_RIGHT BUTTON_RIGHT
392 #define BJACK_LEFT BUTTON_LEFT
394 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
395 #define BJACK_SELECT_NAME "OK"
396 #define BJACK_STAY_NAME "CANCEL"
397 #define BJACK_QUIT_NAME "REC"
398 #define BJACK_DOUBLE_NAME "MENU"
399 #define BJACK_SELECT BUTTON_OK
400 #define BJACK_QUIT BUTTON_REC
401 #define BJACK_STAY BUTTON_CANCEL
402 #define BJACK_DOUBLEDOWN BUTTON_MENU
403 #define BJACK_UP BUTTON_UP
404 #define BJACK_DOWN BUTTON_DOWN
405 #define BJACK_RIGHT BUTTON_NEXT
406 #define BJACK_LEFT BUTTON_PREV
408 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
409 #define BJACK_SELECT_NAME "FUNC"
410 #define BJACK_STAY_NAME "VOL +"
411 #define BJACK_RESUME_NAME "PLAY"
412 #define BJACK_QUIT_NAME "REC+PLAY"
413 #define BJACK_DOUBLE_NAME "VOL -"
414 #define BJACK_SELECT BUTTON_FUNC
415 #define BJACK_QUIT (BUTTON_REC|BUTTON_PLAY)
416 #define BJACK_STAY BUTTON_VOL_UP
417 #define BJACK_DOUBLEDOWN BUTTON_VOL_DOWN
418 #define BJACK_UP BUTTON_REW
419 #define BJACK_DOWN BUTTON_FF
420 #define BJACK_RIGHT BUTTON_VOL_UP
421 #define BJACK_LEFT BUTTON_VOL_DOWN
423 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
424 #define BJACK_SELECT_NAME "ENTER"
425 #define BJACK_STAY_NAME "PLAY"
426 #define BJACK_RESUME_NAME ""
427 #define BJACK_QUIT_NAME "Long MENU"
428 #define BJACK_DOUBLE_NAME "REC"
429 #define BJACK_SELECT BUTTON_ENTER
430 #define BJACK_QUIT (BUTTON_MENU|BUTTON_REPEAT)
431 #define BJACK_STAY BUTTON_PLAY
432 #define BJACK_DOUBLEDOWN BUTTON_REC
433 #define BJACK_UP BUTTON_UP
434 #define BJACK_DOWN BUTTON_DOWN
435 #define BJACK_RIGHT BUTTON_FF
436 #define BJACK_LEFT BUTTON_REW
438 #elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
439 #define BJACK_SELECT_NAME "SELECT"
440 #define BJACK_STAY_NAME "PLAYPAUSE"
441 #define BJACK_RESUME_NAME ""
442 #define BJACK_QUIT_NAME "POWER"
443 #define BJACK_DOUBLE_NAME "BACK"
444 #define BJACK_SELECT BUTTON_SELECT
445 #define BJACK_QUIT BUTTON_POWER
446 #define BJACK_MAX BUTTON_BOTTOMRIGHT
447 #define BJACK_MIN BUTTON_BOTTOMLEFT
448 #define BJACK_STAY BUTTON_BACK
449 #define BJACK_DOUBLEDOWN BUTTON_PLAYPAUSE
450 #define BJACK_UP BUTTON_UP
451 #define BJACK_DOWN BUTTON_DOWN
452 #define BJACK_RIGHT BUTTON_RIGHT
453 #define BJACK_LEFT BUTTON_LEFT
455 #elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
456 #define BJACK_SELECT_NAME "SELECT"
457 #define BJACK_STAY_NAME "MENU"
458 #define BJACK_QUIT_NAME "BACK"
459 #define BJACK_DOUBLE_NAME "USER"
460 #define BJACK_SELECT BUTTON_SELECT
461 #define BJACK_QUIT BUTTON_BACK
462 #define BJACK_MAX (BUTTON_LEFT|BUTTON_UP)
463 #define BJACK_MIN (BUTTON_RIGHT|BUTTON_DOWN)
464 #define BJACK_STAY BUTTON_MENU
465 #define BJACK_DOUBLEDOWN BUTTON_USER
466 #define BJACK_UP BUTTON_UP
467 #define BJACK_DOWN BUTTON_DOWN
468 #define BJACK_RIGHT BUTTON_RIGHT
469 #define BJACK_LEFT BUTTON_LEFT
471 #elif CONFIG_KEYPAD == HM60X_PAD
472 #define BJACK_SELECT_NAME "SELECT"
473 #define BJACK_STAY_NAME "UP+POWER"
474 #define BJACK_QUIT_NAME "POWER"
475 #define BJACK_DOUBLE_NAME "DOWN+POWER"
476 #define BJACK_SELECT BUTTON_SELECT
477 #define BJACK_QUIT BUTTON_POWER
478 #define BJACK_STAY (BUTTON_UP|BUTTON_POWER)
479 #define BJACK_DOUBLEDOWN (BUTTON_DOWN|BUTTON_POWER)
480 #define BJACK_UP BUTTON_UP
481 #define BJACK_DOWN BUTTON_DOWN
482 #define BJACK_RIGHT BUTTON_RIGHT
483 #define BJACK_LEFT BUTTON_LEFT
485 #elif CONFIG_KEYPAD == HM801_PAD
486 #define BJACK_SELECT_NAME "SELECT"
487 #define BJACK_STAY_NAME "PLAY"
488 #define BJACK_QUIT_NAME "POWER"
489 #define BJACK_DOUBLE_NAME "PREV"
490 #define BJACK_SELECT BUTTON_SELECT
491 #define BJACK_QUIT BUTTON_POWER
492 #define BJACK_STAY BUTTON_PLAY
493 #define BJACK_DOUBLEDOWN BUTTON_PREV
494 #define BJACK_UP BUTTON_UP
495 #define BJACK_DOWN BUTTON_DOWN
496 #define BJACK_RIGHT BUTTON_RIGHT
497 #define BJACK_LEFT BUTTON_LEFT
500 #error No keymap defined!
503 #ifdef HAVE_TOUCHSCREEN
504 #ifndef BJACK_DOUBLEDOWN
505 #define BJACK_DOUBLEDOWN BUTTON_MIDLEFT
506 #define BJACK_DOUBLE_NAME "BUTTON_MIDLEFT"
509 #define BJACK_SELECT BUTTON_CENTER
510 #define BJACK_SELECT_NAME "BUTTON_CENTER"
513 #define BJACK_MAX BUTTON_TOPRIGHT
516 #define BJACK_MIN BUTTON_TOPLEFT
519 #define BJACK_STAY BUTTON_BOTTOMLEFT
520 #define BJACK_STAY_NAME "BUTTON_BOTTOMLEFT"
523 #define BJACK_UP BUTTON_TOPMIDDLE
526 #define BJACK_DOWN BUTTON_BOTTOMMIDDLE
529 #define BJACK_RIGHT BUTTON_MIDRIGHT
532 #define BJACK_LEFT BUTTON_MIDLEFT
537 #ifdef HAVE_LCD_COLOR
538 #define BG_COLOR LCD_RGBPACK(0,157,0)
539 #define FG_COLOR LCD_WHITE
541 #define BG_COLOR LCD_WHITE
542 #define FG_COLOR LCD_BLACK
545 #define CARD_WIDTH BMPWIDTH_card_back
546 #define CARD_HEIGHT BMPHEIGHT_card_back
548 /* This is the max amount of cards onscreen before condensing */
549 #define MAX_CARDS LCD_WIDTH/(CARD_WIDTH+4)
551 extern const fb_data card_deck
[];
552 extern const fb_data card_back
[];
554 #define NEXT_CARD bj->player_cards[done][bj->num_player_cards[done]]
556 /* dealer and player card positions */
557 unsigned int dealer_x
, dealer_y
, player_x
, player_y
;
559 typedef struct card
{
560 unsigned int value
; /* Card's value in Blackjack */
561 unsigned int num
; /* Value on card face 0-12 (0=Ace, 1=2, 11=Q) */
562 unsigned int suit
; /* 0:Spades, 1:Hearts, 2: Clubs; 3: Diamonds */
566 typedef struct game_context
{
567 struct card player_cards
[2][22]; /* 22 Cards means the deal was all aces */
568 struct card dealer_cards
[22]; /* That is the worst-case scenario */
569 unsigned int player_total
;
570 unsigned int dealer_total
;
571 signed int player_money
;
572 unsigned int num_player_cards
[2];
573 unsigned int num_dealer_cards
;
574 unsigned int current_bet
;
575 unsigned int split_status
; /* 0 = split hasn't been asked, *
576 * 1 = split did not occur *
577 * 2 = split occurred *
578 * 3 = split occurred and 1st hand done */
581 bool asked_insurance
;
584 static bool resume
= false;
585 static bool resume_file
= false;
586 static struct highscore highscores
[NUM_SCORES
];
588 /*****************************************************************************
589 * blackjack_init() initializes blackjack data structures.
590 ******************************************************************************/
591 static void blackjack_init(struct game_context
* bj
) {
592 /* seed the rand generator */
593 rb
->srand(*rb
->current_tick
);
595 /* reset card positions */
597 dealer_y
= LCD_HEIGHT
/4 - CARD_HEIGHT
/2;
599 player_y
= LCD_HEIGHT
- LCD_HEIGHT
/4 - CARD_HEIGHT
/2;
601 /* check for resumed game */
605 bj
->player_total
= 0;
606 bj
->dealer_total
= 0;
607 bj
->num_player_cards
[0] = 2;
608 bj
->num_player_cards
[1] = 0;
609 bj
->num_dealer_cards
= 2;
610 bj
->end_hand
= false;
611 bj
->split_status
= 0;
612 bj
->is_blackjack
= false;
613 bj
->asked_insurance
= false;
616 /*****************************************************************************
617 * blackjack_drawtable() draws the table and some text.
618 ******************************************************************************/
619 static void blackjack_drawtable(struct game_context
* bj
) {
620 unsigned int w
, h
, y_loc
;
623 #if LCD_HEIGHT <= 64 || LCD_WIDTH <= 96
624 rb
->lcd_getstringsize("Bet", &w
, &h
);
625 rb
->lcd_putsxy(LCD_WIDTH
- w
, 2*h
+ 1, "Bet");
626 rb
->snprintf(str
, 9, "$%d", bj
->current_bet
);
627 rb
->lcd_getstringsize(str
, &w
, &h
);
628 rb
->lcd_putsxy(LCD_WIDTH
- w
, 3*h
+ 1, str
);
629 y_loc
= LCD_HEIGHT
/2;
631 rb
->lcd_getstringsize("Bet", &w
, &h
);
632 rb
->lcd_putsxy(LCD_WIDTH
- w
, 5*h
/ 2, "Bet");
633 rb
->snprintf(str
, 9, "$%d", bj
->current_bet
);
634 rb
->lcd_getstringsize(str
, &w
, &h
);
635 rb
->lcd_putsxy(LCD_WIDTH
- w
, 7*h
/ 2, str
);
636 rb
->lcd_hline(0, LCD_WIDTH
, LCD_HEIGHT
/2);
637 y_loc
= LCD_HEIGHT
/2 + h
;
640 rb
->lcd_putsxy(0,0, "Dealer");
641 rb
->lcd_getstringsize("Player", &w
, &h
);
642 rb
->lcd_putsxy(0, y_loc
, "Player");
643 rb
->lcd_getstringsize("Total", &w
, &h
);
644 rb
->lcd_putsxy(LCD_WIDTH
- w
, y_loc
, "Total");
645 rb
->lcd_getstringsize("Money", &w
, &h
);
646 rb
->lcd_putsxy(LCD_WIDTH
- w
, 0, "Money");
647 rb
->snprintf(str
, 9, "$%d", bj
->player_money
- bj
->current_bet
);
648 rb
->lcd_getstringsize(str
, &w
, &h
);
649 rb
->lcd_putsxy(LCD_WIDTH
- w
, h
+ 1, str
);
650 rb
->snprintf(str
, 3, "%d", bj
->player_total
);
651 rb
->lcd_getstringsize(str
, &w
, &h
);
652 rb
->lcd_putsxy(LCD_WIDTH
- w
, y_loc
+ h
, str
);
655 /*****************************************************************************
656 * find_value() is passed a card and returns its blackjack value.
657 ******************************************************************************/
658 static unsigned int find_value(unsigned int number
) {
659 unsigned int thisValue
;
661 thisValue
= 11; /* Aces get a value of 11 at first */
662 else if (number
< 10)
663 thisValue
= number
+ 1;
665 thisValue
= 10; /* Anything 10 or higher gets a value of 10 */
670 /*****************************************************************************
671 * draw_card() draws a card to the screen.
672 ******************************************************************************/
673 static void draw_card(struct card temp_card
, bool shown
,
674 unsigned int x
, unsigned int y
) {
676 rb
->lcd_bitmap_part(card_deck
, CARD_WIDTH
*temp_card
.num
,
677 CARD_HEIGHT
*temp_card
.suit
,
678 STRIDE( SCREEN_MAIN
, BMPWIDTH_card_deck
,
679 BMPHEIGHT_card_deck
),
680 x
+1, y
+1, CARD_WIDTH
, CARD_HEIGHT
);
682 rb
->lcd_bitmap(card_back
, x
+1, y
+1,CARD_WIDTH
, CARD_HEIGHT
);
684 rb
->lcd_set_foreground(LCD_BLACK
);
689 rb
->lcd_hline(x
+2, x
+CARD_WIDTH
-1, y
);
690 rb
->lcd_hline(x
+2, x
+CARD_WIDTH
-1, y
+CARD_HEIGHT
+1);
691 rb
->lcd_vline(x
, y
+2, y
+CARD_HEIGHT
-3);
692 rb
->lcd_vline(x
+CARD_WIDTH
+1, y
+2, y
+CARD_HEIGHT
-1);
693 rb
->lcd_drawpixel(x
+1, y
+1);
694 rb
->lcd_drawpixel(x
+1, y
+CARD_HEIGHT
);
695 rb
->lcd_drawpixel(x
+CARD_WIDTH
, y
+1);
696 rb
->lcd_drawpixel(x
+CARD_WIDTH
, y
+CARD_HEIGHT
);
698 rb
->lcd_hline(x
+1, x
+CARD_WIDTH
, y
);
699 rb
->lcd_hline(x
+1, x
+CARD_WIDTH
, y
+CARD_HEIGHT
+1);
700 rb
->lcd_vline(x
, y
+1, y
+CARD_HEIGHT
);
701 rb
->lcd_vline(x
+CARD_WIDTH
+1, y
+1, y
+CARD_HEIGHT
);
705 rb
->lcd_set_foreground(FG_COLOR
);
709 /*****************************************************************************
710 * new_card() initializes a new card and gives it values.
711 ******************************************************************************/
712 static struct card
new_card(void) {
713 struct card new_card
;
714 new_card
.suit
= rb
->rand()%4; /* Random number 0-3 */
715 new_card
.num
= rb
->rand()%13; /* Random number 0-12 */
716 new_card
.value
= find_value(new_card
.num
);
717 new_card
.is_soft_ace
= (new_card
.num
== 0);
721 /*****************************************************************************
722 * deal_init_card() deals and draws to the screen the player's and dealer's
724 ******************************************************************************/
725 static void deal_init_cards(struct game_context
* bj
) {
726 bj
->dealer_cards
[0] = new_card();
727 bj
->dealer_total
+= bj
->dealer_cards
[0].value
;
729 draw_card(bj
->dealer_cards
[0], false, dealer_x
, dealer_y
);
731 bj
->dealer_cards
[1] = new_card();
732 bj
->dealer_total
+= bj
->dealer_cards
[1].value
;
733 draw_card(bj
->dealer_cards
[1], true, dealer_x
+ CARD_WIDTH
+ 4, dealer_y
);
735 bj
->player_cards
[0][0] = new_card();
736 bj
->player_total
+= bj
->player_cards
[0][0].value
;
737 draw_card(bj
->player_cards
[0][0], true, player_x
, player_y
);
738 player_x
+= CARD_WIDTH
+ 4;
740 bj
->player_cards
[0][1] = new_card();
741 bj
->player_total
+= bj
->player_cards
[0][1].value
;
742 draw_card(bj
->player_cards
[0][1], true, player_x
, player_y
);
743 player_x
+= CARD_WIDTH
+ 4;
746 /*****************************************************************************
747 * redraw_board() redraws all the cards and the board
748 ******************************************************************************/
749 static void redraw_board(struct game_context
* bj
) {
750 unsigned int i
, n
, upper_bound
;
751 rb
->lcd_clear_display();
753 blackjack_drawtable(bj
);
756 upper_bound
= bj
->split_status
> 1 ? 2 : 1;
758 for (i
= 0; i
< bj
->num_dealer_cards
; i
++) {
760 draw_card(bj
->dealer_cards
[0], false, dealer_x
, dealer_y
);
762 /* increment i so the dealer's first card isn't displayed */
764 dealer_x
+= CARD_WIDTH
+ 4;
766 draw_card(bj
->dealer_cards
[i
], true, dealer_x
, dealer_y
);
768 if (bj
->num_dealer_cards
> MAX_CARDS
-1)
771 dealer_x
+= CARD_WIDTH
+ 4;
774 for (n
= 0; n
< upper_bound
; n
++) {
775 for (i
= 0; i
< bj
->num_player_cards
[n
]; i
++) {
776 draw_card(bj
->player_cards
[n
][i
], true, player_x
, player_y
);
777 if (bj
->split_status
>1 || bj
->num_player_cards
[n
]>MAX_CARDS
)
780 player_x
+= CARD_WIDTH
+ 4;
782 if (bj
->split_status
> 1)
783 player_x
= LCD_WIDTH
/2 + 4;
787 /*****************************************************************************
788 * update_total updates the player's total
789 ******************************************************************************/
790 static void update_total(struct game_context
* bj
) {
793 rb
->snprintf(total
, 3, "%d", bj
->player_total
);
794 rb
->lcd_getstringsize(total
, &w
, &h
);
795 #if LCD_HEIGHT > 64 && LCD_WIDTH > 96
798 rb
->lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 + h
, total
);
799 rb
->lcd_update_rect(LCD_WIDTH
- w
, LCD_HEIGHT
/2 + h
, w
, h
);
803 /*****************************************************************************
804 * check_for_aces() is passed an array of cards and returns where an ace is
805 * located. Otherwise, returns -1.
806 ******************************************************************************/
807 static signed int check_for_aces(struct card temp_cards
[], unsigned int size
) {
809 for(i
= 0; i
< size
; i
++) {
810 if (temp_cards
[i
].is_soft_ace
)
816 /*****************************************************************************
817 * check_totals() compares player and dealer totals.
818 * 0: bust 1: loss, 2: push, 3: win, 4: blackjack, 5: something's not right...
819 ******************************************************************************/
820 static unsigned int check_totals(struct game_context
* bj
) {
822 if (bj
->player_total
> 21)
824 else if (bj
->player_total
== 21 && bj
->is_blackjack
) {
825 if (bj
->dealer_total
== 21 && bj
->num_dealer_cards
== 2)
830 else if (bj
->player_total
== bj
->dealer_total
)
832 else if (bj
->dealer_total
> 21 && bj
->player_total
< 22)
834 else if (bj
->dealer_total
> bj
->player_total
)
836 else if (bj
->player_total
> bj
->dealer_total
)
844 /*****************************************************************************
845 * finish_dealer() draws cards for the dealer until he has 17 or more.
846 ******************************************************************************/
847 static void finish_dealer(struct game_context
* bj
) {
850 if (bj
->dealer_total
> 16 && bj
->dealer_total
< 22)
853 while (bj
->dealer_total
< 17) {
854 bj
->dealer_cards
[bj
->num_dealer_cards
] = new_card();
855 bj
->dealer_total
+= bj
->dealer_cards
[bj
->num_dealer_cards
].value
;
856 bj
->num_dealer_cards
++;
859 while (bj
->dealer_total
> 21) {
860 temp
= check_for_aces(bj
->dealer_cards
, bj
->num_dealer_cards
);
862 bj
->dealer_cards
[temp
].is_soft_ace
= false;
863 bj
->dealer_total
-= 10;
870 /*****************************************************************************
871 * finish_game() completes the game once player's turn is over.
872 ******************************************************************************/
873 static void finish_game(struct game_context
* bj
) {
874 unsigned int rValue
, w
, h
;
879 } while (bj
->dealer_total
< 17);
882 rValue
= check_totals(bj
);
885 rb
->snprintf(str
, sizeof(str
), " Bust! ");
886 bj
->player_money
-= bj
->current_bet
;
888 else if (rValue
== 1) {
889 rb
->snprintf(str
, sizeof(str
), " Sorry, you lost. ");
890 bj
->player_money
-= bj
->current_bet
;
892 else if (rValue
== 2) {
893 rb
->snprintf(str
, sizeof(str
), " Push ");
895 else if (rValue
== 3) {
896 rb
->snprintf(str
, sizeof(str
), " You won! ");
897 bj
->player_money
+= bj
->current_bet
;
900 rb
->snprintf(str
, sizeof(str
), " Blackjack! ");
901 bj
->player_money
+= bj
->current_bet
* 3 / 2;
903 rb
->lcd_getstringsize(str
, &w
, &h
);
905 #if LCD_HEIGHT <= 64 || LCD_WIDTH <= 96
906 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
907 rb
->lcd_fillrect(0, LCD_HEIGHT
/2, LCD_WIDTH
, LCD_HEIGHT
/2);
908 rb
->lcd_set_drawmode(DRMODE_SOLID
);
909 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + h
, str
);
910 rb
->snprintf(str
, 12, "You have %d", bj
->player_total
);
911 rb
->lcd_getstringsize(str
, &w
, &h
);
912 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2, str
);
914 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 - h
/2, str
);
919 /*****************************************************************************
920 * blackjack_loadgame() loads the saved game and returns load success.
921 ******************************************************************************/
922 static bool blackjack_loadgame(struct game_context
* bj
) {
927 fd
= rb
->open(SAVE_FILE
, O_RDONLY
);
928 if(fd
< 0) return false;
930 /* read in saved game */
931 if(rb
->read(fd
, bj
, sizeof(struct game_context
))
932 == (long)sizeof(struct game_context
))
942 /*****************************************************************************
943 * blackjack_savegame() saves the current game state.
944 ******************************************************************************/
945 static void blackjack_savegame(struct game_context
* bj
) {
950 /* write out the game state to the save file */
951 fd
= rb
->open(SAVE_FILE
, O_WRONLY
|O_CREAT
, 0666);
954 rb
->write(fd
, bj
, sizeof(struct game_context
));
958 /*****************************************************************************
959 * blackjack_get_yes_no() gets a yes/no answer from the user
960 ******************************************************************************/
961 static unsigned int blackjack_get_yes_no(char message
[20]) {
963 unsigned int w
, h
, b
, choice
= 0;
964 bool breakout
= false;
965 char message_yes
[24], message_no
[24];
967 rb
->strcpy(message_yes
, message
);
968 rb
->strcpy(message_no
, message
);
969 rb
->strcat(message_yes
, " Yes");
970 rb
->strcat(message_no
, " No");
971 rb
->lcd_getstringsize(message_yes
, &w
, &h
);
972 const char *stg
[] = {message_yes
, message_no
};
974 #if LCD_HEIGHT <= 64 || LCD_WIDTH <= 96
980 #ifdef HAVE_LCD_COLOR
981 rb
->lcd_fillrect(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + b
, w
+1, h
+3);
982 rb
->lcd_set_foreground(LCD_BLACK
);
983 rb
->lcd_set_background(LCD_WHITE
);
985 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
986 rb
->lcd_fillrect(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + b
, w
+1, h
+3);
987 rb
->lcd_set_drawmode(DRMODE_SOLID
);
989 rb
->lcd_drawrect(LCD_WIDTH
/2 - w
/2 - 1, LCD_HEIGHT
/2 + b
- 1, w
+3, h
+4);
992 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + b
+1, stg
[choice
]);
993 rb
->lcd_update_rect(LCD_WIDTH
/2 - w
/2 - 1, LCD_HEIGHT
/2 + b
-1,
995 button
= rb
->button_get(true);
999 case (BJACK_LEFT
|BUTTON_REPEAT
):
1001 case (BJACK_RIGHT
|BUTTON_REPEAT
):
1004 case BJACK_SELECT
: breakout
= true;
1006 case BJACK_QUIT
: breakout
= true;
1013 rb
->lcd_set_foreground(FG_COLOR
);
1014 rb
->lcd_set_background(BG_COLOR
);
1019 /*****************************************************************************
1020 * blackjack_get_amount() gets an amount from the player to be used
1021 ******************************************************************************/
1022 static signed int blackjack_get_amount(const char message
[20],
1023 signed int lower_limit
,
1024 signed int upper_limit
,
1027 bool breakout
= false, changed
= false;
1031 rb
->lcd_getstringsize("A", &w
, &h
); /* find the size of one character */
1033 if (start
> upper_limit
)
1034 amount
= upper_limit
;
1035 else if (start
< lower_limit
)
1036 amount
= lower_limit
;
1041 rb
->lcd_set_background(LCD_WHITE
);
1042 rb
->lcd_set_foreground(LCD_BLACK
);
1045 #if LCD_HEIGHT <= 64 || LCD_WIDTH <= 96
1046 rb
->lcd_clear_display();
1047 rb
->lcd_puts(0, 1, message
);
1048 rb
->lcd_putsf(0, 2, "$%d", amount
);
1049 rb
->lcd_puts(0, 3, "RIGHT: +1");
1050 rb
->lcd_puts(0, 4, "LEFT: -1");
1051 rb
->lcd_puts(0, 5, "UP: +10");
1052 rb
->lcd_puts(0, 6, "DOWN: -10");
1055 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
1056 rb
->lcd_fillrect(LCD_WIDTH
/2 - 9*w
- 1, LCD_HEIGHT
/2 - 4*h
- 3,
1058 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1059 rb
->lcd_drawrect(LCD_WIDTH
/2 - 9*w
- 1, LCD_HEIGHT
/2 - 4*h
- 3,
1061 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 4*h
- 1, message
);
1062 rb
->lcd_putsxyf(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, "$%d", amount
);
1063 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
1064 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
1065 (CONFIG_KEYPAD == IPOD_1G2G_PAD) || \
1066 (CONFIG_KEYPAD == SANSA_E200_PAD) || \
1067 (CONFIG_KEYPAD == SANSA_FUZE_PAD) || \
1068 (CONFIG_KEYPAD == SANSA_CONNECT_PAD) || \
1069 (CONFIG_KEYPAD == MPIO_HD300_PAD)
1070 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - h
-2, " >>|: +1");
1071 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 1, " |<<: -1");
1072 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + h
, "SCROLL+: +10");
1073 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + 2*h
+ 1, "SCROLL-: -10");
1074 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
1075 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - h
-2, "RIGHT: +1");
1076 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 1, "LEFT: -1");
1077 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + h
, "SCROLL+: +10");
1078 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + 2*h
+ 1, "SCROLL-: -10");
1080 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - h
-2, "RIGHT: +1");
1081 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 1, "LEFT: -1");
1082 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + h
, "UP: +10");
1083 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + 2*h
+ 1, "DOWN: -10");
1085 rb
->lcd_update_rect(LCD_WIDTH
/2 - 9*w
- 1, LCD_HEIGHT
/2 - 4*h
- 3,
1090 button
= rb
->button_get(true);
1094 case (BJACK_UP
|BUTTON_REPEAT
):
1095 if (amount
+ 10 < upper_limit
+ 1) {
1101 case (BJACK_DOWN
|BUTTON_REPEAT
):
1102 if (amount
- 10 > lower_limit
- 1) {
1108 case (BJACK_RIGHT
|BUTTON_REPEAT
):
1109 if (amount
+ 1 < upper_limit
+ 1) {
1115 case (BJACK_LEFT
|BUTTON_REPEAT
):
1116 if (amount
- 1 > lower_limit
- 1) {
1123 amount
= upper_limit
;
1129 amount
= lower_limit
;
1143 #if LCD_HEIGHT <= 64 || LCD_WIDTH <= 96
1144 rb
->lcd_putsf(0, 2, "$%d", amount
);
1147 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
1148 rb
->lcd_fillrect(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, 5*w
, h
);
1149 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1150 rb
->lcd_putsxyf(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, "$%d", amount
);
1151 rb
->lcd_update_rect(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, 5*w
, h
);
1158 rb
->lcd_set_foreground(FG_COLOR
);
1159 rb
->lcd_set_background(BG_COLOR
);
1161 rb
->lcd_clear_display();
1165 /*****************************************************************************
1166 * blackjack_get_bet() gets the player's bet.
1167 ******************************************************************************/
1168 static void blackjack_get_bet(struct game_context
* bj
) {
1170 static const char msg
[] = "Enter a bet";
1172 static const char msg
[] = "Please enter a bet";
1174 bj
->current_bet
= blackjack_get_amount(msg
, 10,
1175 bj
->player_money
, bj
->current_bet
);
1178 /*****************************************************************************
1179 * double_down() returns one final card then finishes the game
1180 ******************************************************************************/
1181 static void double_down(struct game_context
* bj
) {
1182 bj
->current_bet
*= 2;
1183 bj
->player_cards
[0][bj
->num_player_cards
[0]] = new_card();
1184 bj
->player_total
+= bj
->player_cards
[0][bj
->num_player_cards
[0]].value
;
1185 bj
->num_player_cards
[0]++;
1188 /*****************************************************************************
1189 * split() checks if the player wants to split and acts accordingly.
1190 * When bj->split_status is 1, no split occurred. 2 means the player split and 3
1191 * means a split has already occurred and the first hand is done.
1192 ******************************************************************************/
1193 static void split(struct game_context
* bj
) {
1194 if (blackjack_get_yes_no("Split?") != 0)
1195 bj
->split_status
= 1;
1197 bj
->split_status
= 2;
1198 bj
->current_bet
*= 2;
1199 bj
->num_player_cards
[0] = 1;
1200 bj
->num_player_cards
[1] = 1;
1201 bj
->player_cards
[1][0] = bj
->player_cards
[0][1];
1202 bj
->player_total
= bj
->player_cards
[0][0].value
;
1206 /*****************************************************************************
1207 * insurance() see if the player wants to buy insurance and how much.
1208 ******************************************************************************/
1209 static unsigned int insurance(struct game_context
* bj
) {
1210 unsigned int insurance
, max_amount
;
1212 insurance
= blackjack_get_yes_no("Buy Insurance?");
1213 bj
->asked_insurance
= true;
1214 max_amount
= bj
->current_bet
< (unsigned int)bj
->player_money
?
1215 bj
->current_bet
/2 : (unsigned int)bj
->player_money
;
1216 if (insurance
!= 0) return 0;
1218 insurance
= blackjack_get_amount("How much?", 0, max_amount
, 0);
1223 /*****************************************************************************
1224 * play_again() checks to see if the player wants to keep playing.
1225 ******************************************************************************/
1226 static unsigned int play_again(void) {
1227 return blackjack_get_yes_no("Play Again?");
1230 /*****************************************************************************
1231 * blackjack_help() displays help text.
1232 ******************************************************************************/
1233 static bool blackjack_help(void) {
1234 static char *help_text
[] = {
1235 "Blackjack", "", "Aim", "",
1236 "Try", "to", "get", "as", "close", "to", "21", "without", "going",
1237 "over", "or", "simply", "beat", "out", "the", "dealer", "for", "the",
1238 "best", "hand.", "", "",
1240 BJACK_SELECT_NAME
, ":", "hit", "/", "select", "",
1241 BJACK_STAY_NAME
, ":", "stay", "",
1242 BJACK_DOUBLE_NAME
, ":", "double", "down", "",
1243 BJACK_QUIT_NAME
, ":", "go", "to", "menu", "",
1245 static struct style_text formation
[]={
1246 { 0, TEXT_CENTER
|TEXT_UNDERLINE
},
1252 rb
->lcd_setfont(FONT_UI
);
1253 #ifdef HAVE_LCD_COLOR
1254 rb
->lcd_set_background(LCD_BLACK
);
1255 rb
->lcd_set_foreground(LCD_WHITE
);
1257 if (display_text(ARRAYLEN(help_text
), help_text
, formation
, NULL
, true))
1259 rb
->lcd_setfont(FONT_SYSFIXED
);
1264 static int blackjack_menu_cb(int action
, const struct menu_item_ex
*this_item
)
1266 int i
= ((intptr_t)this_item
);
1267 if(action
== ACTION_REQUEST_MENUITEM
1268 && !resume
&& (i
==0 || i
==5))
1269 return ACTION_EXIT_MENUITEM
;
1273 /*****************************************************************************
1274 * blackjack_menu() is the initial menu at the start of the game.
1275 ******************************************************************************/
1276 static unsigned int blackjack_menu(void) {
1278 bool breakout
= false;
1280 MENUITEM_STRINGLIST(menu
, "BlackJack Menu", blackjack_menu_cb
,
1281 "Resume Game", "Start New Game",
1282 "High Scores", "Help",
1284 "Quit without Saving", "Quit");
1287 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1291 rb
->remove(SAVE_FILE
);
1292 resume_file
= false;
1299 highscore_show(-1, highscores
, NUM_SCORES
, false);
1302 if(blackjack_help())
1306 if (playback_control(NULL
))
1310 return BJ_QUIT_WITHOUT_SAVING
;
1315 return BJ_QUIT_WITHOUT_SAVING
;
1317 case MENU_ATTACHED_USB
:
1328 /*****************************************************************************
1329 * blackjack() is the main game subroutine, it returns the final game status.
1330 ******************************************************************************/
1331 static int blackjack(struct game_context
* bj
) {
1333 unsigned int w
, h
, temp_var
, done
= 0, todo
= 1;
1335 bool breakout
= false;
1336 bool dbl_down
= false;
1338 /********************
1340 ********************/
1341 temp_var
= blackjack_menu();
1346 rb
->lcd_set_background(BG_COLOR
);
1347 rb
->lcd_set_foreground(FG_COLOR
);
1350 /********************
1352 ********************/
1355 /********************
1357 ********************/
1359 resume_file
= false;
1360 /* check for resumed game */
1364 if (bj
->split_status
== 2) {
1366 player_x
= bj
->num_player_cards
[0] * 10 + 4;
1368 else if (bj
->split_status
== 3) {
1369 player_x
= bj
->num_player_cards
[1] * 10 + LCD_WIDTH
/2 + 4;
1375 bj
->player_money
= 1000;
1376 bj
->current_bet
= 10;
1377 blackjack_get_bet(bj
);
1378 if (bj
->current_bet
== 0)
1380 rb
->lcd_clear_display();
1381 deal_init_cards(bj
);
1382 blackjack_drawtable(bj
);
1390 if(bj
->player_total
== 21 && bj
->num_player_cards
[0] == 2) {
1391 bj
->is_blackjack
= true;
1392 bj
->end_hand
= true;
1395 else if(bj
->dealer_cards
[1].is_soft_ace
&& !breakout
&&
1396 !bj
->asked_insurance
) {
1397 temp_var
= insurance(bj
);
1398 if (bj
->dealer_total
== 21) {
1399 rb
->splash(HZ
, "Dealer has blackjack");
1400 bj
->player_money
+= temp_var
;
1401 bj
->end_hand
= true;
1407 rb
->splash(HZ
, "Dealer does not have blackjack");
1408 bj
->player_money
-= temp_var
;
1414 if(!bj
->end_hand
&& bj
->split_status
== 0 &&
1415 bj
->player_cards
[0][0].num
== bj
->player_cards
[0][1].num
) {
1418 rb
->lcd_update_rect(0, LCD_HEIGHT
/2, LCD_WIDTH
, LCD_HEIGHT
/2);
1419 if (bj
->split_status
== 2) {
1421 player_x
= bj
->num_player_cards
[0] * 10 + 4;
1425 while(!bj
->end_hand
&& done
< todo
) {
1426 button
= rb
->button_get(true);
1430 NEXT_CARD
= new_card();
1431 bj
->player_total
+= NEXT_CARD
.value
;
1432 draw_card(NEXT_CARD
, true, player_x
, player_y
);
1433 bj
->num_player_cards
[done
]++;
1434 if (bj
->num_player_cards
[done
] == MAX_CARDS
+ 1) {
1436 rb
->lcd_update_rect(0, LCD_HEIGHT
/2, LCD_WIDTH
,
1439 else if (bj
->num_player_cards
[done
]>MAX_CARDS
|| todo
> 1) {
1440 rb
->lcd_update_rect(player_x
, player_y
, CARD_WIDTH
+2,
1445 rb
->lcd_update_rect(player_x
, player_y
, CARD_WIDTH
+2,
1447 player_x
+= CARD_WIDTH
+ 4;
1453 bj
->end_hand
= true;
1455 case BJACK_DOUBLEDOWN
:
1456 if ((signed int)bj
->current_bet
* 2 <
1457 bj
->player_money
+ 1 &&
1458 bj
->num_player_cards
[0]==2 && todo
==1) {
1461 if (bj
->player_total
< 22) {
1462 bj
->end_hand
= true;
1466 else if((signed int)bj
->current_bet
* 2 >
1468 rb
->splash(HZ
, "Not enough money to double down.");
1479 while (bj
->player_total
> 21 && !bj
->end_hand
) {
1480 temp
= check_for_aces(bj
->player_cards
[done
],
1481 bj
->num_player_cards
[done
]);
1483 bj
->player_cards
[done
][temp
].is_soft_ace
= false;
1484 bj
->player_total
-= 10;
1487 bj
->end_hand
= true;
1492 bj
->end_hand
= true;
1499 temp
= bj
->player_total
;
1500 bj
->player_total
= temp_var
;
1503 rb
->lcd_getstringsize(" Split 1 ", &w
, &h
);
1504 rb
->lcd_putsxy(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1506 rb
->lcd_update_rect(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1508 bj
->current_bet
/= 2;
1509 rb
->lcd_update_rect(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1512 bj
->player_total
= temp_var
;
1514 rb
->lcd_getstringsize(" Split 2 ", &w
, &h
);
1515 rb
->lcd_putsxy(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1517 rb
->lcd_update_rect(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1522 bj
->end_hand
= false;
1523 bj
->split_status
= 3;
1524 temp_var
= bj
->player_total
;
1525 bj
->player_total
= bj
->player_cards
[1][0].value
;
1537 if (bj
->player_money
< 10) {
1542 if (bj
->end_hand
) { /* If hand is over */
1543 if (play_again() != 0) /* User wants to quit */
1545 else { /* User keeps playing */
1547 temp
= bj
->current_bet
;
1548 bj
->current_bet
= 0;
1551 bj
->current_bet
= temp
;
1553 bj
->current_bet
/= 2;
1559 blackjack_get_bet(bj
);
1560 if (bj
->current_bet
== 0)
1562 deal_init_cards(bj
);
1563 blackjack_drawtable(bj
);
1572 /*****************************************************************************
1573 * plugin entry point.
1574 ******************************************************************************/
1575 enum plugin_status
plugin_start(const void* parameter
)
1577 struct game_context bj
;
1583 rb
->lcd_set_backdrop(NULL
);
1586 /* load high scores */
1587 highscore_load(SCORE_FILE
, highscores
, NUM_SCORES
);
1588 resume
= blackjack_loadgame(&bj
);
1589 resume_file
= resume
;
1591 rb
->lcd_setfont(FONT_SYSFIXED
);
1594 switch(blackjack(&bj
)){
1596 rb
->splash(HZ
, "Not enough money to continue");
1597 /* fall through to BJ_END */
1600 if(!resume
&& bj
.player_money
> 10) {
1601 /* There is no level, so store -1 to blank column */
1602 int position
= highscore_update(bj
.player_money
, -1, "",
1603 highscores
, NUM_SCORES
);
1607 rb
->splash(HZ
*2, "New High Score");
1608 highscore_show(position
, highscores
, NUM_SCORES
, false);
1614 highscore_save(SCORE_FILE
, highscores
, NUM_SCORES
);
1615 return PLUGIN_USB_CONNECTED
;
1618 rb
->splash(HZ
*1, "Saving game...");
1619 blackjack_savegame(&bj
);
1622 case BJ_QUIT_WITHOUT_SAVING
:
1630 highscore_save(SCORE_FILE
, highscores
, NUM_SCORES
);