Minor corrections to the .colours file editing; added .colours to the list of support...
[kugel-rb.git] / apps / plugins / pegbox.c
blob514b92ebb68b113728690598a22785908bbd99d4
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"
23 #include "pluginbitmaps/pegbox_header.h"
24 #include "pluginbitmaps/pegbox_pieces.h"
26 #if LCD_HEIGHT >= 80 /* enough space for a graphical menu */
27 #include "pluginbitmaps/pegbox_menu_top.h"
28 #include "pluginbitmaps/pegbox_menu_items.h"
29 #define MENU_X (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2
30 #define MENU_Y BMPHEIGHT_pegbox_menu_top
31 #define ITEM_WIDTH BMPWIDTH_pegbox_menu_items
32 #define ITEM_HEIGHT (BMPHEIGHT_pegbox_menu_items/9)
33 #endif
35 PLUGIN_HEADER
37 /* final game return status */
38 #define PB_END 3
39 #define PB_USB 2
40 #define PB_QUIT 1
42 #define DATA_FILE PLUGIN_DIR "/games/pegbox.data"
43 #define SAVE_FILE PLUGIN_DIR "/games/pegbox.save"
45 #define ROWS 8 /* Number of rows on each board */
46 #define COLS 12 /* Number of columns on each board */
47 #define NUM_LEVELS 15 /* Number of levels */
49 #define SPACE 0
50 #define WALL 1
51 #define TRIANGLE 2
52 #define CROSS 3
53 #define SQUARE 4
54 #define CIRCLE 5
55 #define HOLE 6
56 #define PLAYER 7
58 #if CONFIG_KEYPAD == RECORDER_PAD
59 #define PEGBOX_SAVE BUTTON_ON
60 #define PEGBOX_QUIT BUTTON_OFF
61 #define PEGBOX_RESTART BUTTON_F2
62 #define PEGBOX_LVL_UP BUTTON_F1
63 #define PEGBOX_LVL_DOWN BUTTON_F3
64 #define PEGBOX_UP BUTTON_UP
65 #define PEGBOX_DOWN BUTTON_DOWN
66 #define PEGBOX_RIGHT BUTTON_RIGHT
67 #define PEGBOX_LEFT BUTTON_LEFT
69 #define SAVE_TEXT "ON"
70 #define QUIT_TEXT "OFF"
71 #define RESTART_TEXT "F2"
72 #define LVL_UP_TEXT "F1"
73 #define LVL_DOWN_TEXT "F3"
75 #elif CONFIG_KEYPAD == ONDIO_PAD
76 #define PEGBOX_SAVE BUTTON_OFF
77 #define PEGBOX_QUIT (BUTTON_MENU | BUTTON_LEFT)
78 #define PEGBOX_RESTART (BUTTON_MENU | BUTTON_RIGHT)
79 #define PEGBOX_LVL_UP (BUTTON_MENU | BUTTON_UP)
80 #define PEGBOX_LVL_DOWN (BUTTON_MENU | BUTTON_DOWN)
81 #define PEGBOX_UP BUTTON_UP
82 #define PEGBOX_DOWN BUTTON_DOWN
83 #define PEGBOX_RIGHT BUTTON_RIGHT
84 #define PEGBOX_LEFT BUTTON_LEFT
86 #define SAVE_TEXT "OFF"
87 #define QUIT_TEXT "M+LEFT"
88 #define RESTART_TEXT "M+RIGHT"
89 #define LVL_UP_TEXT "M+UP"
90 #define LVL_DOWN_TEXT "M+DOWN"
92 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
93 (CONFIG_KEYPAD == IRIVER_H300_PAD)
94 #define PEGBOX_SAVE BUTTON_SELECT
95 #define PEGBOX_QUIT BUTTON_OFF
96 #define PEGBOX_RESTART BUTTON_ON
97 #define PEGBOX_LVL_UP BUTTON_MODE
98 #define PEGBOX_LVL_DOWN BUTTON_REC
99 #define PEGBOX_UP BUTTON_UP
100 #define PEGBOX_DOWN BUTTON_DOWN
101 #define PEGBOX_RIGHT BUTTON_RIGHT
102 #define PEGBOX_LEFT BUTTON_LEFT
104 #define SAVE_TEXT "NAVI"
105 #define QUIT_TEXT "OFF"
106 #define RESTART_TEXT "ON"
107 #define LVL_UP_TEXT "AB"
108 #define LVL_DOWN_TEXT "REC"
110 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
111 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
112 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
113 #define PEGBOX_SAVE (BUTTON_SELECT|BUTTON_RIGHT)
114 #define PEGBOX_QUIT (BUTTON_SELECT|BUTTON_PLAY)
115 #define PEGBOX_RESTART (BUTTON_SELECT|BUTTON_LEFT)
116 #define PEGBOX_LVL_UP (BUTTON_SELECT|BUTTON_MENU)
117 #define PEGBOX_UP BUTTON_MENU
118 #define PEGBOX_DOWN BUTTON_PLAY
119 #define PEGBOX_RIGHT BUTTON_RIGHT
120 #define PEGBOX_LEFT BUTTON_LEFT
122 #define SAVE_TEXT "SELECT+RIGHT"
123 #define QUIT_TEXT "SELECT+PLAY"
124 #define RESTART_TEXT "SELECT+LEFT"
125 #define LVL_UP_TEXT "SELECT+MENU"
126 #define LVL_DOWN_TEXT "-"
128 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
129 #define PEGBOX_SAVE BUTTON_SELECT
130 #define PEGBOX_QUIT BUTTON_POWER
131 #define PEGBOX_RESTART BUTTON_REC
132 #define PEGBOX_LVL_UP BUTTON_PLAY
133 #define PEGBOX_UP BUTTON_UP
134 #define PEGBOX_DOWN BUTTON_DOWN
135 #define PEGBOX_RIGHT BUTTON_RIGHT
136 #define PEGBOX_LEFT BUTTON_LEFT
138 #define SAVE_TEXT "SELECT"
139 #define QUIT_TEXT "OFF"
140 #define RESTART_TEXT "REC"
141 #define LVL_UP_TEXT "PLAY"
142 #define LVL_DOWN_TEXT "-"
144 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
145 #define PEGBOX_SAVE BUTTON_MODE
146 #define PEGBOX_QUIT BUTTON_PLAY
147 #define PEGBOX_RESTART (BUTTON_EQ|BUTTON_MODE)
148 #define PEGBOX_LVL_UP (BUTTON_EQ|BUTTON_UP)
149 #define PEGBOX_LVL_DOWN (BUTTON_EQ|BUTTON_DOWN)
150 #define PEGBOX_UP BUTTON_UP
151 #define PEGBOX_DOWN BUTTON_DOWN
152 #define PEGBOX_RIGHT BUTTON_RIGHT
153 #define PEGBOX_LEFT BUTTON_LEFT
155 #define SAVE_TEXT "MODE"
156 #define QUIT_TEXT "PLAY"
157 #define RESTART_TEXT "EQ+MODE"
158 #define LVL_UP_TEXT "EQ+UP"
159 #define LVL_DOWN_TEXT "EQ+DOWN"
161 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
162 #define PEGBOX_SAVE BUTTON_PLAY
163 #define PEGBOX_QUIT BUTTON_POWER
164 #define PEGBOX_RESTART (BUTTON_FF|BUTTON_REPEAT)
165 #define PEGBOX_LVL_UP (BUTTON_FF|BUTTON_SCROLL_UP)
166 #define PEGBOX_LVL_DOWN (BUTTON_FF|BUTTON_SCROLL_DOWN)
167 #define PEGBOX_UP BUTTON_SCROLL_UP
168 #define PEGBOX_DOWN BUTTON_SCROLL_DOWN
169 #define PEGBOX_RIGHT BUTTON_RIGHT
170 #define PEGBOX_LEFT BUTTON_LEFT
172 #define SAVE_TEXT "PLAY"
173 #define QUIT_TEXT "OFF"
174 #define RESTART_TEXT "LONG FF"
175 #define LVL_UP_TEXT "FF+SCROLL_UP"
176 #define LVL_DOWN_TEXT "FF+SCROLL_DOWN"
178 #elif CONFIG_KEYPAD == SANSA_E200_PAD
179 #define PEGBOX_SAVE BUTTON_SELECT
180 #define PEGBOX_QUIT BUTTON_POWER
181 #define PEGBOX_RESTART BUTTON_REC
182 #define PEGBOX_LVL_UP BUTTON_SCROLL_BACK
183 #define PEGBOX_LVL_DOWN BUTTON_SCROLL_FWD
184 #define PEGBOX_UP BUTTON_UP
185 #define PEGBOX_DOWN BUTTON_DOWN
186 #define PEGBOX_RIGHT BUTTON_RIGHT
187 #define PEGBOX_LEFT BUTTON_LEFT
189 #define SAVE_TEXT "SELECT"
190 #define QUIT_TEXT "POWER"
191 #define RESTART_TEXT "REC"
192 #define LVL_UP_TEXT "SCROLL BACK"
193 #define LVL_DOWN_TEXT "SCROLL FWD"
195 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
196 #define PEGBOX_SAVE BUTTON_SELECT|BUTTON_REL
197 #define PEGBOX_QUIT BUTTON_POWER
198 /* FIXME:
199 #define PEGBOX_RESTART BUTTON_HOME */
200 #define PEGBOX_RESTART BUTTON_SELECT|BUTTON_LEFT
201 #define PEGBOX_LVL_UP BUTTON_SCROLL_BACK
202 #define PEGBOX_LVL_DOWN BUTTON_SCROLL_FWD
203 #define PEGBOX_UP BUTTON_UP
204 #define PEGBOX_DOWN BUTTON_DOWN
205 #define PEGBOX_RIGHT BUTTON_RIGHT
206 #define PEGBOX_LEFT BUTTON_LEFT
208 #define SAVE_TEXT "SELECT"
209 #define QUIT_TEXT "POWER"
210 #define RESTART_TEXT "SELECT & LEFT"
211 #define LVL_UP_TEXT "SCROLL BACK"
212 #define LVL_DOWN_TEXT "SCROLL FWD"
214 #elif CONFIG_KEYPAD == GIGABEAT_PAD
215 #define PEGBOX_SAVE BUTTON_SELECT
216 #define PEGBOX_QUIT BUTTON_POWER
217 #define PEGBOX_RESTART BUTTON_A
218 #define PEGBOX_LVL_UP BUTTON_VOL_UP
219 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
220 #define PEGBOX_UP BUTTON_UP
221 #define PEGBOX_DOWN BUTTON_DOWN
222 #define PEGBOX_RIGHT BUTTON_RIGHT
223 #define PEGBOX_LEFT BUTTON_LEFT
225 #define SAVE_TEXT "SELECT"
226 #define QUIT_TEXT "POWER"
227 #define RESTART_TEXT "A"
228 #define LVL_UP_TEXT "VOL+"
229 #define LVL_DOWN_TEXT "VOL-"
231 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
232 #define PEGBOX_SAVE BUTTON_SELECT
233 #define PEGBOX_QUIT BUTTON_BACK
234 #define PEGBOX_RESTART BUTTON_MENU
235 #define PEGBOX_LVL_UP BUTTON_VOL_UP
236 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
237 #define PEGBOX_UP BUTTON_UP
238 #define PEGBOX_DOWN BUTTON_DOWN
239 #define PEGBOX_RIGHT BUTTON_RIGHT
240 #define PEGBOX_LEFT BUTTON_LEFT
242 #define SAVE_TEXT "SELECT"
243 #define QUIT_TEXT "BACK"
244 #define RESTART_TEXT "MENU"
245 #define LVL_UP_TEXT "VOL+"
246 #define LVL_DOWN_TEXT "VOL-"
248 #elif CONFIG_KEYPAD == MROBE100_PAD
249 #define PEGBOX_SAVE BUTTON_SELECT
250 #define PEGBOX_QUIT BUTTON_POWER
251 #define PEGBOX_RESTART BUTTON_PLAY
252 #define PEGBOX_LVL_UP BUTTON_MENU
253 #define PEGBOX_LVL_DOWN BUTTON_DISPLAY
254 #define PEGBOX_UP BUTTON_UP
255 #define PEGBOX_DOWN BUTTON_DOWN
256 #define PEGBOX_RIGHT BUTTON_RIGHT
257 #define PEGBOX_LEFT BUTTON_LEFT
259 #define SAVE_TEXT "SELECT"
260 #define QUIT_TEXT "POWER"
261 #define RESTART_TEXT "PLAY"
262 #define LVL_UP_TEXT "MENU"
263 #define LVL_DOWN_TEXT "DISPLAY"
265 #elif CONFIG_KEYPAD == SANSA_C200_PAD
266 #define PEGBOX_SAVE BUTTON_SELECT
267 #define PEGBOX_QUIT BUTTON_POWER
268 #define PEGBOX_RESTART BUTTON_REC
269 #define PEGBOX_LVL_UP BUTTON_VOL_UP
270 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
271 #define PEGBOX_UP BUTTON_UP
272 #define PEGBOX_DOWN BUTTON_DOWN
273 #define PEGBOX_RIGHT BUTTON_RIGHT
274 #define PEGBOX_LEFT BUTTON_LEFT
276 #define SAVE_TEXT "SELECT"
277 #define QUIT_TEXT "POWER"
278 #define RESTART_TEXT "REC"
279 #define LVL_UP_TEXT "VOL+"
280 #define LVL_DOWN_TEXT "VOL-"
282 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
283 #define PEGBOX_SAVE BUTTON_SELECT
284 #define PEGBOX_QUIT BUTTON_POWER
285 #define PEGBOX_RESTART BUTTON_HOME
286 #define PEGBOX_LVL_UP BUTTON_VOL_UP
287 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
288 #define PEGBOX_UP BUTTON_UP
289 #define PEGBOX_DOWN BUTTON_DOWN
290 #define PEGBOX_RIGHT BUTTON_RIGHT
291 #define PEGBOX_LEFT BUTTON_LEFT
293 #define SAVE_TEXT "SELECT"
294 #define QUIT_TEXT "POWER"
295 #define RESTART_TEXT "HOME"
296 #define LVL_UP_TEXT "VOL+"
297 #define LVL_DOWN_TEXT "VOL-"
299 #elif CONFIG_KEYPAD == SANSA_M200_PAD
300 #define PEGBOX_SAVE (BUTTON_SELECT | BUTTON_REL)
301 #define PEGBOX_QUIT BUTTON_POWER
302 #define PEGBOX_RESTART (BUTTON_SELECT | BUTTON_UP)
303 #define PEGBOX_LVL_UP BUTTON_VOL_UP
304 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
305 #define PEGBOX_UP BUTTON_UP
306 #define PEGBOX_DOWN BUTTON_DOWN
307 #define PEGBOX_RIGHT BUTTON_RIGHT
308 #define PEGBOX_LEFT BUTTON_LEFT
310 #define SAVE_TEXT "SELECT"
311 #define QUIT_TEXT "POWER"
312 #define RESTART_TEXT "SELECT+UP"
313 #define LVL_UP_TEXT "VOL+"
314 #define LVL_DOWN_TEXT "VOL-"
317 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
318 #define PEGBOX_SAVE BUTTON_RC_PLAY
319 #define PEGBOX_QUIT BUTTON_RC_REC
320 #define PEGBOX_RESTART BUTTON_RC_MODE
321 #define PEGBOX_LVL_UP BUTTON_VOL_UP
322 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
323 #define PEGBOX_UP BUTTON_RC_VOL_UP
324 #define PEGBOX_DOWN BUTTON_RC_VOL_DOWN
325 #define PEGBOX_RIGHT BUTTON_RC_FF
326 #define PEGBOX_LEFT BUTTON_RC_REW
328 #define SAVE_TEXT "REM. PLAY"
329 #define QUIT_TEXT "REM. REC"
330 #define RESTART_TEXT "REM. MODE"
331 #define LVL_UP_TEXT "VOL+"
332 #define LVL_DOWN_TEXT "VOL-"
334 #elif CONFIG_KEYPAD == COWOND2_PAD
335 #define PEGBOX_QUIT BUTTON_POWER
337 #define QUIT_TEXT "POWER"
339 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
340 #define PEGBOX_SAVE BUTTON_CUSTOM
341 #define PEGBOX_QUIT BUTTON_BACK
342 #define PEGBOX_RESTART BUTTON_SELECT
343 #define PEGBOX_LVL_UP BUTTON_PLAY
344 #define PEGBOX_LVL_DOWN BUTTON_MENU
345 #define PEGBOX_UP BUTTON_UP
346 #define PEGBOX_DOWN BUTTON_DOWN
347 #define PEGBOX_RIGHT BUTTON_RIGHT
348 #define PEGBOX_LEFT BUTTON_LEFT
350 #define SAVE_TEXT "CUSTOM"
351 #define QUIT_TEXT "BACK"
352 #define RESTART_TEXT "MIDDLE"
353 #define LVL_UP_TEXT "SELECT"
354 #define LVL_DOWN_TEXT "MENU"
356 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
357 #define PEGBOX_SAVE BUTTON_VIEW
358 #define PEGBOX_QUIT BUTTON_POWER
359 #define PEGBOX_RESTART BUTTON_MENU
360 #define PEGBOX_LVL_UP BUTTON_VOL_UP
361 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
362 #define PEGBOX_UP BUTTON_UP
363 #define PEGBOX_DOWN BUTTON_DOWN
364 #define PEGBOX_RIGHT BUTTON_RIGHT
365 #define PEGBOX_LEFT BUTTON_LEFT
367 #define SAVE_TEXT "VIEW"
368 #define QUIT_TEXT "POWER"
369 #define RESTART_TEXT "MENU"
370 #define LVL_UP_TEXT "VOL+"
371 #define LVL_DOWN_TEXT "VOL-"
373 #else
374 #error Unsupported keymap!
375 #endif
377 #ifdef HAVE_TOUCHSCREEN
378 #ifndef PEGBOX_QUIT
379 #define PEGBOX_QUIT BUTTON_TOPLEFT
380 #endif
381 #ifndef PEGBOX_SAVE
382 #define PEGBOX_SAVE BUTTON_CENTER
383 #endif
384 #ifndef PEGBOX_RESTART
385 #define PEGBOX_RESTART BUTTON_TOPRIGHT
386 #endif
387 #ifndef PEGBOX_LVL_UP
388 #define PEGBOX_LVL_UP BUTTON_BOTTOMLEFT
389 #endif
390 #ifndef PEGBOX_LVL_DOWN
391 #define PEGBOX_LVL_DOWN BUTTON_BOTTOMRIGHT
392 #endif
393 #ifndef PEGBOX_UP
394 #define PEGBOX_UP BUTTON_TOPMIDDLE
395 #endif
396 #ifndef PEGBOX_DOWN
397 #define PEGBOX_DOWN BUTTON_BOTTOMMIDDLE
398 #endif
399 #ifndef PEGBOX_RIGHT
400 #define PEGBOX_RIGHT BUTTON_MIDRIGHT
401 #endif
402 #ifndef PEGBOX_LEFT
403 #define PEGBOX_LEFT BUTTON_MIDLEFT
404 #endif
405 #ifndef SAVE_TEXT
406 #define SAVE_TEXT "CENTER"
407 #endif
408 #ifndef QUIT_TEXT
409 #define QUIT_TEXT "TOPLEFT"
410 #endif
411 #ifndef RESTART_TEXT
412 #define RESTART_TEXT "TOPRIGHT"
413 #endif
414 #ifndef LVL_UP_TEXT
415 #define LVL_UP_TEXT "BOTTOMLEFT"
416 #endif
417 #ifndef LVL_DOWN_TEXT
418 #define LVL_DOWN_TEXT "BOTTOMRIGHT"
419 #endif
420 #endif
423 /* get several sizes from the bitmaps */
424 #ifdef BMPWIDTH_pegbox_pieces
425 #define PIECE_WIDTH BMPWIDTH_pegbox_pieces
426 #define PIECE_HEIGHT (BMPHEIGHT_pegbox_pieces/7)
427 #else
428 /* dummy numbers to avoid #error in dependency generation */
429 #define PIECE_WIDTH 50
430 #define PIECE_HEIGHT 10
431 #endif
433 #define BOARD_WIDTH (12*PIECE_WIDTH)
434 #define BOARD_HEIGHT (8*PIECE_HEIGHT)
437 /* define a wide layout where the statistics are alongside the board, not above
438 * base calculation on the piece bitmaps for the 8x12 board */
439 #if (LCD_WIDTH - BOARD_WIDTH) > (LCD_HEIGHT - BOARD_HEIGHT)
440 #define WIDE_LAYOUT
441 #endif
444 #define HEADER_WIDTH BMPWIDTH_pegbox_header
445 #define HEADER_HEIGHT BMPHEIGHT_pegbox_header
448 #if defined WIDE_LAYOUT
450 #if ((BOARD_WIDTH + HEADER_WIDTH + 4) <= LCD_WIDTH)
451 #define BOARD_X 2
452 #else
453 #define BOARD_X 1
454 #endif
455 #define BOARD_Y (LCD_HEIGHT-BOARD_HEIGHT)/2
457 #if (LCD_WIDTH >= 132) && (LCD_HEIGHT >= 80)
458 #define TEXT_X 116
459 #define LEVEL_TEXT_Y 14
460 #define PEGS_TEXT_Y 58
461 #elif (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 64)
462 #define TEXT_X 114
463 #define LEVEL_TEXT_Y 14
464 #define PEGS_TEXT_Y 58
465 #else
466 #error "Unsupported screen size"
467 #endif
469 #else /* "normal" layout */
471 #define BOARD_X (LCD_WIDTH-BOARD_WIDTH)/2
472 #if ((BOARD_HEIGHT + HEADER_HEIGHT + 4) <= LCD_HEIGHT)
473 #define BOARD_Y HEADER_HEIGHT+2
474 #else
475 #define BOARD_Y HEADER_HEIGHT
476 #endif
478 #if LCD_WIDTH >= 320
479 #define LEVEL_TEXT_X 59
480 #define PEGS_TEXT_X 276
481 #define TEXT_Y 28
482 #elif LCD_WIDTH >= 240
483 #define LEVEL_TEXT_X 59
484 #define PEGS_TEXT_X 196
485 #define TEXT_Y 28
486 #elif LCD_WIDTH >= 220
487 #define LEVEL_TEXT_X 49
488 #define PEGS_TEXT_X 186
489 #define TEXT_Y 28
490 #elif LCD_WIDTH >= 176
491 #define LEVEL_TEXT_X 38
492 #define PEGS_TEXT_X 155
493 #define TEXT_Y 17
494 #elif LCD_WIDTH >= 160
495 #define LEVEL_TEXT_X 37
496 #define PEGS_TEXT_X 140
497 #define TEXT_Y 13
498 #elif LCD_WIDTH >= 138
499 #define LEVEL_TEXT_X 28
500 #define PEGS_TEXT_X 119
501 #define TEXT_Y 15
502 #elif LCD_WIDTH >= 128
503 #if HEADER_HEIGHT > 16
504 #define LEVEL_TEXT_X 26
505 #define PEGS_TEXT_X 107
506 #define TEXT_Y 31
507 #else
508 #define LEVEL_TEXT_X 15
509 #define PEGS_TEXT_X 100
510 #define TEXT_Y 5
511 #endif /* HEADER_HEIGHT */
512 #elif LCD_WIDTH >= 112
513 #define LEVEL_TEXT_X 25
514 #define PEGS_TEXT_X 90
515 #define TEXT_Y 0
516 #endif /* LCD_WIDTH */
518 #endif /* WIDE_LAYOUT */
521 #ifdef HAVE_LCD_COLOR
522 #define BG_COLOR LCD_BLACK
523 #define TEXT_BG LCD_RGBPACK(189,189,189)
524 #endif
527 #ifdef HAVE_TOUCHSCREEN
528 #include "lib/touchscreen.h"
530 static struct ts_mapping main_menu_items[5] =
532 {MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT},
533 {MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT},
534 {MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT},
535 {MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT},
537 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT > 110)
538 0, MENU_Y+4*ITEM_HEIGHT+8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
539 #elif LCD_WIDTH > 112
540 0, LCD_HEIGHT - 8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
541 #else
542 #error "Touchscreen isn't supported on non-bitmap screens!"
543 #endif
547 static struct ts_mappings main_menu = {main_menu_items, 5};
549 static struct ts_raster pegbox_raster =
550 { BOARD_X, BOARD_Y, COLS*PIECE_WIDTH, ROWS*PIECE_HEIGHT,
551 PIECE_WIDTH, PIECE_HEIGHT };
552 static struct ts_raster_button_mapping pegbox_raster_btn =
553 { &pegbox_raster, false, false, true, false, true, {0, 0}, 0, 0, 0 };
554 #endif
556 struct game_context {
557 unsigned int level;
558 unsigned int highlevel;
559 signed int player_row;
560 signed int player_col;
561 unsigned int num_left;
562 bool save_exist;
563 unsigned int playboard[ROWS][COLS];
566 char levels[NUM_LEVELS][ROWS][COLS] = {
567 /* Level 1 */
568 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
569 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
570 {1, 0, 0, 0, 7, 0, 0, 5, 0, 0, 0, 1,},
571 {1, 0, 0, 0, 0, 3, 3, 2, 0, 0, 0, 1,},
572 {1, 0, 0, 0, 4, 6, 0, 5, 0, 0, 0, 1,},
573 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
574 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
575 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
577 /* Level 2 */
578 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
579 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,},
580 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
581 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
582 {7, 0, 0, 0, 2, 2, 5, 5, 0, 0, 0, 1,},
583 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
584 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
585 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,}},
587 /* Level 3 */
588 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
589 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
590 {1, 0, 0, 0, 0, 0, 2, 0, 7, 0, 0, 0,},
591 {1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 2, 1,},
592 {1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1,},
593 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,},
594 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
595 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
597 /* Level 4 */
598 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
599 {6, 0, 4, 0, 2, 0, 2, 0, 0, 0, 0, 1,},
600 {6, 0, 3, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
601 {6, 0, 5, 0, 4, 7, 2, 0, 0, 0, 0, 1,},
602 {6, 0, 2, 0, 4, 0, 2, 0, 3, 0, 0, 1,},
603 {6, 0, 4, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
604 {6, 0, 5, 0, 4, 0, 2, 0, 0, 0, 0, 1,},
605 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
607 /* Level 5 */
608 {{0, 6, 6, 0, 4, 6, 0, 0, 6, 0, 0, 0,},
609 {0, 6, 6, 0, 4, 4, 0, 0, 6, 0, 0, 2,},
610 {2, 6, 6, 0, 6, 6, 6, 0, 1, 2, 2, 2,},
611 {0, 6, 6, 0, 6, 4, 6, 0, 1, 2, 0, 2,},
612 {0, 6, 6, 0, 6, 7, 6, 5, 6, 0, 0, 0,},
613 {2, 6, 6, 0, 6, 6, 6, 0, 6, 0, 0, 0,},
614 {0, 6, 6, 0, 4, 0, 0, 0, 6, 0, 0, 0,},
615 {0, 6, 6, 0, 0, 5, 0, 0, 6, 5, 5, 0,}},
617 /* Level 6 */
618 {{7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
619 {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,},
620 {2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0,},
621 {0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 0,},
622 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
623 {0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1,},
624 {0, 3, 0, 0, 0, 0, 0, 0, 5, 4, 6, 0,},
625 {0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1,}},
627 /* Level 7 */
628 {{1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,},
629 {1, 1, 1, 6, 0, 0, 4, 6, 0, 1, 1, 1,},
630 {1, 1, 1, 1, 0, 1, 5, 1, 0, 1, 1, 1,},
631 {1, 1, 1, 2, 3, 3, 7, 4, 2, 6, 1, 1,},
632 {1, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1,},
633 {1, 1, 1, 1, 0, 0, 5, 0, 0, 1, 0, 1,},
634 {1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,},
635 {1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,}},
637 /* Level 8 */
638 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
639 {0, 0, 3, 3, 3, 3, 3, 4, 3, 3, 0, 0,},
640 {0, 0, 3, 3, 3, 2, 3, 3, 5, 3, 0, 0,},
641 {7, 0, 3, 3, 3, 2, 3, 3, 4, 3, 0, 0,},
642 {0, 0, 3, 3, 4, 5, 3, 3, 3, 3, 0, 0,},
643 {0, 0, 3, 3, 5, 2, 3, 3, 3, 3, 0, 0,},
644 {0, 0, 3, 3, 2, 4, 3, 3, 3, 3, 0, 0,},
645 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
647 /* Level 9 */
648 {{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
649 {0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
650 {0, 0, 0, 0, 2, 4, 4, 3, 0, 1, 1, 0,},
651 {0, 1, 0, 0, 2, 1, 0, 0, 0, 1, 1, 1,},
652 {0, 0, 0, 2, 2, 7, 1, 0, 0, 0, 0, 2,},
653 {0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 1, 1,},
654 {0, 3, 1, 0, 2, 5, 5, 0, 0, 0, 3, 0,},
655 {0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0,}},
657 /* Level 10 */
658 {{1, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0,},
659 {1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 7,},
660 {0, 0, 4, 0, 6, 6, 6, 0, 0, 0, 3, 0,},
661 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
662 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
663 {0, 0, 0, 0, 6, 6, 6, 0, 3, 0, 0, 0,},
664 {1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0,},
665 {1, 1, 1, 1, 1, 2, 1, 1, 0, 0, 0, 0,}},
667 /* Level 11 */
668 {{1, 7, 1, 0, 1, 1, 6, 0, 0, 1, 1, 0,},
669 {1, 0, 0, 0, 5, 4, 6, 6, 0, 2, 2, 0,},
670 {1, 2, 1, 2, 0, 1, 6, 0, 0, 2, 2, 0,},
671 {1, 0, 0, 2, 0, 1, 0, 0, 0, 3, 3, 0,},
672 {1, 2, 1, 0, 0, 1, 0, 1, 0, 3, 3, 0,},
673 {0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0,},
674 {0, 3, 4, 3, 0, 1, 0, 1, 0, 0, 0, 0,},
675 {0, 0, 0, 0, 2, 2, 2, 1, 1, 1, 1, 1,}},
677 /* Level 12 */
678 {{7, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,},
679 {1, 2, 1, 2, 1, 2, 1, 1, 0, 0, 0, 1,},
680 {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,},
681 {1, 2, 1, 2, 1, 2, 1, 0, 0, 0, 0, 1,},
682 {0, 0, 0, 0, 0, 0, 1, 1, 5, 5, 6, 1,},
683 {1, 2, 1, 2, 1, 2, 1, 1, 0, 2, 2, 1,},
684 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1,},
685 {1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,}},
687 /* Level 13 */
688 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
689 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
690 {0, 0, 2, 0, 5, 0, 2, 0, 4, 0, 0, 6,},
691 {7, 0, 3, 0, 4, 0, 5, 0, 4, 0, 0, 6,},
692 {0, 0, 5, 0, 4, 0, 2, 0, 4, 0, 0, 6,},
693 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
694 {0, 0, 3, 0, 3, 0, 2, 0, 4, 0, 0, 6,},
695 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
697 /* Level 14 */
698 {{1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,},
699 {1, 1, 0, 2, 0, 0, 4, 0, 0, 2, 0, 1,},
700 {1, 6, 0, 0, 5, 1, 0, 1, 1, 0, 0, 1,},
701 {1, 1, 1, 0, 0, 3, 5, 3, 0, 0, 1, 1,},
702 {1, 1, 0, 0, 1, 1, 0, 1, 5, 0, 0, 6,},
703 {1, 1, 0, 2, 0, 0, 4, 0, 0, 0, 7, 1,},
704 {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,},
705 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
707 /* Level 15 */
708 {{0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
709 {0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
710 {0, 3, 4, 6, 0, 6, 0, 6, 0, 6, 0, 2,},
711 {0, 4, 0, 6, 0, 6, 4, 6, 0, 6, 0, 1,},
712 {0, 3, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
713 {7, 0, 0, 6, 4, 6, 0, 6, 0, 6, 0, 1,},
714 {0, 0, 4, 6, 0, 6, 0, 6, 4, 6, 0, 1,},
715 {0, 0, 4, 6, 0, 6, 0, 6, 0, 6, 0, 1,}}
719 /*****************************************************************************
720 * display_text() formats and outputs text.
721 ******************************************************************************/
722 static void display_text(char *str, bool waitkey)
724 int chars_by_line;
725 int lines_by_screen;
726 int chars_for_line;
727 int current_line = 0;
728 int char_width, char_height;
729 int first_char_index = 0;
730 char *ptr_char;
731 char *ptr_line;
732 int i;
733 char line[255];
734 int key;
735 bool go_on;
737 rb->lcd_clear_display();
739 rb->lcd_getstringsize("a", &char_width, &char_height);
741 chars_by_line = LCD_WIDTH / char_width;
742 lines_by_screen = LCD_HEIGHT / char_height;
746 ptr_char = str + first_char_index;
747 chars_for_line = 0;
748 i = 0;
749 ptr_line = line;
750 while (i < chars_by_line)
752 switch (*ptr_char)
754 case '\t':
755 case ' ':
756 *(ptr_line++) = ' ';
757 case '\n':
758 case '\0':
759 chars_for_line = i;
760 break;
762 default:
763 *(ptr_line++) = *ptr_char;
765 if (*ptr_char == '\n' || *ptr_char == '\0')
766 break;
767 ptr_char++;
768 i++;
771 if (chars_for_line == 0)
772 chars_for_line = i;
774 line[chars_for_line] = '\0';
776 /* test if we have cut a word. If it is the case we don't have to */
777 /* skip the space */
778 if (i == chars_by_line && chars_for_line == chars_by_line)
779 first_char_index += chars_for_line;
780 else
781 first_char_index += chars_for_line + 1;
783 /* print the line on the screen */
784 rb->lcd_putsxy(0, current_line * char_height, line);
786 /* if the number of line showed on the screen is equals to the */
787 /* maximum number of line we can show, we wait for a key pressed to */
788 /* clear and show the remaining text. */
789 current_line++;
790 if (current_line == lines_by_screen || *ptr_char == '\0')
792 current_line = 0;
793 rb->lcd_update();
794 go_on = false;
795 while (waitkey && !go_on)
797 key = rb->button_get(true);
798 switch (key)
800 #ifdef HAVE_TOUCHSCREEN
801 case BUTTON_TOUCHSCREEN:
802 #endif
803 case PEGBOX_QUIT:
804 case PEGBOX_LEFT:
805 case PEGBOX_DOWN:
806 go_on = true;
807 break;
809 default:
810 /*if (rb->default_event_handler(key) == SYS_USB_CONNECTED)
812 usb_detected = true;
813 go_on = true;
814 break;
816 break;
819 rb->lcd_clear_display();
821 } while (*ptr_char != '\0');
824 /*****************************************************************************
825 * draw_board() draws the game's current level.
826 ******************************************************************************/
827 static void draw_board(struct game_context* pb) {
828 unsigned int r, c, type;
829 pb->num_left = 0;
830 char str[5];
832 rb->lcd_clear_display();
833 #ifdef WIDE_LAYOUT
834 rb->lcd_bitmap(pegbox_header,LCD_WIDTH-HEADER_WIDTH,0,
835 HEADER_WIDTH,LCD_HEIGHT);
836 #else
837 rb->lcd_bitmap(pegbox_header,(LCD_WIDTH-HEADER_WIDTH)/2,0,
838 HEADER_WIDTH, HEADER_HEIGHT);
839 #endif /* WIDE_LAYOUT */
841 #if ((BOARD_HEIGHT + HEADER_HEIGHT + 4) <= LCD_HEIGHT)
842 rb->lcd_drawrect(BOARD_X-2,BOARD_Y-2,BOARD_WIDTH+4,BOARD_HEIGHT+4);
843 #endif /* enough space for a frame? */
845 #ifdef HAVE_LCD_COLOR
846 rb->lcd_set_foreground(LCD_WHITE);
847 rb->lcd_fillrect(BOARD_X-1,BOARD_Y-1,BOARD_WIDTH+2,BOARD_HEIGHT+2);
848 rb->lcd_set_foreground(LCD_BLACK);
849 rb->lcd_set_background(TEXT_BG);
850 #endif
852 for (r=0 ; r < ROWS ; r++) {
853 for (c = 0 ; c < COLS ; c++) {
855 type = pb->playboard[r][c];
857 switch(type) {
858 case SPACE:
859 break;
861 default:
862 rb->lcd_bitmap_part(pegbox_pieces, 0, (type-1)*PIECE_HEIGHT,
863 PIECE_WIDTH, c * PIECE_WIDTH + BOARD_X,
864 r * PIECE_HEIGHT + BOARD_Y, PIECE_WIDTH,
865 PIECE_HEIGHT);
866 break;
869 if(pb->playboard[r][c] == PLAYER) {
870 pb->player_row=r;
871 pb->player_col=c;
873 else if (type != WALL && type != SPACE && type != HOLE)
874 pb->num_left++;
878 #ifdef WIDE_LAYOUT
879 rb->snprintf(str, 3, "%d", pb->level);
880 rb->lcd_putsxy(TEXT_X, LEVEL_TEXT_Y, str);
881 rb->snprintf(str, 3, "%d", pb->num_left);
882 rb->lcd_putsxy(TEXT_X, PEGS_TEXT_Y, str);
883 #else
884 rb->snprintf(str, 3, "%d", pb->level);
885 rb->lcd_putsxy(LEVEL_TEXT_X, TEXT_Y, str);
886 rb->snprintf(str, 3, "%d", pb->num_left);
887 rb->lcd_putsxy(PEGS_TEXT_X, TEXT_Y, str);
888 #endif /*WIDE_LAYOUT*/
890 #ifdef HAVE_LCD_COLOR
891 rb->lcd_set_background(BG_COLOR);
892 rb->lcd_set_foreground(LCD_WHITE);
893 #endif
894 /* print out the screen */
895 rb->lcd_update();
898 /*****************************************************************************
899 * load_level() loads the player's current level from the array and sets the
900 * player's position.
901 ******************************************************************************/
902 static void load_level(struct game_context* pb) {
903 int r, c;
905 for(r = 0; r < ROWS; r++)
906 for(c = 0; c < COLS; c++)
907 pb->playboard[r][c] = levels[pb->level-1][r][c];
910 /*****************************************************************************
911 * new_piece() creates a new piece at a specified location. The player
912 * navigates through the pieces and selects one.
913 ******************************************************************************/
914 static void new_piece(struct game_context* pb, unsigned int x_loc,
915 unsigned int y_loc) {
916 int button;
917 bool exit = false;
919 pb->playboard[x_loc][y_loc] = TRIANGLE;
921 while (!exit) {
922 draw_board(pb);
923 button = rb->button_get(true);
924 #ifdef HAVE_TOUCHSCREEN
925 if(button & BUTTON_TOUCHSCREEN)
927 pegbox_raster_btn.two_d_from.y = x_loc;
928 pegbox_raster_btn.two_d_from.x = y_loc;
930 struct ts_raster_button_result ret =
931 touchscreen_raster_map_button(&pegbox_raster_btn,
932 rb->button_get_data() >> 16,
933 rb->button_get_data() & 0xffff,
934 button);
935 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
937 if(ret.to.x > ret.from.x)
938 button = PEGBOX_UP;
939 else if(ret.to.x < ret.from.x)
940 button = PEGBOX_DOWN;
941 else if(ret.to.y > ret.from.y)
942 button = PEGBOX_LEFT;
943 else if(ret.to.y < ret.from.y)
944 button = PEGBOX_RIGHT;
946 else if(ret.action == TS_ACTION_CLICK
947 && (unsigned)ret.to.x == y_loc
948 && (unsigned)ret.to.y == x_loc)
949 button = PEGBOX_SAVE;
951 #endif
952 switch(button){
953 case PEGBOX_LEFT:
954 case (PEGBOX_LEFT|BUTTON_REPEAT):
955 case PEGBOX_DOWN:
956 case (PEGBOX_DOWN|BUTTON_REPEAT):
957 if (pb->playboard[x_loc][y_loc] < 5)
958 pb->playboard[x_loc][y_loc]++;
959 else
960 pb->playboard[x_loc][y_loc] = TRIANGLE;
961 break;
962 case PEGBOX_RIGHT:
963 case (PEGBOX_RIGHT|BUTTON_REPEAT):
964 case PEGBOX_UP:
965 case (PEGBOX_UP|BUTTON_REPEAT):
966 if (pb->playboard[x_loc][y_loc] > 2)
967 pb->playboard[x_loc][y_loc]--;
968 else
969 pb->playboard[x_loc][y_loc] = CIRCLE;
970 break;
971 case PEGBOX_SAVE:
972 exit = true;
973 break;
978 /*****************************************************************************
979 * move_player() moves the player and pieces and updates the board accordingly.
980 ******************************************************************************/
981 static void move_player(struct game_context* pb, signed int x_dir,
982 signed int y_dir) {
983 unsigned int type1, type2;
984 signed int r,c;
986 r = pb->player_row+y_dir;
987 c = pb->player_col+x_dir;
989 type1 = pb->playboard[r][c];
990 type2 = pb->playboard[r+y_dir][c+x_dir];
992 if (r == ROWS || c == COLS || r < 0 || c < 0 || type1 == WALL)
993 return;
994 else if(type1 != SPACE) {
995 if (type2 == WALL || r+y_dir == ROWS || c+x_dir == COLS ||
996 r+y_dir < 0 || c+x_dir < 0)
997 return;
1001 pb->playboard[pb->player_row][pb->player_col] = SPACE;
1002 pb->player_row += y_dir;
1003 pb->player_col += x_dir;
1005 if (type1 == HOLE) {
1006 draw_board(pb);
1007 rb->splash(HZ*2, "You fell down a hole!");
1008 load_level(pb);
1010 else if (type1 == SPACE)
1011 pb->playboard[r][c] = PLAYER;
1012 else {
1013 pb->playboard[r][c] = PLAYER;
1014 if(type1 == type2) {
1015 if (type1 == TRIANGLE)
1016 pb->playboard[r+y_dir][c+x_dir] = WALL;
1017 else if (type1 == CROSS) {
1018 pb->playboard[r][c] = SPACE;
1019 new_piece(pb, r+y_dir, c+x_dir);
1020 pb->playboard[r][c] = PLAYER;
1022 else
1023 pb->playboard[r+y_dir][c+x_dir] = SPACE;
1025 else if (type2 == SPACE)
1026 pb->playboard[r+y_dir][c+x_dir] = type1;
1027 else if (type2 == HOLE) {
1028 if (type1 == SQUARE)
1029 pb->playboard[r+y_dir][c+x_dir] = SPACE;
1031 else {
1032 rb->splash(HZ*2, "Illegal Move!");
1033 load_level(pb);
1037 draw_board(pb);
1040 /*****************************************************************************
1041 * pegbox_loadgame() loads the saved game and returns load success.
1042 ******************************************************************************/
1043 static bool pegbox_loadgame(struct game_context* pb) {
1044 signed int fd;
1045 bool loaded = false;
1047 /* open game file */
1048 fd = rb->open(SAVE_FILE, O_RDONLY);
1049 if(fd < 0) return loaded;
1051 /* read in saved game */
1052 while(true) {
1053 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
1054 if(rb->read(fd, &pb->playboard, sizeof(pb->playboard)) <= 0)
1056 loaded = true;
1057 break;
1059 break;
1062 rb->close(fd);
1063 return loaded;
1066 /*****************************************************************************
1067 * pegbox_savegame() saves the current game state.
1068 ******************************************************************************/
1069 static void pegbox_savegame(struct game_context* pb) {
1070 unsigned int fd;
1072 /* write out the game state to the save file */
1073 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
1074 rb->write(fd, &pb->level, sizeof(pb->level));
1075 rb->write(fd, &pb->playboard, sizeof(pb->playboard));
1076 rb->close(fd);
1079 /*****************************************************************************
1080 * pegbox_loaddata() loads the level and highlevel and returns load success.
1081 ******************************************************************************/
1082 static void pegbox_loaddata(struct game_context* pb) {
1083 signed int fd;
1085 /* open game file */
1086 fd = rb->open(DATA_FILE, O_RDONLY);
1087 if(fd < 0) {
1088 pb->level = 1;
1089 pb->highlevel = 1;
1090 return;
1093 /* read in saved game */
1094 while(true) {
1095 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
1096 if(rb->read(fd, &pb->highlevel, sizeof(pb->highlevel)) <= 0) break;
1097 break;
1100 rb->close(fd);
1101 return;
1104 /*****************************************************************************
1105 * pegbox_savedata() saves the level and highlevel.
1106 ******************************************************************************/
1107 static void pegbox_savedata(struct game_context* pb) {
1108 unsigned int fd;
1110 /* write out the game state to the save file */
1111 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT);
1112 rb->write(fd, &pb->level, sizeof(pb->level));
1113 rb->write(fd, &pb->highlevel, sizeof(pb->highlevel));
1114 rb->close(fd);
1117 /*****************************************************************************
1118 * pegbox_callback() is the default event handler callback which is called
1119 * on usb connect and shutdown.
1120 ******************************************************************************/
1121 static void pegbox_callback(void* param) {
1122 struct game_context* pb = (struct game_context*) param;
1123 rb->splash(HZ, "Saving data...");
1124 pegbox_savedata(pb);
1127 /*****************************************************************************
1128 * pegbox_menu() is the initial menu at the start of the game.
1129 ******************************************************************************/
1130 static unsigned int pegbox_menu(struct game_context* pb) {
1131 int button;
1132 char str[30];
1133 unsigned int startlevel = 1, loc = 0;
1134 bool breakout = false, can_resume = false;
1136 if (pb->num_left > 0 || pb->save_exist)
1137 can_resume = true;
1139 while(!breakout){
1140 #if LCD_HEIGHT >= 80
1141 rb->lcd_clear_display();
1142 rb->lcd_bitmap(pegbox_menu_top,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_menu_top);
1144 /* menu bitmaps */
1145 if (loc == 0) {
1146 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT, ITEM_WIDTH,
1147 MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT);
1149 else {
1150 rb->lcd_bitmap_part(pegbox_menu_items, 0, 0, ITEM_WIDTH,
1151 MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT);
1153 if (can_resume) {
1154 if (loc == 1) {
1155 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*3, ITEM_WIDTH,
1156 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1158 else {
1159 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*2, ITEM_WIDTH,
1160 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1163 else {
1164 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*4, ITEM_WIDTH,
1165 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1168 if (loc==2) {
1169 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*6, ITEM_WIDTH,
1170 MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT);
1172 else {
1173 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*5, ITEM_WIDTH,
1174 MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT);
1177 if (loc==3) {
1178 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*8, ITEM_WIDTH,
1179 MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT);
1181 else {
1182 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*7, ITEM_WIDTH,
1183 MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT);
1185 #else
1186 unsigned int w,h;
1187 rb->lcd_clear_display();
1188 rb->lcd_getstringsize("PegBox", &w, &h);
1189 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, "PegBox");
1190 rb->lcd_putsxy((LCD_WIDTH)/4, 16, "New Game");
1191 rb->lcd_putsxy((LCD_WIDTH)/4, 24, "Resume");
1192 rb->lcd_putsxy((LCD_WIDTH)/4, 32, "Help");
1193 rb->lcd_putsxy((LCD_WIDTH)/4, 40, "Quit");
1195 if(!can_resume)
1196 rb->lcd_hline((LCD_WIDTH)/4, (LCD_WIDTH)/4+30, 28);
1198 rb->lcd_putsxy((LCD_WIDTH)/4-8, loc*8+16, "*");
1201 #endif
1202 rb->snprintf(str, 28, "Start on level %d of %d", startlevel,
1203 pb->highlevel);
1204 #if LCD_HEIGHT > 110
1205 rb->lcd_putsxy(0, MENU_Y+4*ITEM_HEIGHT+8, str);
1206 #elif LCD_HEIGHT > 64
1207 rb->lcd_putsxy(0, LCD_HEIGHT - 8, str);
1208 #else
1209 rb->lcd_puts_scroll(0, 7, str);
1210 #endif
1211 rb->lcd_update();
1213 /* handle menu button presses */
1214 button = rb->button_get(true);
1216 #ifdef HAVE_TOUCHSCREEN
1217 if(button & BUTTON_TOUCHSCREEN)
1219 unsigned int result = touchscreen_map(&main_menu,
1220 rb->button_get_data() >> 16,
1221 rb->button_get_data() & 0xffff);
1222 if(result != (unsigned)-1 && button & BUTTON_REL)
1224 if(result == 4)
1225 button = PEGBOX_LVL_UP;
1226 else
1228 if(loc == result)
1229 button = PEGBOX_RIGHT;
1230 loc = result;
1234 #endif
1236 switch(button) {
1237 case PEGBOX_SAVE: /* start playing */
1238 case PEGBOX_RIGHT:
1239 if (loc == 0) {
1240 breakout = true;
1241 pb->level = startlevel;
1242 load_level(pb);
1244 else if (loc == 1 && can_resume) {
1245 if(pb->save_exist)
1247 rb->remove(SAVE_FILE);
1248 pb->save_exist = false;
1250 breakout = true;
1252 else if (loc == 2)
1253 display_text("How to Play\nTo beat each level, you must "
1254 "destroy all of the pegs. If two like pegs are "
1255 "pushed into each other they disappear except "
1256 "for triangles which form a solid block and "
1257 "crosses which allow you to choose a "
1258 "replacement block.\n\n"
1259 "Controls\n"
1260 #if LCD_HEIGHT > 64
1261 RESTART_TEXT " to restart level\n"
1262 LVL_UP_TEXT " to go up a level\n"
1263 LVL_DOWN_TEXT " to go down a level\n"
1264 SAVE_TEXT " to select/save\n"
1265 QUIT_TEXT " to quit\n",true);
1266 #else
1267 RESTART_TEXT ": restart\n"
1268 LVL_UP_TEXT ": level up\n"
1269 LVL_DOWN_TEXT " level down\n"
1270 SAVE_TEXT " select/save\n"
1271 QUIT_TEXT " quit\n",true);
1272 #endif
1273 else if (loc == 3)
1274 return PB_QUIT;
1275 break;
1277 case PEGBOX_QUIT: /* quit program */
1278 return PB_QUIT;
1280 case (PEGBOX_UP|BUTTON_REPEAT):
1281 case PEGBOX_UP:
1282 if (loc <= 0)
1283 loc = 3;
1284 else
1285 loc--;
1286 if (!can_resume && loc == 1) {
1287 loc = 0;
1289 break;
1292 case (PEGBOX_DOWN|BUTTON_REPEAT):
1293 case PEGBOX_DOWN:
1294 if (loc >= 3)
1295 loc = 0;
1296 else
1297 loc++;
1298 if (!can_resume && loc == 1) {
1299 loc = 2;
1301 break;
1303 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1304 case PEGBOX_LVL_UP: /* increase starting level */
1305 if(startlevel >= pb->highlevel) {
1306 startlevel = 1;
1307 } else {
1308 startlevel++;
1310 break;
1312 /* only for targets with enough buttons */
1313 #ifdef PEGBOX_LVL_DOWN
1314 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1315 case PEGBOX_LVL_DOWN: /* decrease starting level */
1316 if(startlevel <= 1) {
1317 startlevel = pb->highlevel;
1318 } else {
1319 startlevel--;
1321 break;
1322 #endif
1323 default:
1324 if(rb->default_event_handler_ex(button, pegbox_callback,
1325 (void*) pb) == SYS_USB_CONNECTED)
1326 return PB_USB;
1327 break;
1331 draw_board(pb);
1333 return 0;
1336 /*****************************************************************************
1337 * pegbox() is the main game subroutine, it returns the final game status.
1338 ******************************************************************************/
1339 static int pegbox(struct game_context* pb) {
1340 int temp_var;
1342 /********************
1343 * menu *
1344 ********************/
1345 temp_var = pegbox_menu(pb);
1346 if (temp_var == PB_QUIT || temp_var == PB_USB)
1347 return temp_var;
1349 while (true) {
1350 temp_var = rb->button_get(true);
1351 #ifdef HAVE_TOUCHSCREEN
1352 if(temp_var & BUTTON_TOUCHSCREEN)
1354 pegbox_raster_btn.two_d_from.y = pb->player_row;
1355 pegbox_raster_btn.two_d_from.x = pb->player_col;
1357 struct ts_raster_button_result ret =
1358 touchscreen_raster_map_button(&pegbox_raster_btn,
1359 rb->button_get_data() >> 16,
1360 rb->button_get_data() & 0xffff,
1361 temp_var);
1362 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
1363 move_player(pb, ret.to.x - ret.from.x, ret.to.y - ret.from.y);
1365 #endif
1366 switch(temp_var){
1367 case PEGBOX_LEFT: /* move cursor left */
1368 case (PEGBOX_LEFT|BUTTON_REPEAT):
1369 move_player(pb, -1, 0);
1370 break;
1372 case PEGBOX_RIGHT: /* move cursor right */
1373 case (PEGBOX_RIGHT|BUTTON_REPEAT):
1374 move_player(pb, 1, 0);
1375 break;
1377 case PEGBOX_DOWN: /* move cursor down */
1378 case (PEGBOX_DOWN|BUTTON_REPEAT):
1379 move_player(pb, 0, 1);
1380 break;
1382 case PEGBOX_UP: /* move cursor up */
1383 case (PEGBOX_UP|BUTTON_REPEAT):
1384 move_player(pb, 0, -1);
1385 break;
1387 case PEGBOX_SAVE: /* save and end game */
1388 rb->splash(HZ, "Saving game...");
1389 pegbox_savegame(pb);
1390 /* fall through to PEGBOX_QUIT */
1392 case PEGBOX_QUIT:
1393 return PB_END;
1395 case PEGBOX_RESTART:
1396 load_level(pb);
1397 draw_board(pb);
1398 break;
1400 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1401 case PEGBOX_LVL_UP:
1402 if(pb->level >= pb->highlevel) {
1403 pb->level = 1;
1404 } else {
1405 pb->level++;
1407 load_level(pb);
1408 draw_board(pb);
1409 break;
1411 /* only for targets with enough buttons */
1412 #ifdef PEGBOX_LVL_DOWN
1413 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1414 case PEGBOX_LVL_DOWN:
1415 if(pb->level <= 1) {
1416 pb->level = pb->highlevel;
1417 } else {
1418 pb->level--;
1420 load_level(pb);
1421 draw_board(pb);
1422 break;
1423 #endif
1427 if(pb->num_left == 0) {
1428 rb->splash(HZ*2, "Nice Pegging!");
1429 if(pb->level == NUM_LEVELS) {
1430 draw_board(pb);
1431 rb->splash(HZ*2, "You Won!");
1432 break;
1434 else {
1435 pb->level++;
1436 load_level(pb);
1437 draw_board(pb);
1440 if(pb->level > pb->highlevel)
1441 pb->highlevel = pb->level;
1446 return PLUGIN_OK;
1450 /*****************************************************************************
1451 * plugin entry point.
1452 ******************************************************************************/
1453 enum plugin_status plugin_start(const void* parameter) {
1454 bool exit = false;
1455 struct game_context pb;
1457 (void)parameter;
1459 rb->lcd_setfont(FONT_SYSFIXED);
1460 #if LCD_DEPTH > 1
1461 rb->lcd_set_backdrop(NULL);
1462 #endif
1463 #ifdef HAVE_LCD_COLOR
1464 rb->lcd_set_foreground(LCD_WHITE);
1465 rb->lcd_set_background(BG_COLOR);
1466 #endif
1468 rb->splash(0, "Loading...");
1469 pegbox_loaddata(&pb);
1470 pb.save_exist = pegbox_loadgame(&pb);
1471 pb.num_left = 0;
1473 rb->lcd_clear_display();
1476 while(!exit) {
1477 switch(pegbox(&pb)){
1478 case PB_END:
1479 break;
1481 case PB_USB:
1482 rb->lcd_setfont(FONT_UI);
1483 return PLUGIN_USB_CONNECTED;
1485 case PB_QUIT:
1486 rb->splash(HZ, "Saving data...");
1487 pegbox_savedata(&pb);
1488 exit = true;
1489 break;
1491 default:
1492 break;
1496 rb->lcd_setfont(FONT_UI);
1497 return PLUGIN_OK;