use lib display text to display help messages (FS#10099).
[kugel-rb.git] / apps / plugins / pegbox.c
blobeb53eca8b59a763e244bd3339e816023e1475445
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 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 ****************************************************************************/
21 #include "plugin.h"
22 #include "lib/display_text.h"
24 #include "pluginbitmaps/pegbox_header.h"
25 #include "pluginbitmaps/pegbox_pieces.h"
27 #if LCD_HEIGHT >= 80 /* enough space for a graphical menu */
28 #include "pluginbitmaps/pegbox_menu_top.h"
29 #include "pluginbitmaps/pegbox_menu_items.h"
30 #define MENU_X (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2
31 #define MENU_Y BMPHEIGHT_pegbox_menu_top
32 #define ITEM_WIDTH BMPWIDTH_pegbox_menu_items
33 #define ITEM_HEIGHT (BMPHEIGHT_pegbox_menu_items/9)
34 #endif
36 PLUGIN_HEADER
38 /* final game return status */
39 #define PB_END 3
40 #define PB_USB 2
41 #define PB_QUIT 1
43 #define DATA_FILE PLUGIN_GAMES_DIR "/pegbox.data"
44 #define SAVE_FILE PLUGIN_GAMES_DIR "/pegbox.save"
46 #define ROWS 8 /* Number of rows on each board */
47 #define COLS 12 /* Number of columns on each board */
48 #define NUM_LEVELS 15 /* Number of levels */
50 #define SPACE 0
51 #define WALL 1
52 #define TRIANGLE 2
53 #define CROSS 3
54 #define SQUARE 4
55 #define CIRCLE 5
56 #define HOLE 6
57 #define PLAYER 7
59 #if CONFIG_KEYPAD == RECORDER_PAD
60 #define PEGBOX_SAVE BUTTON_ON
61 #define PEGBOX_QUIT BUTTON_OFF
62 #define PEGBOX_RESTART BUTTON_F2
63 #define PEGBOX_LVL_UP BUTTON_F1
64 #define PEGBOX_LVL_DOWN BUTTON_F3
65 #define PEGBOX_UP BUTTON_UP
66 #define PEGBOX_DOWN BUTTON_DOWN
67 #define PEGBOX_RIGHT BUTTON_RIGHT
68 #define PEGBOX_LEFT BUTTON_LEFT
70 #define SAVE_TEXT "ON"
71 #define QUIT_TEXT "OFF"
72 #define RESTART_TEXT "F2"
73 #define LVL_UP_TEXT "F1"
74 #define LVL_DOWN_TEXT "F3"
76 #elif CONFIG_KEYPAD == ONDIO_PAD
77 #define PEGBOX_SAVE BUTTON_OFF
78 #define PEGBOX_QUIT (BUTTON_MENU | BUTTON_LEFT)
79 #define PEGBOX_RESTART (BUTTON_MENU | BUTTON_RIGHT)
80 #define PEGBOX_LVL_UP (BUTTON_MENU | BUTTON_UP)
81 #define PEGBOX_LVL_DOWN (BUTTON_MENU | BUTTON_DOWN)
82 #define PEGBOX_UP BUTTON_UP
83 #define PEGBOX_DOWN BUTTON_DOWN
84 #define PEGBOX_RIGHT BUTTON_RIGHT
85 #define PEGBOX_LEFT BUTTON_LEFT
87 #define SAVE_TEXT "OFF"
88 #define QUIT_TEXT "M+LEFT"
89 #define RESTART_TEXT "M+RIGHT"
90 #define LVL_UP_TEXT "M+UP"
91 #define LVL_DOWN_TEXT "M+DOWN"
93 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
94 (CONFIG_KEYPAD == IRIVER_H300_PAD)
95 #define PEGBOX_SAVE BUTTON_SELECT
96 #define PEGBOX_QUIT BUTTON_OFF
97 #define PEGBOX_RESTART BUTTON_ON
98 #define PEGBOX_LVL_UP BUTTON_MODE
99 #define PEGBOX_LVL_DOWN BUTTON_REC
100 #define PEGBOX_UP BUTTON_UP
101 #define PEGBOX_DOWN BUTTON_DOWN
102 #define PEGBOX_RIGHT BUTTON_RIGHT
103 #define PEGBOX_LEFT BUTTON_LEFT
105 #define SAVE_TEXT "NAVI"
106 #define QUIT_TEXT "OFF"
107 #define RESTART_TEXT "ON"
108 #define LVL_UP_TEXT "AB"
109 #define LVL_DOWN_TEXT "REC"
111 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
112 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
113 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
114 #define PEGBOX_SAVE (BUTTON_SELECT|BUTTON_RIGHT)
115 #define PEGBOX_QUIT (BUTTON_SELECT|BUTTON_PLAY)
116 #define PEGBOX_RESTART (BUTTON_SELECT|BUTTON_LEFT)
117 #define PEGBOX_LVL_UP (BUTTON_SELECT|BUTTON_MENU)
118 #define PEGBOX_UP BUTTON_MENU
119 #define PEGBOX_DOWN BUTTON_PLAY
120 #define PEGBOX_RIGHT BUTTON_RIGHT
121 #define PEGBOX_LEFT BUTTON_LEFT
123 #define SAVE_TEXT "SELECT+RIGHT"
124 #define QUIT_TEXT "SELECT+PLAY"
125 #define RESTART_TEXT "SELECT+LEFT"
126 #define LVL_UP_TEXT "SELECT+MENU"
127 #define LVL_DOWN_TEXT "-"
129 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
130 #define PEGBOX_SAVE BUTTON_SELECT
131 #define PEGBOX_QUIT BUTTON_POWER
132 #define PEGBOX_RESTART BUTTON_REC
133 #define PEGBOX_LVL_UP BUTTON_PLAY
134 #define PEGBOX_UP BUTTON_UP
135 #define PEGBOX_DOWN BUTTON_DOWN
136 #define PEGBOX_RIGHT BUTTON_RIGHT
137 #define PEGBOX_LEFT BUTTON_LEFT
139 #define SAVE_TEXT "SELECT"
140 #define QUIT_TEXT "OFF"
141 #define RESTART_TEXT "REC"
142 #define LVL_UP_TEXT "PLAY"
143 #define LVL_DOWN_TEXT "-"
145 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
146 #define PEGBOX_SAVE BUTTON_MODE
147 #define PEGBOX_QUIT BUTTON_PLAY
148 #define PEGBOX_RESTART (BUTTON_EQ|BUTTON_MODE)
149 #define PEGBOX_LVL_UP (BUTTON_EQ|BUTTON_UP)
150 #define PEGBOX_LVL_DOWN (BUTTON_EQ|BUTTON_DOWN)
151 #define PEGBOX_UP BUTTON_UP
152 #define PEGBOX_DOWN BUTTON_DOWN
153 #define PEGBOX_RIGHT BUTTON_RIGHT
154 #define PEGBOX_LEFT BUTTON_LEFT
156 #define SAVE_TEXT "MODE"
157 #define QUIT_TEXT "PLAY"
158 #define RESTART_TEXT "EQ+MODE"
159 #define LVL_UP_TEXT "EQ+UP"
160 #define LVL_DOWN_TEXT "EQ+DOWN"
162 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
163 #define PEGBOX_SAVE BUTTON_PLAY
164 #define PEGBOX_QUIT BUTTON_POWER
165 #define PEGBOX_RESTART (BUTTON_FF|BUTTON_REPEAT)
166 #define PEGBOX_LVL_UP (BUTTON_FF|BUTTON_SCROLL_UP)
167 #define PEGBOX_LVL_DOWN (BUTTON_FF|BUTTON_SCROLL_DOWN)
168 #define PEGBOX_UP BUTTON_SCROLL_UP
169 #define PEGBOX_DOWN BUTTON_SCROLL_DOWN
170 #define PEGBOX_RIGHT BUTTON_RIGHT
171 #define PEGBOX_LEFT BUTTON_LEFT
173 #define SAVE_TEXT "PLAY"
174 #define QUIT_TEXT "OFF"
175 #define RESTART_TEXT "LONG FF"
176 #define LVL_UP_TEXT "FF+SCROLL_UP"
177 #define LVL_DOWN_TEXT "FF+SCROLL_DOWN"
179 #elif CONFIG_KEYPAD == SANSA_E200_PAD
180 #define PEGBOX_SAVE BUTTON_SELECT
181 #define PEGBOX_QUIT BUTTON_POWER
182 #define PEGBOX_RESTART BUTTON_REC
183 #define PEGBOX_LVL_UP BUTTON_SCROLL_BACK
184 #define PEGBOX_LVL_DOWN BUTTON_SCROLL_FWD
185 #define PEGBOX_UP BUTTON_UP
186 #define PEGBOX_DOWN BUTTON_DOWN
187 #define PEGBOX_RIGHT BUTTON_RIGHT
188 #define PEGBOX_LEFT BUTTON_LEFT
190 #define SAVE_TEXT "SELECT"
191 #define QUIT_TEXT "POWER"
192 #define RESTART_TEXT "REC"
193 #define LVL_UP_TEXT "SCROLL BACK"
194 #define LVL_DOWN_TEXT "SCROLL FWD"
196 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
197 #define PEGBOX_SAVE BUTTON_SELECT|BUTTON_REL
198 #define PEGBOX_QUIT (BUTTON_HOME|BUTTON_REPEAT)
199 #define PEGBOX_RESTART (BUTTON_SELECT|BUTTON_LEFT)
200 #define PEGBOX_LVL_UP (BUTTON_SELECT|BUTTON_UP)
201 #define PEGBOX_LVL_DOWN (BUTTON_SELECT|BUTTON_DOWN)
202 #define PEGBOX_UP BUTTON_UP
203 #define PEGBOX_DOWN BUTTON_DOWN
204 #define PEGBOX_RIGHT BUTTON_RIGHT
205 #define PEGBOX_LEFT BUTTON_LEFT
207 #define SAVE_TEXT "SELECT"
208 #define QUIT_TEXT "HOME"
209 #define RESTART_TEXT "SELECT & LEFT"
210 #define LVL_UP_TEXT "SELECT & UP"
211 #define LVL_DOWN_TEXT "SELECT & DOWN"
213 #elif CONFIG_KEYPAD == GIGABEAT_PAD
214 #define PEGBOX_SAVE BUTTON_SELECT
215 #define PEGBOX_QUIT BUTTON_POWER
216 #define PEGBOX_RESTART BUTTON_A
217 #define PEGBOX_LVL_UP BUTTON_VOL_UP
218 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
219 #define PEGBOX_UP BUTTON_UP
220 #define PEGBOX_DOWN BUTTON_DOWN
221 #define PEGBOX_RIGHT BUTTON_RIGHT
222 #define PEGBOX_LEFT BUTTON_LEFT
224 #define SAVE_TEXT "SELECT"
225 #define QUIT_TEXT "POWER"
226 #define RESTART_TEXT "A"
227 #define LVL_UP_TEXT "VOL+"
228 #define LVL_DOWN_TEXT "VOL-"
230 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
231 #define PEGBOX_SAVE BUTTON_SELECT
232 #define PEGBOX_QUIT BUTTON_BACK
233 #define PEGBOX_RESTART BUTTON_MENU
234 #define PEGBOX_LVL_UP BUTTON_VOL_UP
235 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
236 #define PEGBOX_UP BUTTON_UP
237 #define PEGBOX_DOWN BUTTON_DOWN
238 #define PEGBOX_RIGHT BUTTON_RIGHT
239 #define PEGBOX_LEFT BUTTON_LEFT
241 #define SAVE_TEXT "SELECT"
242 #define QUIT_TEXT "BACK"
243 #define RESTART_TEXT "MENU"
244 #define LVL_UP_TEXT "VOL+"
245 #define LVL_DOWN_TEXT "VOL-"
247 #elif CONFIG_KEYPAD == MROBE100_PAD
248 #define PEGBOX_SAVE BUTTON_SELECT
249 #define PEGBOX_QUIT BUTTON_POWER
250 #define PEGBOX_RESTART BUTTON_PLAY
251 #define PEGBOX_LVL_UP BUTTON_MENU
252 #define PEGBOX_LVL_DOWN BUTTON_DISPLAY
253 #define PEGBOX_UP BUTTON_UP
254 #define PEGBOX_DOWN BUTTON_DOWN
255 #define PEGBOX_RIGHT BUTTON_RIGHT
256 #define PEGBOX_LEFT BUTTON_LEFT
258 #define SAVE_TEXT "SELECT"
259 #define QUIT_TEXT "POWER"
260 #define RESTART_TEXT "PLAY"
261 #define LVL_UP_TEXT "MENU"
262 #define LVL_DOWN_TEXT "DISPLAY"
264 #elif CONFIG_KEYPAD == SANSA_C200_PAD
265 #define PEGBOX_SAVE BUTTON_SELECT
266 #define PEGBOX_QUIT BUTTON_POWER
267 #define PEGBOX_RESTART BUTTON_REC
268 #define PEGBOX_LVL_UP BUTTON_VOL_UP
269 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
270 #define PEGBOX_UP BUTTON_UP
271 #define PEGBOX_DOWN BUTTON_DOWN
272 #define PEGBOX_RIGHT BUTTON_RIGHT
273 #define PEGBOX_LEFT BUTTON_LEFT
275 #define SAVE_TEXT "SELECT"
276 #define QUIT_TEXT "POWER"
277 #define RESTART_TEXT "REC"
278 #define LVL_UP_TEXT "VOL+"
279 #define LVL_DOWN_TEXT "VOL-"
281 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
282 #define PEGBOX_SAVE BUTTON_SELECT
283 #define PEGBOX_QUIT BUTTON_POWER
284 #define PEGBOX_RESTART BUTTON_HOME
285 #define PEGBOX_LVL_UP BUTTON_VOL_UP
286 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
287 #define PEGBOX_UP BUTTON_UP
288 #define PEGBOX_DOWN BUTTON_DOWN
289 #define PEGBOX_RIGHT BUTTON_RIGHT
290 #define PEGBOX_LEFT BUTTON_LEFT
292 #define SAVE_TEXT "SELECT"
293 #define QUIT_TEXT "POWER"
294 #define RESTART_TEXT "HOME"
295 #define LVL_UP_TEXT "VOL+"
296 #define LVL_DOWN_TEXT "VOL-"
298 #elif CONFIG_KEYPAD == SANSA_M200_PAD
299 #define PEGBOX_SAVE (BUTTON_SELECT | BUTTON_REL)
300 #define PEGBOX_QUIT BUTTON_POWER
301 #define PEGBOX_RESTART (BUTTON_SELECT | BUTTON_UP)
302 #define PEGBOX_LVL_UP BUTTON_VOL_UP
303 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
304 #define PEGBOX_UP BUTTON_UP
305 #define PEGBOX_DOWN BUTTON_DOWN
306 #define PEGBOX_RIGHT BUTTON_RIGHT
307 #define PEGBOX_LEFT BUTTON_LEFT
309 #define SAVE_TEXT "SELECT"
310 #define QUIT_TEXT "POWER"
311 #define RESTART_TEXT "SELECT+UP"
312 #define LVL_UP_TEXT "VOL+"
313 #define LVL_DOWN_TEXT "VOL-"
316 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
317 #define PEGBOX_SAVE BUTTON_RC_PLAY
318 #define PEGBOX_QUIT BUTTON_RC_REC
319 #define PEGBOX_RESTART BUTTON_RC_MODE
320 #define PEGBOX_LVL_UP BUTTON_VOL_UP
321 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
322 #define PEGBOX_UP BUTTON_RC_VOL_UP
323 #define PEGBOX_DOWN BUTTON_RC_VOL_DOWN
324 #define PEGBOX_RIGHT BUTTON_RC_FF
325 #define PEGBOX_LEFT BUTTON_RC_REW
327 #define SAVE_TEXT "REM. PLAY"
328 #define QUIT_TEXT "REM. REC"
329 #define RESTART_TEXT "REM. MODE"
330 #define LVL_UP_TEXT "VOL+"
331 #define LVL_DOWN_TEXT "VOL-"
333 #elif CONFIG_KEYPAD == COWOND2_PAD
334 #define PEGBOX_QUIT BUTTON_POWER
336 #define QUIT_TEXT "POWER"
338 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
339 #define PEGBOX_SAVE BUTTON_CUSTOM
340 #define PEGBOX_QUIT BUTTON_BACK
341 #define PEGBOX_RESTART BUTTON_SELECT
342 #define PEGBOX_LVL_UP BUTTON_PLAY
343 #define PEGBOX_LVL_DOWN BUTTON_MENU
344 #define PEGBOX_UP BUTTON_UP
345 #define PEGBOX_DOWN BUTTON_DOWN
346 #define PEGBOX_RIGHT BUTTON_RIGHT
347 #define PEGBOX_LEFT BUTTON_LEFT
349 #define SAVE_TEXT "CUSTOM"
350 #define QUIT_TEXT "BACK"
351 #define RESTART_TEXT "MIDDLE"
352 #define LVL_UP_TEXT "SELECT"
353 #define LVL_DOWN_TEXT "MENU"
355 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
356 #define PEGBOX_SAVE BUTTON_VIEW
357 #define PEGBOX_QUIT BUTTON_POWER
358 #define PEGBOX_RESTART BUTTON_MENU
359 #define PEGBOX_LVL_UP BUTTON_VOL_UP
360 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
361 #define PEGBOX_UP BUTTON_UP
362 #define PEGBOX_DOWN BUTTON_DOWN
363 #define PEGBOX_RIGHT BUTTON_RIGHT
364 #define PEGBOX_LEFT BUTTON_LEFT
366 #define SAVE_TEXT "VIEW"
367 #define QUIT_TEXT "POWER"
368 #define RESTART_TEXT "MENU"
369 #define LVL_UP_TEXT "VOL+"
370 #define LVL_DOWN_TEXT "VOL-"
372 #elif CONFIG_KEYPAD == ONDAVX747_PAD || CONFIG_KEYPAD == MROBE500_PAD
373 #define PEGBOX_QUIT BUTTON_POWER
375 #define QUIT_TEXT "POWER"
377 #else
378 #error Unsupported keymap!
379 #endif
381 #ifdef HAVE_TOUCHSCREEN
382 #ifndef PEGBOX_QUIT
383 #define PEGBOX_QUIT BUTTON_TOPLEFT
384 #endif
385 #ifndef PEGBOX_SAVE
386 #define PEGBOX_SAVE BUTTON_CENTER
387 #endif
388 #ifndef PEGBOX_RESTART
389 #define PEGBOX_RESTART BUTTON_TOPRIGHT
390 #endif
391 #ifndef PEGBOX_LVL_UP
392 #define PEGBOX_LVL_UP BUTTON_BOTTOMLEFT
393 #endif
394 #ifndef PEGBOX_LVL_DOWN
395 #define PEGBOX_LVL_DOWN BUTTON_BOTTOMRIGHT
396 #endif
397 #ifndef PEGBOX_UP
398 #define PEGBOX_UP BUTTON_TOPMIDDLE
399 #endif
400 #ifndef PEGBOX_DOWN
401 #define PEGBOX_DOWN BUTTON_BOTTOMMIDDLE
402 #endif
403 #ifndef PEGBOX_RIGHT
404 #define PEGBOX_RIGHT BUTTON_MIDRIGHT
405 #endif
406 #ifndef PEGBOX_LEFT
407 #define PEGBOX_LEFT BUTTON_MIDLEFT
408 #endif
409 #ifndef SAVE_TEXT
410 #define SAVE_TEXT "CENTER"
411 #endif
412 #ifndef QUIT_TEXT
413 #define QUIT_TEXT "TOPLEFT"
414 #endif
415 #ifndef RESTART_TEXT
416 #define RESTART_TEXT "TOPRIGHT"
417 #endif
418 #ifndef LVL_UP_TEXT
419 #define LVL_UP_TEXT "BOTTOMLEFT"
420 #endif
421 #ifndef LVL_DOWN_TEXT
422 #define LVL_DOWN_TEXT "BOTTOMRIGHT"
423 #endif
424 #endif
427 /* get several sizes from the bitmaps */
428 #ifdef BMPWIDTH_pegbox_pieces
429 #define PIECE_WIDTH BMPWIDTH_pegbox_pieces
430 #define PIECE_HEIGHT (BMPHEIGHT_pegbox_pieces/7)
431 #else
432 /* dummy numbers to avoid #error in dependency generation */
433 #define PIECE_WIDTH 50
434 #define PIECE_HEIGHT 10
435 #endif
437 #define BOARD_WIDTH (12*PIECE_WIDTH)
438 #define BOARD_HEIGHT (8*PIECE_HEIGHT)
441 /* define a wide layout where the statistics are alongside the board, not above
442 * base calculation on the piece bitmaps for the 8x12 board */
443 #if (LCD_WIDTH - BOARD_WIDTH) > (LCD_HEIGHT - BOARD_HEIGHT)
444 #define WIDE_LAYOUT
445 #endif
448 #define HEADER_WIDTH BMPWIDTH_pegbox_header
449 #define HEADER_HEIGHT BMPHEIGHT_pegbox_header
452 #if defined WIDE_LAYOUT
454 #if ((BOARD_WIDTH + HEADER_WIDTH + 4) <= LCD_WIDTH)
455 #define BOARD_X 2
456 #else
457 #define BOARD_X 1
458 #endif
459 #define BOARD_Y (LCD_HEIGHT-BOARD_HEIGHT)/2
461 #if (LCD_WIDTH >= 132) && (LCD_HEIGHT >= 80)
462 #define TEXT_X 116
463 #define LEVEL_TEXT_Y 14
464 #define PEGS_TEXT_Y 58
465 #elif (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 64)
466 #define TEXT_X 112
467 #define LEVEL_TEXT_Y 27
468 #define PEGS_TEXT_Y 50
469 #else
470 #error "Unsupported screen size"
471 #endif
473 #else /* "normal" layout */
475 #define BOARD_X (LCD_WIDTH-BOARD_WIDTH)/2
476 #if ((BOARD_HEIGHT + HEADER_HEIGHT + 4) <= LCD_HEIGHT)
477 #define BOARD_Y HEADER_HEIGHT+2
478 #else
479 #define BOARD_Y HEADER_HEIGHT
480 #endif
482 #if LCD_WIDTH >= 320
483 #define LEVEL_TEXT_X 59
484 #define PEGS_TEXT_X 276
485 #define TEXT_Y 28
486 #elif LCD_WIDTH >= 240
487 #define LEVEL_TEXT_X 59
488 #define PEGS_TEXT_X 196
489 #define TEXT_Y 28
490 #elif LCD_WIDTH >= 220
491 #define LEVEL_TEXT_X 49
492 #define PEGS_TEXT_X 186
493 #define TEXT_Y 28
494 #elif LCD_WIDTH >= 176
495 #define LEVEL_TEXT_X 38
496 #define PEGS_TEXT_X 155
497 #define TEXT_Y 17
498 #elif LCD_WIDTH >= 160
499 #define LEVEL_TEXT_X 37
500 #define PEGS_TEXT_X 140
501 #define TEXT_Y 13
502 #elif LCD_WIDTH >= 138
503 #define LEVEL_TEXT_X 28
504 #define PEGS_TEXT_X 119
505 #define TEXT_Y 15
506 #elif LCD_WIDTH >= 128
507 #if HEADER_HEIGHT > 16
508 #define LEVEL_TEXT_X 26
509 #define PEGS_TEXT_X 107
510 #define TEXT_Y 31
511 #else
512 #define LEVEL_TEXT_X 15
513 #define PEGS_TEXT_X 100
514 #define TEXT_Y 5
515 #endif /* HEADER_HEIGHT */
516 #elif LCD_WIDTH >= 112
517 #define LEVEL_TEXT_X 25
518 #define PEGS_TEXT_X 90
519 #define TEXT_Y 0
520 #endif /* LCD_WIDTH */
522 #endif /* WIDE_LAYOUT */
525 #ifdef HAVE_LCD_COLOR
526 #define BG_COLOR LCD_BLACK
527 #define TEXT_BG LCD_RGBPACK(189,189,189)
528 #endif
531 #ifdef HAVE_TOUCHSCREEN
532 #include "lib/touchscreen.h"
534 static struct ts_mapping main_menu_items[5] =
536 {MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT},
537 {MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT},
538 {MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT},
539 {MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT},
541 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT > 110)
542 0, MENU_Y+4*ITEM_HEIGHT+8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
543 #elif LCD_WIDTH > 112
544 0, LCD_HEIGHT - 8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
545 #else
546 #error "Touchscreen isn't supported on non-bitmap screens!"
547 #endif
551 static struct ts_mappings main_menu = {main_menu_items, 5};
553 static struct ts_raster pegbox_raster =
554 { BOARD_X, BOARD_Y, COLS*PIECE_WIDTH, ROWS*PIECE_HEIGHT,
555 PIECE_WIDTH, PIECE_HEIGHT };
556 static struct ts_raster_button_mapping pegbox_raster_btn =
557 { &pegbox_raster, false, false, true, false, true, {0, 0}, 0, 0, 0 };
558 #endif
560 struct game_context {
561 unsigned int level;
562 unsigned int highlevel;
563 signed int player_row;
564 signed int player_col;
565 unsigned int num_left;
566 bool save_exist;
567 unsigned int playboard[ROWS][COLS];
570 char levels[NUM_LEVELS][ROWS][COLS] = {
571 /* Level 1 */
572 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
573 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
574 {1, 0, 0, 0, 7, 0, 0, 5, 0, 0, 0, 1,},
575 {1, 0, 0, 0, 0, 3, 3, 2, 0, 0, 0, 1,},
576 {1, 0, 0, 0, 4, 6, 0, 5, 0, 0, 0, 1,},
577 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
578 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
579 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
581 /* Level 2 */
582 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
583 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,},
584 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
585 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
586 {7, 0, 0, 0, 2, 2, 5, 5, 0, 0, 0, 1,},
587 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
588 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
589 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,}},
591 /* Level 3 */
592 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
593 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
594 {1, 0, 0, 0, 0, 0, 2, 0, 7, 0, 0, 0,},
595 {1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 2, 1,},
596 {1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1,},
597 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,},
598 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
599 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
601 /* Level 4 */
602 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
603 {6, 0, 4, 0, 2, 0, 2, 0, 0, 0, 0, 1,},
604 {6, 0, 3, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
605 {6, 0, 5, 0, 4, 7, 2, 0, 0, 0, 0, 1,},
606 {6, 0, 2, 0, 4, 0, 2, 0, 3, 0, 0, 1,},
607 {6, 0, 4, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
608 {6, 0, 5, 0, 4, 0, 2, 0, 0, 0, 0, 1,},
609 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
611 /* Level 5 */
612 {{0, 6, 6, 0, 4, 6, 0, 0, 6, 0, 0, 0,},
613 {0, 6, 6, 0, 4, 4, 0, 0, 6, 0, 0, 2,},
614 {2, 6, 6, 0, 6, 6, 6, 0, 1, 2, 2, 2,},
615 {0, 6, 6, 0, 6, 4, 6, 0, 1, 2, 0, 2,},
616 {0, 6, 6, 0, 6, 7, 6, 5, 6, 0, 0, 0,},
617 {2, 6, 6, 0, 6, 6, 6, 0, 6, 0, 0, 0,},
618 {0, 6, 6, 0, 4, 0, 0, 0, 6, 0, 0, 0,},
619 {0, 6, 6, 0, 0, 5, 0, 0, 6, 5, 5, 0,}},
621 /* Level 6 */
622 {{7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
623 {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,},
624 {2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0,},
625 {0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 0,},
626 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
627 {0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1,},
628 {0, 3, 0, 0, 0, 0, 0, 0, 5, 4, 6, 0,},
629 {0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1,}},
631 /* Level 7 */
632 {{1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,},
633 {1, 1, 1, 6, 0, 0, 4, 6, 0, 1, 1, 1,},
634 {1, 1, 1, 1, 0, 1, 5, 1, 0, 1, 1, 1,},
635 {1, 1, 1, 2, 3, 3, 7, 4, 2, 6, 1, 1,},
636 {1, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1,},
637 {1, 1, 1, 1, 0, 0, 5, 0, 0, 1, 0, 1,},
638 {1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,},
639 {1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,}},
641 /* Level 8 */
642 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
643 {0, 0, 3, 3, 3, 3, 3, 4, 3, 3, 0, 0,},
644 {0, 0, 3, 3, 3, 2, 3, 3, 5, 3, 0, 0,},
645 {7, 0, 3, 3, 3, 2, 3, 3, 4, 3, 0, 0,},
646 {0, 0, 3, 3, 4, 5, 3, 3, 3, 3, 0, 0,},
647 {0, 0, 3, 3, 5, 2, 3, 3, 3, 3, 0, 0,},
648 {0, 0, 3, 3, 2, 4, 3, 3, 3, 3, 0, 0,},
649 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
651 /* Level 9 */
652 {{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
653 {0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
654 {0, 0, 0, 0, 2, 4, 4, 3, 0, 1, 1, 0,},
655 {0, 1, 0, 0, 2, 1, 0, 0, 0, 1, 1, 1,},
656 {0, 0, 0, 2, 2, 7, 1, 0, 0, 0, 0, 2,},
657 {0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 1, 1,},
658 {0, 3, 1, 0, 2, 5, 5, 0, 0, 0, 3, 0,},
659 {0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0,}},
661 /* Level 10 */
662 {{1, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0,},
663 {1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 7,},
664 {0, 0, 4, 0, 6, 6, 6, 0, 0, 0, 3, 0,},
665 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
666 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
667 {0, 0, 0, 0, 6, 6, 6, 0, 3, 0, 0, 0,},
668 {1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0,},
669 {1, 1, 1, 1, 1, 2, 1, 1, 0, 0, 0, 0,}},
671 /* Level 11 */
672 {{1, 7, 1, 0, 1, 1, 6, 0, 0, 1, 1, 0,},
673 {1, 0, 0, 0, 5, 4, 6, 6, 0, 2, 2, 0,},
674 {1, 2, 1, 2, 0, 1, 6, 0, 0, 2, 2, 0,},
675 {1, 0, 0, 2, 0, 1, 0, 0, 0, 3, 3, 0,},
676 {1, 2, 1, 0, 0, 1, 0, 1, 0, 3, 3, 0,},
677 {0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0,},
678 {0, 3, 4, 3, 0, 1, 0, 1, 0, 0, 0, 0,},
679 {0, 0, 0, 0, 2, 2, 2, 1, 1, 1, 1, 1,}},
681 /* Level 12 */
682 {{7, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,},
683 {1, 2, 1, 2, 1, 2, 1, 1, 0, 0, 0, 1,},
684 {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,},
685 {1, 2, 1, 2, 1, 2, 1, 0, 0, 0, 0, 1,},
686 {0, 0, 0, 0, 0, 0, 1, 1, 5, 5, 6, 1,},
687 {1, 2, 1, 2, 1, 2, 1, 1, 0, 2, 2, 1,},
688 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1,},
689 {1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,}},
691 /* Level 13 */
692 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
693 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
694 {0, 0, 2, 0, 5, 0, 2, 0, 4, 0, 0, 6,},
695 {7, 0, 3, 0, 4, 0, 5, 0, 4, 0, 0, 6,},
696 {0, 0, 5, 0, 4, 0, 2, 0, 4, 0, 0, 6,},
697 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
698 {0, 0, 3, 0, 3, 0, 2, 0, 4, 0, 0, 6,},
699 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
701 /* Level 14 */
702 {{1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,},
703 {1, 1, 0, 2, 0, 0, 4, 0, 0, 2, 0, 1,},
704 {1, 6, 0, 0, 5, 1, 0, 1, 1, 0, 0, 1,},
705 {1, 1, 1, 0, 0, 3, 5, 3, 0, 0, 1, 1,},
706 {1, 1, 0, 0, 1, 1, 0, 1, 5, 0, 0, 6,},
707 {1, 1, 0, 2, 0, 0, 4, 0, 0, 0, 7, 1,},
708 {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,},
709 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
711 /* Level 15 */
712 {{0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
713 {0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
714 {0, 3, 4, 6, 0, 6, 0, 6, 0, 6, 0, 2,},
715 {0, 4, 0, 6, 0, 6, 4, 6, 0, 6, 0, 1,},
716 {0, 3, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
717 {7, 0, 0, 6, 4, 6, 0, 6, 0, 6, 0, 1,},
718 {0, 0, 4, 6, 0, 6, 0, 6, 4, 6, 0, 1,},
719 {0, 0, 4, 6, 0, 6, 0, 6, 0, 6, 0, 1,}}
723 /*****************************************************************************
724 * draw_board() draws the game's current level.
725 ******************************************************************************/
726 static void draw_board(struct game_context* pb) {
727 unsigned int r, c, type;
728 pb->num_left = 0;
729 char str[5];
731 rb->lcd_clear_display();
732 #ifdef WIDE_LAYOUT
733 rb->lcd_bitmap(pegbox_header,LCD_WIDTH-HEADER_WIDTH,0,
734 HEADER_WIDTH,LCD_HEIGHT);
735 #else
736 rb->lcd_bitmap(pegbox_header,(LCD_WIDTH-HEADER_WIDTH)/2,0,
737 HEADER_WIDTH, HEADER_HEIGHT);
738 #endif /* WIDE_LAYOUT */
740 #if ((BOARD_HEIGHT + HEADER_HEIGHT + 4) <= LCD_HEIGHT)
741 rb->lcd_drawrect(BOARD_X-2,BOARD_Y-2,BOARD_WIDTH+4,BOARD_HEIGHT+4);
742 #endif /* enough space for a frame? */
744 #ifdef HAVE_LCD_COLOR
745 rb->lcd_set_foreground(LCD_WHITE);
746 rb->lcd_fillrect(BOARD_X-1,BOARD_Y-1,BOARD_WIDTH+2,BOARD_HEIGHT+2);
747 rb->lcd_set_foreground(LCD_BLACK);
748 rb->lcd_set_background(TEXT_BG);
749 #endif
751 for (r=0 ; r < ROWS ; r++) {
752 for (c = 0 ; c < COLS ; c++) {
754 type = pb->playboard[r][c];
756 switch(type) {
757 case SPACE:
758 break;
760 default:
761 rb->lcd_bitmap_part(pegbox_pieces, 0, (type-1)*PIECE_HEIGHT,
762 PIECE_WIDTH, c * PIECE_WIDTH + BOARD_X,
763 r * PIECE_HEIGHT + BOARD_Y, PIECE_WIDTH,
764 PIECE_HEIGHT);
765 break;
768 if(pb->playboard[r][c] == PLAYER) {
769 pb->player_row=r;
770 pb->player_col=c;
772 else if (type != WALL && type != SPACE && type != HOLE)
773 pb->num_left++;
777 #ifdef WIDE_LAYOUT
778 rb->snprintf(str, 3, "%d", pb->level);
779 rb->lcd_putsxy(TEXT_X, LEVEL_TEXT_Y, str);
780 rb->snprintf(str, 3, "%d", pb->num_left);
781 rb->lcd_putsxy(TEXT_X, PEGS_TEXT_Y, str);
782 #else
783 rb->snprintf(str, 3, "%d", pb->level);
784 rb->lcd_putsxy(LEVEL_TEXT_X, TEXT_Y, str);
785 rb->snprintf(str, 3, "%d", pb->num_left);
786 rb->lcd_putsxy(PEGS_TEXT_X, TEXT_Y, str);
787 #endif /*WIDE_LAYOUT*/
789 #ifdef HAVE_LCD_COLOR
790 rb->lcd_set_background(BG_COLOR);
791 rb->lcd_set_foreground(LCD_WHITE);
792 #endif
793 /* print out the screen */
794 rb->lcd_update();
797 /*****************************************************************************
798 * load_level() loads the player's current level from the array and sets the
799 * player's position.
800 ******************************************************************************/
801 static void load_level(struct game_context* pb) {
802 int r, c;
804 for(r = 0; r < ROWS; r++)
805 for(c = 0; c < COLS; c++)
806 pb->playboard[r][c] = levels[pb->level-1][r][c];
809 /*****************************************************************************
810 * new_piece() creates a new piece at a specified location. The player
811 * navigates through the pieces and selects one.
812 ******************************************************************************/
813 static void new_piece(struct game_context* pb, unsigned int x_loc,
814 unsigned int y_loc) {
815 int button;
816 bool exit = false;
818 pb->playboard[x_loc][y_loc] = TRIANGLE;
820 while (!exit) {
821 draw_board(pb);
822 button = rb->button_get(true);
823 #ifdef HAVE_TOUCHSCREEN
824 if(button & BUTTON_TOUCHSCREEN)
826 pegbox_raster_btn.two_d_from.y = x_loc;
827 pegbox_raster_btn.two_d_from.x = y_loc;
829 struct ts_raster_button_result ret =
830 touchscreen_raster_map_button(&pegbox_raster_btn,
831 rb->button_get_data() >> 16,
832 rb->button_get_data() & 0xffff,
833 button);
834 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
836 if(ret.to.x > ret.from.x)
837 button = PEGBOX_UP;
838 else if(ret.to.x < ret.from.x)
839 button = PEGBOX_DOWN;
840 else if(ret.to.y > ret.from.y)
841 button = PEGBOX_LEFT;
842 else if(ret.to.y < ret.from.y)
843 button = PEGBOX_RIGHT;
845 else if(ret.action == TS_ACTION_CLICK
846 && (unsigned)ret.to.x == y_loc
847 && (unsigned)ret.to.y == x_loc)
848 button = PEGBOX_SAVE;
850 #endif
851 switch(button){
852 case PEGBOX_LEFT:
853 case (PEGBOX_LEFT|BUTTON_REPEAT):
854 case PEGBOX_DOWN:
855 case (PEGBOX_DOWN|BUTTON_REPEAT):
856 if (pb->playboard[x_loc][y_loc] < 5)
857 pb->playboard[x_loc][y_loc]++;
858 else
859 pb->playboard[x_loc][y_loc] = TRIANGLE;
860 break;
861 case PEGBOX_RIGHT:
862 case (PEGBOX_RIGHT|BUTTON_REPEAT):
863 case PEGBOX_UP:
864 case (PEGBOX_UP|BUTTON_REPEAT):
865 if (pb->playboard[x_loc][y_loc] > 2)
866 pb->playboard[x_loc][y_loc]--;
867 else
868 pb->playboard[x_loc][y_loc] = CIRCLE;
869 break;
870 case PEGBOX_SAVE:
871 exit = true;
872 break;
877 /*****************************************************************************
878 * move_player() moves the player and pieces and updates the board accordingly.
879 ******************************************************************************/
880 static void move_player(struct game_context* pb, signed int x_dir,
881 signed int y_dir) {
882 unsigned int type1, type2;
883 signed int r,c;
885 r = pb->player_row+y_dir;
886 c = pb->player_col+x_dir;
888 type1 = pb->playboard[r][c];
889 type2 = pb->playboard[r+y_dir][c+x_dir];
891 if (r == ROWS || c == COLS || r < 0 || c < 0 || type1 == WALL)
892 return;
893 else if(type1 != SPACE) {
894 if (type2 == WALL || r+y_dir == ROWS || c+x_dir == COLS ||
895 r+y_dir < 0 || c+x_dir < 0)
896 return;
900 pb->playboard[pb->player_row][pb->player_col] = SPACE;
901 pb->player_row += y_dir;
902 pb->player_col += x_dir;
904 if (type1 == HOLE) {
905 draw_board(pb);
906 rb->splash(HZ*2, "You fell down a hole!");
907 load_level(pb);
909 else if (type1 == SPACE)
910 pb->playboard[r][c] = PLAYER;
911 else {
912 pb->playboard[r][c] = PLAYER;
913 if(type1 == type2) {
914 if (type1 == TRIANGLE)
915 pb->playboard[r+y_dir][c+x_dir] = WALL;
916 else if (type1 == CROSS) {
917 pb->playboard[r][c] = SPACE;
918 new_piece(pb, r+y_dir, c+x_dir);
919 pb->playboard[r][c] = PLAYER;
921 else
922 pb->playboard[r+y_dir][c+x_dir] = SPACE;
924 else if (type2 == SPACE)
925 pb->playboard[r+y_dir][c+x_dir] = type1;
926 else if (type2 == HOLE) {
927 if (type1 == SQUARE)
928 pb->playboard[r+y_dir][c+x_dir] = SPACE;
930 else {
931 rb->splash(HZ*2, "Illegal Move!");
932 load_level(pb);
936 draw_board(pb);
939 /*****************************************************************************
940 * pegbox_loadgame() loads the saved game and returns load success.
941 ******************************************************************************/
942 static bool pegbox_loadgame(struct game_context* pb) {
943 signed int fd;
944 bool loaded = false;
946 /* open game file */
947 fd = rb->open(SAVE_FILE, O_RDONLY);
948 if(fd < 0) return loaded;
950 /* read in saved game */
951 while(true) {
952 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
953 if(rb->read(fd, &pb->playboard, sizeof(pb->playboard)) <= 0)
955 loaded = true;
956 break;
958 break;
961 rb->close(fd);
962 return loaded;
965 /*****************************************************************************
966 * pegbox_savegame() saves the current game state.
967 ******************************************************************************/
968 static void pegbox_savegame(struct game_context* pb) {
969 unsigned int fd;
971 /* write out the game state to the save file */
972 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
973 rb->write(fd, &pb->level, sizeof(pb->level));
974 rb->write(fd, &pb->playboard, sizeof(pb->playboard));
975 rb->close(fd);
978 /*****************************************************************************
979 * pegbox_loaddata() loads the level and highlevel and returns load success.
980 ******************************************************************************/
981 static void pegbox_loaddata(struct game_context* pb) {
982 signed int fd;
984 /* open game file */
985 fd = rb->open(DATA_FILE, O_RDONLY);
986 if(fd < 0) {
987 pb->level = 1;
988 pb->highlevel = 1;
989 return;
992 /* read in saved game */
993 while(true) {
994 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
995 if(rb->read(fd, &pb->highlevel, sizeof(pb->highlevel)) <= 0) break;
996 break;
999 rb->close(fd);
1000 return;
1003 /*****************************************************************************
1004 * pegbox_savedata() saves the level and highlevel.
1005 ******************************************************************************/
1006 static void pegbox_savedata(struct game_context* pb) {
1007 unsigned int fd;
1009 /* write out the game state to the save file */
1010 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT);
1011 rb->write(fd, &pb->level, sizeof(pb->level));
1012 rb->write(fd, &pb->highlevel, sizeof(pb->highlevel));
1013 rb->close(fd);
1016 /*****************************************************************************
1017 * pegbox_callback() is the default event handler callback which is called
1018 * on usb connect and shutdown.
1019 ******************************************************************************/
1020 static void pegbox_callback(void* param) {
1021 struct game_context* pb = (struct game_context*) param;
1022 rb->splash(HZ, "Saving data...");
1023 pegbox_savedata(pb);
1026 /***********************************************************************
1027 * pegbox_help() display help text
1028 ************************************************************************/
1029 static bool pegbox_help(void)
1031 int button;
1032 #define WORDS (sizeof help_text / sizeof (char*))
1033 static char* help_text[] = {
1034 "Pegbox", "", "Aim", "",
1035 "To", "beat", "each", "level,", "you", "must", "destroy", "all", "of",
1036 "the", "pegs.", "If", "two", "like", "pegs", "are", "pushed", "into",
1037 "each", "other,", "they", "disappear", "except", "for", "triangles",
1038 "which", "form", "a", "solid", "block", "and", "crosses", "which",
1039 "allow", "you", "to", "choose", "a", "replacement", "block.", "", "",
1040 "Controls", "",
1041 RESTART_TEXT, "to", "restart", "level", "",
1042 LVL_UP_TEXT, "to", "go", "up", "a", "level", "",
1043 LVL_DOWN_TEXT, "to", "go", "down", "a", "level", "",
1044 SAVE_TEXT, "to", "select/save", "",
1045 QUIT_TEXT, "to", "quit"
1047 static struct style_text formation[]={
1048 { 0, TEXT_CENTER|TEXT_UNDERLINE },
1049 { 2, C_RED },
1050 { 46, C_RED },
1051 { -1, 0 }
1054 rb->lcd_setfont(FONT_UI);
1056 if (display_text(WORDS, help_text, formation, NULL))
1057 return true;
1058 do {
1059 button = rb->button_get(true);
1060 if ( rb->default_event_handler( button ) == SYS_USB_CONNECTED )
1061 return true;
1062 } while( ( button == BUTTON_NONE )
1063 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
1064 rb->lcd_setfont(FONT_SYSFIXED);
1065 return false;
1068 /*****************************************************************************
1069 * pegbox_menu() is the initial menu at the start of the game.
1070 ******************************************************************************/
1071 static unsigned int pegbox_menu(struct game_context* pb) {
1072 int button;
1073 char str[30];
1074 unsigned int startlevel = 1, loc = 0;
1075 bool breakout = false, can_resume = false;
1077 if (pb->num_left > 0 || pb->save_exist)
1078 can_resume = true;
1080 while(!breakout){
1081 #if LCD_HEIGHT >= 80
1082 rb->lcd_clear_display();
1083 rb->lcd_bitmap(pegbox_menu_top,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_menu_top);
1085 /* menu bitmaps */
1086 if (loc == 0) {
1087 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT, ITEM_WIDTH,
1088 MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT);
1090 else {
1091 rb->lcd_bitmap_part(pegbox_menu_items, 0, 0, ITEM_WIDTH,
1092 MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT);
1094 if (can_resume) {
1095 if (loc == 1) {
1096 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*3, ITEM_WIDTH,
1097 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1099 else {
1100 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*2, ITEM_WIDTH,
1101 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1104 else {
1105 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*4, ITEM_WIDTH,
1106 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1109 if (loc==2) {
1110 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*6, ITEM_WIDTH,
1111 MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT);
1113 else {
1114 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*5, ITEM_WIDTH,
1115 MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT);
1118 if (loc==3) {
1119 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*8, ITEM_WIDTH,
1120 MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT);
1122 else {
1123 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*7, ITEM_WIDTH,
1124 MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT);
1126 #else
1127 unsigned int w,h;
1128 rb->lcd_clear_display();
1129 rb->lcd_getstringsize("PegBox", &w, &h);
1130 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, "PegBox");
1131 rb->lcd_putsxy((LCD_WIDTH)/4, 16, "New Game");
1132 rb->lcd_putsxy((LCD_WIDTH)/4, 24, "Resume");
1133 rb->lcd_putsxy((LCD_WIDTH)/4, 32, "Help");
1134 rb->lcd_putsxy((LCD_WIDTH)/4, 40, "Quit");
1136 if(!can_resume)
1137 rb->lcd_hline((LCD_WIDTH)/4, (LCD_WIDTH)/4+30, 28);
1139 rb->lcd_putsxy((LCD_WIDTH)/4-8, loc*8+16, "*");
1142 #endif
1143 rb->snprintf(str, 28, "Start on level %d of %d", startlevel,
1144 pb->highlevel);
1145 #if LCD_HEIGHT > 110
1146 rb->lcd_putsxy(0, MENU_Y+4*ITEM_HEIGHT+8, str);
1147 #elif LCD_HEIGHT > 64
1148 rb->lcd_putsxy(0, LCD_HEIGHT - 8, str);
1149 #else
1150 rb->lcd_puts_scroll(0, 7, str);
1151 #endif
1152 rb->lcd_update();
1154 /* handle menu button presses */
1155 button = rb->button_get(true);
1157 #ifdef HAVE_TOUCHSCREEN
1158 if(button & BUTTON_TOUCHSCREEN)
1160 unsigned int result = touchscreen_map(&main_menu,
1161 rb->button_get_data() >> 16,
1162 rb->button_get_data() & 0xffff);
1163 if(result != (unsigned)-1 && button & BUTTON_REL)
1165 if(result == 4)
1166 button = PEGBOX_LVL_UP;
1167 else
1169 if(loc == result)
1170 button = PEGBOX_RIGHT;
1171 loc = result;
1175 #endif
1177 switch(button) {
1178 case PEGBOX_SAVE: /* start playing */
1179 case PEGBOX_RIGHT:
1180 if (loc == 0) {
1181 breakout = true;
1182 pb->level = startlevel;
1183 load_level(pb);
1185 else if (loc == 1 && can_resume) {
1186 if(pb->save_exist)
1188 rb->remove(SAVE_FILE);
1189 pb->save_exist = false;
1191 breakout = true;
1193 else if (loc == 2)
1195 if(pegbox_help())
1196 return PB_USB;
1198 else if (loc == 3)
1199 return PB_QUIT;
1200 break;
1202 case PEGBOX_QUIT: /* quit program */
1203 return PB_QUIT;
1205 case (PEGBOX_UP|BUTTON_REPEAT):
1206 case PEGBOX_UP:
1207 if (loc <= 0)
1208 loc = 3;
1209 else
1210 loc--;
1211 if (!can_resume && loc == 1) {
1212 loc = 0;
1214 break;
1217 case (PEGBOX_DOWN|BUTTON_REPEAT):
1218 case PEGBOX_DOWN:
1219 if (loc >= 3)
1220 loc = 0;
1221 else
1222 loc++;
1223 if (!can_resume && loc == 1) {
1224 loc = 2;
1226 break;
1228 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1229 case PEGBOX_LVL_UP: /* increase starting level */
1230 if(startlevel >= pb->highlevel) {
1231 startlevel = 1;
1232 } else {
1233 startlevel++;
1235 break;
1237 /* only for targets with enough buttons */
1238 #ifdef PEGBOX_LVL_DOWN
1239 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1240 case PEGBOX_LVL_DOWN: /* decrease starting level */
1241 if(startlevel <= 1) {
1242 startlevel = pb->highlevel;
1243 } else {
1244 startlevel--;
1246 break;
1247 #endif
1248 default:
1249 if(rb->default_event_handler_ex(button, pegbox_callback,
1250 (void*) pb) == SYS_USB_CONNECTED)
1251 return PB_USB;
1252 break;
1256 draw_board(pb);
1258 return 0;
1261 /*****************************************************************************
1262 * pegbox() is the main game subroutine, it returns the final game status.
1263 ******************************************************************************/
1264 static int pegbox(struct game_context* pb) {
1265 int temp_var;
1267 /********************
1268 * menu *
1269 ********************/
1270 temp_var = pegbox_menu(pb);
1271 if (temp_var == PB_QUIT || temp_var == PB_USB)
1272 return temp_var;
1274 while (true) {
1275 temp_var = rb->button_get(true);
1276 #ifdef HAVE_TOUCHSCREEN
1277 if(temp_var & BUTTON_TOUCHSCREEN)
1279 pegbox_raster_btn.two_d_from.y = pb->player_row;
1280 pegbox_raster_btn.two_d_from.x = pb->player_col;
1282 struct ts_raster_button_result ret =
1283 touchscreen_raster_map_button(&pegbox_raster_btn,
1284 rb->button_get_data() >> 16,
1285 rb->button_get_data() & 0xffff,
1286 temp_var);
1287 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
1288 move_player(pb, ret.to.x - ret.from.x, ret.to.y - ret.from.y);
1290 #endif
1291 switch(temp_var){
1292 case PEGBOX_LEFT: /* move cursor left */
1293 case (PEGBOX_LEFT|BUTTON_REPEAT):
1294 move_player(pb, -1, 0);
1295 break;
1297 case PEGBOX_RIGHT: /* move cursor right */
1298 case (PEGBOX_RIGHT|BUTTON_REPEAT):
1299 move_player(pb, 1, 0);
1300 break;
1302 case PEGBOX_DOWN: /* move cursor down */
1303 case (PEGBOX_DOWN|BUTTON_REPEAT):
1304 move_player(pb, 0, 1);
1305 break;
1307 case PEGBOX_UP: /* move cursor up */
1308 case (PEGBOX_UP|BUTTON_REPEAT):
1309 move_player(pb, 0, -1);
1310 break;
1312 case PEGBOX_SAVE: /* save and end game */
1313 rb->splash(HZ, "Saving game...");
1314 pegbox_savegame(pb);
1315 /* fall through to PEGBOX_QUIT */
1317 case PEGBOX_QUIT:
1318 return PB_END;
1320 case PEGBOX_RESTART:
1321 load_level(pb);
1322 draw_board(pb);
1323 break;
1325 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1326 case PEGBOX_LVL_UP:
1327 if(pb->level >= pb->highlevel) {
1328 pb->level = 1;
1329 } else {
1330 pb->level++;
1332 load_level(pb);
1333 draw_board(pb);
1334 break;
1336 /* only for targets with enough buttons */
1337 #ifdef PEGBOX_LVL_DOWN
1338 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1339 case PEGBOX_LVL_DOWN:
1340 if(pb->level <= 1) {
1341 pb->level = pb->highlevel;
1342 } else {
1343 pb->level--;
1345 load_level(pb);
1346 draw_board(pb);
1347 break;
1348 #endif
1352 if(pb->num_left == 0) {
1353 rb->splash(HZ*2, "Nice Pegging!");
1354 if(pb->level == NUM_LEVELS) {
1355 draw_board(pb);
1356 rb->splash(HZ*2, "You Won!");
1357 break;
1359 else {
1360 pb->level++;
1361 load_level(pb);
1362 draw_board(pb);
1365 if(pb->level > pb->highlevel)
1366 pb->highlevel = pb->level;
1371 return PLUGIN_OK;
1375 /*****************************************************************************
1376 * plugin entry point.
1377 ******************************************************************************/
1378 enum plugin_status plugin_start(const void* parameter) {
1379 bool exit = false;
1380 struct game_context pb;
1382 (void)parameter;
1384 rb->lcd_setfont(FONT_SYSFIXED);
1385 #if LCD_DEPTH > 1
1386 rb->lcd_set_backdrop(NULL);
1387 #endif
1388 #ifdef HAVE_LCD_COLOR
1389 rb->lcd_set_foreground(LCD_WHITE);
1390 rb->lcd_set_background(BG_COLOR);
1391 #endif
1393 rb->splash(0, "Loading...");
1394 pegbox_loaddata(&pb);
1395 pb.save_exist = pegbox_loadgame(&pb);
1396 pb.num_left = 0;
1398 rb->lcd_clear_display();
1401 while(!exit) {
1402 switch(pegbox(&pb)){
1403 case PB_END:
1404 break;
1406 case PB_USB:
1407 rb->lcd_setfont(FONT_UI);
1408 return PLUGIN_USB_CONNECTED;
1410 case PB_QUIT:
1411 rb->splash(HZ, "Saving data...");
1412 pegbox_savedata(&pb);
1413 exit = true;
1414 break;
1416 default:
1417 break;
1421 rb->lcd_setfont(FONT_UI);
1422 return PLUGIN_OK;