Added dummy numbers to avoid #error during dependency generation.
[kugel-rb.git] / apps / plugins / pegbox.c
blobb6221448fbfe333d058e7bd0ca0290277be2d673
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 static const struct plugin_api* rb;
37 PLUGIN_HEADER
39 /* final game return status */
40 #define PB_END 3
41 #define PB_USB 2
42 #define PB_QUIT 1
44 #define DATA_FILE PLUGIN_DIR "/games/pegbox.data"
45 #define SAVE_FILE PLUGIN_DIR "/games/pegbox.save"
47 #define ROWS 8 /* Number of rows on each board */
48 #define COLS 12 /* Number of columns on each board */
49 #define NUM_LEVELS 15 /* Number of levels */
51 #define SPACE 0
52 #define WALL 1
53 #define TRIANGLE 2
54 #define CROSS 3
55 #define SQUARE 4
56 #define CIRCLE 5
57 #define HOLE 6
58 #define PLAYER 7
60 #if CONFIG_KEYPAD == RECORDER_PAD
61 #define PEGBOX_SAVE BUTTON_ON
62 #define PEGBOX_QUIT BUTTON_OFF
63 #define PEGBOX_RESTART BUTTON_F2
64 #define PEGBOX_LVL_UP BUTTON_F1
65 #define PEGBOX_LVL_DOWN BUTTON_F3
66 #define PEGBOX_UP BUTTON_UP
67 #define PEGBOX_DOWN BUTTON_DOWN
68 #define PEGBOX_RIGHT BUTTON_RIGHT
69 #define PEGBOX_LEFT BUTTON_LEFT
71 #define SAVE_TEXT "ON"
72 #define QUIT_TEXT "OFF"
73 #define RESTART_TEXT "F2"
74 #define LVL_UP_TEXT "F1"
75 #define LVL_DOWN_TEXT "F3"
77 #elif CONFIG_KEYPAD == ONDIO_PAD
78 #define PEGBOX_SAVE BUTTON_OFF
79 #define PEGBOX_QUIT (BUTTON_MENU | BUTTON_LEFT)
80 #define PEGBOX_RESTART (BUTTON_MENU | BUTTON_RIGHT)
81 #define PEGBOX_LVL_UP (BUTTON_MENU | BUTTON_UP)
82 #define PEGBOX_LVL_DOWN (BUTTON_MENU | BUTTON_DOWN)
83 #define PEGBOX_UP BUTTON_UP
84 #define PEGBOX_DOWN BUTTON_DOWN
85 #define PEGBOX_RIGHT BUTTON_RIGHT
86 #define PEGBOX_LEFT BUTTON_LEFT
88 #define SAVE_TEXT "OFF"
89 #define QUIT_TEXT "M+LEFT"
90 #define RESTART_TEXT "M+RIGHT"
91 #define LVL_UP_TEXT "M+UP"
92 #define LVL_DOWN_TEXT "M+DOWN"
94 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
95 (CONFIG_KEYPAD == IRIVER_H300_PAD)
96 #define PEGBOX_SAVE BUTTON_SELECT
97 #define PEGBOX_QUIT BUTTON_OFF
98 #define PEGBOX_RESTART BUTTON_ON
99 #define PEGBOX_LVL_UP BUTTON_MODE
100 #define PEGBOX_LVL_DOWN BUTTON_REC
101 #define PEGBOX_UP BUTTON_UP
102 #define PEGBOX_DOWN BUTTON_DOWN
103 #define PEGBOX_RIGHT BUTTON_RIGHT
104 #define PEGBOX_LEFT BUTTON_LEFT
106 #define SAVE_TEXT "NAVI"
107 #define QUIT_TEXT "OFF"
108 #define RESTART_TEXT "ON"
109 #define LVL_UP_TEXT "AB"
110 #define LVL_DOWN_TEXT "REC"
112 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
113 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
114 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
115 #define PEGBOX_SAVE (BUTTON_SELECT|BUTTON_RIGHT)
116 #define PEGBOX_QUIT (BUTTON_SELECT|BUTTON_PLAY)
117 #define PEGBOX_RESTART (BUTTON_SELECT|BUTTON_LEFT)
118 #define PEGBOX_LVL_UP (BUTTON_SELECT|BUTTON_MENU)
119 #define PEGBOX_UP BUTTON_MENU
120 #define PEGBOX_DOWN BUTTON_PLAY
121 #define PEGBOX_RIGHT BUTTON_RIGHT
122 #define PEGBOX_LEFT BUTTON_LEFT
124 #define SAVE_TEXT "SELECT+RIGHT"
125 #define QUIT_TEXT "SELECT+PLAY"
126 #define RESTART_TEXT "SELECT+LEFT"
127 #define LVL_UP_TEXT "SELECT+MENU"
128 #define LVL_DOWN_TEXT "-"
130 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
131 #define PEGBOX_SAVE BUTTON_SELECT
132 #define PEGBOX_QUIT BUTTON_POWER
133 #define PEGBOX_RESTART BUTTON_REC
134 #define PEGBOX_LVL_UP BUTTON_PLAY
135 #define PEGBOX_UP BUTTON_UP
136 #define PEGBOX_DOWN BUTTON_DOWN
137 #define PEGBOX_RIGHT BUTTON_RIGHT
138 #define PEGBOX_LEFT BUTTON_LEFT
140 #define SAVE_TEXT "SELECT"
141 #define QUIT_TEXT "OFF"
142 #define RESTART_TEXT "REC"
143 #define LVL_UP_TEXT "PLAY"
144 #define LVL_DOWN_TEXT "-"
146 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
147 #define PEGBOX_SAVE BUTTON_MODE
148 #define PEGBOX_QUIT BUTTON_PLAY
149 #define PEGBOX_RESTART (BUTTON_EQ|BUTTON_MODE)
150 #define PEGBOX_LVL_UP (BUTTON_EQ|BUTTON_UP)
151 #define PEGBOX_LVL_DOWN (BUTTON_EQ|BUTTON_DOWN)
152 #define PEGBOX_UP BUTTON_UP
153 #define PEGBOX_DOWN BUTTON_DOWN
154 #define PEGBOX_RIGHT BUTTON_RIGHT
155 #define PEGBOX_LEFT BUTTON_LEFT
157 #define SAVE_TEXT "MODE"
158 #define QUIT_TEXT "PLAY"
159 #define RESTART_TEXT "EQ+MODE"
160 #define LVL_UP_TEXT "EQ+UP"
161 #define LVL_DOWN_TEXT "EQ+DOWN"
163 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
164 #define PEGBOX_SAVE BUTTON_PLAY
165 #define PEGBOX_QUIT BUTTON_POWER
166 #define PEGBOX_RESTART (BUTTON_FF|BUTTON_REPEAT)
167 #define PEGBOX_LVL_UP (BUTTON_FF|BUTTON_SCROLL_UP)
168 #define PEGBOX_LVL_DOWN (BUTTON_FF|BUTTON_SCROLL_DOWN)
169 #define PEGBOX_UP BUTTON_SCROLL_UP
170 #define PEGBOX_DOWN BUTTON_SCROLL_DOWN
171 #define PEGBOX_RIGHT BUTTON_RIGHT
172 #define PEGBOX_LEFT BUTTON_LEFT
174 #define SAVE_TEXT "PLAY"
175 #define QUIT_TEXT "OFF"
176 #define RESTART_TEXT "LONG FF"
177 #define LVL_UP_TEXT "FF+SCROLL_UP"
178 #define LVL_DOWN_TEXT "FF+SCROLL_DOWN"
180 #elif CONFIG_KEYPAD == SANSA_E200_PAD
181 #define PEGBOX_SAVE BUTTON_SELECT
182 #define PEGBOX_QUIT BUTTON_POWER
183 #define PEGBOX_RESTART BUTTON_REC
184 #define PEGBOX_LVL_UP BUTTON_SCROLL_BACK
185 #define PEGBOX_LVL_DOWN BUTTON_SCROLL_FWD
186 #define PEGBOX_UP BUTTON_UP
187 #define PEGBOX_DOWN BUTTON_DOWN
188 #define PEGBOX_RIGHT BUTTON_RIGHT
189 #define PEGBOX_LEFT BUTTON_LEFT
191 #define SAVE_TEXT "SELECT"
192 #define QUIT_TEXT "POWER"
193 #define RESTART_TEXT "REC"
194 #define LVL_UP_TEXT "SCROLL BACK"
195 #define LVL_DOWN_TEXT "SCROLL FWD"
197 #elif CONFIG_KEYPAD == GIGABEAT_PAD
198 #define PEGBOX_SAVE BUTTON_SELECT
199 #define PEGBOX_QUIT BUTTON_POWER
200 #define PEGBOX_RESTART BUTTON_A
201 #define PEGBOX_LVL_UP BUTTON_VOL_UP
202 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
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 "A"
211 #define LVL_UP_TEXT "VOL+"
212 #define LVL_DOWN_TEXT "VOL-"
214 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
215 #define PEGBOX_SAVE BUTTON_SELECT
216 #define PEGBOX_QUIT BUTTON_BACK
217 #define PEGBOX_RESTART BUTTON_MENU
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 "BACK"
227 #define RESTART_TEXT "MENU"
228 #define LVL_UP_TEXT "VOL+"
229 #define LVL_DOWN_TEXT "VOL-"
231 #elif CONFIG_KEYPAD == MROBE100_PAD
232 #define PEGBOX_SAVE BUTTON_SELECT
233 #define PEGBOX_QUIT BUTTON_POWER
234 #define PEGBOX_RESTART BUTTON_PLAY
235 #define PEGBOX_LVL_UP BUTTON_MENU
236 #define PEGBOX_LVL_DOWN BUTTON_DISPLAY
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 "POWER"
244 #define RESTART_TEXT "PLAY"
245 #define LVL_UP_TEXT "MENU"
246 #define LVL_DOWN_TEXT "DISPLAY"
248 #elif CONFIG_KEYPAD == SANSA_C200_PAD
249 #define PEGBOX_SAVE BUTTON_SELECT
250 #define PEGBOX_QUIT BUTTON_POWER
251 #define PEGBOX_RESTART BUTTON_REC
252 #define PEGBOX_LVL_UP BUTTON_VOL_UP
253 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
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 "REC"
262 #define LVL_UP_TEXT "VOL+"
263 #define LVL_DOWN_TEXT "VOL-"
265 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
266 #define PEGBOX_SAVE BUTTON_RC_PLAY
267 #define PEGBOX_QUIT BUTTON_RC_REC
268 #define PEGBOX_RESTART BUTTON_RC_MODE
269 #define PEGBOX_LVL_UP BUTTON_VOL_UP
270 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
271 #define PEGBOX_UP BUTTON_RC_VOL_UP
272 #define PEGBOX_DOWN BUTTON_RC_VOL_DOWN
273 #define PEGBOX_RIGHT BUTTON_RC_FF
274 #define PEGBOX_LEFT BUTTON_RC_REW
276 #define SAVE_TEXT "REM. PLAY"
277 #define QUIT_TEXT "REM. REC"
278 #define RESTART_TEXT "REM. MODE"
279 #define LVL_UP_TEXT "VOL+"
280 #define LVL_DOWN_TEXT "VOL-"
282 #elif CONFIG_KEYPAD == COWOND2_PAD
283 #define PEGBOX_QUIT BUTTON_POWER
285 #define QUIT_TEXT "POWER"
286 #else
287 #error Unsupported keymap!
288 #endif
290 #ifdef HAVE_TOUCHSCREEN
291 #ifndef PEGBOX_QUIT
292 #define PEGBOX_QUIT BUTTON_TOPLEFT
293 #endif
294 #ifndef PEGBOX_SAVE
295 #define PEGBOX_SAVE BUTTON_CENTER
296 #endif
297 #ifndef PEGBOX_RESTART
298 #define PEGBOX_RESTART BUTTON_TOPRIGHT
299 #endif
300 #ifndef PEGBOX_LVL_UP
301 #define PEGBOX_LVL_UP BUTTON_BOTTOMLEFT
302 #endif
303 #ifndef PEGBOX_LVL_DOWN
304 #define PEGBOX_LVL_DOWN BUTTON_BOTTOMRIGHT
305 #endif
306 #ifndef PEGBOX_UP
307 #define PEGBOX_UP BUTTON_TOPMIDDLE
308 #endif
309 #ifndef PEGBOX_DOWN
310 #define PEGBOX_DOWN BUTTON_BOTTOMMIDDLE
311 #endif
312 #ifndef PEGBOX_RIGHT
313 #define PEGBOX_RIGHT BUTTON_MIDRIGHT
314 #endif
315 #ifndef PEGBOX_LEFT
316 #define PEGBOX_LEFT BUTTON_MIDLEFT
317 #endif
318 #ifndef SAVE_TEXT
319 #define SAVE_TEXT "CENTER"
320 #endif
321 #ifndef QUIT_TEXT
322 #define QUIT_TEXT "TOPLEFT"
323 #endif
324 #ifndef RESTART_TEXT
325 #define RESTART_TEXT "TOPRIGHT"
326 #endif
327 #ifndef LVL_UP_TEXT
328 #define LVL_UP_TEXT "BOTTOMLEFT"
329 #endif
330 #ifndef LVL_DOWN_TEXT
331 #define LVL_DOWN_TEXT "BOTTOMRIGHT"
332 #endif
333 #endif
336 /* get several sizes from the bitmaps */
337 #ifdef BMPWIDTH_pegbox_pieces
338 #define PIECE_WIDTH BMPWIDTH_pegbox_pieces
339 #define PIECE_HEIGHT (BMPHEIGHT_pegbox_pieces/7)
340 #else
341 /* dummy numbers to avoid #error in dependency generation */
342 #define PIECE_WIDTH 50
343 #define PIECE_HEIGHT 10
344 #endif
345 #define BOARD_WIDTH (12*PIECE_WIDTH)
346 #define BOARD_HEIGHT (8*PIECE_HEIGHT)
349 /* define a wide layout where the statistics are alongside the board, not above
350 * base calculation on the piece bitmaps for the 8x12 board */
351 #if (LCD_WIDTH - BOARD_WIDTH) > (LCD_HEIGHT - BOARD_HEIGHT)
352 #define WIDE_LAYOUT
353 #endif
356 #define HEADER_WIDTH BMPWIDTH_pegbox_header
357 #define HEADER_HEIGHT BMPHEIGHT_pegbox_header
360 #if defined WIDE_LAYOUT
362 #if ((BOARD_WIDTH + HEADER_WIDTH + 4) <= LCD_WIDTH)
363 #define BOARD_X 2
364 #else
365 #define BOARD_X 1
366 #endif
367 #define BOARD_Y (LCD_HEIGHT-BOARD_HEIGHT)/2
369 #if (LCD_WIDTH >= 132) && (LCD_HEIGHT >= 80)
370 #define TEXT_X 116
371 #define LEVEL_TEXT_Y 14
372 #define PEGS_TEXT_Y 58
373 #else
374 #error "Unsupported screen size"
375 #endif
377 #else /* "normal" layout */
379 #define BOARD_X (LCD_WIDTH-BOARD_WIDTH)/2
380 #if ((BOARD_HEIGHT + HEADER_HEIGHT + 4) <= LCD_HEIGHT)
381 #define BOARD_Y HEADER_HEIGHT+2
382 #else
383 #define BOARD_Y HEADER_HEIGHT
384 #endif
386 #if LCD_WIDTH >= 320
387 #define LEVEL_TEXT_X 59
388 #define PEGS_TEXT_X 276
389 #define TEXT_Y 28
390 #elif LCD_WIDTH >= 240
391 #define LEVEL_TEXT_X 59
392 #define PEGS_TEXT_X 196
393 #define TEXT_Y 28
394 #elif LCD_WIDTH >= 220
395 #define LEVEL_TEXT_X 49
396 #define PEGS_TEXT_X 186
397 #define TEXT_Y 28
398 #elif LCD_WIDTH >= 176
399 #define LEVEL_TEXT_X 38
400 #define PEGS_TEXT_X 155
401 #define TEXT_Y 17
402 #elif LCD_WIDTH >= 160
403 #define LEVEL_TEXT_X 37
404 #define PEGS_TEXT_X 140
405 #define TEXT_Y 13
406 #elif LCD_WIDTH >= 138
407 #define LEVEL_TEXT_X 28
408 #define PEGS_TEXT_X 119
409 #define TEXT_Y 15
410 #elif LCD_WIDTH >= 128
411 #if HEADER_HEIGHT > 16
412 #define LEVEL_TEXT_X 26
413 #define PEGS_TEXT_X 107
414 #define TEXT_Y 31
415 #else
416 #define LEVEL_TEXT_X 15
417 #define PEGS_TEXT_X 100
418 #define TEXT_Y 5
419 #endif /* HEADER_HEIGHT */
420 #elif LCD_WIDTH >= 112
421 #define LEVEL_TEXT_X 25
422 #define PEGS_TEXT_X 90
423 #define TEXT_Y 0
424 #endif /* LCD_WIDTH */
426 #endif /* WIDE_LAYOUT */
429 #ifdef HAVE_LCD_COLOR
430 #define BG_COLOR LCD_BLACK
431 #define TEXT_BG LCD_RGBPACK(189,189,189)
432 #endif
435 #ifdef HAVE_TOUCHSCREEN
436 #include "lib/touchscreen.h"
438 static struct ts_mapping main_menu_items[5] =
440 {MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT},
441 {MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT},
442 {MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT},
443 {MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT},
445 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT > 110)
446 0, MENU_Y+4*ITEM_HEIGHT+8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
447 #elif LCD_WIDTH > 112
448 0, LCD_HEIGHT - 8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
449 #else
450 #error "Touchscreen isn't supported on non-bitmap screens!"
451 #endif
455 static struct ts_mappings main_menu = {main_menu_items, 5};
457 static struct ts_raster pegbox_raster =
458 { BOARD_X, BOARD_Y, COLS*PIECE_WIDTH, ROWS*PIECE_HEIGHT,
459 PIECE_WIDTH, PIECE_HEIGHT };
460 static struct ts_raster_button_mapping pegbox_raster_btn =
461 { &pegbox_raster, false, false, true, false, true, {0, 0}, 0, 0, 0 };
462 #endif
464 struct game_context {
465 unsigned int level;
466 unsigned int highlevel;
467 signed int player_row;
468 signed int player_col;
469 unsigned int num_left;
470 bool save_exist;
471 unsigned int playboard[ROWS][COLS];
474 char levels[NUM_LEVELS][ROWS][COLS] = {
475 /* Level 1 */
476 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
477 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
478 {1, 0, 0, 0, 7, 0, 0, 5, 0, 0, 0, 1,},
479 {1, 0, 0, 0, 0, 3, 3, 2, 0, 0, 0, 1,},
480 {1, 0, 0, 0, 4, 6, 0, 5, 0, 0, 0, 1,},
481 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
482 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
483 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
485 /* Level 2 */
486 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
487 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,},
488 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
489 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
490 {7, 0, 0, 0, 2, 2, 5, 5, 0, 0, 0, 1,},
491 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
492 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
493 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,}},
495 /* Level 3 */
496 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
497 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
498 {1, 0, 0, 0, 0, 0, 2, 0, 7, 0, 0, 0,},
499 {1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 2, 1,},
500 {1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1,},
501 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,},
502 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
503 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
505 /* Level 4 */
506 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
507 {6, 0, 4, 0, 2, 0, 2, 0, 0, 0, 0, 1,},
508 {6, 0, 3, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
509 {6, 0, 5, 0, 4, 7, 2, 0, 0, 0, 0, 1,},
510 {6, 0, 2, 0, 4, 0, 2, 0, 3, 0, 0, 1,},
511 {6, 0, 4, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
512 {6, 0, 5, 0, 4, 0, 2, 0, 0, 0, 0, 1,},
513 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
515 /* Level 5 */
516 {{0, 6, 6, 0, 4, 6, 0, 0, 6, 0, 0, 0,},
517 {0, 6, 6, 0, 4, 4, 0, 0, 6, 0, 0, 2,},
518 {2, 6, 6, 0, 6, 6, 6, 0, 1, 2, 2, 2,},
519 {0, 6, 6, 0, 6, 4, 6, 0, 1, 2, 0, 2,},
520 {0, 6, 6, 0, 6, 7, 6, 5, 6, 0, 0, 0,},
521 {2, 6, 6, 0, 6, 6, 6, 0, 6, 0, 0, 0,},
522 {0, 6, 6, 0, 4, 0, 0, 0, 6, 0, 0, 0,},
523 {0, 6, 6, 0, 0, 5, 0, 0, 6, 5, 5, 0,}},
525 /* Level 6 */
526 {{7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
527 {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,},
528 {2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0,},
529 {0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 0,},
530 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
531 {0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1,},
532 {0, 3, 0, 0, 0, 0, 0, 0, 5, 4, 6, 0,},
533 {0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1,}},
535 /* Level 7 */
536 {{1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,},
537 {1, 1, 1, 6, 0, 0, 4, 6, 0, 1, 1, 1,},
538 {1, 1, 1, 1, 0, 1, 5, 1, 0, 1, 1, 1,},
539 {1, 1, 1, 2, 3, 3, 7, 4, 2, 6, 1, 1,},
540 {1, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1,},
541 {1, 1, 1, 1, 0, 0, 5, 0, 0, 1, 0, 1,},
542 {1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,},
543 {1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,}},
545 /* Level 8 */
546 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
547 {0, 0, 3, 3, 3, 3, 3, 4, 3, 3, 0, 0,},
548 {0, 0, 3, 3, 3, 2, 3, 3, 5, 3, 0, 0,},
549 {7, 0, 3, 3, 3, 2, 3, 3, 4, 3, 0, 0,},
550 {0, 0, 3, 3, 4, 5, 3, 3, 3, 3, 0, 0,},
551 {0, 0, 3, 3, 5, 2, 3, 3, 3, 3, 0, 0,},
552 {0, 0, 3, 3, 2, 4, 3, 3, 3, 3, 0, 0,},
553 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
555 /* Level 9 */
556 {{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
557 {0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
558 {0, 0, 0, 0, 2, 4, 4, 3, 0, 1, 1, 0,},
559 {0, 1, 0, 0, 2, 1, 0, 0, 0, 1, 1, 1,},
560 {0, 0, 0, 2, 2, 7, 1, 0, 0, 0, 0, 2,},
561 {0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 1, 1,},
562 {0, 3, 1, 0, 2, 5, 5, 0, 0, 0, 3, 0,},
563 {0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0,}},
565 /* Level 10 */
566 {{1, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0,},
567 {1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 7,},
568 {0, 0, 4, 0, 6, 6, 6, 0, 0, 0, 3, 0,},
569 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
570 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
571 {0, 0, 0, 0, 6, 6, 6, 0, 3, 0, 0, 0,},
572 {1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0,},
573 {1, 1, 1, 1, 1, 2, 1, 1, 0, 0, 0, 0,}},
575 /* Level 11 */
576 {{1, 7, 1, 0, 1, 1, 6, 0, 0, 1, 1, 0,},
577 {1, 0, 0, 0, 5, 4, 6, 6, 0, 2, 2, 0,},
578 {1, 2, 1, 2, 0, 1, 6, 0, 0, 2, 2, 0,},
579 {1, 0, 0, 2, 0, 1, 0, 0, 0, 3, 3, 0,},
580 {1, 2, 1, 0, 0, 1, 0, 1, 0, 3, 3, 0,},
581 {0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0,},
582 {0, 3, 4, 3, 0, 1, 0, 1, 0, 0, 0, 0,},
583 {0, 0, 0, 0, 2, 2, 2, 1, 1, 1, 1, 1,}},
585 /* Level 12 */
586 {{7, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,},
587 {1, 2, 1, 2, 1, 2, 1, 1, 0, 0, 0, 1,},
588 {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,},
589 {1, 2, 1, 2, 1, 2, 1, 0, 0, 0, 0, 1,},
590 {0, 0, 0, 0, 0, 0, 1, 1, 5, 5, 6, 1,},
591 {1, 2, 1, 2, 1, 2, 1, 1, 0, 2, 2, 1,},
592 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1,},
593 {1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,}},
595 /* Level 13 */
596 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
597 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
598 {0, 0, 2, 0, 5, 0, 2, 0, 4, 0, 0, 6,},
599 {7, 0, 3, 0, 4, 0, 5, 0, 4, 0, 0, 6,},
600 {0, 0, 5, 0, 4, 0, 2, 0, 4, 0, 0, 6,},
601 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
602 {0, 0, 3, 0, 3, 0, 2, 0, 4, 0, 0, 6,},
603 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
605 /* Level 14 */
606 {{1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,},
607 {1, 1, 0, 2, 0, 0, 4, 0, 0, 2, 0, 1,},
608 {1, 6, 0, 0, 5, 1, 0, 1, 1, 0, 0, 1,},
609 {1, 1, 1, 0, 0, 3, 5, 3, 0, 0, 1, 1,},
610 {1, 1, 0, 0, 1, 1, 0, 1, 5, 0, 0, 6,},
611 {1, 1, 0, 2, 0, 0, 4, 0, 0, 0, 7, 1,},
612 {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,},
613 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
615 /* Level 15 */
616 {{0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
617 {0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
618 {0, 3, 4, 6, 0, 6, 0, 6, 0, 6, 0, 2,},
619 {0, 4, 0, 6, 0, 6, 4, 6, 0, 6, 0, 1,},
620 {0, 3, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
621 {7, 0, 0, 6, 4, 6, 0, 6, 0, 6, 0, 1,},
622 {0, 0, 4, 6, 0, 6, 0, 6, 4, 6, 0, 1,},
623 {0, 0, 4, 6, 0, 6, 0, 6, 0, 6, 0, 1,}}
627 /*****************************************************************************
628 * display_text() formats and outputs text.
629 ******************************************************************************/
630 static void display_text(char *str, bool waitkey)
632 int chars_by_line;
633 int lines_by_screen;
634 int chars_for_line;
635 int current_line = 0;
636 int char_width, char_height;
637 int first_char_index = 0;
638 char *ptr_char;
639 char *ptr_line;
640 int i;
641 char line[255];
642 int key;
643 bool go_on;
645 rb->lcd_clear_display();
647 rb->lcd_getstringsize("a", &char_width, &char_height);
649 chars_by_line = LCD_WIDTH / char_width;
650 lines_by_screen = LCD_HEIGHT / char_height;
654 ptr_char = str + first_char_index;
655 chars_for_line = 0;
656 i = 0;
657 ptr_line = line;
658 while (i < chars_by_line)
660 switch (*ptr_char)
662 case '\t':
663 case ' ':
664 *(ptr_line++) = ' ';
665 case '\n':
666 case '\0':
667 chars_for_line = i;
668 break;
670 default:
671 *(ptr_line++) = *ptr_char;
673 if (*ptr_char == '\n' || *ptr_char == '\0')
674 break;
675 ptr_char++;
676 i++;
679 if (chars_for_line == 0)
680 chars_for_line = i;
682 line[chars_for_line] = '\0';
684 /* test if we have cut a word. If it is the case we don't have to */
685 /* skip the space */
686 if (i == chars_by_line && chars_for_line == chars_by_line)
687 first_char_index += chars_for_line;
688 else
689 first_char_index += chars_for_line + 1;
691 /* print the line on the screen */
692 rb->lcd_putsxy(0, current_line * char_height, line);
694 /* if the number of line showed on the screen is equals to the */
695 /* maximum number of line we can show, we wait for a key pressed to */
696 /* clear and show the remaining text. */
697 current_line++;
698 if (current_line == lines_by_screen || *ptr_char == '\0')
700 current_line = 0;
701 rb->lcd_update();
702 go_on = false;
703 while (waitkey && !go_on)
705 key = rb->button_get(true);
706 switch (key)
708 #ifdef HAVE_TOUCHSCREEN
709 case BUTTON_TOUCHSCREEN:
710 #endif
711 case PEGBOX_QUIT:
712 case PEGBOX_LEFT:
713 case PEGBOX_DOWN:
714 go_on = true;
715 break;
717 default:
718 /*if (rb->default_event_handler(key) == SYS_USB_CONNECTED)
720 usb_detected = true;
721 go_on = true;
722 break;
724 break;
727 rb->lcd_clear_display();
729 } while (*ptr_char != '\0');
732 /*****************************************************************************
733 * draw_board() draws the game's current level.
734 ******************************************************************************/
735 static void draw_board(struct game_context* pb) {
736 unsigned int r, c, type;
737 pb->num_left = 0;
738 char str[5];
740 rb->lcd_clear_display();
741 #ifdef WIDE_LAYOUT
742 rb->lcd_bitmap(pegbox_header,LCD_WIDTH-HEADER_WIDTH,0,
743 HEADER_WIDTH,LCD_HEIGHT);
744 #else
745 rb->lcd_bitmap(pegbox_header,(LCD_WIDTH-HEADER_WIDTH)/2,0,
746 HEADER_WIDTH, HEADER_HEIGHT);
747 #endif /* WIDE_LAYOUT */
749 #if ((BOARD_HEIGHT + HEADER_HEIGHT + 4) <= LCD_HEIGHT)
750 rb->lcd_drawrect(BOARD_X-2,BOARD_Y-2,BOARD_WIDTH+4,BOARD_HEIGHT+4);
751 #endif /* enough space for a frame? */
753 #ifdef HAVE_LCD_COLOR
754 rb->lcd_set_foreground(LCD_WHITE);
755 rb->lcd_fillrect(BOARD_X-1,BOARD_Y-1,BOARD_WIDTH+2,BOARD_HEIGHT+2);
756 rb->lcd_set_foreground(LCD_BLACK);
757 rb->lcd_set_background(TEXT_BG);
758 #endif
760 for (r=0 ; r < ROWS ; r++) {
761 for (c = 0 ; c < COLS ; c++) {
763 type = pb->playboard[r][c];
765 switch(type) {
766 case SPACE:
767 break;
769 default:
770 rb->lcd_bitmap_part(pegbox_pieces, 0, (type-1)*PIECE_HEIGHT,
771 PIECE_WIDTH, c * PIECE_WIDTH + BOARD_X,
772 r * PIECE_HEIGHT + BOARD_Y, PIECE_WIDTH,
773 PIECE_HEIGHT);
774 break;
777 if(pb->playboard[r][c] == PLAYER) {
778 pb->player_row=r;
779 pb->player_col=c;
781 else if (type != WALL && type != SPACE && type != HOLE)
782 pb->num_left++;
786 #ifdef WIDE_LAYOUT
787 rb->snprintf(str, 3, "%d", pb->level);
788 rb->lcd_putsxy(TEXT_X, LEVEL_TEXT_Y, str);
789 rb->snprintf(str, 3, "%d", pb->num_left);
790 rb->lcd_putsxy(TEXT_X, PEGS_TEXT_Y, str);
791 #else
792 rb->snprintf(str, 3, "%d", pb->level);
793 rb->lcd_putsxy(LEVEL_TEXT_X, TEXT_Y, str);
794 rb->snprintf(str, 3, "%d", pb->num_left);
795 rb->lcd_putsxy(PEGS_TEXT_X, TEXT_Y, str);
796 #endif /*WIDE_LAYOUT*/
798 #ifdef HAVE_LCD_COLOR
799 rb->lcd_set_background(BG_COLOR);
800 rb->lcd_set_foreground(LCD_WHITE);
801 #endif
802 /* print out the screen */
803 rb->lcd_update();
806 /*****************************************************************************
807 * load_level() loads the player's current level from the array and sets the
808 * player's position.
809 ******************************************************************************/
810 static void load_level(struct game_context* pb) {
811 int r, c;
813 for(r = 0; r < ROWS; r++)
814 for(c = 0; c < COLS; c++)
815 pb->playboard[r][c] = levels[pb->level-1][r][c];
818 /*****************************************************************************
819 * new_piece() creates a new piece at a specified location. The player
820 * navigates through the pieces and selects one.
821 ******************************************************************************/
822 static void new_piece(struct game_context* pb, unsigned int x_loc,
823 unsigned int y_loc) {
824 int button;
825 bool exit = false;
827 pb->playboard[x_loc][y_loc] = TRIANGLE;
829 while (!exit) {
830 draw_board(pb);
831 button = rb->button_get(true);
832 #ifdef HAVE_TOUCHSCREEN
833 if(button & BUTTON_TOUCHSCREEN)
835 pegbox_raster_btn.two_d_from.y = x_loc;
836 pegbox_raster_btn.two_d_from.x = y_loc;
838 struct ts_raster_button_result ret =
839 touchscreen_raster_map_button(&pegbox_raster_btn,
840 rb->button_get_data() >> 16,
841 rb->button_get_data() & 0xffff,
842 button);
843 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
845 if(ret.to.x > ret.from.x)
846 button = PEGBOX_UP;
847 else if(ret.to.x < ret.from.x)
848 button = PEGBOX_DOWN;
849 else if(ret.to.y > ret.from.y)
850 button = PEGBOX_LEFT;
851 else if(ret.to.y < ret.from.y)
852 button = PEGBOX_RIGHT;
854 else if(ret.action == TS_ACTION_CLICK
855 && (unsigned)ret.to.x == y_loc
856 && (unsigned)ret.to.y == x_loc)
857 button = PEGBOX_SAVE;
859 #endif
860 switch(button){
861 case PEGBOX_LEFT:
862 case (PEGBOX_LEFT|BUTTON_REPEAT):
863 case PEGBOX_DOWN:
864 case (PEGBOX_DOWN|BUTTON_REPEAT):
865 if (pb->playboard[x_loc][y_loc] < 5)
866 pb->playboard[x_loc][y_loc]++;
867 else
868 pb->playboard[x_loc][y_loc] = TRIANGLE;
869 break;
870 case PEGBOX_RIGHT:
871 case (PEGBOX_RIGHT|BUTTON_REPEAT):
872 case PEGBOX_UP:
873 case (PEGBOX_UP|BUTTON_REPEAT):
874 if (pb->playboard[x_loc][y_loc] > 2)
875 pb->playboard[x_loc][y_loc]--;
876 else
877 pb->playboard[x_loc][y_loc] = CIRCLE;
878 break;
879 case PEGBOX_SAVE:
880 exit = true;
881 break;
886 /*****************************************************************************
887 * move_player() moves the player and pieces and updates the board accordingly.
888 ******************************************************************************/
889 static void move_player(struct game_context* pb, signed int x_dir,
890 signed int y_dir) {
891 unsigned int type1, type2;
892 signed int r,c;
894 r = pb->player_row+y_dir;
895 c = pb->player_col+x_dir;
897 type1 = pb->playboard[r][c];
898 type2 = pb->playboard[r+y_dir][c+x_dir];
900 if (r == ROWS || c == COLS || r < 0 || c < 0 || type1 == WALL)
901 return;
902 else if(type1 != SPACE) {
903 if (type2 == WALL || r+y_dir == ROWS || c+x_dir == COLS ||
904 r+y_dir < 0 || c+x_dir < 0)
905 return;
909 pb->playboard[pb->player_row][pb->player_col] = SPACE;
910 pb->player_row += y_dir;
911 pb->player_col += x_dir;
913 if (type1 == HOLE) {
914 draw_board(pb);
915 rb->splash(HZ*2, "You fell down a hole!");
916 load_level(pb);
918 else if (type1 == SPACE)
919 pb->playboard[r][c] = PLAYER;
920 else {
921 pb->playboard[r][c] = PLAYER;
922 if(type1 == type2) {
923 if (type1 == TRIANGLE)
924 pb->playboard[r+y_dir][c+x_dir] = WALL;
925 else if (type1 == CROSS) {
926 pb->playboard[r][c] = SPACE;
927 new_piece(pb, r+y_dir, c+x_dir);
928 pb->playboard[r][c] = PLAYER;
930 else
931 pb->playboard[r+y_dir][c+x_dir] = SPACE;
933 else if (type2 == SPACE)
934 pb->playboard[r+y_dir][c+x_dir] = type1;
935 else if (type2 == HOLE) {
936 if (type1 == SQUARE)
937 pb->playboard[r+y_dir][c+x_dir] = SPACE;
939 else {
940 rb->splash(HZ*2, "Illegal Move!");
941 load_level(pb);
945 draw_board(pb);
948 /*****************************************************************************
949 * pegbox_loadgame() loads the saved game and returns load success.
950 ******************************************************************************/
951 static bool pegbox_loadgame(struct game_context* pb) {
952 signed int fd;
953 bool loaded = false;
955 /* open game file */
956 fd = rb->open(SAVE_FILE, O_RDONLY);
957 if(fd < 0) return loaded;
959 /* read in saved game */
960 while(true) {
961 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
962 if(rb->read(fd, &pb->playboard, sizeof(pb->playboard)) <= 0)
964 loaded = true;
965 break;
967 break;
970 rb->close(fd);
971 return loaded;
974 /*****************************************************************************
975 * pegbox_savegame() saves the current game state.
976 ******************************************************************************/
977 static void pegbox_savegame(struct game_context* pb) {
978 unsigned int fd;
980 /* write out the game state to the save file */
981 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
982 rb->write(fd, &pb->level, sizeof(pb->level));
983 rb->write(fd, &pb->playboard, sizeof(pb->playboard));
984 rb->close(fd);
987 /*****************************************************************************
988 * pegbox_loaddata() loads the level and highlevel and returns load success.
989 ******************************************************************************/
990 static void pegbox_loaddata(struct game_context* pb) {
991 signed int fd;
993 /* open game file */
994 fd = rb->open(DATA_FILE, O_RDONLY);
995 if(fd < 0) {
996 pb->level = 1;
997 pb->highlevel = 1;
998 return;
1001 /* read in saved game */
1002 while(true) {
1003 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
1004 if(rb->read(fd, &pb->highlevel, sizeof(pb->highlevel)) <= 0) break;
1005 break;
1008 rb->close(fd);
1009 return;
1012 /*****************************************************************************
1013 * pegbox_savedata() saves the level and highlevel.
1014 ******************************************************************************/
1015 static void pegbox_savedata(struct game_context* pb) {
1016 unsigned int fd;
1018 /* write out the game state to the save file */
1019 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT);
1020 rb->write(fd, &pb->level, sizeof(pb->level));
1021 rb->write(fd, &pb->highlevel, sizeof(pb->highlevel));
1022 rb->close(fd);
1025 /*****************************************************************************
1026 * pegbox_callback() is the default event handler callback which is called
1027 * on usb connect and shutdown.
1028 ******************************************************************************/
1029 static void pegbox_callback(void* param) {
1030 struct game_context* pb = (struct game_context*) param;
1031 rb->splash(HZ, "Saving data...");
1032 pegbox_savedata(pb);
1035 /*****************************************************************************
1036 * pegbox_menu() is the initial menu at the start of the game.
1037 ******************************************************************************/
1038 static unsigned int pegbox_menu(struct game_context* pb) {
1039 int button;
1040 char str[30];
1041 unsigned int startlevel = 1, loc = 0;
1042 bool breakout = false, can_resume = false;
1044 if (pb->num_left > 0 || pb->save_exist)
1045 can_resume = true;
1047 while(!breakout){
1048 #if LCD_HEIGHT >= 80
1049 rb->lcd_clear_display();
1050 rb->lcd_bitmap(pegbox_menu_top,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_menu_top);
1052 /* menu bitmaps */
1053 if (loc == 0) {
1054 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT, ITEM_WIDTH,
1055 MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT);
1057 else {
1058 rb->lcd_bitmap_part(pegbox_menu_items, 0, 0, ITEM_WIDTH,
1059 MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT);
1061 if (can_resume) {
1062 if (loc == 1) {
1063 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*3, ITEM_WIDTH,
1064 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1066 else {
1067 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*2, ITEM_WIDTH,
1068 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1071 else {
1072 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*4, ITEM_WIDTH,
1073 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1076 if (loc==2) {
1077 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*6, ITEM_WIDTH,
1078 MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT);
1080 else {
1081 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*5, ITEM_WIDTH,
1082 MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT);
1085 if (loc==3) {
1086 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*8, ITEM_WIDTH,
1087 MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT);
1089 else {
1090 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*7, ITEM_WIDTH,
1091 MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT);
1093 #else
1094 unsigned int w,h;
1095 rb->lcd_clear_display();
1096 rb->lcd_getstringsize("PegBox", &w, &h);
1097 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, "PegBox");
1098 rb->lcd_putsxy((LCD_WIDTH)/4, 16, "New Game");
1099 rb->lcd_putsxy((LCD_WIDTH)/4, 24, "Resume");
1100 rb->lcd_putsxy((LCD_WIDTH)/4, 32, "Help");
1101 rb->lcd_putsxy((LCD_WIDTH)/4, 40, "Quit");
1103 if(!can_resume)
1104 rb->lcd_hline((LCD_WIDTH)/4, (LCD_WIDTH)/4+30, 28);
1106 rb->lcd_putsxy((LCD_WIDTH)/4-8, loc*8+16, "*");
1109 #endif
1110 rb->snprintf(str, 28, "Start on level %d of %d", startlevel,
1111 pb->highlevel);
1112 #if LCD_HEIGHT > 110
1113 rb->lcd_putsxy(0, MENU_Y+4*ITEM_HEIGHT+8, str);
1114 #elif LCD_HEIGHT > 64
1115 rb->lcd_putsxy(0, LCD_HEIGHT - 8, str);
1116 #else
1117 rb->lcd_puts_scroll(0, 7, str);
1118 #endif
1119 rb->lcd_update();
1121 /* handle menu button presses */
1122 button = rb->button_get(true);
1124 #ifdef HAVE_TOUCHSCREEN
1125 if(button & BUTTON_TOUCHSCREEN)
1127 unsigned int result = touchscreen_map(&main_menu,
1128 rb->button_get_data() >> 16,
1129 rb->button_get_data() & 0xffff);
1130 if(result != (unsigned)-1 && button & BUTTON_REL)
1132 if(result == 4)
1133 button = PEGBOX_LVL_UP;
1134 else
1136 if(loc == result)
1137 button = PEGBOX_RIGHT;
1138 loc = result;
1142 #endif
1144 switch(button) {
1145 case PEGBOX_SAVE: /* start playing */
1146 case PEGBOX_RIGHT:
1147 if (loc == 0) {
1148 breakout = true;
1149 pb->level = startlevel;
1150 load_level(pb);
1152 else if (loc == 1 && can_resume) {
1153 if(pb->save_exist)
1155 rb->remove(SAVE_FILE);
1156 pb->save_exist = false;
1158 breakout = true;
1160 else if (loc == 2)
1161 display_text("How to Play\nTo beat each level, you must "
1162 "destroy all of the pegs. If two like pegs are "
1163 "pushed into each other they disappear except "
1164 "for triangles which form a solid block and "
1165 "crosses which allow you to choose a "
1166 "replacement block.\n\n"
1167 "Controls\n"
1168 #if LCD_HEIGHT > 64
1169 RESTART_TEXT " to restart level\n"
1170 LVL_UP_TEXT " to go up a level\n"
1171 LVL_DOWN_TEXT " to go down a level\n"
1172 SAVE_TEXT " to select/save\n"
1173 QUIT_TEXT " to quit\n",true);
1174 #else
1175 RESTART_TEXT ": restart\n"
1176 LVL_UP_TEXT ": level up\n"
1177 LVL_DOWN_TEXT " level down\n"
1178 SAVE_TEXT " select/save\n"
1179 QUIT_TEXT " quit\n",true);
1180 #endif
1181 else if (loc == 3)
1182 return PB_QUIT;
1183 break;
1185 case PEGBOX_QUIT: /* quit program */
1186 return PB_QUIT;
1188 case (PEGBOX_UP|BUTTON_REPEAT):
1189 case PEGBOX_UP:
1190 if (loc <= 0)
1191 loc = 3;
1192 else
1193 loc--;
1194 if (!can_resume && loc == 1) {
1195 loc = 0;
1197 break;
1200 case (PEGBOX_DOWN|BUTTON_REPEAT):
1201 case PEGBOX_DOWN:
1202 if (loc >= 3)
1203 loc = 0;
1204 else
1205 loc++;
1206 if (!can_resume && loc == 1) {
1207 loc = 2;
1209 break;
1211 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1212 case PEGBOX_LVL_UP: /* increase starting level */
1213 if(startlevel >= pb->highlevel) {
1214 startlevel = 1;
1215 } else {
1216 startlevel++;
1218 break;
1220 /* only for targets with enough buttons */
1221 #ifdef PEGBOX_LVL_DOWN
1222 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1223 case PEGBOX_LVL_DOWN: /* decrease starting level */
1224 if(startlevel <= 1) {
1225 startlevel = pb->highlevel;
1226 } else {
1227 startlevel--;
1229 break;
1230 #endif
1231 default:
1232 if(rb->default_event_handler_ex(button, pegbox_callback,
1233 (void*) pb) == SYS_USB_CONNECTED)
1234 return PB_USB;
1235 break;
1239 draw_board(pb);
1241 return 0;
1244 /*****************************************************************************
1245 * pegbox() is the main game subroutine, it returns the final game status.
1246 ******************************************************************************/
1247 static int pegbox(struct game_context* pb) {
1248 int temp_var;
1250 /********************
1251 * menu *
1252 ********************/
1253 temp_var = pegbox_menu(pb);
1254 if (temp_var == PB_QUIT || temp_var == PB_USB)
1255 return temp_var;
1257 while (true) {
1258 temp_var = rb->button_get(true);
1259 #ifdef HAVE_TOUCHSCREEN
1260 if(temp_var & BUTTON_TOUCHSCREEN)
1262 pegbox_raster_btn.two_d_from.y = pb->player_row;
1263 pegbox_raster_btn.two_d_from.x = pb->player_col;
1265 struct ts_raster_button_result ret =
1266 touchscreen_raster_map_button(&pegbox_raster_btn,
1267 rb->button_get_data() >> 16,
1268 rb->button_get_data() & 0xffff,
1269 temp_var);
1270 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
1271 move_player(pb, ret.to.x - ret.from.x, ret.to.y - ret.from.y);
1273 #endif
1274 switch(temp_var){
1275 case PEGBOX_LEFT: /* move cursor left */
1276 case (PEGBOX_LEFT|BUTTON_REPEAT):
1277 move_player(pb, -1, 0);
1278 break;
1280 case PEGBOX_RIGHT: /* move cursor right */
1281 case (PEGBOX_RIGHT|BUTTON_REPEAT):
1282 move_player(pb, 1, 0);
1283 break;
1285 case PEGBOX_DOWN: /* move cursor down */
1286 case (PEGBOX_DOWN|BUTTON_REPEAT):
1287 move_player(pb, 0, 1);
1288 break;
1290 case PEGBOX_UP: /* move cursor up */
1291 case (PEGBOX_UP|BUTTON_REPEAT):
1292 move_player(pb, 0, -1);
1293 break;
1295 case PEGBOX_SAVE: /* save and end game */
1296 rb->splash(HZ, "Saving game...");
1297 pegbox_savegame(pb);
1298 /* fall through to PEGBOX_QUIT */
1300 case PEGBOX_QUIT:
1301 return PB_END;
1303 case PEGBOX_RESTART:
1304 load_level(pb);
1305 draw_board(pb);
1306 break;
1308 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1309 case PEGBOX_LVL_UP:
1310 if(pb->level >= pb->highlevel) {
1311 pb->level = 1;
1312 } else {
1313 pb->level++;
1315 load_level(pb);
1316 draw_board(pb);
1317 break;
1319 /* only for targets with enough buttons */
1320 #ifdef PEGBOX_LVL_DOWN
1321 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1322 case PEGBOX_LVL_DOWN:
1323 if(pb->level <= 1) {
1324 pb->level = pb->highlevel;
1325 } else {
1326 pb->level--;
1328 load_level(pb);
1329 draw_board(pb);
1330 break;
1331 #endif
1335 if(pb->num_left == 0) {
1336 rb->splash(HZ*2, "Nice Pegging!");
1337 if(pb->level == NUM_LEVELS) {
1338 draw_board(pb);
1339 rb->splash(HZ*2, "You Won!");
1340 break;
1342 else {
1343 pb->level++;
1344 load_level(pb);
1345 draw_board(pb);
1348 if(pb->level > pb->highlevel)
1349 pb->highlevel = pb->level;
1354 return PLUGIN_OK;
1358 /*****************************************************************************
1359 * plugin entry point.
1360 ******************************************************************************/
1361 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter) {
1362 bool exit = false;
1363 struct game_context pb;
1365 (void)parameter;
1366 rb = api;
1368 rb->lcd_setfont(FONT_SYSFIXED);
1369 #if LCD_DEPTH > 1
1370 rb->lcd_set_backdrop(NULL);
1371 #endif
1372 #ifdef HAVE_LCD_COLOR
1373 rb->lcd_set_foreground(LCD_WHITE);
1374 rb->lcd_set_background(BG_COLOR);
1375 #endif
1377 rb->splash(0, "Loading...");
1378 pegbox_loaddata(&pb);
1379 pb.save_exist = pegbox_loadgame(&pb);
1380 pb.num_left = 0;
1382 rb->lcd_clear_display();
1385 while(!exit) {
1386 switch(pegbox(&pb)){
1387 case PB_END:
1388 break;
1390 case PB_USB:
1391 rb->lcd_setfont(FONT_UI);
1392 return PLUGIN_USB_CONNECTED;
1394 case PB_QUIT:
1395 rb->splash(HZ, "Saving data...");
1396 pegbox_savedata(&pb);
1397 exit = true;
1398 break;
1400 default:
1401 break;
1405 rb->lcd_setfont(FONT_UI);
1406 return PLUGIN_OK;