New makefile solution: A single invocation of 'make' to build the entire tree. Fully...
[kugel-rb.git] / apps / plugins / pegbox.c
blob643e793fdc5b93b0ada14879586f029e4593dad3
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 #define PIECE_WIDTH BMPWIDTH_pegbox_pieces
338 #define PIECE_HEIGHT (BMPHEIGHT_pegbox_pieces/7)
339 #define BOARD_WIDTH (12*PIECE_WIDTH)
340 #define BOARD_HEIGHT (8*PIECE_HEIGHT)
343 /* define a wide layout where the statistics are alongside the board, not above
344 * base calculation on the piece bitmaps for the 8x12 board */
345 #if (LCD_WIDTH - BOARD_WIDTH) > (LCD_HEIGHT - BOARD_HEIGHT)
346 #define WIDE_LAYOUT
347 #endif
350 #define HEADER_WIDTH BMPWIDTH_pegbox_header
351 #define HEADER_HEIGHT BMPHEIGHT_pegbox_header
354 #if defined WIDE_LAYOUT
356 #if ((BOARD_WIDTH + HEADER_WIDTH + 4) <= LCD_WIDTH)
357 #define BOARD_X 2
358 #else
359 #define BOARD_X 1
360 #endif
361 #define BOARD_Y (LCD_HEIGHT-BOARD_HEIGHT)/2
363 #if (LCD_WIDTH >= 132) && (LCD_HEIGHT >= 80)
364 #define TEXT_X 116
365 #define LEVEL_TEXT_Y 14
366 #define PEGS_TEXT_Y 58
367 #else
368 #error "Unsupported screen size"
369 #endif
371 #else /* "normal" layout */
373 #define BOARD_X (LCD_WIDTH-BOARD_WIDTH)/2
374 #if ((BOARD_HEIGHT + HEADER_HEIGHT + 4) <= LCD_HEIGHT)
375 #define BOARD_Y HEADER_HEIGHT+2
376 #else
377 #define BOARD_Y HEADER_HEIGHT
378 #endif
380 #if LCD_WIDTH >= 320
381 #define LEVEL_TEXT_X 59
382 #define PEGS_TEXT_X 276
383 #define TEXT_Y 28
384 #elif LCD_WIDTH >= 240
385 #define LEVEL_TEXT_X 59
386 #define PEGS_TEXT_X 196
387 #define TEXT_Y 28
388 #elif LCD_WIDTH >= 220
389 #define LEVEL_TEXT_X 49
390 #define PEGS_TEXT_X 186
391 #define TEXT_Y 28
392 #elif LCD_WIDTH >= 176
393 #define LEVEL_TEXT_X 38
394 #define PEGS_TEXT_X 155
395 #define TEXT_Y 17
396 #elif LCD_WIDTH >= 160
397 #define LEVEL_TEXT_X 37
398 #define PEGS_TEXT_X 140
399 #define TEXT_Y 13
400 #elif LCD_WIDTH >= 138
401 #define LEVEL_TEXT_X 28
402 #define PEGS_TEXT_X 119
403 #define TEXT_Y 15
404 #elif LCD_WIDTH >= 128
405 #if HEADER_HEIGHT > 16
406 #define LEVEL_TEXT_X 26
407 #define PEGS_TEXT_X 107
408 #define TEXT_Y 31
409 #else
410 #define LEVEL_TEXT_X 15
411 #define PEGS_TEXT_X 100
412 #define TEXT_Y 5
413 #endif /* HEADER_HEIGHT */
414 #elif LCD_WIDTH >= 112
415 #define LEVEL_TEXT_X 25
416 #define PEGS_TEXT_X 90
417 #define TEXT_Y 0
418 #endif /* LCD_WIDTH */
420 #endif /* WIDE_LAYOUT */
423 #ifdef HAVE_LCD_COLOR
424 #define BG_COLOR LCD_BLACK
425 #define TEXT_BG LCD_RGBPACK(189,189,189)
426 #endif
429 #ifdef HAVE_TOUCHSCREEN
430 #include "lib/touchscreen.h"
432 static struct ts_mapping main_menu_items[5] =
434 {MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT},
435 {MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT},
436 {MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT},
437 {MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT},
439 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT > 110)
440 0, MENU_Y+4*ITEM_HEIGHT+8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
441 #elif LCD_WIDTH > 112
442 0, LCD_HEIGHT - 8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
443 #else
444 #error "Touchscreen isn't supported on non-bitmap screens!"
445 #endif
449 static struct ts_mappings main_menu = {main_menu_items, 5};
451 static struct ts_raster pegbox_raster =
452 { BOARD_X, BOARD_Y, COLS*PIECE_WIDTH, ROWS*PIECE_HEIGHT,
453 PIECE_WIDTH, PIECE_HEIGHT };
454 static struct ts_raster_button_mapping pegbox_raster_btn =
455 { &pegbox_raster, false, false, true, false, true, {0, 0}, 0, 0, 0 };
456 #endif
458 struct game_context {
459 unsigned int level;
460 unsigned int highlevel;
461 signed int player_row;
462 signed int player_col;
463 unsigned int num_left;
464 bool save_exist;
465 unsigned int playboard[ROWS][COLS];
468 char levels[NUM_LEVELS][ROWS][COLS] = {
469 /* Level 1 */
470 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
471 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
472 {1, 0, 0, 0, 7, 0, 0, 5, 0, 0, 0, 1,},
473 {1, 0, 0, 0, 0, 3, 3, 2, 0, 0, 0, 1,},
474 {1, 0, 0, 0, 4, 6, 0, 5, 0, 0, 0, 1,},
475 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
476 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
477 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
479 /* Level 2 */
480 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
481 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,},
482 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
483 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
484 {7, 0, 0, 0, 2, 2, 5, 5, 0, 0, 0, 1,},
485 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
486 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
487 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,}},
489 /* Level 3 */
490 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
491 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
492 {1, 0, 0, 0, 0, 0, 2, 0, 7, 0, 0, 0,},
493 {1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 2, 1,},
494 {1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1,},
495 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,},
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,}},
499 /* Level 4 */
500 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
501 {6, 0, 4, 0, 2, 0, 2, 0, 0, 0, 0, 1,},
502 {6, 0, 3, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
503 {6, 0, 5, 0, 4, 7, 2, 0, 0, 0, 0, 1,},
504 {6, 0, 2, 0, 4, 0, 2, 0, 3, 0, 0, 1,},
505 {6, 0, 4, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
506 {6, 0, 5, 0, 4, 0, 2, 0, 0, 0, 0, 1,},
507 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
509 /* Level 5 */
510 {{0, 6, 6, 0, 4, 6, 0, 0, 6, 0, 0, 0,},
511 {0, 6, 6, 0, 4, 4, 0, 0, 6, 0, 0, 2,},
512 {2, 6, 6, 0, 6, 6, 6, 0, 1, 2, 2, 2,},
513 {0, 6, 6, 0, 6, 4, 6, 0, 1, 2, 0, 2,},
514 {0, 6, 6, 0, 6, 7, 6, 5, 6, 0, 0, 0,},
515 {2, 6, 6, 0, 6, 6, 6, 0, 6, 0, 0, 0,},
516 {0, 6, 6, 0, 4, 0, 0, 0, 6, 0, 0, 0,},
517 {0, 6, 6, 0, 0, 5, 0, 0, 6, 5, 5, 0,}},
519 /* Level 6 */
520 {{7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
521 {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,},
522 {2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0,},
523 {0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 0,},
524 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
525 {0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1,},
526 {0, 3, 0, 0, 0, 0, 0, 0, 5, 4, 6, 0,},
527 {0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1,}},
529 /* Level 7 */
530 {{1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,},
531 {1, 1, 1, 6, 0, 0, 4, 6, 0, 1, 1, 1,},
532 {1, 1, 1, 1, 0, 1, 5, 1, 0, 1, 1, 1,},
533 {1, 1, 1, 2, 3, 3, 7, 4, 2, 6, 1, 1,},
534 {1, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1,},
535 {1, 1, 1, 1, 0, 0, 5, 0, 0, 1, 0, 1,},
536 {1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,},
537 {1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,}},
539 /* Level 8 */
540 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
541 {0, 0, 3, 3, 3, 3, 3, 4, 3, 3, 0, 0,},
542 {0, 0, 3, 3, 3, 2, 3, 3, 5, 3, 0, 0,},
543 {7, 0, 3, 3, 3, 2, 3, 3, 4, 3, 0, 0,},
544 {0, 0, 3, 3, 4, 5, 3, 3, 3, 3, 0, 0,},
545 {0, 0, 3, 3, 5, 2, 3, 3, 3, 3, 0, 0,},
546 {0, 0, 3, 3, 2, 4, 3, 3, 3, 3, 0, 0,},
547 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
549 /* Level 9 */
550 {{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
551 {0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
552 {0, 0, 0, 0, 2, 4, 4, 3, 0, 1, 1, 0,},
553 {0, 1, 0, 0, 2, 1, 0, 0, 0, 1, 1, 1,},
554 {0, 0, 0, 2, 2, 7, 1, 0, 0, 0, 0, 2,},
555 {0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 1, 1,},
556 {0, 3, 1, 0, 2, 5, 5, 0, 0, 0, 3, 0,},
557 {0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0,}},
559 /* Level 10 */
560 {{1, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0,},
561 {1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 7,},
562 {0, 0, 4, 0, 6, 6, 6, 0, 0, 0, 3, 0,},
563 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
564 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
565 {0, 0, 0, 0, 6, 6, 6, 0, 3, 0, 0, 0,},
566 {1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0,},
567 {1, 1, 1, 1, 1, 2, 1, 1, 0, 0, 0, 0,}},
569 /* Level 11 */
570 {{1, 7, 1, 0, 1, 1, 6, 0, 0, 1, 1, 0,},
571 {1, 0, 0, 0, 5, 4, 6, 6, 0, 2, 2, 0,},
572 {1, 2, 1, 2, 0, 1, 6, 0, 0, 2, 2, 0,},
573 {1, 0, 0, 2, 0, 1, 0, 0, 0, 3, 3, 0,},
574 {1, 2, 1, 0, 0, 1, 0, 1, 0, 3, 3, 0,},
575 {0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0,},
576 {0, 3, 4, 3, 0, 1, 0, 1, 0, 0, 0, 0,},
577 {0, 0, 0, 0, 2, 2, 2, 1, 1, 1, 1, 1,}},
579 /* Level 12 */
580 {{7, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,},
581 {1, 2, 1, 2, 1, 2, 1, 1, 0, 0, 0, 1,},
582 {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,},
583 {1, 2, 1, 2, 1, 2, 1, 0, 0, 0, 0, 1,},
584 {0, 0, 0, 0, 0, 0, 1, 1, 5, 5, 6, 1,},
585 {1, 2, 1, 2, 1, 2, 1, 1, 0, 2, 2, 1,},
586 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1,},
587 {1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,}},
589 /* Level 13 */
590 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
591 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
592 {0, 0, 2, 0, 5, 0, 2, 0, 4, 0, 0, 6,},
593 {7, 0, 3, 0, 4, 0, 5, 0, 4, 0, 0, 6,},
594 {0, 0, 5, 0, 4, 0, 2, 0, 4, 0, 0, 6,},
595 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
596 {0, 0, 3, 0, 3, 0, 2, 0, 4, 0, 0, 6,},
597 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
599 /* Level 14 */
600 {{1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,},
601 {1, 1, 0, 2, 0, 0, 4, 0, 0, 2, 0, 1,},
602 {1, 6, 0, 0, 5, 1, 0, 1, 1, 0, 0, 1,},
603 {1, 1, 1, 0, 0, 3, 5, 3, 0, 0, 1, 1,},
604 {1, 1, 0, 0, 1, 1, 0, 1, 5, 0, 0, 6,},
605 {1, 1, 0, 2, 0, 0, 4, 0, 0, 0, 7, 1,},
606 {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,},
607 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
609 /* Level 15 */
610 {{0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
611 {0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
612 {0, 3, 4, 6, 0, 6, 0, 6, 0, 6, 0, 2,},
613 {0, 4, 0, 6, 0, 6, 4, 6, 0, 6, 0, 1,},
614 {0, 3, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
615 {7, 0, 0, 6, 4, 6, 0, 6, 0, 6, 0, 1,},
616 {0, 0, 4, 6, 0, 6, 0, 6, 4, 6, 0, 1,},
617 {0, 0, 4, 6, 0, 6, 0, 6, 0, 6, 0, 1,}}
621 /*****************************************************************************
622 * display_text() formats and outputs text.
623 ******************************************************************************/
624 static void display_text(char *str, bool waitkey)
626 int chars_by_line;
627 int lines_by_screen;
628 int chars_for_line;
629 int current_line = 0;
630 int char_width, char_height;
631 int first_char_index = 0;
632 char *ptr_char;
633 char *ptr_line;
634 int i;
635 char line[255];
636 int key;
637 bool go_on;
639 rb->lcd_clear_display();
641 rb->lcd_getstringsize("a", &char_width, &char_height);
643 chars_by_line = LCD_WIDTH / char_width;
644 lines_by_screen = LCD_HEIGHT / char_height;
648 ptr_char = str + first_char_index;
649 chars_for_line = 0;
650 i = 0;
651 ptr_line = line;
652 while (i < chars_by_line)
654 switch (*ptr_char)
656 case '\t':
657 case ' ':
658 *(ptr_line++) = ' ';
659 case '\n':
660 case '\0':
661 chars_for_line = i;
662 break;
664 default:
665 *(ptr_line++) = *ptr_char;
667 if (*ptr_char == '\n' || *ptr_char == '\0')
668 break;
669 ptr_char++;
670 i++;
673 if (chars_for_line == 0)
674 chars_for_line = i;
676 line[chars_for_line] = '\0';
678 /* test if we have cut a word. If it is the case we don't have to */
679 /* skip the space */
680 if (i == chars_by_line && chars_for_line == chars_by_line)
681 first_char_index += chars_for_line;
682 else
683 first_char_index += chars_for_line + 1;
685 /* print the line on the screen */
686 rb->lcd_putsxy(0, current_line * char_height, line);
688 /* if the number of line showed on the screen is equals to the */
689 /* maximum number of line we can show, we wait for a key pressed to */
690 /* clear and show the remaining text. */
691 current_line++;
692 if (current_line == lines_by_screen || *ptr_char == '\0')
694 current_line = 0;
695 rb->lcd_update();
696 go_on = false;
697 while (waitkey && !go_on)
699 key = rb->button_get(true);
700 switch (key)
702 #ifdef HAVE_TOUCHSCREEN
703 case BUTTON_TOUCHSCREEN:
704 #endif
705 case PEGBOX_QUIT:
706 case PEGBOX_LEFT:
707 case PEGBOX_DOWN:
708 go_on = true;
709 break;
711 default:
712 /*if (rb->default_event_handler(key) == SYS_USB_CONNECTED)
714 usb_detected = true;
715 go_on = true;
716 break;
718 break;
721 rb->lcd_clear_display();
723 } while (*ptr_char != '\0');
726 /*****************************************************************************
727 * draw_board() draws the game's current level.
728 ******************************************************************************/
729 static void draw_board(struct game_context* pb) {
730 unsigned int r, c, type;
731 pb->num_left = 0;
732 char str[5];
734 rb->lcd_clear_display();
735 #ifdef WIDE_LAYOUT
736 rb->lcd_bitmap(pegbox_header,LCD_WIDTH-HEADER_WIDTH,0,
737 HEADER_WIDTH,LCD_HEIGHT);
738 #else
739 rb->lcd_bitmap(pegbox_header,(LCD_WIDTH-HEADER_WIDTH)/2,0,
740 HEADER_WIDTH, HEADER_HEIGHT);
741 #endif /* WIDE_LAYOUT */
743 #if ((BOARD_HEIGHT + HEADER_HEIGHT + 4) <= LCD_HEIGHT)
744 rb->lcd_drawrect(BOARD_X-2,BOARD_Y-2,BOARD_WIDTH+4,BOARD_HEIGHT+4);
745 #endif /* enough space for a frame? */
747 #ifdef HAVE_LCD_COLOR
748 rb->lcd_set_foreground(LCD_WHITE);
749 rb->lcd_fillrect(BOARD_X-1,BOARD_Y-1,BOARD_WIDTH+2,BOARD_HEIGHT+2);
750 rb->lcd_set_foreground(LCD_BLACK);
751 rb->lcd_set_background(TEXT_BG);
752 #endif
754 for (r=0 ; r < ROWS ; r++) {
755 for (c = 0 ; c < COLS ; c++) {
757 type = pb->playboard[r][c];
759 switch(type) {
760 case SPACE:
761 break;
763 default:
764 rb->lcd_bitmap_part(pegbox_pieces, 0, (type-1)*PIECE_HEIGHT,
765 PIECE_WIDTH, c * PIECE_WIDTH + BOARD_X,
766 r * PIECE_HEIGHT + BOARD_Y, PIECE_WIDTH,
767 PIECE_HEIGHT);
768 break;
771 if(pb->playboard[r][c] == PLAYER) {
772 pb->player_row=r;
773 pb->player_col=c;
775 else if (type != WALL && type != SPACE && type != HOLE)
776 pb->num_left++;
780 #ifdef WIDE_LAYOUT
781 rb->snprintf(str, 3, "%d", pb->level);
782 rb->lcd_putsxy(TEXT_X, LEVEL_TEXT_Y, str);
783 rb->snprintf(str, 3, "%d", pb->num_left);
784 rb->lcd_putsxy(TEXT_X, PEGS_TEXT_Y, str);
785 #else
786 rb->snprintf(str, 3, "%d", pb->level);
787 rb->lcd_putsxy(LEVEL_TEXT_X, TEXT_Y, str);
788 rb->snprintf(str, 3, "%d", pb->num_left);
789 rb->lcd_putsxy(PEGS_TEXT_X, TEXT_Y, str);
790 #endif /*WIDE_LAYOUT*/
792 #ifdef HAVE_LCD_COLOR
793 rb->lcd_set_background(BG_COLOR);
794 rb->lcd_set_foreground(LCD_WHITE);
795 #endif
796 /* print out the screen */
797 rb->lcd_update();
800 /*****************************************************************************
801 * load_level() loads the player's current level from the array and sets the
802 * player's position.
803 ******************************************************************************/
804 static void load_level(struct game_context* pb) {
805 int r, c;
807 for(r = 0; r < ROWS; r++)
808 for(c = 0; c < COLS; c++)
809 pb->playboard[r][c] = levels[pb->level-1][r][c];
812 /*****************************************************************************
813 * new_piece() creates a new piece at a specified location. The player
814 * navigates through the pieces and selects one.
815 ******************************************************************************/
816 static void new_piece(struct game_context* pb, unsigned int x_loc,
817 unsigned int y_loc) {
818 int button;
819 bool exit = false;
821 pb->playboard[x_loc][y_loc] = TRIANGLE;
823 while (!exit) {
824 draw_board(pb);
825 button = rb->button_get(true);
826 #ifdef HAVE_TOUCHSCREEN
827 if(button & BUTTON_TOUCHSCREEN)
829 pegbox_raster_btn.two_d_from.y = x_loc;
830 pegbox_raster_btn.two_d_from.x = y_loc;
832 struct ts_raster_button_result ret =
833 touchscreen_raster_map_button(&pegbox_raster_btn,
834 rb->button_get_data() >> 16,
835 rb->button_get_data() & 0xffff,
836 button);
837 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
839 if(ret.to.x > ret.from.x)
840 button = PEGBOX_UP;
841 else if(ret.to.x < ret.from.x)
842 button = PEGBOX_DOWN;
843 else if(ret.to.y > ret.from.y)
844 button = PEGBOX_LEFT;
845 else if(ret.to.y < ret.from.y)
846 button = PEGBOX_RIGHT;
848 else if(ret.action == TS_ACTION_CLICK
849 && (unsigned)ret.to.x == y_loc
850 && (unsigned)ret.to.y == x_loc)
851 button = PEGBOX_SAVE;
853 #endif
854 switch(button){
855 case PEGBOX_LEFT:
856 case (PEGBOX_LEFT|BUTTON_REPEAT):
857 case PEGBOX_DOWN:
858 case (PEGBOX_DOWN|BUTTON_REPEAT):
859 if (pb->playboard[x_loc][y_loc] < 5)
860 pb->playboard[x_loc][y_loc]++;
861 else
862 pb->playboard[x_loc][y_loc] = TRIANGLE;
863 break;
864 case PEGBOX_RIGHT:
865 case (PEGBOX_RIGHT|BUTTON_REPEAT):
866 case PEGBOX_UP:
867 case (PEGBOX_UP|BUTTON_REPEAT):
868 if (pb->playboard[x_loc][y_loc] > 2)
869 pb->playboard[x_loc][y_loc]--;
870 else
871 pb->playboard[x_loc][y_loc] = CIRCLE;
872 break;
873 case PEGBOX_SAVE:
874 exit = true;
875 break;
880 /*****************************************************************************
881 * move_player() moves the player and pieces and updates the board accordingly.
882 ******************************************************************************/
883 static void move_player(struct game_context* pb, signed int x_dir,
884 signed int y_dir) {
885 unsigned int type1, type2;
886 signed int r,c;
888 r = pb->player_row+y_dir;
889 c = pb->player_col+x_dir;
891 type1 = pb->playboard[r][c];
892 type2 = pb->playboard[r+y_dir][c+x_dir];
894 if (r == ROWS || c == COLS || r < 0 || c < 0 || type1 == WALL)
895 return;
896 else if(type1 != SPACE) {
897 if (type2 == WALL || r+y_dir == ROWS || c+x_dir == COLS ||
898 r+y_dir < 0 || c+x_dir < 0)
899 return;
903 pb->playboard[pb->player_row][pb->player_col] = SPACE;
904 pb->player_row += y_dir;
905 pb->player_col += x_dir;
907 if (type1 == HOLE) {
908 draw_board(pb);
909 rb->splash(HZ*2, "You fell down a hole!");
910 load_level(pb);
912 else if (type1 == SPACE)
913 pb->playboard[r][c] = PLAYER;
914 else {
915 pb->playboard[r][c] = PLAYER;
916 if(type1 == type2) {
917 if (type1 == TRIANGLE)
918 pb->playboard[r+y_dir][c+x_dir] = WALL;
919 else if (type1 == CROSS) {
920 pb->playboard[r][c] = SPACE;
921 new_piece(pb, r+y_dir, c+x_dir);
922 pb->playboard[r][c] = PLAYER;
924 else
925 pb->playboard[r+y_dir][c+x_dir] = SPACE;
927 else if (type2 == SPACE)
928 pb->playboard[r+y_dir][c+x_dir] = type1;
929 else if (type2 == HOLE) {
930 if (type1 == SQUARE)
931 pb->playboard[r+y_dir][c+x_dir] = SPACE;
933 else {
934 rb->splash(HZ*2, "Illegal Move!");
935 load_level(pb);
939 draw_board(pb);
942 /*****************************************************************************
943 * pegbox_loadgame() loads the saved game and returns load success.
944 ******************************************************************************/
945 static bool pegbox_loadgame(struct game_context* pb) {
946 signed int fd;
947 bool loaded = false;
949 /* open game file */
950 fd = rb->open(SAVE_FILE, O_RDONLY);
951 if(fd < 0) return loaded;
953 /* read in saved game */
954 while(true) {
955 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
956 if(rb->read(fd, &pb->playboard, sizeof(pb->playboard)) <= 0)
958 loaded = true;
959 break;
961 break;
964 rb->close(fd);
965 return loaded;
968 /*****************************************************************************
969 * pegbox_savegame() saves the current game state.
970 ******************************************************************************/
971 static void pegbox_savegame(struct game_context* pb) {
972 unsigned int fd;
974 /* write out the game state to the save file */
975 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
976 rb->write(fd, &pb->level, sizeof(pb->level));
977 rb->write(fd, &pb->playboard, sizeof(pb->playboard));
978 rb->close(fd);
981 /*****************************************************************************
982 * pegbox_loaddata() loads the level and highlevel and returns load success.
983 ******************************************************************************/
984 static void pegbox_loaddata(struct game_context* pb) {
985 signed int fd;
987 /* open game file */
988 fd = rb->open(DATA_FILE, O_RDONLY);
989 if(fd < 0) {
990 pb->level = 1;
991 pb->highlevel = 1;
992 return;
995 /* read in saved game */
996 while(true) {
997 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
998 if(rb->read(fd, &pb->highlevel, sizeof(pb->highlevel)) <= 0) break;
999 break;
1002 rb->close(fd);
1003 return;
1006 /*****************************************************************************
1007 * pegbox_savedata() saves the level and highlevel.
1008 ******************************************************************************/
1009 static void pegbox_savedata(struct game_context* pb) {
1010 unsigned int fd;
1012 /* write out the game state to the save file */
1013 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT);
1014 rb->write(fd, &pb->level, sizeof(pb->level));
1015 rb->write(fd, &pb->highlevel, sizeof(pb->highlevel));
1016 rb->close(fd);
1019 /*****************************************************************************
1020 * pegbox_callback() is the default event handler callback which is called
1021 * on usb connect and shutdown.
1022 ******************************************************************************/
1023 static void pegbox_callback(void* param) {
1024 struct game_context* pb = (struct game_context*) param;
1025 rb->splash(HZ, "Saving data...");
1026 pegbox_savedata(pb);
1029 /*****************************************************************************
1030 * pegbox_menu() is the initial menu at the start of the game.
1031 ******************************************************************************/
1032 static unsigned int pegbox_menu(struct game_context* pb) {
1033 int button;
1034 char str[30];
1035 unsigned int startlevel = 1, loc = 0;
1036 bool breakout = false, can_resume = false;
1038 if (pb->num_left > 0 || pb->save_exist)
1039 can_resume = true;
1041 while(!breakout){
1042 #if LCD_HEIGHT >= 80
1043 rb->lcd_clear_display();
1044 rb->lcd_bitmap(pegbox_menu_top,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_menu_top);
1046 /* menu bitmaps */
1047 if (loc == 0) {
1048 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT, ITEM_WIDTH,
1049 MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT);
1051 else {
1052 rb->lcd_bitmap_part(pegbox_menu_items, 0, 0, ITEM_WIDTH,
1053 MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT);
1055 if (can_resume) {
1056 if (loc == 1) {
1057 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*3, ITEM_WIDTH,
1058 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1060 else {
1061 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*2, ITEM_WIDTH,
1062 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1065 else {
1066 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*4, ITEM_WIDTH,
1067 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1070 if (loc==2) {
1071 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*6, ITEM_WIDTH,
1072 MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT);
1074 else {
1075 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*5, ITEM_WIDTH,
1076 MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT);
1079 if (loc==3) {
1080 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*8, ITEM_WIDTH,
1081 MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT);
1083 else {
1084 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*7, ITEM_WIDTH,
1085 MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT);
1087 #else
1088 unsigned int w,h;
1089 rb->lcd_clear_display();
1090 rb->lcd_getstringsize("PegBox", &w, &h);
1091 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, "PegBox");
1092 rb->lcd_putsxy((LCD_WIDTH)/4, 16, "New Game");
1093 rb->lcd_putsxy((LCD_WIDTH)/4, 24, "Resume");
1094 rb->lcd_putsxy((LCD_WIDTH)/4, 32, "Help");
1095 rb->lcd_putsxy((LCD_WIDTH)/4, 40, "Quit");
1097 if(!can_resume)
1098 rb->lcd_hline((LCD_WIDTH)/4, (LCD_WIDTH)/4+30, 28);
1100 rb->lcd_putsxy((LCD_WIDTH)/4-8, loc*8+16, "*");
1103 #endif
1104 rb->snprintf(str, 28, "Start on level %d of %d", startlevel,
1105 pb->highlevel);
1106 #if LCD_HEIGHT > 110
1107 rb->lcd_putsxy(0, MENU_Y+4*ITEM_HEIGHT+8, str);
1108 #elif LCD_HEIGHT > 64
1109 rb->lcd_putsxy(0, LCD_HEIGHT - 8, str);
1110 #else
1111 rb->lcd_puts_scroll(0, 7, str);
1112 #endif
1113 rb->lcd_update();
1115 /* handle menu button presses */
1116 button = rb->button_get(true);
1118 #ifdef HAVE_TOUCHSCREEN
1119 if(button & BUTTON_TOUCHSCREEN)
1121 unsigned int result = touchscreen_map(&main_menu,
1122 rb->button_get_data() >> 16,
1123 rb->button_get_data() & 0xffff);
1124 if(result != (unsigned)-1 && button & BUTTON_REL)
1126 if(result == 4)
1127 button = PEGBOX_LVL_UP;
1128 else
1130 if(loc == result)
1131 button = PEGBOX_RIGHT;
1132 loc = result;
1136 #endif
1138 switch(button) {
1139 case PEGBOX_SAVE: /* start playing */
1140 case PEGBOX_RIGHT:
1141 if (loc == 0) {
1142 breakout = true;
1143 pb->level = startlevel;
1144 load_level(pb);
1146 else if (loc == 1 && can_resume) {
1147 if(pb->save_exist)
1149 rb->remove(SAVE_FILE);
1150 pb->save_exist = false;
1152 breakout = true;
1154 else if (loc == 2)
1155 display_text("How to Play\nTo beat each level, you must "
1156 "destroy all of the pegs. If two like pegs are "
1157 "pushed into each other they disappear except "
1158 "for triangles which form a solid block and "
1159 "crosses which allow you to choose a "
1160 "replacement block.\n\n"
1161 "Controls\n"
1162 #if LCD_HEIGHT > 64
1163 RESTART_TEXT " to restart level\n"
1164 LVL_UP_TEXT " to go up a level\n"
1165 LVL_DOWN_TEXT " to go down a level\n"
1166 SAVE_TEXT " to select/save\n"
1167 QUIT_TEXT " to quit\n",true);
1168 #else
1169 RESTART_TEXT ": restart\n"
1170 LVL_UP_TEXT ": level up\n"
1171 LVL_DOWN_TEXT " level down\n"
1172 SAVE_TEXT " select/save\n"
1173 QUIT_TEXT " quit\n",true);
1174 #endif
1175 else if (loc == 3)
1176 return PB_QUIT;
1177 break;
1179 case PEGBOX_QUIT: /* quit program */
1180 return PB_QUIT;
1182 case (PEGBOX_UP|BUTTON_REPEAT):
1183 case PEGBOX_UP:
1184 if (loc <= 0)
1185 loc = 3;
1186 else
1187 loc--;
1188 if (!can_resume && loc == 1) {
1189 loc = 0;
1191 break;
1194 case (PEGBOX_DOWN|BUTTON_REPEAT):
1195 case PEGBOX_DOWN:
1196 if (loc >= 3)
1197 loc = 0;
1198 else
1199 loc++;
1200 if (!can_resume && loc == 1) {
1201 loc = 2;
1203 break;
1205 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1206 case PEGBOX_LVL_UP: /* increase starting level */
1207 if(startlevel >= pb->highlevel) {
1208 startlevel = 1;
1209 } else {
1210 startlevel++;
1212 break;
1214 /* only for targets with enough buttons */
1215 #ifdef PEGBOX_LVL_DOWN
1216 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1217 case PEGBOX_LVL_DOWN: /* decrease starting level */
1218 if(startlevel <= 1) {
1219 startlevel = pb->highlevel;
1220 } else {
1221 startlevel--;
1223 break;
1224 #endif
1225 default:
1226 if(rb->default_event_handler_ex(button, pegbox_callback,
1227 (void*) pb) == SYS_USB_CONNECTED)
1228 return PB_USB;
1229 break;
1233 draw_board(pb);
1235 return 0;
1238 /*****************************************************************************
1239 * pegbox() is the main game subroutine, it returns the final game status.
1240 ******************************************************************************/
1241 static int pegbox(struct game_context* pb) {
1242 int temp_var;
1244 /********************
1245 * menu *
1246 ********************/
1247 temp_var = pegbox_menu(pb);
1248 if (temp_var == PB_QUIT || temp_var == PB_USB)
1249 return temp_var;
1251 while (true) {
1252 temp_var = rb->button_get(true);
1253 #ifdef HAVE_TOUCHSCREEN
1254 if(temp_var & BUTTON_TOUCHSCREEN)
1256 pegbox_raster_btn.two_d_from.y = pb->player_row;
1257 pegbox_raster_btn.two_d_from.x = pb->player_col;
1259 struct ts_raster_button_result ret =
1260 touchscreen_raster_map_button(&pegbox_raster_btn,
1261 rb->button_get_data() >> 16,
1262 rb->button_get_data() & 0xffff,
1263 temp_var);
1264 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
1265 move_player(pb, ret.to.x - ret.from.x, ret.to.y - ret.from.y);
1267 #endif
1268 switch(temp_var){
1269 case PEGBOX_LEFT: /* move cursor left */
1270 case (PEGBOX_LEFT|BUTTON_REPEAT):
1271 move_player(pb, -1, 0);
1272 break;
1274 case PEGBOX_RIGHT: /* move cursor right */
1275 case (PEGBOX_RIGHT|BUTTON_REPEAT):
1276 move_player(pb, 1, 0);
1277 break;
1279 case PEGBOX_DOWN: /* move cursor down */
1280 case (PEGBOX_DOWN|BUTTON_REPEAT):
1281 move_player(pb, 0, 1);
1282 break;
1284 case PEGBOX_UP: /* move cursor up */
1285 case (PEGBOX_UP|BUTTON_REPEAT):
1286 move_player(pb, 0, -1);
1287 break;
1289 case PEGBOX_SAVE: /* save and end game */
1290 rb->splash(HZ, "Saving game...");
1291 pegbox_savegame(pb);
1292 /* fall through to PEGBOX_QUIT */
1294 case PEGBOX_QUIT:
1295 return PB_END;
1297 case PEGBOX_RESTART:
1298 load_level(pb);
1299 draw_board(pb);
1300 break;
1302 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1303 case PEGBOX_LVL_UP:
1304 if(pb->level >= pb->highlevel) {
1305 pb->level = 1;
1306 } else {
1307 pb->level++;
1309 load_level(pb);
1310 draw_board(pb);
1311 break;
1313 /* only for targets with enough buttons */
1314 #ifdef PEGBOX_LVL_DOWN
1315 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1316 case PEGBOX_LVL_DOWN:
1317 if(pb->level <= 1) {
1318 pb->level = pb->highlevel;
1319 } else {
1320 pb->level--;
1322 load_level(pb);
1323 draw_board(pb);
1324 break;
1325 #endif
1329 if(pb->num_left == 0) {
1330 rb->splash(HZ*2, "Nice Pegging!");
1331 if(pb->level == NUM_LEVELS) {
1332 draw_board(pb);
1333 rb->splash(HZ*2, "You Won!");
1334 break;
1336 else {
1337 pb->level++;
1338 load_level(pb);
1339 draw_board(pb);
1342 if(pb->level > pb->highlevel)
1343 pb->highlevel = pb->level;
1348 return PLUGIN_OK;
1352 /*****************************************************************************
1353 * plugin entry point.
1354 ******************************************************************************/
1355 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter) {
1356 bool exit = false;
1357 struct game_context pb;
1359 (void)parameter;
1360 rb = api;
1362 rb->lcd_setfont(FONT_SYSFIXED);
1363 #if LCD_DEPTH > 1
1364 rb->lcd_set_backdrop(NULL);
1365 #endif
1366 #ifdef HAVE_LCD_COLOR
1367 rb->lcd_set_foreground(LCD_WHITE);
1368 rb->lcd_set_background(BG_COLOR);
1369 #endif
1371 rb->splash(0, "Loading...");
1372 pegbox_loaddata(&pb);
1373 pb.save_exist = pegbox_loadgame(&pb);
1374 pb.num_left = 0;
1376 rb->lcd_clear_display();
1379 while(!exit) {
1380 switch(pegbox(&pb)){
1381 case PB_END:
1382 break;
1384 case PB_USB:
1385 rb->lcd_setfont(FONT_UI);
1386 return PLUGIN_USB_CONNECTED;
1388 case PB_QUIT:
1389 rb->splash(HZ, "Saving data...");
1390 pegbox_savedata(&pb);
1391 exit = true;
1392 break;
1394 default:
1395 break;
1399 rb->lcd_setfont(FONT_UI);
1400 return PLUGIN_OK;