Reverting parts of r19760 that was mistakenly committed.
[kugel-rb.git] / apps / plugins / pegbox.c
blob25f8adfbed4967f9b987da44c7d7903d1fcb21e7
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 /* FIXME: USE PLUGIN_GAMES_DIR */
45 #define DATA_FILE PLUGIN_DIR "/games/pegbox.data"
46 #define SAVE_FILE PLUGIN_DIR "/games/pegbox.save"
48 #define ROWS 8 /* Number of rows on each board */
49 #define COLS 12 /* Number of columns on each board */
50 #define NUM_LEVELS 15 /* Number of levels */
52 #define SPACE 0
53 #define WALL 1
54 #define TRIANGLE 2
55 #define CROSS 3
56 #define SQUARE 4
57 #define CIRCLE 5
58 #define HOLE 6
59 #define PLAYER 7
61 #if CONFIG_KEYPAD == RECORDER_PAD
62 #define PEGBOX_SAVE BUTTON_ON
63 #define PEGBOX_QUIT BUTTON_OFF
64 #define PEGBOX_RESTART BUTTON_F2
65 #define PEGBOX_LVL_UP BUTTON_F1
66 #define PEGBOX_LVL_DOWN BUTTON_F3
67 #define PEGBOX_UP BUTTON_UP
68 #define PEGBOX_DOWN BUTTON_DOWN
69 #define PEGBOX_RIGHT BUTTON_RIGHT
70 #define PEGBOX_LEFT BUTTON_LEFT
72 #define SAVE_TEXT "ON"
73 #define QUIT_TEXT "OFF"
74 #define RESTART_TEXT "F2"
75 #define LVL_UP_TEXT "F1"
76 #define LVL_DOWN_TEXT "F3"
78 #elif CONFIG_KEYPAD == ONDIO_PAD
79 #define PEGBOX_SAVE BUTTON_OFF
80 #define PEGBOX_QUIT (BUTTON_MENU | BUTTON_LEFT)
81 #define PEGBOX_RESTART (BUTTON_MENU | BUTTON_RIGHT)
82 #define PEGBOX_LVL_UP (BUTTON_MENU | BUTTON_UP)
83 #define PEGBOX_LVL_DOWN (BUTTON_MENU | BUTTON_DOWN)
84 #define PEGBOX_UP BUTTON_UP
85 #define PEGBOX_DOWN BUTTON_DOWN
86 #define PEGBOX_RIGHT BUTTON_RIGHT
87 #define PEGBOX_LEFT BUTTON_LEFT
89 #define SAVE_TEXT "OFF"
90 #define QUIT_TEXT "M+LEFT"
91 #define RESTART_TEXT "M+RIGHT"
92 #define LVL_UP_TEXT "M+UP"
93 #define LVL_DOWN_TEXT "M+DOWN"
95 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
96 (CONFIG_KEYPAD == IRIVER_H300_PAD)
97 #define PEGBOX_SAVE BUTTON_SELECT
98 #define PEGBOX_QUIT BUTTON_OFF
99 #define PEGBOX_RESTART BUTTON_ON
100 #define PEGBOX_LVL_UP BUTTON_MODE
101 #define PEGBOX_LVL_DOWN BUTTON_REC
102 #define PEGBOX_UP BUTTON_UP
103 #define PEGBOX_DOWN BUTTON_DOWN
104 #define PEGBOX_RIGHT BUTTON_RIGHT
105 #define PEGBOX_LEFT BUTTON_LEFT
107 #define SAVE_TEXT "NAVI"
108 #define QUIT_TEXT "OFF"
109 #define RESTART_TEXT "ON"
110 #define LVL_UP_TEXT "AB"
111 #define LVL_DOWN_TEXT "REC"
113 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
114 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
115 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
116 #define PEGBOX_SAVE (BUTTON_SELECT|BUTTON_RIGHT)
117 #define PEGBOX_QUIT (BUTTON_SELECT|BUTTON_PLAY)
118 #define PEGBOX_RESTART (BUTTON_SELECT|BUTTON_LEFT)
119 #define PEGBOX_LVL_UP (BUTTON_SELECT|BUTTON_MENU)
120 #define PEGBOX_UP BUTTON_MENU
121 #define PEGBOX_DOWN BUTTON_PLAY
122 #define PEGBOX_RIGHT BUTTON_RIGHT
123 #define PEGBOX_LEFT BUTTON_LEFT
125 #define SAVE_TEXT "SELECT+RIGHT"
126 #define QUIT_TEXT "SELECT+PLAY"
127 #define RESTART_TEXT "SELECT+LEFT"
128 #define LVL_UP_TEXT "SELECT+MENU"
129 #define LVL_DOWN_TEXT "-"
131 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
132 #define PEGBOX_SAVE BUTTON_SELECT
133 #define PEGBOX_QUIT BUTTON_POWER
134 #define PEGBOX_RESTART BUTTON_REC
135 #define PEGBOX_LVL_UP BUTTON_PLAY
136 #define PEGBOX_UP BUTTON_UP
137 #define PEGBOX_DOWN BUTTON_DOWN
138 #define PEGBOX_RIGHT BUTTON_RIGHT
139 #define PEGBOX_LEFT BUTTON_LEFT
141 #define SAVE_TEXT "SELECT"
142 #define QUIT_TEXT "OFF"
143 #define RESTART_TEXT "REC"
144 #define LVL_UP_TEXT "PLAY"
145 #define LVL_DOWN_TEXT "-"
147 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
148 #define PEGBOX_SAVE BUTTON_MODE
149 #define PEGBOX_QUIT BUTTON_PLAY
150 #define PEGBOX_RESTART (BUTTON_EQ|BUTTON_MODE)
151 #define PEGBOX_LVL_UP (BUTTON_EQ|BUTTON_UP)
152 #define PEGBOX_LVL_DOWN (BUTTON_EQ|BUTTON_DOWN)
153 #define PEGBOX_UP BUTTON_UP
154 #define PEGBOX_DOWN BUTTON_DOWN
155 #define PEGBOX_RIGHT BUTTON_RIGHT
156 #define PEGBOX_LEFT BUTTON_LEFT
158 #define SAVE_TEXT "MODE"
159 #define QUIT_TEXT "PLAY"
160 #define RESTART_TEXT "EQ+MODE"
161 #define LVL_UP_TEXT "EQ+UP"
162 #define LVL_DOWN_TEXT "EQ+DOWN"
164 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
165 #define PEGBOX_SAVE BUTTON_PLAY
166 #define PEGBOX_QUIT BUTTON_POWER
167 #define PEGBOX_RESTART (BUTTON_FF|BUTTON_REPEAT)
168 #define PEGBOX_LVL_UP (BUTTON_FF|BUTTON_SCROLL_UP)
169 #define PEGBOX_LVL_DOWN (BUTTON_FF|BUTTON_SCROLL_DOWN)
170 #define PEGBOX_UP BUTTON_SCROLL_UP
171 #define PEGBOX_DOWN BUTTON_SCROLL_DOWN
172 #define PEGBOX_RIGHT BUTTON_RIGHT
173 #define PEGBOX_LEFT BUTTON_LEFT
175 #define SAVE_TEXT "PLAY"
176 #define QUIT_TEXT "OFF"
177 #define RESTART_TEXT "LONG FF"
178 #define LVL_UP_TEXT "FF+SCROLL_UP"
179 #define LVL_DOWN_TEXT "FF+SCROLL_DOWN"
181 #elif CONFIG_KEYPAD == SANSA_E200_PAD
182 #define PEGBOX_SAVE BUTTON_SELECT
183 #define PEGBOX_QUIT BUTTON_POWER
184 #define PEGBOX_RESTART BUTTON_REC
185 #define PEGBOX_LVL_UP BUTTON_SCROLL_BACK
186 #define PEGBOX_LVL_DOWN BUTTON_SCROLL_FWD
187 #define PEGBOX_UP BUTTON_UP
188 #define PEGBOX_DOWN BUTTON_DOWN
189 #define PEGBOX_RIGHT BUTTON_RIGHT
190 #define PEGBOX_LEFT BUTTON_LEFT
192 #define SAVE_TEXT "SELECT"
193 #define QUIT_TEXT "POWER"
194 #define RESTART_TEXT "REC"
195 #define LVL_UP_TEXT "SCROLL BACK"
196 #define LVL_DOWN_TEXT "SCROLL FWD"
198 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
199 #define PEGBOX_SAVE BUTTON_SELECT|BUTTON_REL
200 #define PEGBOX_QUIT BUTTON_POWER
201 /* FIXME:
202 #define PEGBOX_RESTART BUTTON_HOME */
203 #define PEGBOX_RESTART BUTTON_SELECT|BUTTON_LEFT
204 #define PEGBOX_LVL_UP BUTTON_SCROLL_BACK
205 #define PEGBOX_LVL_DOWN BUTTON_SCROLL_FWD
206 #define PEGBOX_UP BUTTON_UP
207 #define PEGBOX_DOWN BUTTON_DOWN
208 #define PEGBOX_RIGHT BUTTON_RIGHT
209 #define PEGBOX_LEFT BUTTON_LEFT
211 #define SAVE_TEXT "SELECT"
212 #define QUIT_TEXT "POWER"
213 #define RESTART_TEXT "SELECT & LEFT"
214 #define LVL_UP_TEXT "SCROLL BACK"
215 #define LVL_DOWN_TEXT "SCROLL FWD"
217 #elif CONFIG_KEYPAD == GIGABEAT_PAD
218 #define PEGBOX_SAVE BUTTON_SELECT
219 #define PEGBOX_QUIT BUTTON_POWER
220 #define PEGBOX_RESTART BUTTON_A
221 #define PEGBOX_LVL_UP BUTTON_VOL_UP
222 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
223 #define PEGBOX_UP BUTTON_UP
224 #define PEGBOX_DOWN BUTTON_DOWN
225 #define PEGBOX_RIGHT BUTTON_RIGHT
226 #define PEGBOX_LEFT BUTTON_LEFT
228 #define SAVE_TEXT "SELECT"
229 #define QUIT_TEXT "POWER"
230 #define RESTART_TEXT "A"
231 #define LVL_UP_TEXT "VOL+"
232 #define LVL_DOWN_TEXT "VOL-"
234 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
235 #define PEGBOX_SAVE BUTTON_SELECT
236 #define PEGBOX_QUIT BUTTON_BACK
237 #define PEGBOX_RESTART BUTTON_MENU
238 #define PEGBOX_LVL_UP BUTTON_VOL_UP
239 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
240 #define PEGBOX_UP BUTTON_UP
241 #define PEGBOX_DOWN BUTTON_DOWN
242 #define PEGBOX_RIGHT BUTTON_RIGHT
243 #define PEGBOX_LEFT BUTTON_LEFT
245 #define SAVE_TEXT "SELECT"
246 #define QUIT_TEXT "BACK"
247 #define RESTART_TEXT "MENU"
248 #define LVL_UP_TEXT "VOL+"
249 #define LVL_DOWN_TEXT "VOL-"
251 #elif CONFIG_KEYPAD == MROBE100_PAD
252 #define PEGBOX_SAVE BUTTON_SELECT
253 #define PEGBOX_QUIT BUTTON_POWER
254 #define PEGBOX_RESTART BUTTON_PLAY
255 #define PEGBOX_LVL_UP BUTTON_MENU
256 #define PEGBOX_LVL_DOWN BUTTON_DISPLAY
257 #define PEGBOX_UP BUTTON_UP
258 #define PEGBOX_DOWN BUTTON_DOWN
259 #define PEGBOX_RIGHT BUTTON_RIGHT
260 #define PEGBOX_LEFT BUTTON_LEFT
262 #define SAVE_TEXT "SELECT"
263 #define QUIT_TEXT "POWER"
264 #define RESTART_TEXT "PLAY"
265 #define LVL_UP_TEXT "MENU"
266 #define LVL_DOWN_TEXT "DISPLAY"
268 #elif CONFIG_KEYPAD == SANSA_C200_PAD
269 #define PEGBOX_SAVE BUTTON_SELECT
270 #define PEGBOX_QUIT BUTTON_POWER
271 #define PEGBOX_RESTART BUTTON_REC
272 #define PEGBOX_LVL_UP BUTTON_VOL_UP
273 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
274 #define PEGBOX_UP BUTTON_UP
275 #define PEGBOX_DOWN BUTTON_DOWN
276 #define PEGBOX_RIGHT BUTTON_RIGHT
277 #define PEGBOX_LEFT BUTTON_LEFT
279 #define SAVE_TEXT "SELECT"
280 #define QUIT_TEXT "POWER"
281 #define RESTART_TEXT "REC"
282 #define LVL_UP_TEXT "VOL+"
283 #define LVL_DOWN_TEXT "VOL-"
285 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
286 #define PEGBOX_SAVE BUTTON_SELECT
287 #define PEGBOX_QUIT BUTTON_POWER
288 #define PEGBOX_RESTART BUTTON_HOME
289 #define PEGBOX_LVL_UP BUTTON_VOL_UP
290 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
291 #define PEGBOX_UP BUTTON_UP
292 #define PEGBOX_DOWN BUTTON_DOWN
293 #define PEGBOX_RIGHT BUTTON_RIGHT
294 #define PEGBOX_LEFT BUTTON_LEFT
296 #define SAVE_TEXT "SELECT"
297 #define QUIT_TEXT "POWER"
298 #define RESTART_TEXT "HOME"
299 #define LVL_UP_TEXT "VOL+"
300 #define LVL_DOWN_TEXT "VOL-"
302 #elif CONFIG_KEYPAD == SANSA_M200_PAD
303 #define PEGBOX_SAVE (BUTTON_SELECT | BUTTON_REL)
304 #define PEGBOX_QUIT BUTTON_POWER
305 #define PEGBOX_RESTART (BUTTON_SELECT | BUTTON_UP)
306 #define PEGBOX_LVL_UP BUTTON_VOL_UP
307 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
308 #define PEGBOX_UP BUTTON_UP
309 #define PEGBOX_DOWN BUTTON_DOWN
310 #define PEGBOX_RIGHT BUTTON_RIGHT
311 #define PEGBOX_LEFT BUTTON_LEFT
313 #define SAVE_TEXT "SELECT"
314 #define QUIT_TEXT "POWER"
315 #define RESTART_TEXT "SELECT+UP"
316 #define LVL_UP_TEXT "VOL+"
317 #define LVL_DOWN_TEXT "VOL-"
320 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
321 #define PEGBOX_SAVE BUTTON_RC_PLAY
322 #define PEGBOX_QUIT BUTTON_RC_REC
323 #define PEGBOX_RESTART BUTTON_RC_MODE
324 #define PEGBOX_LVL_UP BUTTON_VOL_UP
325 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
326 #define PEGBOX_UP BUTTON_RC_VOL_UP
327 #define PEGBOX_DOWN BUTTON_RC_VOL_DOWN
328 #define PEGBOX_RIGHT BUTTON_RC_FF
329 #define PEGBOX_LEFT BUTTON_RC_REW
331 #define SAVE_TEXT "REM. PLAY"
332 #define QUIT_TEXT "REM. REC"
333 #define RESTART_TEXT "REM. MODE"
334 #define LVL_UP_TEXT "VOL+"
335 #define LVL_DOWN_TEXT "VOL-"
337 #elif CONFIG_KEYPAD == COWOND2_PAD
338 #define PEGBOX_QUIT BUTTON_POWER
340 #define QUIT_TEXT "POWER"
342 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
343 #define PEGBOX_SAVE BUTTON_CUSTOM
344 #define PEGBOX_QUIT BUTTON_BACK
345 #define PEGBOX_RESTART BUTTON_SELECT
346 #define PEGBOX_LVL_UP BUTTON_PLAY
347 #define PEGBOX_LVL_DOWN BUTTON_MENU
348 #define PEGBOX_UP BUTTON_UP
349 #define PEGBOX_DOWN BUTTON_DOWN
350 #define PEGBOX_RIGHT BUTTON_RIGHT
351 #define PEGBOX_LEFT BUTTON_LEFT
353 #define SAVE_TEXT "CUSTOM"
354 #define QUIT_TEXT "BACK"
355 #define RESTART_TEXT "MIDDLE"
356 #define LVL_UP_TEXT "SELECT"
357 #define LVL_DOWN_TEXT "MENU"
359 #else
360 #error Unsupported keymap!
361 #endif
363 #ifdef HAVE_TOUCHSCREEN
364 #ifndef PEGBOX_QUIT
365 #define PEGBOX_QUIT BUTTON_TOPLEFT
366 #endif
367 #ifndef PEGBOX_SAVE
368 #define PEGBOX_SAVE BUTTON_CENTER
369 #endif
370 #ifndef PEGBOX_RESTART
371 #define PEGBOX_RESTART BUTTON_TOPRIGHT
372 #endif
373 #ifndef PEGBOX_LVL_UP
374 #define PEGBOX_LVL_UP BUTTON_BOTTOMLEFT
375 #endif
376 #ifndef PEGBOX_LVL_DOWN
377 #define PEGBOX_LVL_DOWN BUTTON_BOTTOMRIGHT
378 #endif
379 #ifndef PEGBOX_UP
380 #define PEGBOX_UP BUTTON_TOPMIDDLE
381 #endif
382 #ifndef PEGBOX_DOWN
383 #define PEGBOX_DOWN BUTTON_BOTTOMMIDDLE
384 #endif
385 #ifndef PEGBOX_RIGHT
386 #define PEGBOX_RIGHT BUTTON_MIDRIGHT
387 #endif
388 #ifndef PEGBOX_LEFT
389 #define PEGBOX_LEFT BUTTON_MIDLEFT
390 #endif
391 #ifndef SAVE_TEXT
392 #define SAVE_TEXT "CENTER"
393 #endif
394 #ifndef QUIT_TEXT
395 #define QUIT_TEXT "TOPLEFT"
396 #endif
397 #ifndef RESTART_TEXT
398 #define RESTART_TEXT "TOPRIGHT"
399 #endif
400 #ifndef LVL_UP_TEXT
401 #define LVL_UP_TEXT "BOTTOMLEFT"
402 #endif
403 #ifndef LVL_DOWN_TEXT
404 #define LVL_DOWN_TEXT "BOTTOMRIGHT"
405 #endif
406 #endif
409 /* get several sizes from the bitmaps */
410 #ifdef BMPWIDTH_pegbox_pieces
411 #define PIECE_WIDTH BMPWIDTH_pegbox_pieces
412 #define PIECE_HEIGHT (BMPHEIGHT_pegbox_pieces/7)
413 #else
414 /* dummy numbers to avoid #error in dependency generation */
415 #define PIECE_WIDTH 50
416 #define PIECE_HEIGHT 10
417 #endif
419 #define BOARD_WIDTH (12*PIECE_WIDTH)
420 #define BOARD_HEIGHT (8*PIECE_HEIGHT)
423 /* define a wide layout where the statistics are alongside the board, not above
424 * base calculation on the piece bitmaps for the 8x12 board */
425 #if (LCD_WIDTH - BOARD_WIDTH) > (LCD_HEIGHT - BOARD_HEIGHT)
426 #define WIDE_LAYOUT
427 #endif
430 #define HEADER_WIDTH BMPWIDTH_pegbox_header
431 #define HEADER_HEIGHT BMPHEIGHT_pegbox_header
434 #if defined WIDE_LAYOUT
436 #if ((BOARD_WIDTH + HEADER_WIDTH + 4) <= LCD_WIDTH)
437 #define BOARD_X 2
438 #else
439 #define BOARD_X 1
440 #endif
441 #define BOARD_Y (LCD_HEIGHT-BOARD_HEIGHT)/2
443 #if (LCD_WIDTH >= 132) && (LCD_HEIGHT >= 80)
444 #define TEXT_X 116
445 #define LEVEL_TEXT_Y 14
446 #define PEGS_TEXT_Y 58
447 #elif (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 64)
448 #define TEXT_X 114
449 #define LEVEL_TEXT_Y 14
450 #define PEGS_TEXT_Y 58
451 #else
452 #error "Unsupported screen size"
453 #endif
455 #else /* "normal" layout */
457 #define BOARD_X (LCD_WIDTH-BOARD_WIDTH)/2
458 #if ((BOARD_HEIGHT + HEADER_HEIGHT + 4) <= LCD_HEIGHT)
459 #define BOARD_Y HEADER_HEIGHT+2
460 #else
461 #define BOARD_Y HEADER_HEIGHT
462 #endif
464 #if LCD_WIDTH >= 320
465 #define LEVEL_TEXT_X 59
466 #define PEGS_TEXT_X 276
467 #define TEXT_Y 28
468 #elif LCD_WIDTH >= 240
469 #define LEVEL_TEXT_X 59
470 #define PEGS_TEXT_X 196
471 #define TEXT_Y 28
472 #elif LCD_WIDTH >= 220
473 #define LEVEL_TEXT_X 49
474 #define PEGS_TEXT_X 186
475 #define TEXT_Y 28
476 #elif LCD_WIDTH >= 176
477 #define LEVEL_TEXT_X 38
478 #define PEGS_TEXT_X 155
479 #define TEXT_Y 17
480 #elif LCD_WIDTH >= 160
481 #define LEVEL_TEXT_X 37
482 #define PEGS_TEXT_X 140
483 #define TEXT_Y 13
484 #elif LCD_WIDTH >= 138
485 #define LEVEL_TEXT_X 28
486 #define PEGS_TEXT_X 119
487 #define TEXT_Y 15
488 #elif LCD_WIDTH >= 128
489 #if HEADER_HEIGHT > 16
490 #define LEVEL_TEXT_X 26
491 #define PEGS_TEXT_X 107
492 #define TEXT_Y 31
493 #else
494 #define LEVEL_TEXT_X 15
495 #define PEGS_TEXT_X 100
496 #define TEXT_Y 5
497 #endif /* HEADER_HEIGHT */
498 #elif LCD_WIDTH >= 112
499 #define LEVEL_TEXT_X 25
500 #define PEGS_TEXT_X 90
501 #define TEXT_Y 0
502 #endif /* LCD_WIDTH */
504 #endif /* WIDE_LAYOUT */
507 #ifdef HAVE_LCD_COLOR
508 #define BG_COLOR LCD_BLACK
509 #define TEXT_BG LCD_RGBPACK(189,189,189)
510 #endif
513 #ifdef HAVE_TOUCHSCREEN
514 #include "lib/touchscreen.h"
516 static struct ts_mapping main_menu_items[5] =
518 {MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT},
519 {MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT},
520 {MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT},
521 {MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT},
523 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT > 110)
524 0, MENU_Y+4*ITEM_HEIGHT+8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
525 #elif LCD_WIDTH > 112
526 0, LCD_HEIGHT - 8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
527 #else
528 #error "Touchscreen isn't supported on non-bitmap screens!"
529 #endif
533 static struct ts_mappings main_menu = {main_menu_items, 5};
535 static struct ts_raster pegbox_raster =
536 { BOARD_X, BOARD_Y, COLS*PIECE_WIDTH, ROWS*PIECE_HEIGHT,
537 PIECE_WIDTH, PIECE_HEIGHT };
538 static struct ts_raster_button_mapping pegbox_raster_btn =
539 { &pegbox_raster, false, false, true, false, true, {0, 0}, 0, 0, 0 };
540 #endif
542 struct game_context {
543 unsigned int level;
544 unsigned int highlevel;
545 signed int player_row;
546 signed int player_col;
547 unsigned int num_left;
548 bool save_exist;
549 unsigned int playboard[ROWS][COLS];
552 char levels[NUM_LEVELS][ROWS][COLS] = {
553 /* Level 1 */
554 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
555 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
556 {1, 0, 0, 0, 7, 0, 0, 5, 0, 0, 0, 1,},
557 {1, 0, 0, 0, 0, 3, 3, 2, 0, 0, 0, 1,},
558 {1, 0, 0, 0, 4, 6, 0, 5, 0, 0, 0, 1,},
559 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
560 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
561 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
563 /* Level 2 */
564 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
565 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,},
566 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
567 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
568 {7, 0, 0, 0, 2, 2, 5, 5, 0, 0, 0, 1,},
569 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
570 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
571 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,}},
573 /* Level 3 */
574 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
575 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
576 {1, 0, 0, 0, 0, 0, 2, 0, 7, 0, 0, 0,},
577 {1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 2, 1,},
578 {1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1,},
579 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,},
580 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
581 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
583 /* Level 4 */
584 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
585 {6, 0, 4, 0, 2, 0, 2, 0, 0, 0, 0, 1,},
586 {6, 0, 3, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
587 {6, 0, 5, 0, 4, 7, 2, 0, 0, 0, 0, 1,},
588 {6, 0, 2, 0, 4, 0, 2, 0, 3, 0, 0, 1,},
589 {6, 0, 4, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
590 {6, 0, 5, 0, 4, 0, 2, 0, 0, 0, 0, 1,},
591 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
593 /* Level 5 */
594 {{0, 6, 6, 0, 4, 6, 0, 0, 6, 0, 0, 0,},
595 {0, 6, 6, 0, 4, 4, 0, 0, 6, 0, 0, 2,},
596 {2, 6, 6, 0, 6, 6, 6, 0, 1, 2, 2, 2,},
597 {0, 6, 6, 0, 6, 4, 6, 0, 1, 2, 0, 2,},
598 {0, 6, 6, 0, 6, 7, 6, 5, 6, 0, 0, 0,},
599 {2, 6, 6, 0, 6, 6, 6, 0, 6, 0, 0, 0,},
600 {0, 6, 6, 0, 4, 0, 0, 0, 6, 0, 0, 0,},
601 {0, 6, 6, 0, 0, 5, 0, 0, 6, 5, 5, 0,}},
603 /* Level 6 */
604 {{7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
605 {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,},
606 {2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0,},
607 {0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 0,},
608 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
609 {0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1,},
610 {0, 3, 0, 0, 0, 0, 0, 0, 5, 4, 6, 0,},
611 {0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1,}},
613 /* Level 7 */
614 {{1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,},
615 {1, 1, 1, 6, 0, 0, 4, 6, 0, 1, 1, 1,},
616 {1, 1, 1, 1, 0, 1, 5, 1, 0, 1, 1, 1,},
617 {1, 1, 1, 2, 3, 3, 7, 4, 2, 6, 1, 1,},
618 {1, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1,},
619 {1, 1, 1, 1, 0, 0, 5, 0, 0, 1, 0, 1,},
620 {1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,},
621 {1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,}},
623 /* Level 8 */
624 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
625 {0, 0, 3, 3, 3, 3, 3, 4, 3, 3, 0, 0,},
626 {0, 0, 3, 3, 3, 2, 3, 3, 5, 3, 0, 0,},
627 {7, 0, 3, 3, 3, 2, 3, 3, 4, 3, 0, 0,},
628 {0, 0, 3, 3, 4, 5, 3, 3, 3, 3, 0, 0,},
629 {0, 0, 3, 3, 5, 2, 3, 3, 3, 3, 0, 0,},
630 {0, 0, 3, 3, 2, 4, 3, 3, 3, 3, 0, 0,},
631 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
633 /* Level 9 */
634 {{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
635 {0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
636 {0, 0, 0, 0, 2, 4, 4, 3, 0, 1, 1, 0,},
637 {0, 1, 0, 0, 2, 1, 0, 0, 0, 1, 1, 1,},
638 {0, 0, 0, 2, 2, 7, 1, 0, 0, 0, 0, 2,},
639 {0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 1, 1,},
640 {0, 3, 1, 0, 2, 5, 5, 0, 0, 0, 3, 0,},
641 {0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0,}},
643 /* Level 10 */
644 {{1, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0,},
645 {1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 7,},
646 {0, 0, 4, 0, 6, 6, 6, 0, 0, 0, 3, 0,},
647 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
648 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
649 {0, 0, 0, 0, 6, 6, 6, 0, 3, 0, 0, 0,},
650 {1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0,},
651 {1, 1, 1, 1, 1, 2, 1, 1, 0, 0, 0, 0,}},
653 /* Level 11 */
654 {{1, 7, 1, 0, 1, 1, 6, 0, 0, 1, 1, 0,},
655 {1, 0, 0, 0, 5, 4, 6, 6, 0, 2, 2, 0,},
656 {1, 2, 1, 2, 0, 1, 6, 0, 0, 2, 2, 0,},
657 {1, 0, 0, 2, 0, 1, 0, 0, 0, 3, 3, 0,},
658 {1, 2, 1, 0, 0, 1, 0, 1, 0, 3, 3, 0,},
659 {0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0,},
660 {0, 3, 4, 3, 0, 1, 0, 1, 0, 0, 0, 0,},
661 {0, 0, 0, 0, 2, 2, 2, 1, 1, 1, 1, 1,}},
663 /* Level 12 */
664 {{7, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,},
665 {1, 2, 1, 2, 1, 2, 1, 1, 0, 0, 0, 1,},
666 {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,},
667 {1, 2, 1, 2, 1, 2, 1, 0, 0, 0, 0, 1,},
668 {0, 0, 0, 0, 0, 0, 1, 1, 5, 5, 6, 1,},
669 {1, 2, 1, 2, 1, 2, 1, 1, 0, 2, 2, 1,},
670 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1,},
671 {1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,}},
673 /* Level 13 */
674 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
675 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
676 {0, 0, 2, 0, 5, 0, 2, 0, 4, 0, 0, 6,},
677 {7, 0, 3, 0, 4, 0, 5, 0, 4, 0, 0, 6,},
678 {0, 0, 5, 0, 4, 0, 2, 0, 4, 0, 0, 6,},
679 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
680 {0, 0, 3, 0, 3, 0, 2, 0, 4, 0, 0, 6,},
681 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
683 /* Level 14 */
684 {{1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,},
685 {1, 1, 0, 2, 0, 0, 4, 0, 0, 2, 0, 1,},
686 {1, 6, 0, 0, 5, 1, 0, 1, 1, 0, 0, 1,},
687 {1, 1, 1, 0, 0, 3, 5, 3, 0, 0, 1, 1,},
688 {1, 1, 0, 0, 1, 1, 0, 1, 5, 0, 0, 6,},
689 {1, 1, 0, 2, 0, 0, 4, 0, 0, 0, 7, 1,},
690 {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,},
691 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
693 /* Level 15 */
694 {{0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
695 {0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
696 {0, 3, 4, 6, 0, 6, 0, 6, 0, 6, 0, 2,},
697 {0, 4, 0, 6, 0, 6, 4, 6, 0, 6, 0, 1,},
698 {0, 3, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
699 {7, 0, 0, 6, 4, 6, 0, 6, 0, 6, 0, 1,},
700 {0, 0, 4, 6, 0, 6, 0, 6, 4, 6, 0, 1,},
701 {0, 0, 4, 6, 0, 6, 0, 6, 0, 6, 0, 1,}}
705 /*****************************************************************************
706 * display_text() formats and outputs text.
707 ******************************************************************************/
708 static void display_text(char *str, bool waitkey)
710 int chars_by_line;
711 int lines_by_screen;
712 int chars_for_line;
713 int current_line = 0;
714 int char_width, char_height;
715 int first_char_index = 0;
716 char *ptr_char;
717 char *ptr_line;
718 int i;
719 char line[255];
720 int key;
721 bool go_on;
723 rb->lcd_clear_display();
725 rb->lcd_getstringsize("a", &char_width, &char_height);
727 chars_by_line = LCD_WIDTH / char_width;
728 lines_by_screen = LCD_HEIGHT / char_height;
732 ptr_char = str + first_char_index;
733 chars_for_line = 0;
734 i = 0;
735 ptr_line = line;
736 while (i < chars_by_line)
738 switch (*ptr_char)
740 case '\t':
741 case ' ':
742 *(ptr_line++) = ' ';
743 case '\n':
744 case '\0':
745 chars_for_line = i;
746 break;
748 default:
749 *(ptr_line++) = *ptr_char;
751 if (*ptr_char == '\n' || *ptr_char == '\0')
752 break;
753 ptr_char++;
754 i++;
757 if (chars_for_line == 0)
758 chars_for_line = i;
760 line[chars_for_line] = '\0';
762 /* test if we have cut a word. If it is the case we don't have to */
763 /* skip the space */
764 if (i == chars_by_line && chars_for_line == chars_by_line)
765 first_char_index += chars_for_line;
766 else
767 first_char_index += chars_for_line + 1;
769 /* print the line on the screen */
770 rb->lcd_putsxy(0, current_line * char_height, line);
772 /* if the number of line showed on the screen is equals to the */
773 /* maximum number of line we can show, we wait for a key pressed to */
774 /* clear and show the remaining text. */
775 current_line++;
776 if (current_line == lines_by_screen || *ptr_char == '\0')
778 current_line = 0;
779 rb->lcd_update();
780 go_on = false;
781 while (waitkey && !go_on)
783 key = rb->button_get(true);
784 switch (key)
786 #ifdef HAVE_TOUCHSCREEN
787 case BUTTON_TOUCHSCREEN:
788 #endif
789 case PEGBOX_QUIT:
790 case PEGBOX_LEFT:
791 case PEGBOX_DOWN:
792 go_on = true;
793 break;
795 default:
796 /*if (rb->default_event_handler(key) == SYS_USB_CONNECTED)
798 usb_detected = true;
799 go_on = true;
800 break;
802 break;
805 rb->lcd_clear_display();
807 } while (*ptr_char != '\0');
810 /*****************************************************************************
811 * draw_board() draws the game's current level.
812 ******************************************************************************/
813 static void draw_board(struct game_context* pb) {
814 unsigned int r, c, type;
815 pb->num_left = 0;
816 char str[5];
818 rb->lcd_clear_display();
819 #ifdef WIDE_LAYOUT
820 rb->lcd_bitmap(pegbox_header,LCD_WIDTH-HEADER_WIDTH,0,
821 HEADER_WIDTH,LCD_HEIGHT);
822 #else
823 rb->lcd_bitmap(pegbox_header,(LCD_WIDTH-HEADER_WIDTH)/2,0,
824 HEADER_WIDTH, HEADER_HEIGHT);
825 #endif /* WIDE_LAYOUT */
827 #if ((BOARD_HEIGHT + HEADER_HEIGHT + 4) <= LCD_HEIGHT)
828 rb->lcd_drawrect(BOARD_X-2,BOARD_Y-2,BOARD_WIDTH+4,BOARD_HEIGHT+4);
829 #endif /* enough space for a frame? */
831 #ifdef HAVE_LCD_COLOR
832 rb->lcd_set_foreground(LCD_WHITE);
833 rb->lcd_fillrect(BOARD_X-1,BOARD_Y-1,BOARD_WIDTH+2,BOARD_HEIGHT+2);
834 rb->lcd_set_foreground(LCD_BLACK);
835 rb->lcd_set_background(TEXT_BG);
836 #endif
838 for (r=0 ; r < ROWS ; r++) {
839 for (c = 0 ; c < COLS ; c++) {
841 type = pb->playboard[r][c];
843 switch(type) {
844 case SPACE:
845 break;
847 default:
848 rb->lcd_bitmap_part(pegbox_pieces, 0, (type-1)*PIECE_HEIGHT,
849 PIECE_WIDTH, c * PIECE_WIDTH + BOARD_X,
850 r * PIECE_HEIGHT + BOARD_Y, PIECE_WIDTH,
851 PIECE_HEIGHT);
852 break;
855 if(pb->playboard[r][c] == PLAYER) {
856 pb->player_row=r;
857 pb->player_col=c;
859 else if (type != WALL && type != SPACE && type != HOLE)
860 pb->num_left++;
864 #ifdef WIDE_LAYOUT
865 rb->snprintf(str, 3, "%d", pb->level);
866 rb->lcd_putsxy(TEXT_X, LEVEL_TEXT_Y, str);
867 rb->snprintf(str, 3, "%d", pb->num_left);
868 rb->lcd_putsxy(TEXT_X, PEGS_TEXT_Y, str);
869 #else
870 rb->snprintf(str, 3, "%d", pb->level);
871 rb->lcd_putsxy(LEVEL_TEXT_X, TEXT_Y, str);
872 rb->snprintf(str, 3, "%d", pb->num_left);
873 rb->lcd_putsxy(PEGS_TEXT_X, TEXT_Y, str);
874 #endif /*WIDE_LAYOUT*/
876 #ifdef HAVE_LCD_COLOR
877 rb->lcd_set_background(BG_COLOR);
878 rb->lcd_set_foreground(LCD_WHITE);
879 #endif
880 /* print out the screen */
881 rb->lcd_update();
884 /*****************************************************************************
885 * load_level() loads the player's current level from the array and sets the
886 * player's position.
887 ******************************************************************************/
888 static void load_level(struct game_context* pb) {
889 int r, c;
891 for(r = 0; r < ROWS; r++)
892 for(c = 0; c < COLS; c++)
893 pb->playboard[r][c] = levels[pb->level-1][r][c];
896 /*****************************************************************************
897 * new_piece() creates a new piece at a specified location. The player
898 * navigates through the pieces and selects one.
899 ******************************************************************************/
900 static void new_piece(struct game_context* pb, unsigned int x_loc,
901 unsigned int y_loc) {
902 int button;
903 bool exit = false;
905 pb->playboard[x_loc][y_loc] = TRIANGLE;
907 while (!exit) {
908 draw_board(pb);
909 button = rb->button_get(true);
910 #ifdef HAVE_TOUCHSCREEN
911 if(button & BUTTON_TOUCHSCREEN)
913 pegbox_raster_btn.two_d_from.y = x_loc;
914 pegbox_raster_btn.two_d_from.x = y_loc;
916 struct ts_raster_button_result ret =
917 touchscreen_raster_map_button(&pegbox_raster_btn,
918 rb->button_get_data() >> 16,
919 rb->button_get_data() & 0xffff,
920 button);
921 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
923 if(ret.to.x > ret.from.x)
924 button = PEGBOX_UP;
925 else if(ret.to.x < ret.from.x)
926 button = PEGBOX_DOWN;
927 else if(ret.to.y > ret.from.y)
928 button = PEGBOX_LEFT;
929 else if(ret.to.y < ret.from.y)
930 button = PEGBOX_RIGHT;
932 else if(ret.action == TS_ACTION_CLICK
933 && (unsigned)ret.to.x == y_loc
934 && (unsigned)ret.to.y == x_loc)
935 button = PEGBOX_SAVE;
937 #endif
938 switch(button){
939 case PEGBOX_LEFT:
940 case (PEGBOX_LEFT|BUTTON_REPEAT):
941 case PEGBOX_DOWN:
942 case (PEGBOX_DOWN|BUTTON_REPEAT):
943 if (pb->playboard[x_loc][y_loc] < 5)
944 pb->playboard[x_loc][y_loc]++;
945 else
946 pb->playboard[x_loc][y_loc] = TRIANGLE;
947 break;
948 case PEGBOX_RIGHT:
949 case (PEGBOX_RIGHT|BUTTON_REPEAT):
950 case PEGBOX_UP:
951 case (PEGBOX_UP|BUTTON_REPEAT):
952 if (pb->playboard[x_loc][y_loc] > 2)
953 pb->playboard[x_loc][y_loc]--;
954 else
955 pb->playboard[x_loc][y_loc] = CIRCLE;
956 break;
957 case PEGBOX_SAVE:
958 exit = true;
959 break;
964 /*****************************************************************************
965 * move_player() moves the player and pieces and updates the board accordingly.
966 ******************************************************************************/
967 static void move_player(struct game_context* pb, signed int x_dir,
968 signed int y_dir) {
969 unsigned int type1, type2;
970 signed int r,c;
972 r = pb->player_row+y_dir;
973 c = pb->player_col+x_dir;
975 type1 = pb->playboard[r][c];
976 type2 = pb->playboard[r+y_dir][c+x_dir];
978 if (r == ROWS || c == COLS || r < 0 || c < 0 || type1 == WALL)
979 return;
980 else if(type1 != SPACE) {
981 if (type2 == WALL || r+y_dir == ROWS || c+x_dir == COLS ||
982 r+y_dir < 0 || c+x_dir < 0)
983 return;
987 pb->playboard[pb->player_row][pb->player_col] = SPACE;
988 pb->player_row += y_dir;
989 pb->player_col += x_dir;
991 if (type1 == HOLE) {
992 draw_board(pb);
993 rb->splash(HZ*2, "You fell down a hole!");
994 load_level(pb);
996 else if (type1 == SPACE)
997 pb->playboard[r][c] = PLAYER;
998 else {
999 pb->playboard[r][c] = PLAYER;
1000 if(type1 == type2) {
1001 if (type1 == TRIANGLE)
1002 pb->playboard[r+y_dir][c+x_dir] = WALL;
1003 else if (type1 == CROSS) {
1004 pb->playboard[r][c] = SPACE;
1005 new_piece(pb, r+y_dir, c+x_dir);
1006 pb->playboard[r][c] = PLAYER;
1008 else
1009 pb->playboard[r+y_dir][c+x_dir] = SPACE;
1011 else if (type2 == SPACE)
1012 pb->playboard[r+y_dir][c+x_dir] = type1;
1013 else if (type2 == HOLE) {
1014 if (type1 == SQUARE)
1015 pb->playboard[r+y_dir][c+x_dir] = SPACE;
1017 else {
1018 rb->splash(HZ*2, "Illegal Move!");
1019 load_level(pb);
1023 draw_board(pb);
1026 /*****************************************************************************
1027 * pegbox_loadgame() loads the saved game and returns load success.
1028 ******************************************************************************/
1029 static bool pegbox_loadgame(struct game_context* pb) {
1030 signed int fd;
1031 bool loaded = false;
1033 /* open game file */
1034 fd = rb->open(SAVE_FILE, O_RDONLY);
1035 if(fd < 0) return loaded;
1037 /* read in saved game */
1038 while(true) {
1039 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
1040 if(rb->read(fd, &pb->playboard, sizeof(pb->playboard)) <= 0)
1042 loaded = true;
1043 break;
1045 break;
1048 rb->close(fd);
1049 return loaded;
1052 /*****************************************************************************
1053 * pegbox_savegame() saves the current game state.
1054 ******************************************************************************/
1055 static void pegbox_savegame(struct game_context* pb) {
1056 unsigned int fd;
1058 /* write out the game state to the save file */
1059 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
1060 rb->write(fd, &pb->level, sizeof(pb->level));
1061 rb->write(fd, &pb->playboard, sizeof(pb->playboard));
1062 rb->close(fd);
1065 /*****************************************************************************
1066 * pegbox_loaddata() loads the level and highlevel and returns load success.
1067 ******************************************************************************/
1068 static void pegbox_loaddata(struct game_context* pb) {
1069 signed int fd;
1071 /* open game file */
1072 fd = rb->open(DATA_FILE, O_RDONLY);
1073 if(fd < 0) {
1074 pb->level = 1;
1075 pb->highlevel = 1;
1076 return;
1079 /* read in saved game */
1080 while(true) {
1081 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
1082 if(rb->read(fd, &pb->highlevel, sizeof(pb->highlevel)) <= 0) break;
1083 break;
1086 rb->close(fd);
1087 return;
1090 /*****************************************************************************
1091 * pegbox_savedata() saves the level and highlevel.
1092 ******************************************************************************/
1093 static void pegbox_savedata(struct game_context* pb) {
1094 unsigned int fd;
1096 /* write out the game state to the save file */
1097 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT);
1098 rb->write(fd, &pb->level, sizeof(pb->level));
1099 rb->write(fd, &pb->highlevel, sizeof(pb->highlevel));
1100 rb->close(fd);
1103 /*****************************************************************************
1104 * pegbox_callback() is the default event handler callback which is called
1105 * on usb connect and shutdown.
1106 ******************************************************************************/
1107 static void pegbox_callback(void* param) {
1108 struct game_context* pb = (struct game_context*) param;
1109 rb->splash(HZ, "Saving data...");
1110 pegbox_savedata(pb);
1113 /*****************************************************************************
1114 * pegbox_menu() is the initial menu at the start of the game.
1115 ******************************************************************************/
1116 static unsigned int pegbox_menu(struct game_context* pb) {
1117 int button;
1118 char str[30];
1119 unsigned int startlevel = 1, loc = 0;
1120 bool breakout = false, can_resume = false;
1122 if (pb->num_left > 0 || pb->save_exist)
1123 can_resume = true;
1125 while(!breakout){
1126 #if LCD_HEIGHT >= 80
1127 rb->lcd_clear_display();
1128 rb->lcd_bitmap(pegbox_menu_top,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_menu_top);
1130 /* menu bitmaps */
1131 if (loc == 0) {
1132 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT, ITEM_WIDTH,
1133 MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT);
1135 else {
1136 rb->lcd_bitmap_part(pegbox_menu_items, 0, 0, ITEM_WIDTH,
1137 MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT);
1139 if (can_resume) {
1140 if (loc == 1) {
1141 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*3, ITEM_WIDTH,
1142 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1144 else {
1145 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*2, ITEM_WIDTH,
1146 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1149 else {
1150 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*4, ITEM_WIDTH,
1151 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1154 if (loc==2) {
1155 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*6, ITEM_WIDTH,
1156 MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT);
1158 else {
1159 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*5, ITEM_WIDTH,
1160 MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT);
1163 if (loc==3) {
1164 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*8, ITEM_WIDTH,
1165 MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT);
1167 else {
1168 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*7, ITEM_WIDTH,
1169 MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT);
1171 #else
1172 unsigned int w,h;
1173 rb->lcd_clear_display();
1174 rb->lcd_getstringsize("PegBox", &w, &h);
1175 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, "PegBox");
1176 rb->lcd_putsxy((LCD_WIDTH)/4, 16, "New Game");
1177 rb->lcd_putsxy((LCD_WIDTH)/4, 24, "Resume");
1178 rb->lcd_putsxy((LCD_WIDTH)/4, 32, "Help");
1179 rb->lcd_putsxy((LCD_WIDTH)/4, 40, "Quit");
1181 if(!can_resume)
1182 rb->lcd_hline((LCD_WIDTH)/4, (LCD_WIDTH)/4+30, 28);
1184 rb->lcd_putsxy((LCD_WIDTH)/4-8, loc*8+16, "*");
1187 #endif
1188 rb->snprintf(str, 28, "Start on level %d of %d", startlevel,
1189 pb->highlevel);
1190 #if LCD_HEIGHT > 110
1191 rb->lcd_putsxy(0, MENU_Y+4*ITEM_HEIGHT+8, str);
1192 #elif LCD_HEIGHT > 64
1193 rb->lcd_putsxy(0, LCD_HEIGHT - 8, str);
1194 #else
1195 rb->lcd_puts_scroll(0, 7, str);
1196 #endif
1197 rb->lcd_update();
1199 /* handle menu button presses */
1200 button = rb->button_get(true);
1202 #ifdef HAVE_TOUCHSCREEN
1203 if(button & BUTTON_TOUCHSCREEN)
1205 unsigned int result = touchscreen_map(&main_menu,
1206 rb->button_get_data() >> 16,
1207 rb->button_get_data() & 0xffff);
1208 if(result != (unsigned)-1 && button & BUTTON_REL)
1210 if(result == 4)
1211 button = PEGBOX_LVL_UP;
1212 else
1214 if(loc == result)
1215 button = PEGBOX_RIGHT;
1216 loc = result;
1220 #endif
1222 switch(button) {
1223 case PEGBOX_SAVE: /* start playing */
1224 case PEGBOX_RIGHT:
1225 if (loc == 0) {
1226 breakout = true;
1227 pb->level = startlevel;
1228 load_level(pb);
1230 else if (loc == 1 && can_resume) {
1231 if(pb->save_exist)
1233 rb->remove(SAVE_FILE);
1234 pb->save_exist = false;
1236 breakout = true;
1238 else if (loc == 2)
1239 display_text("How to Play\nTo beat each level, you must "
1240 "destroy all of the pegs. If two like pegs are "
1241 "pushed into each other they disappear except "
1242 "for triangles which form a solid block and "
1243 "crosses which allow you to choose a "
1244 "replacement block.\n\n"
1245 "Controls\n"
1246 #if LCD_HEIGHT > 64
1247 RESTART_TEXT " to restart level\n"
1248 LVL_UP_TEXT " to go up a level\n"
1249 LVL_DOWN_TEXT " to go down a level\n"
1250 SAVE_TEXT " to select/save\n"
1251 QUIT_TEXT " to quit\n",true);
1252 #else
1253 RESTART_TEXT ": restart\n"
1254 LVL_UP_TEXT ": level up\n"
1255 LVL_DOWN_TEXT " level down\n"
1256 SAVE_TEXT " select/save\n"
1257 QUIT_TEXT " quit\n",true);
1258 #endif
1259 else if (loc == 3)
1260 return PB_QUIT;
1261 break;
1263 case PEGBOX_QUIT: /* quit program */
1264 return PB_QUIT;
1266 case (PEGBOX_UP|BUTTON_REPEAT):
1267 case PEGBOX_UP:
1268 if (loc <= 0)
1269 loc = 3;
1270 else
1271 loc--;
1272 if (!can_resume && loc == 1) {
1273 loc = 0;
1275 break;
1278 case (PEGBOX_DOWN|BUTTON_REPEAT):
1279 case PEGBOX_DOWN:
1280 if (loc >= 3)
1281 loc = 0;
1282 else
1283 loc++;
1284 if (!can_resume && loc == 1) {
1285 loc = 2;
1287 break;
1289 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1290 case PEGBOX_LVL_UP: /* increase starting level */
1291 if(startlevel >= pb->highlevel) {
1292 startlevel = 1;
1293 } else {
1294 startlevel++;
1296 break;
1298 /* only for targets with enough buttons */
1299 #ifdef PEGBOX_LVL_DOWN
1300 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1301 case PEGBOX_LVL_DOWN: /* decrease starting level */
1302 if(startlevel <= 1) {
1303 startlevel = pb->highlevel;
1304 } else {
1305 startlevel--;
1307 break;
1308 #endif
1309 default:
1310 if(rb->default_event_handler_ex(button, pegbox_callback,
1311 (void*) pb) == SYS_USB_CONNECTED)
1312 return PB_USB;
1313 break;
1317 draw_board(pb);
1319 return 0;
1322 /*****************************************************************************
1323 * pegbox() is the main game subroutine, it returns the final game status.
1324 ******************************************************************************/
1325 static int pegbox(struct game_context* pb) {
1326 int temp_var;
1328 /********************
1329 * menu *
1330 ********************/
1331 temp_var = pegbox_menu(pb);
1332 if (temp_var == PB_QUIT || temp_var == PB_USB)
1333 return temp_var;
1335 while (true) {
1336 temp_var = rb->button_get(true);
1337 #ifdef HAVE_TOUCHSCREEN
1338 if(temp_var & BUTTON_TOUCHSCREEN)
1340 pegbox_raster_btn.two_d_from.y = pb->player_row;
1341 pegbox_raster_btn.two_d_from.x = pb->player_col;
1343 struct ts_raster_button_result ret =
1344 touchscreen_raster_map_button(&pegbox_raster_btn,
1345 rb->button_get_data() >> 16,
1346 rb->button_get_data() & 0xffff,
1347 temp_var);
1348 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
1349 move_player(pb, ret.to.x - ret.from.x, ret.to.y - ret.from.y);
1351 #endif
1352 switch(temp_var){
1353 case PEGBOX_LEFT: /* move cursor left */
1354 case (PEGBOX_LEFT|BUTTON_REPEAT):
1355 move_player(pb, -1, 0);
1356 break;
1358 case PEGBOX_RIGHT: /* move cursor right */
1359 case (PEGBOX_RIGHT|BUTTON_REPEAT):
1360 move_player(pb, 1, 0);
1361 break;
1363 case PEGBOX_DOWN: /* move cursor down */
1364 case (PEGBOX_DOWN|BUTTON_REPEAT):
1365 move_player(pb, 0, 1);
1366 break;
1368 case PEGBOX_UP: /* move cursor up */
1369 case (PEGBOX_UP|BUTTON_REPEAT):
1370 move_player(pb, 0, -1);
1371 break;
1373 case PEGBOX_SAVE: /* save and end game */
1374 rb->splash(HZ, "Saving game...");
1375 pegbox_savegame(pb);
1376 /* fall through to PEGBOX_QUIT */
1378 case PEGBOX_QUIT:
1379 return PB_END;
1381 case PEGBOX_RESTART:
1382 load_level(pb);
1383 draw_board(pb);
1384 break;
1386 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1387 case PEGBOX_LVL_UP:
1388 if(pb->level >= pb->highlevel) {
1389 pb->level = 1;
1390 } else {
1391 pb->level++;
1393 load_level(pb);
1394 draw_board(pb);
1395 break;
1397 /* only for targets with enough buttons */
1398 #ifdef PEGBOX_LVL_DOWN
1399 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1400 case PEGBOX_LVL_DOWN:
1401 if(pb->level <= 1) {
1402 pb->level = pb->highlevel;
1403 } else {
1404 pb->level--;
1406 load_level(pb);
1407 draw_board(pb);
1408 break;
1409 #endif
1413 if(pb->num_left == 0) {
1414 rb->splash(HZ*2, "Nice Pegging!");
1415 if(pb->level == NUM_LEVELS) {
1416 draw_board(pb);
1417 rb->splash(HZ*2, "You Won!");
1418 break;
1420 else {
1421 pb->level++;
1422 load_level(pb);
1423 draw_board(pb);
1426 if(pb->level > pb->highlevel)
1427 pb->highlevel = pb->level;
1432 return PLUGIN_OK;
1436 /*****************************************************************************
1437 * plugin entry point.
1438 ******************************************************************************/
1439 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter) {
1440 bool exit = false;
1441 struct game_context pb;
1443 (void)parameter;
1444 rb = api;
1446 rb->lcd_setfont(FONT_SYSFIXED);
1447 #if LCD_DEPTH > 1
1448 rb->lcd_set_backdrop(NULL);
1449 #endif
1450 #ifdef HAVE_LCD_COLOR
1451 rb->lcd_set_foreground(LCD_WHITE);
1452 rb->lcd_set_background(BG_COLOR);
1453 #endif
1455 rb->splash(0, "Loading...");
1456 pegbox_loaddata(&pb);
1457 pb.save_exist = pegbox_loadgame(&pb);
1458 pb.num_left = 0;
1460 rb->lcd_clear_display();
1463 while(!exit) {
1464 switch(pegbox(&pb)){
1465 case PB_END:
1466 break;
1468 case PB_USB:
1469 rb->lcd_setfont(FONT_UI);
1470 return PLUGIN_USB_CONNECTED;
1472 case PB_QUIT:
1473 rb->splash(HZ, "Saving data...");
1474 pegbox_savedata(&pb);
1475 exit = true;
1476 break;
1478 default:
1479 break;
1483 rb->lcd_setfont(FONT_UI);
1484 return PLUGIN_OK;