FS#12756 by Marek Salaba - update Czech translation
[maemo-rb.git] / apps / plugins / blackjack.c
blob37ba0835803ebcfd09cc66e0fce0be2cb656f4b6
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
22 #include "plugin.h"
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"
31 /* save files */
32 #define SCORE_FILE PLUGIN_GAMES_DATA_DIR "/blackjack.score"
33 #define SAVE_FILE PLUGIN_GAMES_DATA_DIR "/blackjack.save"
34 #define NUM_SCORES 5
36 /* final game return status */
37 enum {
38 BJ_LOSE,
39 BJ_QUIT_WITHOUT_SAVING,
40 BJ_QUIT,
41 BJ_USB,
42 BJ_END,
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 "ENTER"
441 #define BJACK_STAY_NAME "PLAY"
442 #define BJACK_RESUME_NAME ""
443 #define BJACK_QUIT_NAME "Long MENU"
444 #define BJACK_DOUBLE_NAME "REC"
445 #define BJACK_SELECT BUTTON_ENTER
446 #define BJACK_QUIT (BUTTON_MENU|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_MAX BUTTON_BOTTOMRIGHT
463 #define BJACK_MIN BUTTON_BOTTOMLEFT
464 #define BJACK_STAY BUTTON_BACK
465 #define BJACK_DOUBLEDOWN BUTTON_PLAYPAUSE
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 == SAMSUNG_YPR0_PAD
472 #define BJACK_SELECT_NAME "SELECT"
473 #define BJACK_STAY_NAME "MENU"
474 #define BJACK_QUIT_NAME "BACK"
475 #define BJACK_DOUBLE_NAME "USER"
476 #define BJACK_SELECT BUTTON_SELECT
477 #define BJACK_QUIT BUTTON_BACK
478 #define BJACK_MAX (BUTTON_LEFT|BUTTON_UP)
479 #define BJACK_MIN (BUTTON_RIGHT|BUTTON_DOWN)
480 #define BJACK_STAY BUTTON_MENU
481 #define BJACK_DOUBLEDOWN BUTTON_USER
482 #define BJACK_UP BUTTON_UP
483 #define BJACK_DOWN BUTTON_DOWN
484 #define BJACK_RIGHT BUTTON_RIGHT
485 #define BJACK_LEFT BUTTON_LEFT
487 #elif CONFIG_KEYPAD == HM60X_PAD
488 #define BJACK_SELECT_NAME "SELECT"
489 #define BJACK_STAY_NAME "UP+POWER"
490 #define BJACK_QUIT_NAME "POWER"
491 #define BJACK_DOUBLE_NAME "DOWN+POWER"
492 #define BJACK_SELECT BUTTON_SELECT
493 #define BJACK_QUIT BUTTON_POWER
494 #define BJACK_STAY (BUTTON_UP|BUTTON_POWER)
495 #define BJACK_DOUBLEDOWN (BUTTON_DOWN|BUTTON_POWER)
496 #define BJACK_UP BUTTON_UP
497 #define BJACK_DOWN BUTTON_DOWN
498 #define BJACK_RIGHT BUTTON_RIGHT
499 #define BJACK_LEFT BUTTON_LEFT
501 #elif CONFIG_KEYPAD == HM801_PAD
502 #define BJACK_SELECT_NAME "SELECT"
503 #define BJACK_STAY_NAME "PLAY"
504 #define BJACK_QUIT_NAME "POWER"
505 #define BJACK_DOUBLE_NAME "PREV"
506 #define BJACK_SELECT BUTTON_SELECT
507 #define BJACK_QUIT BUTTON_POWER
508 #define BJACK_STAY BUTTON_PLAY
509 #define BJACK_DOUBLEDOWN BUTTON_PREV
510 #define BJACK_UP BUTTON_UP
511 #define BJACK_DOWN BUTTON_DOWN
512 #define BJACK_RIGHT BUTTON_RIGHT
513 #define BJACK_LEFT BUTTON_LEFT
515 #else
516 #error No keymap defined!
517 #endif
519 #ifdef HAVE_TOUCHSCREEN
520 #ifndef BJACK_DOUBLEDOWN
521 #define BJACK_DOUBLEDOWN BUTTON_MIDLEFT
522 #define BJACK_DOUBLE_NAME "BUTTON_MIDLEFT"
523 #endif
524 #ifndef BJACK_SELECT
525 #define BJACK_SELECT BUTTON_CENTER
526 #define BJACK_SELECT_NAME "BUTTON_CENTER"
527 #endif
528 #ifndef BJACK_MAX
529 #define BJACK_MAX BUTTON_TOPRIGHT
530 #endif
531 #ifndef BJACK_MIN
532 #define BJACK_MIN BUTTON_TOPLEFT
533 #endif
534 #ifndef BJACK_STAY
535 #define BJACK_STAY BUTTON_BOTTOMLEFT
536 #define BJACK_STAY_NAME "BUTTON_BOTTOMLEFT"
537 #endif
538 #ifndef BJACK_UP
539 #define BJACK_UP BUTTON_TOPMIDDLE
540 #endif
541 #ifndef BJACK_DOWN
542 #define BJACK_DOWN BUTTON_BOTTOMMIDDLE
543 #endif
544 #ifndef BJACK_RIGHT
545 #define BJACK_RIGHT BUTTON_MIDRIGHT
546 #endif
547 #ifndef BJACK_LEFT
548 #define BJACK_LEFT BUTTON_MIDLEFT
549 #endif
551 #endif
553 #ifdef HAVE_LCD_COLOR
554 #define BG_COLOR LCD_RGBPACK(0,157,0)
555 #define FG_COLOR LCD_WHITE
556 #elif LCD_DEPTH > 1
557 #define BG_COLOR LCD_WHITE
558 #define FG_COLOR LCD_BLACK
559 #endif
561 #define CARD_WIDTH BMPWIDTH_card_back
562 #define CARD_HEIGHT BMPHEIGHT_card_back
564 /* This is the max amount of cards onscreen before condensing */
565 #define MAX_CARDS LCD_WIDTH/(CARD_WIDTH+4)
567 extern const fb_data card_deck[];
568 extern const fb_data card_back[];
570 #define NEXT_CARD bj->player_cards[done][bj->num_player_cards[done]]
572 /* dealer and player card positions */
573 unsigned int dealer_x, dealer_y, player_x, player_y;
575 typedef struct card {
576 unsigned int value; /* Card's value in Blackjack */
577 unsigned int num; /* Value on card face 0-12 (0=Ace, 1=2, 11=Q) */
578 unsigned int suit; /* 0:Spades, 1:Hearts, 2: Clubs; 3: Diamonds */
579 bool is_soft_ace;
580 } card;
582 typedef struct game_context {
583 struct card player_cards[2][22]; /* 22 Cards means the deal was all aces */
584 struct card dealer_cards[22]; /* That is the worst-case scenario */
585 unsigned int player_total;
586 unsigned int dealer_total;
587 signed int player_money;
588 unsigned int num_player_cards[2];
589 unsigned int num_dealer_cards;
590 unsigned int current_bet;
591 unsigned int split_status; /* 0 = split hasn't been asked, *
592 * 1 = split did not occur *
593 * 2 = split occurred *
594 * 3 = split occurred and 1st hand done */
595 bool is_blackjack;
596 bool end_hand;
597 bool asked_insurance;
598 } game_context;
600 static bool resume = false;
601 static bool resume_file = false;
602 static struct highscore highscores[NUM_SCORES];
604 /*****************************************************************************
605 * blackjack_init() initializes blackjack data structures.
606 ******************************************************************************/
607 static void blackjack_init(struct game_context* bj) {
608 /* seed the rand generator */
609 rb->srand(*rb->current_tick);
611 /* reset card positions */
612 dealer_x = 4;
613 dealer_y = LCD_HEIGHT/4 - CARD_HEIGHT/2;
614 player_x = 4;
615 player_y = LCD_HEIGHT - LCD_HEIGHT/4 - CARD_HEIGHT/2;
617 /* check for resumed game */
618 if(resume) return;
620 /* reset scoring */
621 bj->player_total = 0;
622 bj->dealer_total = 0;
623 bj->num_player_cards[0] = 2;
624 bj->num_player_cards[1] = 0;
625 bj->num_dealer_cards = 2;
626 bj->end_hand = false;
627 bj->split_status = 0;
628 bj->is_blackjack = false;
629 bj->asked_insurance = false;
632 /*****************************************************************************
633 * blackjack_drawtable() draws the table and some text.
634 ******************************************************************************/
635 static void blackjack_drawtable(struct game_context* bj) {
636 unsigned int w, h, y_loc;
637 char str[10];
639 #if LCD_HEIGHT <= 64
640 rb->lcd_getstringsize("Bet", &w, &h);
641 rb->lcd_putsxy(LCD_WIDTH - w, 2*h + 1, "Bet");
642 rb->snprintf(str, 9, "$%d", bj->current_bet);
643 rb->lcd_getstringsize(str, &w, &h);
644 rb->lcd_putsxy(LCD_WIDTH - w, 3*h + 1, str);
645 y_loc = LCD_HEIGHT/2;
646 #else
647 rb->lcd_getstringsize("Bet", &w, &h);
648 rb->lcd_putsxy(LCD_WIDTH - w, 5*h / 2, "Bet");
649 rb->snprintf(str, 9, "$%d", bj->current_bet);
650 rb->lcd_getstringsize(str, &w, &h);
651 rb->lcd_putsxy(LCD_WIDTH - w, 7*h / 2, str);
652 rb->lcd_hline(0, LCD_WIDTH, LCD_HEIGHT/2);
653 y_loc = LCD_HEIGHT/2 + h;
654 #endif
656 rb->lcd_putsxy(0,0, "Dealer");
657 rb->lcd_getstringsize("Player", &w, &h);
658 rb->lcd_putsxy(0, y_loc, "Player");
659 rb->lcd_getstringsize("Total", &w, &h);
660 rb->lcd_putsxy(LCD_WIDTH - w, y_loc, "Total");
661 rb->lcd_getstringsize("Money", &w, &h);
662 rb->lcd_putsxy(LCD_WIDTH - w, 0, "Money");
663 rb->snprintf(str, 9, "$%d", bj->player_money - bj->current_bet);
664 rb->lcd_getstringsize(str, &w, &h);
665 rb->lcd_putsxy(LCD_WIDTH - w, h + 1, str);
666 rb->snprintf(str, 3, "%d", bj->player_total);
667 rb->lcd_getstringsize(str, &w, &h);
668 rb->lcd_putsxy(LCD_WIDTH - w, y_loc + h, str);
671 /*****************************************************************************
672 * find_value() is passed a card and returns its blackjack value.
673 ******************************************************************************/
674 static unsigned int find_value(unsigned int number) {
675 unsigned int thisValue;
676 if (number == 0)
677 thisValue = 11; /* Aces get a value of 11 at first */
678 else if (number < 10)
679 thisValue = number + 1;
680 else
681 thisValue = 10; /* Anything 10 or higher gets a value of 10 */
683 return thisValue;
686 /*****************************************************************************
687 * draw_card() draws a card to the screen.
688 ******************************************************************************/
689 static void draw_card(struct card temp_card, bool shown,
690 unsigned int x, unsigned int y) {
691 if(shown)
692 rb->lcd_bitmap_part(card_deck, CARD_WIDTH*temp_card.num,
693 CARD_HEIGHT*temp_card.suit,
694 STRIDE( SCREEN_MAIN, BMPWIDTH_card_deck,
695 BMPHEIGHT_card_deck),
696 x+1, y+1, CARD_WIDTH, CARD_HEIGHT);
697 else
698 rb->lcd_bitmap(card_back, x+1, y+1,CARD_WIDTH, CARD_HEIGHT);
699 #if LCD_DEPTH > 1
700 rb->lcd_set_foreground(LCD_BLACK);
701 #endif
703 /* Print outlines */
704 #if CARD_WIDTH >= 26
705 rb->lcd_hline(x+2, x+CARD_WIDTH-1, y);
706 rb->lcd_hline(x+2, x+CARD_WIDTH-1, y+CARD_HEIGHT+1);
707 rb->lcd_vline(x, y+2, y+CARD_HEIGHT-3);
708 rb->lcd_vline(x+CARD_WIDTH+1, y+2, y+CARD_HEIGHT-1);
709 rb->lcd_drawpixel(x+1, y+1);
710 rb->lcd_drawpixel(x+1, y+CARD_HEIGHT);
711 rb->lcd_drawpixel(x+CARD_WIDTH, y+1);
712 rb->lcd_drawpixel(x+CARD_WIDTH, y+CARD_HEIGHT);
713 #else
714 rb->lcd_hline(x+1, x+CARD_WIDTH, y);
715 rb->lcd_hline(x+1, x+CARD_WIDTH, y+CARD_HEIGHT+1);
716 rb->lcd_vline(x, y+1, y+CARD_HEIGHT);
717 rb->lcd_vline(x+CARD_WIDTH+1, y+1, y+CARD_HEIGHT);
718 #endif
720 #if LCD_DEPTH > 1
721 rb->lcd_set_foreground(FG_COLOR);
722 #endif
725 /*****************************************************************************
726 * new_card() initializes a new card and gives it values.
727 ******************************************************************************/
728 static struct card new_card(void) {
729 struct card new_card;
730 new_card.suit = rb->rand()%4; /* Random number 0-3 */
731 new_card.num = rb->rand()%13; /* Random number 0-12 */
732 new_card.value = find_value(new_card.num);
733 new_card.is_soft_ace = (new_card.num == 0);
734 return new_card;
737 /*****************************************************************************
738 * deal_init_card() deals and draws to the screen the player's and dealer's
739 * initial cards.
740 ******************************************************************************/
741 static void deal_init_cards(struct game_context* bj) {
742 bj->dealer_cards[0] = new_card();
743 bj->dealer_total += bj->dealer_cards[0].value;
745 draw_card(bj->dealer_cards[0], false, dealer_x, dealer_y);
747 bj->dealer_cards[1] = new_card();
748 bj->dealer_total += bj->dealer_cards[1].value;
749 draw_card(bj->dealer_cards[1], true, dealer_x + CARD_WIDTH + 4, dealer_y);
751 bj->player_cards[0][0] = new_card();
752 bj->player_total += bj->player_cards[0][0].value;
753 draw_card(bj->player_cards[0][0], true, player_x, player_y);
754 player_x += CARD_WIDTH + 4;
756 bj->player_cards[0][1] = new_card();
757 bj->player_total += bj->player_cards[0][1].value;
758 draw_card(bj->player_cards[0][1], true, player_x, player_y);
759 player_x += CARD_WIDTH + 4;
762 /*****************************************************************************
763 * redraw_board() redraws all the cards and the board
764 ******************************************************************************/
765 static void redraw_board(struct game_context* bj) {
766 unsigned int i, n, upper_bound;
767 rb->lcd_clear_display();
769 blackjack_drawtable(bj);
770 player_x = 4;
771 dealer_x = 4;
772 upper_bound = bj->split_status > 1 ? 2 : 1;
774 for (i = 0; i < bj->num_dealer_cards; i++) {
775 if (!bj->end_hand) {
776 draw_card(bj->dealer_cards[0], false, dealer_x, dealer_y);
778 /* increment i so the dealer's first card isn't displayed */
779 i++;
780 dealer_x += CARD_WIDTH + 4;
782 draw_card(bj->dealer_cards[i], true, dealer_x, dealer_y);
784 if (bj->num_dealer_cards > MAX_CARDS-1)
785 dealer_x += 10;
786 else
787 dealer_x += CARD_WIDTH + 4;
790 for (n = 0; n < upper_bound; n++) {
791 for (i = 0; i < bj->num_player_cards[n]; i++) {
792 draw_card(bj->player_cards[n][i], true, player_x, player_y);
793 if (bj->split_status>1 || bj->num_player_cards[n]>MAX_CARDS)
794 player_x += 10;
795 else
796 player_x += CARD_WIDTH + 4;
798 if (bj->split_status > 1)
799 player_x = LCD_WIDTH/2 + 4;
803 /*****************************************************************************
804 * update_total updates the player's total
805 ******************************************************************************/
806 static void update_total(struct game_context* bj) {
807 char total[3];
808 unsigned int w, h;
809 rb->snprintf(total, 3, "%d", bj->player_total);
810 rb->lcd_getstringsize(total, &w, &h);
811 #if LCD_HEIGHT > 64
812 h *= 2;
813 #endif
814 rb->lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2 + h, total);
815 rb->lcd_update_rect(LCD_WIDTH - w, LCD_HEIGHT/2 + h, w, h);
819 /*****************************************************************************
820 * check_for_aces() is passed an array of cards and returns where an ace is
821 * located. Otherwise, returns -1.
822 ******************************************************************************/
823 static signed int check_for_aces(struct card temp_cards[], unsigned int size) {
824 unsigned int i;
825 for(i = 0; i < size; i++) {
826 if (temp_cards[i].is_soft_ace)
827 return i;
829 return -1;
832 /*****************************************************************************
833 * check_totals() compares player and dealer totals.
834 * 0: bust 1: loss, 2: push, 3: win, 4: blackjack, 5: something's not right...
835 ******************************************************************************/
836 static unsigned int check_totals(struct game_context* bj) {
837 unsigned int temp;
838 if (bj->player_total > 21)
839 temp = 0;
840 else if (bj->player_total == 21 && bj->is_blackjack) {
841 if (bj->dealer_total == 21 && bj->num_dealer_cards == 2)
842 temp = 2;
843 else
844 temp = 4;
846 else if (bj->player_total == bj->dealer_total)
847 temp = 2;
848 else if (bj->dealer_total > 21 && bj->player_total < 22)
849 temp = 3;
850 else if (bj->dealer_total > bj->player_total)
851 temp = 1;
852 else if (bj->player_total > bj->dealer_total)
853 temp = 3;
854 else
855 temp = 5;
857 return temp;
860 /*****************************************************************************
861 * finish_dealer() draws cards for the dealer until he has 17 or more.
862 ******************************************************************************/
863 static void finish_dealer(struct game_context* bj) {
864 signed int temp = 0;
866 if (bj->dealer_total > 16 && bj->dealer_total < 22)
867 return;
869 while (bj->dealer_total < 17) {
870 bj->dealer_cards[bj->num_dealer_cards] = new_card();
871 bj->dealer_total += bj->dealer_cards[bj->num_dealer_cards].value;
872 bj->num_dealer_cards++;
875 while (bj->dealer_total > 21) {
876 temp = check_for_aces(bj->dealer_cards, bj->num_dealer_cards);
877 if(temp != -1) {
878 bj->dealer_cards[temp].is_soft_ace = false;
879 bj->dealer_total -= 10;
881 else
882 return;
886 /*****************************************************************************
887 * finish_game() completes the game once player's turn is over.
888 ******************************************************************************/
889 static void finish_game(struct game_context* bj) {
890 unsigned int rValue, w, h;
891 char str[19];
893 do {
894 finish_dealer(bj);
895 } while (bj->dealer_total < 17);
897 redraw_board(bj);
898 rValue = check_totals(bj);
900 if (rValue == 0) {
901 rb->snprintf(str, sizeof(str), " Bust! ");
902 bj->player_money -= bj->current_bet;
904 else if (rValue == 1) {
905 rb->snprintf(str, sizeof(str), " Sorry, you lost. ");
906 bj->player_money -= bj->current_bet;
908 else if (rValue == 2) {
909 rb->snprintf(str, sizeof(str), " Push ");
911 else if (rValue == 3) {
912 rb->snprintf(str, sizeof(str), " You won! ");
913 bj->player_money+= bj->current_bet;
915 else {
916 rb->snprintf(str, sizeof(str), " Blackjack! ");
917 bj->player_money += bj->current_bet * 3 / 2;
919 rb->lcd_getstringsize(str, &w, &h);
921 #if LCD_HEIGHT <= 64
922 rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID);
923 rb->lcd_fillrect(0, LCD_HEIGHT/2, LCD_WIDTH, LCD_HEIGHT/2);
924 rb->lcd_set_drawmode(DRMODE_SOLID);
925 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + h, str);
926 rb->snprintf(str, 12, "You have %d", bj->player_total);
927 rb->lcd_getstringsize(str, &w, &h);
928 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2, str);
929 #else
930 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h/2, str);
931 #endif
932 rb->lcd_update();
935 /*****************************************************************************
936 * blackjack_loadgame() loads the saved game and returns load success.
937 ******************************************************************************/
938 static bool blackjack_loadgame(struct game_context* bj) {
939 signed int fd;
940 bool loaded = false;
942 /* open game file */
943 fd = rb->open(SAVE_FILE, O_RDONLY);
944 if(fd < 0) return false;
946 /* read in saved game */
947 if(rb->read(fd, bj, sizeof(struct game_context))
948 == (long)sizeof(struct game_context))
950 loaded = true;
953 rb->close(fd);
955 return loaded;
958 /*****************************************************************************
959 * blackjack_savegame() saves the current game state.
960 ******************************************************************************/
961 static void blackjack_savegame(struct game_context* bj) {
962 int fd;
964 if(!resume)
965 return;
966 /* write out the game state to the save file */
967 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT, 0666);
968 if(fd < 0)
969 return;
970 rb->write(fd, bj, sizeof(struct game_context));
971 rb->close(fd);
974 /*****************************************************************************
975 * blackjack_get_yes_no() gets a yes/no answer from the user
976 ******************************************************************************/
977 static unsigned int blackjack_get_yes_no(char message[20]) {
978 int button;
979 unsigned int w, h, b, choice = 0;
980 bool breakout = false;
981 char message_yes[24], message_no[24];
983 rb->strcpy(message_yes, message);
984 rb->strcpy(message_no, message);
985 rb->strcat(message_yes, " Yes");
986 rb->strcat(message_no, " No");
987 rb->lcd_getstringsize(message_yes, &w, &h);
988 const char *stg[] = {message_yes, message_no};
990 #if LCD_HEIGHT <= 64
991 b = 2*h+1;
992 #else
993 b = h-1;
994 #endif
996 #ifdef HAVE_LCD_COLOR
997 rb->lcd_fillrect(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b, w+1, h+3);
998 rb->lcd_set_foreground(LCD_BLACK);
999 rb->lcd_set_background(LCD_WHITE);
1000 #else
1001 rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID);
1002 rb->lcd_fillrect(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b, w+1, h+3);
1003 rb->lcd_set_drawmode(DRMODE_SOLID);
1004 #endif
1005 rb->lcd_drawrect(LCD_WIDTH/2 - w/2 - 1, LCD_HEIGHT/2 + b - 1, w+3, h+4);
1007 while(!breakout) {
1008 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b +1, stg[choice]);
1009 rb->lcd_update_rect(LCD_WIDTH/2 - w/2 - 1, LCD_HEIGHT/2 + b -1,
1010 w+3, h+4);
1011 button = rb->button_get(true);
1013 switch(button) {
1014 case BJACK_LEFT:
1015 case (BJACK_LEFT|BUTTON_REPEAT):
1016 case BJACK_RIGHT:
1017 case (BJACK_RIGHT|BUTTON_REPEAT):
1018 choice ^= 1;
1019 break;
1020 case BJACK_SELECT: breakout = true;
1021 break;
1022 case BJACK_QUIT: breakout = true;
1023 choice = 1;
1024 break;
1028 #if LCD_DEPTH > 1
1029 rb->lcd_set_foreground(FG_COLOR);
1030 rb->lcd_set_background(BG_COLOR);
1031 #endif
1032 return choice;
1035 /*****************************************************************************
1036 * blackjack_get_amount() gets an amount from the player to be used
1037 ******************************************************************************/
1038 static signed int blackjack_get_amount(char message[20], signed int lower_limit,
1039 signed int upper_limit,
1040 signed int start) {
1041 int button;
1042 bool breakout = false, changed = false;
1043 unsigned int w, h;
1044 signed int amount;
1046 rb->lcd_getstringsize("A", &w, &h); /* find the size of one character */
1048 if (start > upper_limit)
1049 amount = upper_limit;
1050 else if (start < lower_limit)
1051 amount = lower_limit;
1052 else
1053 amount = start;
1055 #if LCD_DEPTH > 1
1056 rb->lcd_set_background(LCD_WHITE);
1057 rb->lcd_set_foreground(LCD_BLACK);
1058 #endif
1060 #if LCD_HEIGHT <= 64
1061 rb->lcd_clear_display();
1062 rb->lcd_puts(0, 1, message);
1063 rb->lcd_putsf(0, 2, "$%d", amount);
1064 rb->lcd_puts(0, 3, "RIGHT: +1");
1065 rb->lcd_puts(0, 4, "LEFT: -1");
1066 rb->lcd_puts(0, 5, "UP: +10");
1067 rb->lcd_puts(0, 6, "DOWN: -10");
1068 rb->lcd_update();
1069 #else
1070 rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID);
1071 rb->lcd_fillrect(LCD_WIDTH/2 - 9*w - 1, LCD_HEIGHT/2 - 4*h - 3,
1072 37*w / 2, 8*h -3);
1073 rb->lcd_set_drawmode(DRMODE_SOLID);
1074 rb->lcd_drawrect(LCD_WIDTH/2 - 9*w - 1, LCD_HEIGHT/2 - 4*h - 3,
1075 37*w / 2, 8*h -3);
1076 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 4*h - 1, message);
1077 rb->lcd_putsxyf(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, "$%d", amount);
1078 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
1079 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
1080 (CONFIG_KEYPAD == IPOD_1G2G_PAD) || \
1081 (CONFIG_KEYPAD == SANSA_E200_PAD) || \
1082 (CONFIG_KEYPAD == SANSA_FUZE_PAD) || \
1083 (CONFIG_KEYPAD == SANSA_CONNECT_PAD) || \
1084 (CONFIG_KEYPAD == MPIO_HD300_PAD)
1085 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, " >>|: +1");
1086 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, " |<<: -1");
1087 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "SCROLL+: +10");
1088 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "SCROLL-: -10");
1089 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
1090 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, "RIGHT: +1");
1091 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, "LEFT: -1");
1092 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "SCROLL+: +10");
1093 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "SCROLL-: -10");
1094 #else
1095 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, "RIGHT: +1");
1096 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, "LEFT: -1");
1097 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "UP: +10");
1098 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "DOWN: -10");
1099 #endif
1100 rb->lcd_update_rect(LCD_WIDTH/2 - 9*w - 1, LCD_HEIGHT/2 - 4*h - 3,
1101 37*w / 2, 8*h -3);
1102 #endif
1104 while(!breakout) {
1105 button = rb->button_get(true);
1107 switch(button) {
1108 case BJACK_UP:
1109 case (BJACK_UP|BUTTON_REPEAT):
1110 if (amount + 10 < upper_limit + 1) {
1111 amount += 10;
1112 changed = true;
1114 break;
1115 case BJACK_DOWN:
1116 case (BJACK_DOWN|BUTTON_REPEAT):
1117 if (amount - 10 > lower_limit - 1) {
1118 amount -= 10;
1119 changed = true;
1121 break;
1122 case BJACK_RIGHT:
1123 case (BJACK_RIGHT|BUTTON_REPEAT):
1124 if (amount + 1 < upper_limit + 1) {
1125 amount++;
1126 changed = true;
1128 break;
1129 case BJACK_LEFT:
1130 case (BJACK_LEFT|BUTTON_REPEAT):
1131 if (amount - 1 > lower_limit - 1) {
1132 amount--;
1133 changed = true;
1135 break;
1136 #ifdef BJACK_MAX
1137 case BJACK_MAX :
1138 amount = upper_limit;
1139 changed = true;
1140 break;
1141 #endif
1142 #ifdef BJACK_MIN
1143 case BJACK_MIN :
1144 amount = lower_limit;
1145 changed = true;
1146 break;
1147 #endif
1148 case BJACK_QUIT:
1149 breakout = true;
1150 amount = 0;
1151 break;
1152 case BJACK_SELECT:
1153 breakout = true;
1154 break;
1157 if(changed) {
1158 #if LCD_HEIGHT <= 64
1159 rb->lcd_putsf(0, 2, "$%d", amount);
1160 rb->lcd_update();
1161 #else
1162 rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID);
1163 rb->lcd_fillrect(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, 5*w, h);
1164 rb->lcd_set_drawmode(DRMODE_SOLID);
1165 rb->lcd_putsxyf(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, "$%d", amount);
1166 rb->lcd_update_rect(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, 5*w, h);
1167 #endif
1168 changed = false;
1172 #if LCD_DEPTH > 1
1173 rb->lcd_set_foreground(FG_COLOR);
1174 rb->lcd_set_background(BG_COLOR);
1175 #endif
1176 rb->lcd_clear_display();
1177 return amount;
1180 /*****************************************************************************
1181 * blackjack_get_bet() gets the player's bet.
1182 ******************************************************************************/
1183 static void blackjack_get_bet(struct game_context* bj) {
1184 bj->current_bet = blackjack_get_amount("Please enter a bet", 10,
1185 bj->player_money, bj->current_bet);
1188 /*****************************************************************************
1189 * double_down() returns one final card then finishes the game
1190 ******************************************************************************/
1191 static void double_down(struct game_context* bj) {
1192 bj->current_bet *= 2;
1193 bj->player_cards[0][bj->num_player_cards[0]] = new_card();
1194 bj->player_total += bj->player_cards[0][bj->num_player_cards[0]].value;
1195 bj->num_player_cards[0]++;
1198 /*****************************************************************************
1199 * split() checks if the player wants to split and acts accordingly.
1200 * When bj->split_status is 1, no split occurred. 2 means the player split and 3
1201 * means a split has already occurred and the first hand is done.
1202 ******************************************************************************/
1203 static void split(struct game_context* bj) {
1204 if (blackjack_get_yes_no("Split?") != 0)
1205 bj->split_status = 1;
1206 else {
1207 bj->split_status = 2;
1208 bj->current_bet *= 2;
1209 bj->num_player_cards[0] = 1;
1210 bj->num_player_cards[1] = 1;
1211 bj->player_cards[1][0] = bj->player_cards[0][1];
1212 bj->player_total = bj->player_cards[0][0].value;
1216 /*****************************************************************************
1217 * insurance() see if the player wants to buy insurance and how much.
1218 ******************************************************************************/
1219 static unsigned int insurance(struct game_context* bj) {
1220 unsigned int insurance, max_amount;
1222 insurance = blackjack_get_yes_no("Buy Insurance?");
1223 bj->asked_insurance = true;
1224 max_amount = bj->current_bet < (unsigned int)bj->player_money ?
1225 bj->current_bet/2 : (unsigned int)bj->player_money;
1226 if (insurance != 0) return 0;
1228 insurance = blackjack_get_amount("How much?", 0, max_amount, 0);
1229 redraw_board(bj);
1230 return insurance;
1233 /*****************************************************************************
1234 * play_again() checks to see if the player wants to keep playing.
1235 ******************************************************************************/
1236 static unsigned int play_again(void) {
1237 return blackjack_get_yes_no("Play Again?");
1240 /*****************************************************************************
1241 * blackjack_help() displays help text.
1242 ******************************************************************************/
1243 static bool blackjack_help(void) {
1244 static char *help_text[] = {
1245 "Blackjack", "", "Aim", "",
1246 "Try", "to", "get", "as", "close", "to", "21", "without", "going",
1247 "over", "or", "simply", "beat", "out", "the", "dealer", "for", "the",
1248 "best", "hand.", "", "",
1249 "Controls", "",
1250 BJACK_SELECT_NAME, ":", "hit", "/", "select", "",
1251 BJACK_STAY_NAME, ":", "stay", "",
1252 BJACK_DOUBLE_NAME, ":", "double", "down", "",
1253 BJACK_QUIT_NAME, ":", "go", "to", "menu", "",
1255 static struct style_text formation[]={
1256 { 0, TEXT_CENTER|TEXT_UNDERLINE },
1257 { 2, C_RED },
1258 { 26, C_RED },
1259 LAST_STYLE_ITEM
1262 rb->lcd_setfont(FONT_UI);
1263 #ifdef HAVE_LCD_COLOR
1264 rb->lcd_set_background(LCD_BLACK);
1265 rb->lcd_set_foreground(LCD_WHITE);
1266 #endif
1267 if (display_text(ARRAYLEN(help_text), help_text, formation, NULL, true))
1268 return true;
1269 rb->lcd_setfont(FONT_SYSFIXED);
1271 return false;
1274 static int blackjack_menu_cb(int action, const struct menu_item_ex *this_item)
1276 int i = ((intptr_t)this_item);
1277 if(action == ACTION_REQUEST_MENUITEM
1278 && !resume && (i==0 || i==5))
1279 return ACTION_EXIT_MENUITEM;
1280 return action;
1283 /*****************************************************************************
1284 * blackjack_menu() is the initial menu at the start of the game.
1285 ******************************************************************************/
1286 static unsigned int blackjack_menu(void) {
1287 int selection = 0;
1288 bool breakout = false;
1290 MENUITEM_STRINGLIST(menu, "BlackJack Menu", blackjack_menu_cb,
1291 "Resume Game", "Start New Game",
1292 "High Scores", "Help",
1293 "Playback Control",
1294 "Quit without Saving", "Quit");
1296 while(!breakout) {
1297 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1298 case 0:
1299 breakout = true;
1300 if(resume_file)
1301 rb->remove(SAVE_FILE);
1302 resume_file = false;
1303 break;
1304 case 1:
1305 breakout = true;
1306 resume = false;
1307 break;
1308 case 2:
1309 highscore_show(-1, highscores, NUM_SCORES, false);
1310 break;
1311 case 3:
1312 if(blackjack_help())
1313 return BJ_USB;
1314 break;
1315 case 4:
1316 if (playback_control(NULL))
1317 return BJ_USB;
1318 break;
1319 case 5:
1320 return BJ_QUIT_WITHOUT_SAVING;
1321 case 6:
1322 if (resume)
1323 return BJ_QUIT;
1324 else
1325 return BJ_QUIT_WITHOUT_SAVING;
1327 case MENU_ATTACHED_USB:
1328 return BJ_USB;
1330 default:
1331 break;
1335 return 0;
1338 /*****************************************************************************
1339 * blackjack() is the main game subroutine, it returns the final game status.
1340 ******************************************************************************/
1341 static int blackjack(struct game_context* bj) {
1342 int button;
1343 unsigned int w, h, temp_var, done = 0, todo = 1;
1344 signed int temp;
1345 bool breakout = false;
1346 bool dbl_down = false;
1348 /********************
1349 * menu *
1350 ********************/
1351 temp_var = blackjack_menu();
1352 if (temp_var != 0)
1353 return temp_var;
1355 #if LCD_DEPTH > 1
1356 rb->lcd_set_background(BG_COLOR);
1357 rb->lcd_set_foreground(FG_COLOR);
1358 #endif
1360 /********************
1361 * init *
1362 ********************/
1363 blackjack_init(bj);
1365 /********************
1366 * play *
1367 ********************/
1369 resume_file = false;
1370 /* check for resumed game */
1371 if(resume) {
1372 resume = false;
1373 redraw_board(bj);
1374 if (bj->split_status == 2) {
1375 todo=2;
1376 player_x = bj->num_player_cards[0] * 10 + 4;
1378 else if (bj->split_status == 3) {
1379 player_x = bj->num_player_cards[1] * 10 + LCD_WIDTH/2 + 4;
1380 todo=2;
1381 done=1;
1384 else {
1385 bj->player_money = 1000;
1386 bj->current_bet = 10;
1387 blackjack_get_bet(bj);
1388 if (bj->current_bet == 0)
1389 return -1;
1390 rb->lcd_clear_display();
1391 deal_init_cards(bj);
1392 blackjack_drawtable(bj);
1395 rb->lcd_update();
1397 breakout = false;
1399 while(true){
1400 if(bj->player_total == 21 && bj->num_player_cards[0] == 2) {
1401 bj->is_blackjack = true;
1402 bj->end_hand = true;
1403 finish_game(bj);
1405 else if(bj->dealer_cards[1].is_soft_ace && !breakout &&
1406 !bj->asked_insurance) {
1407 temp_var = insurance(bj);
1408 if (bj->dealer_total == 21) {
1409 rb->splash(HZ, "Dealer has blackjack");
1410 bj->player_money += temp_var;
1411 bj->end_hand = true;
1412 breakout = true;
1413 redraw_board(bj);
1414 finish_game(bj);
1416 else {
1417 rb->splash(HZ, "Dealer does not have blackjack");
1418 bj->player_money -= temp_var;
1419 breakout = true;
1420 redraw_board(bj);
1421 rb->lcd_update();
1424 if(!bj->end_hand && bj->split_status == 0 &&
1425 bj->player_cards[0][0].num == bj->player_cards[0][1].num) {
1426 split(bj);
1427 redraw_board(bj);
1428 rb->lcd_update_rect(0, LCD_HEIGHT/2, LCD_WIDTH, LCD_HEIGHT/2);
1429 if (bj->split_status == 2) {
1430 todo++;
1431 player_x = bj->num_player_cards[0] * 10 + 4;
1435 while(!bj->end_hand && done < todo) {
1436 button = rb->button_get(true);
1438 switch(button) {
1439 case BJACK_SELECT:
1440 NEXT_CARD = new_card();
1441 bj->player_total += NEXT_CARD.value;
1442 draw_card(NEXT_CARD, true, player_x, player_y);
1443 bj->num_player_cards[done]++;
1444 if (bj->num_player_cards[done] == MAX_CARDS + 1) {
1445 redraw_board(bj);
1446 rb->lcd_update_rect(0, LCD_HEIGHT/2, LCD_WIDTH,
1447 LCD_HEIGHT/2);
1449 else if (bj->num_player_cards[done]>MAX_CARDS || todo > 1) {
1450 rb->lcd_update_rect(player_x, player_y, CARD_WIDTH+2,
1451 CARD_HEIGHT+2);
1452 player_x += 10;
1454 else {
1455 rb->lcd_update_rect(player_x, player_y, CARD_WIDTH+2,
1456 CARD_HEIGHT+2);
1457 player_x += CARD_WIDTH + 4;
1459 update_total(bj);
1461 break;
1462 case BJACK_STAY:
1463 bj->end_hand = true;
1464 break;
1465 case BJACK_DOUBLEDOWN:
1466 if ((signed int)bj->current_bet * 2 <
1467 bj->player_money + 1 &&
1468 bj->num_player_cards[0]==2 && todo==1) {
1469 double_down(bj);
1470 dbl_down = true;
1471 if (bj->player_total < 22) {
1472 bj->end_hand = true;
1473 finish_game(bj);
1476 else if((signed int)bj->current_bet * 2 >
1477 bj->player_money){
1478 rb->splash(HZ, "Not enough money to double down.");
1479 redraw_board(bj);
1480 rb->lcd_update();
1482 break;
1484 case BJACK_QUIT:
1485 resume = true;
1486 return BJ_END;
1489 while (bj->player_total > 21 && !bj->end_hand) {
1490 temp = check_for_aces(bj->player_cards[done],
1491 bj->num_player_cards[done]);
1492 if(temp != -1) {
1493 bj->player_cards[done][temp].is_soft_ace = false;
1494 bj->player_total -= 10;
1495 update_total(bj);
1496 if (dbl_down) {
1497 bj->end_hand = true;
1498 finish_game(bj);
1501 else
1502 bj->end_hand = true;
1505 if (bj->end_hand) {
1506 done++;
1507 if(todo > 1) {
1508 if (done == 2) {
1509 temp = bj->player_total;
1510 bj->player_total = temp_var;
1511 temp_var = temp;
1512 finish_game(bj);
1513 rb->lcd_getstringsize(" Split 1 ", &w, &h);
1514 rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1515 " Split 1 ");
1516 rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1517 w,h);
1518 bj->current_bet /= 2;
1519 rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1520 w,h);
1521 rb->sleep(HZ*2);
1522 bj->player_total = temp_var;
1523 finish_game(bj);
1524 rb->lcd_getstringsize(" Split 2 ", &w, &h);
1525 rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1526 " Split 2 ");
1527 rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1528 w,h);
1529 rb->sleep(HZ*2);
1531 else {
1532 bj->end_hand = false;
1533 bj->split_status = 3;
1534 temp_var = bj->player_total;
1535 bj->player_total = bj->player_cards[1][0].value;
1536 update_total(bj);
1537 redraw_board(bj);
1538 player_x += 10;
1539 rb->lcd_update();
1542 else
1543 finish_game(bj);
1547 if (bj->player_money < 10) {
1548 rb->sleep(HZ);
1549 return BJ_LOSE;
1552 if (bj->end_hand) { /* If hand is over */
1553 if (play_again() != 0) /* User wants to quit */
1554 return BJ_END;
1555 else { /* User keeps playing */
1556 breakout = false;
1557 temp = bj->current_bet;
1558 bj->current_bet = 0;
1559 redraw_board(bj);
1560 rb->lcd_update();
1561 bj->current_bet = temp;
1562 if(dbl_down) {
1563 bj->current_bet /= 2;
1564 dbl_down = false;
1566 done = 0;
1567 todo = 1;
1568 blackjack_init(bj);
1569 blackjack_get_bet(bj);
1570 if (bj->current_bet == 0)
1571 return BJ_END;
1572 deal_init_cards(bj);
1573 blackjack_drawtable(bj);
1574 rb->lcd_update();
1578 /* Never reached */
1579 return PLUGIN_OK;
1582 /*****************************************************************************
1583 * plugin entry point.
1584 ******************************************************************************/
1585 enum plugin_status plugin_start(const void* parameter)
1587 struct game_context bj;
1588 bool exit = false;
1590 (void)parameter;
1592 #if LCD_DEPTH > 1
1593 rb->lcd_set_backdrop(NULL);
1594 #endif
1596 /* load high scores */
1597 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
1598 resume = blackjack_loadgame(&bj);
1599 resume_file = resume;
1601 rb->lcd_setfont(FONT_SYSFIXED);
1603 while(!exit) {
1604 switch(blackjack(&bj)){
1605 case BJ_LOSE:
1606 rb->splash(HZ, "Not enough money to continue");
1607 /* fall through to BJ_END */
1609 case BJ_END:
1610 if(!resume && bj.player_money > 10) {
1611 /* There is no level, so store -1 to blank column */
1612 int position = highscore_update(bj.player_money, -1, "",
1613 highscores, NUM_SCORES);
1614 if (position != -1)
1616 if (position==0)
1617 rb->splash(HZ*2, "New High Score");
1618 highscore_show(position, highscores, NUM_SCORES, false);
1621 break;
1623 case BJ_USB:
1624 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
1625 return PLUGIN_USB_CONNECTED;
1627 case BJ_QUIT:
1628 rb->splash(HZ*1, "Saving game...");
1629 blackjack_savegame(&bj);
1630 /* fall through */
1632 case BJ_QUIT_WITHOUT_SAVING:
1633 exit = true;
1634 break;
1636 default:
1637 break;
1640 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
1641 return PLUGIN_OK;