Use the AMS_LOWMEM define to indicate memory size as the .lds files do in config...
[kugel-rb.git] / apps / plugins / pegbox.c
blob23470d478021af283ec2076f88fb6c1258139e1f
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Tom Ross
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "plugin.h"
23 #include "pluginbitmaps/pegbox_header.h"
24 #include "pluginbitmaps/pegbox_pieces.h"
26 #if LCD_HEIGHT >= 80 /* enough space for a graphical menu */
27 #include "pluginbitmaps/pegbox_menu_top.h"
28 #include "pluginbitmaps/pegbox_menu_items.h"
29 #define MENU_X (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2
30 #define MENU_Y BMPHEIGHT_pegbox_menu_top
31 #define ITEM_WIDTH BMPWIDTH_pegbox_menu_items
32 #define ITEM_HEIGHT (BMPHEIGHT_pegbox_menu_items/9)
33 #endif
35 PLUGIN_HEADER
37 /* final game return status */
38 #define PB_END 3
39 #define PB_USB 2
40 #define PB_QUIT 1
42 #define DATA_FILE PLUGIN_GAMES_DIR "/pegbox.data"
43 #define SAVE_FILE PLUGIN_GAMES_DIR "/pegbox.save"
45 #define ROWS 8 /* Number of rows on each board */
46 #define COLS 12 /* Number of columns on each board */
47 #define NUM_LEVELS 15 /* Number of levels */
49 #define SPACE 0
50 #define WALL 1
51 #define TRIANGLE 2
52 #define CROSS 3
53 #define SQUARE 4
54 #define CIRCLE 5
55 #define HOLE 6
56 #define PLAYER 7
58 #if CONFIG_KEYPAD == RECORDER_PAD
59 #define PEGBOX_SAVE BUTTON_ON
60 #define PEGBOX_QUIT BUTTON_OFF
61 #define PEGBOX_RESTART BUTTON_F2
62 #define PEGBOX_LVL_UP BUTTON_F1
63 #define PEGBOX_LVL_DOWN BUTTON_F3
64 #define PEGBOX_UP BUTTON_UP
65 #define PEGBOX_DOWN BUTTON_DOWN
66 #define PEGBOX_RIGHT BUTTON_RIGHT
67 #define PEGBOX_LEFT BUTTON_LEFT
69 #define SAVE_TEXT "ON"
70 #define QUIT_TEXT "OFF"
71 #define RESTART_TEXT "F2"
72 #define LVL_UP_TEXT "F1"
73 #define LVL_DOWN_TEXT "F3"
75 #elif CONFIG_KEYPAD == ONDIO_PAD
76 #define PEGBOX_SAVE BUTTON_OFF
77 #define PEGBOX_QUIT (BUTTON_MENU | BUTTON_LEFT)
78 #define PEGBOX_RESTART (BUTTON_MENU | BUTTON_RIGHT)
79 #define PEGBOX_LVL_UP (BUTTON_MENU | BUTTON_UP)
80 #define PEGBOX_LVL_DOWN (BUTTON_MENU | BUTTON_DOWN)
81 #define PEGBOX_UP BUTTON_UP
82 #define PEGBOX_DOWN BUTTON_DOWN
83 #define PEGBOX_RIGHT BUTTON_RIGHT
84 #define PEGBOX_LEFT BUTTON_LEFT
86 #define SAVE_TEXT "OFF"
87 #define QUIT_TEXT "M+LEFT"
88 #define RESTART_TEXT "M+RIGHT"
89 #define LVL_UP_TEXT "M+UP"
90 #define LVL_DOWN_TEXT "M+DOWN"
92 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
93 (CONFIG_KEYPAD == IRIVER_H300_PAD)
94 #define PEGBOX_SAVE BUTTON_SELECT
95 #define PEGBOX_QUIT BUTTON_OFF
96 #define PEGBOX_RESTART BUTTON_ON
97 #define PEGBOX_LVL_UP BUTTON_MODE
98 #define PEGBOX_LVL_DOWN BUTTON_REC
99 #define PEGBOX_UP BUTTON_UP
100 #define PEGBOX_DOWN BUTTON_DOWN
101 #define PEGBOX_RIGHT BUTTON_RIGHT
102 #define PEGBOX_LEFT BUTTON_LEFT
104 #define SAVE_TEXT "NAVI"
105 #define QUIT_TEXT "OFF"
106 #define RESTART_TEXT "ON"
107 #define LVL_UP_TEXT "AB"
108 #define LVL_DOWN_TEXT "REC"
110 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
111 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
112 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
113 #define PEGBOX_SAVE (BUTTON_SELECT|BUTTON_RIGHT)
114 #define PEGBOX_QUIT (BUTTON_SELECT|BUTTON_PLAY)
115 #define PEGBOX_RESTART (BUTTON_SELECT|BUTTON_LEFT)
116 #define PEGBOX_LVL_UP (BUTTON_SELECT|BUTTON_MENU)
117 #define PEGBOX_UP BUTTON_MENU
118 #define PEGBOX_DOWN BUTTON_PLAY
119 #define PEGBOX_RIGHT BUTTON_RIGHT
120 #define PEGBOX_LEFT BUTTON_LEFT
122 #define SAVE_TEXT "SELECT+RIGHT"
123 #define QUIT_TEXT "SELECT+PLAY"
124 #define RESTART_TEXT "SELECT+LEFT"
125 #define LVL_UP_TEXT "SELECT+MENU"
126 #define LVL_DOWN_TEXT "-"
128 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
129 #define PEGBOX_SAVE BUTTON_SELECT
130 #define PEGBOX_QUIT BUTTON_POWER
131 #define PEGBOX_RESTART BUTTON_REC
132 #define PEGBOX_LVL_UP BUTTON_PLAY
133 #define PEGBOX_UP BUTTON_UP
134 #define PEGBOX_DOWN BUTTON_DOWN
135 #define PEGBOX_RIGHT BUTTON_RIGHT
136 #define PEGBOX_LEFT BUTTON_LEFT
138 #define SAVE_TEXT "SELECT"
139 #define QUIT_TEXT "OFF"
140 #define RESTART_TEXT "REC"
141 #define LVL_UP_TEXT "PLAY"
142 #define LVL_DOWN_TEXT "-"
144 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
145 #define PEGBOX_SAVE BUTTON_MODE
146 #define PEGBOX_QUIT BUTTON_PLAY
147 #define PEGBOX_RESTART (BUTTON_EQ|BUTTON_MODE)
148 #define PEGBOX_LVL_UP (BUTTON_EQ|BUTTON_UP)
149 #define PEGBOX_LVL_DOWN (BUTTON_EQ|BUTTON_DOWN)
150 #define PEGBOX_UP BUTTON_UP
151 #define PEGBOX_DOWN BUTTON_DOWN
152 #define PEGBOX_RIGHT BUTTON_RIGHT
153 #define PEGBOX_LEFT BUTTON_LEFT
155 #define SAVE_TEXT "MODE"
156 #define QUIT_TEXT "PLAY"
157 #define RESTART_TEXT "EQ+MODE"
158 #define LVL_UP_TEXT "EQ+UP"
159 #define LVL_DOWN_TEXT "EQ+DOWN"
161 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
162 #define PEGBOX_SAVE BUTTON_PLAY
163 #define PEGBOX_QUIT BUTTON_POWER
164 #define PEGBOX_RESTART (BUTTON_FF|BUTTON_REPEAT)
165 #define PEGBOX_LVL_UP (BUTTON_FF|BUTTON_SCROLL_UP)
166 #define PEGBOX_LVL_DOWN (BUTTON_FF|BUTTON_SCROLL_DOWN)
167 #define PEGBOX_UP BUTTON_SCROLL_UP
168 #define PEGBOX_DOWN BUTTON_SCROLL_DOWN
169 #define PEGBOX_RIGHT BUTTON_RIGHT
170 #define PEGBOX_LEFT BUTTON_LEFT
172 #define SAVE_TEXT "PLAY"
173 #define QUIT_TEXT "OFF"
174 #define RESTART_TEXT "LONG FF"
175 #define LVL_UP_TEXT "FF+SCROLL_UP"
176 #define LVL_DOWN_TEXT "FF+SCROLL_DOWN"
178 #elif CONFIG_KEYPAD == SANSA_E200_PAD
179 #define PEGBOX_SAVE BUTTON_SELECT
180 #define PEGBOX_QUIT BUTTON_POWER
181 #define PEGBOX_RESTART BUTTON_REC
182 #define PEGBOX_LVL_UP BUTTON_SCROLL_BACK
183 #define PEGBOX_LVL_DOWN BUTTON_SCROLL_FWD
184 #define PEGBOX_UP BUTTON_UP
185 #define PEGBOX_DOWN BUTTON_DOWN
186 #define PEGBOX_RIGHT BUTTON_RIGHT
187 #define PEGBOX_LEFT BUTTON_LEFT
189 #define SAVE_TEXT "SELECT"
190 #define QUIT_TEXT "POWER"
191 #define RESTART_TEXT "REC"
192 #define LVL_UP_TEXT "SCROLL BACK"
193 #define LVL_DOWN_TEXT "SCROLL FWD"
195 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
196 #define PEGBOX_SAVE BUTTON_SELECT|BUTTON_REL
197 #define PEGBOX_QUIT (BUTTON_HOME|BUTTON_REPEAT)
198 #define PEGBOX_RESTART BUTTON_SELECT|BUTTON_LEFT
199 #define PEGBOX_LVL_UP BUTTON_SCROLL_BACK
200 #define PEGBOX_LVL_DOWN BUTTON_SCROLL_FWD
201 #define PEGBOX_UP BUTTON_UP
202 #define PEGBOX_DOWN BUTTON_DOWN
203 #define PEGBOX_RIGHT BUTTON_RIGHT
204 #define PEGBOX_LEFT BUTTON_LEFT
206 #define SAVE_TEXT "SELECT"
207 #define QUIT_TEXT "HOME"
208 #define RESTART_TEXT "SELECT & LEFT"
209 #define LVL_UP_TEXT "SCROLL BACK"
210 #define LVL_DOWN_TEXT "SCROLL FWD"
212 #elif CONFIG_KEYPAD == GIGABEAT_PAD
213 #define PEGBOX_SAVE BUTTON_SELECT
214 #define PEGBOX_QUIT BUTTON_POWER
215 #define PEGBOX_RESTART BUTTON_A
216 #define PEGBOX_LVL_UP BUTTON_VOL_UP
217 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
218 #define PEGBOX_UP BUTTON_UP
219 #define PEGBOX_DOWN BUTTON_DOWN
220 #define PEGBOX_RIGHT BUTTON_RIGHT
221 #define PEGBOX_LEFT BUTTON_LEFT
223 #define SAVE_TEXT "SELECT"
224 #define QUIT_TEXT "POWER"
225 #define RESTART_TEXT "A"
226 #define LVL_UP_TEXT "VOL+"
227 #define LVL_DOWN_TEXT "VOL-"
229 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
230 #define PEGBOX_SAVE BUTTON_SELECT
231 #define PEGBOX_QUIT BUTTON_BACK
232 #define PEGBOX_RESTART BUTTON_MENU
233 #define PEGBOX_LVL_UP BUTTON_VOL_UP
234 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
235 #define PEGBOX_UP BUTTON_UP
236 #define PEGBOX_DOWN BUTTON_DOWN
237 #define PEGBOX_RIGHT BUTTON_RIGHT
238 #define PEGBOX_LEFT BUTTON_LEFT
240 #define SAVE_TEXT "SELECT"
241 #define QUIT_TEXT "BACK"
242 #define RESTART_TEXT "MENU"
243 #define LVL_UP_TEXT "VOL+"
244 #define LVL_DOWN_TEXT "VOL-"
246 #elif CONFIG_KEYPAD == MROBE100_PAD
247 #define PEGBOX_SAVE BUTTON_SELECT
248 #define PEGBOX_QUIT BUTTON_POWER
249 #define PEGBOX_RESTART BUTTON_PLAY
250 #define PEGBOX_LVL_UP BUTTON_MENU
251 #define PEGBOX_LVL_DOWN BUTTON_DISPLAY
252 #define PEGBOX_UP BUTTON_UP
253 #define PEGBOX_DOWN BUTTON_DOWN
254 #define PEGBOX_RIGHT BUTTON_RIGHT
255 #define PEGBOX_LEFT BUTTON_LEFT
257 #define SAVE_TEXT "SELECT"
258 #define QUIT_TEXT "POWER"
259 #define RESTART_TEXT "PLAY"
260 #define LVL_UP_TEXT "MENU"
261 #define LVL_DOWN_TEXT "DISPLAY"
263 #elif CONFIG_KEYPAD == SANSA_C200_PAD
264 #define PEGBOX_SAVE BUTTON_SELECT
265 #define PEGBOX_QUIT BUTTON_POWER
266 #define PEGBOX_RESTART BUTTON_REC
267 #define PEGBOX_LVL_UP BUTTON_VOL_UP
268 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
269 #define PEGBOX_UP BUTTON_UP
270 #define PEGBOX_DOWN BUTTON_DOWN
271 #define PEGBOX_RIGHT BUTTON_RIGHT
272 #define PEGBOX_LEFT BUTTON_LEFT
274 #define SAVE_TEXT "SELECT"
275 #define QUIT_TEXT "POWER"
276 #define RESTART_TEXT "REC"
277 #define LVL_UP_TEXT "VOL+"
278 #define LVL_DOWN_TEXT "VOL-"
280 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
281 #define PEGBOX_SAVE BUTTON_SELECT
282 #define PEGBOX_QUIT BUTTON_POWER
283 #define PEGBOX_RESTART BUTTON_HOME
284 #define PEGBOX_LVL_UP BUTTON_VOL_UP
285 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
286 #define PEGBOX_UP BUTTON_UP
287 #define PEGBOX_DOWN BUTTON_DOWN
288 #define PEGBOX_RIGHT BUTTON_RIGHT
289 #define PEGBOX_LEFT BUTTON_LEFT
291 #define SAVE_TEXT "SELECT"
292 #define QUIT_TEXT "POWER"
293 #define RESTART_TEXT "HOME"
294 #define LVL_UP_TEXT "VOL+"
295 #define LVL_DOWN_TEXT "VOL-"
297 #elif CONFIG_KEYPAD == SANSA_M200_PAD
298 #define PEGBOX_SAVE (BUTTON_SELECT | BUTTON_REL)
299 #define PEGBOX_QUIT BUTTON_POWER
300 #define PEGBOX_RESTART (BUTTON_SELECT | BUTTON_UP)
301 #define PEGBOX_LVL_UP BUTTON_VOL_UP
302 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
303 #define PEGBOX_UP BUTTON_UP
304 #define PEGBOX_DOWN BUTTON_DOWN
305 #define PEGBOX_RIGHT BUTTON_RIGHT
306 #define PEGBOX_LEFT BUTTON_LEFT
308 #define SAVE_TEXT "SELECT"
309 #define QUIT_TEXT "POWER"
310 #define RESTART_TEXT "SELECT+UP"
311 #define LVL_UP_TEXT "VOL+"
312 #define LVL_DOWN_TEXT "VOL-"
315 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
316 #define PEGBOX_SAVE BUTTON_RC_PLAY
317 #define PEGBOX_QUIT BUTTON_RC_REC
318 #define PEGBOX_RESTART BUTTON_RC_MODE
319 #define PEGBOX_LVL_UP BUTTON_VOL_UP
320 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
321 #define PEGBOX_UP BUTTON_RC_VOL_UP
322 #define PEGBOX_DOWN BUTTON_RC_VOL_DOWN
323 #define PEGBOX_RIGHT BUTTON_RC_FF
324 #define PEGBOX_LEFT BUTTON_RC_REW
326 #define SAVE_TEXT "REM. PLAY"
327 #define QUIT_TEXT "REM. REC"
328 #define RESTART_TEXT "REM. MODE"
329 #define LVL_UP_TEXT "VOL+"
330 #define LVL_DOWN_TEXT "VOL-"
332 #elif CONFIG_KEYPAD == COWOND2_PAD
333 #define PEGBOX_QUIT BUTTON_POWER
335 #define QUIT_TEXT "POWER"
337 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
338 #define PEGBOX_SAVE BUTTON_CUSTOM
339 #define PEGBOX_QUIT BUTTON_BACK
340 #define PEGBOX_RESTART BUTTON_SELECT
341 #define PEGBOX_LVL_UP BUTTON_PLAY
342 #define PEGBOX_LVL_DOWN BUTTON_MENU
343 #define PEGBOX_UP BUTTON_UP
344 #define PEGBOX_DOWN BUTTON_DOWN
345 #define PEGBOX_RIGHT BUTTON_RIGHT
346 #define PEGBOX_LEFT BUTTON_LEFT
348 #define SAVE_TEXT "CUSTOM"
349 #define QUIT_TEXT "BACK"
350 #define RESTART_TEXT "MIDDLE"
351 #define LVL_UP_TEXT "SELECT"
352 #define LVL_DOWN_TEXT "MENU"
354 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
355 #define PEGBOX_SAVE BUTTON_VIEW
356 #define PEGBOX_QUIT BUTTON_POWER
357 #define PEGBOX_RESTART BUTTON_MENU
358 #define PEGBOX_LVL_UP BUTTON_VOL_UP
359 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
360 #define PEGBOX_UP BUTTON_UP
361 #define PEGBOX_DOWN BUTTON_DOWN
362 #define PEGBOX_RIGHT BUTTON_RIGHT
363 #define PEGBOX_LEFT BUTTON_LEFT
365 #define SAVE_TEXT "VIEW"
366 #define QUIT_TEXT "POWER"
367 #define RESTART_TEXT "MENU"
368 #define LVL_UP_TEXT "VOL+"
369 #define LVL_DOWN_TEXT "VOL-"
371 #elif CONFIG_KEYPAD == ONDAVX747_PAD || CONFIG_KEYPAD == MROBE500_PAD
372 #define PEGBOX_QUIT BUTTON_POWER
374 #define QUIT_TEXT "POWER"
376 #else
377 #error Unsupported keymap!
378 #endif
380 #ifdef HAVE_TOUCHSCREEN
381 #ifndef PEGBOX_QUIT
382 #define PEGBOX_QUIT BUTTON_TOPLEFT
383 #endif
384 #ifndef PEGBOX_SAVE
385 #define PEGBOX_SAVE BUTTON_CENTER
386 #endif
387 #ifndef PEGBOX_RESTART
388 #define PEGBOX_RESTART BUTTON_TOPRIGHT
389 #endif
390 #ifndef PEGBOX_LVL_UP
391 #define PEGBOX_LVL_UP BUTTON_BOTTOMLEFT
392 #endif
393 #ifndef PEGBOX_LVL_DOWN
394 #define PEGBOX_LVL_DOWN BUTTON_BOTTOMRIGHT
395 #endif
396 #ifndef PEGBOX_UP
397 #define PEGBOX_UP BUTTON_TOPMIDDLE
398 #endif
399 #ifndef PEGBOX_DOWN
400 #define PEGBOX_DOWN BUTTON_BOTTOMMIDDLE
401 #endif
402 #ifndef PEGBOX_RIGHT
403 #define PEGBOX_RIGHT BUTTON_MIDRIGHT
404 #endif
405 #ifndef PEGBOX_LEFT
406 #define PEGBOX_LEFT BUTTON_MIDLEFT
407 #endif
408 #ifndef SAVE_TEXT
409 #define SAVE_TEXT "CENTER"
410 #endif
411 #ifndef QUIT_TEXT
412 #define QUIT_TEXT "TOPLEFT"
413 #endif
414 #ifndef RESTART_TEXT
415 #define RESTART_TEXT "TOPRIGHT"
416 #endif
417 #ifndef LVL_UP_TEXT
418 #define LVL_UP_TEXT "BOTTOMLEFT"
419 #endif
420 #ifndef LVL_DOWN_TEXT
421 #define LVL_DOWN_TEXT "BOTTOMRIGHT"
422 #endif
423 #endif
426 /* get several sizes from the bitmaps */
427 #ifdef BMPWIDTH_pegbox_pieces
428 #define PIECE_WIDTH BMPWIDTH_pegbox_pieces
429 #define PIECE_HEIGHT (BMPHEIGHT_pegbox_pieces/7)
430 #else
431 /* dummy numbers to avoid #error in dependency generation */
432 #define PIECE_WIDTH 50
433 #define PIECE_HEIGHT 10
434 #endif
436 #define BOARD_WIDTH (12*PIECE_WIDTH)
437 #define BOARD_HEIGHT (8*PIECE_HEIGHT)
440 /* define a wide layout where the statistics are alongside the board, not above
441 * base calculation on the piece bitmaps for the 8x12 board */
442 #if (LCD_WIDTH - BOARD_WIDTH) > (LCD_HEIGHT - BOARD_HEIGHT)
443 #define WIDE_LAYOUT
444 #endif
447 #define HEADER_WIDTH BMPWIDTH_pegbox_header
448 #define HEADER_HEIGHT BMPHEIGHT_pegbox_header
451 #if defined WIDE_LAYOUT
453 #if ((BOARD_WIDTH + HEADER_WIDTH + 4) <= LCD_WIDTH)
454 #define BOARD_X 2
455 #else
456 #define BOARD_X 1
457 #endif
458 #define BOARD_Y (LCD_HEIGHT-BOARD_HEIGHT)/2
460 #if (LCD_WIDTH >= 132) && (LCD_HEIGHT >= 80)
461 #define TEXT_X 116
462 #define LEVEL_TEXT_Y 14
463 #define PEGS_TEXT_Y 58
464 #elif (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 64)
465 #define TEXT_X 112
466 #define LEVEL_TEXT_Y 27
467 #define PEGS_TEXT_Y 50
468 #else
469 #error "Unsupported screen size"
470 #endif
472 #else /* "normal" layout */
474 #define BOARD_X (LCD_WIDTH-BOARD_WIDTH)/2
475 #if ((BOARD_HEIGHT + HEADER_HEIGHT + 4) <= LCD_HEIGHT)
476 #define BOARD_Y HEADER_HEIGHT+2
477 #else
478 #define BOARD_Y HEADER_HEIGHT
479 #endif
481 #if LCD_WIDTH >= 320
482 #define LEVEL_TEXT_X 59
483 #define PEGS_TEXT_X 276
484 #define TEXT_Y 28
485 #elif LCD_WIDTH >= 240
486 #define LEVEL_TEXT_X 59
487 #define PEGS_TEXT_X 196
488 #define TEXT_Y 28
489 #elif LCD_WIDTH >= 220
490 #define LEVEL_TEXT_X 49
491 #define PEGS_TEXT_X 186
492 #define TEXT_Y 28
493 #elif LCD_WIDTH >= 176
494 #define LEVEL_TEXT_X 38
495 #define PEGS_TEXT_X 155
496 #define TEXT_Y 17
497 #elif LCD_WIDTH >= 160
498 #define LEVEL_TEXT_X 37
499 #define PEGS_TEXT_X 140
500 #define TEXT_Y 13
501 #elif LCD_WIDTH >= 138
502 #define LEVEL_TEXT_X 28
503 #define PEGS_TEXT_X 119
504 #define TEXT_Y 15
505 #elif LCD_WIDTH >= 128
506 #if HEADER_HEIGHT > 16
507 #define LEVEL_TEXT_X 26
508 #define PEGS_TEXT_X 107
509 #define TEXT_Y 31
510 #else
511 #define LEVEL_TEXT_X 15
512 #define PEGS_TEXT_X 100
513 #define TEXT_Y 5
514 #endif /* HEADER_HEIGHT */
515 #elif LCD_WIDTH >= 112
516 #define LEVEL_TEXT_X 25
517 #define PEGS_TEXT_X 90
518 #define TEXT_Y 0
519 #endif /* LCD_WIDTH */
521 #endif /* WIDE_LAYOUT */
524 #ifdef HAVE_LCD_COLOR
525 #define BG_COLOR LCD_BLACK
526 #define TEXT_BG LCD_RGBPACK(189,189,189)
527 #endif
530 #ifdef HAVE_TOUCHSCREEN
531 #include "lib/touchscreen.h"
533 static struct ts_mapping main_menu_items[5] =
535 {MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT},
536 {MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT},
537 {MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT},
538 {MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT},
540 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT > 110)
541 0, MENU_Y+4*ITEM_HEIGHT+8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
542 #elif LCD_WIDTH > 112
543 0, LCD_HEIGHT - 8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
544 #else
545 #error "Touchscreen isn't supported on non-bitmap screens!"
546 #endif
550 static struct ts_mappings main_menu = {main_menu_items, 5};
552 static struct ts_raster pegbox_raster =
553 { BOARD_X, BOARD_Y, COLS*PIECE_WIDTH, ROWS*PIECE_HEIGHT,
554 PIECE_WIDTH, PIECE_HEIGHT };
555 static struct ts_raster_button_mapping pegbox_raster_btn =
556 { &pegbox_raster, false, false, true, false, true, {0, 0}, 0, 0, 0 };
557 #endif
559 struct game_context {
560 unsigned int level;
561 unsigned int highlevel;
562 signed int player_row;
563 signed int player_col;
564 unsigned int num_left;
565 bool save_exist;
566 unsigned int playboard[ROWS][COLS];
569 char levels[NUM_LEVELS][ROWS][COLS] = {
570 /* Level 1 */
571 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
572 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
573 {1, 0, 0, 0, 7, 0, 0, 5, 0, 0, 0, 1,},
574 {1, 0, 0, 0, 0, 3, 3, 2, 0, 0, 0, 1,},
575 {1, 0, 0, 0, 4, 6, 0, 5, 0, 0, 0, 1,},
576 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
577 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
578 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
580 /* Level 2 */
581 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
582 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,},
583 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
584 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
585 {7, 0, 0, 0, 2, 2, 5, 5, 0, 0, 0, 1,},
586 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
587 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
588 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,}},
590 /* Level 3 */
591 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
592 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
593 {1, 0, 0, 0, 0, 0, 2, 0, 7, 0, 0, 0,},
594 {1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 2, 1,},
595 {1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1,},
596 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,},
597 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
598 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
600 /* Level 4 */
601 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
602 {6, 0, 4, 0, 2, 0, 2, 0, 0, 0, 0, 1,},
603 {6, 0, 3, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
604 {6, 0, 5, 0, 4, 7, 2, 0, 0, 0, 0, 1,},
605 {6, 0, 2, 0, 4, 0, 2, 0, 3, 0, 0, 1,},
606 {6, 0, 4, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
607 {6, 0, 5, 0, 4, 0, 2, 0, 0, 0, 0, 1,},
608 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
610 /* Level 5 */
611 {{0, 6, 6, 0, 4, 6, 0, 0, 6, 0, 0, 0,},
612 {0, 6, 6, 0, 4, 4, 0, 0, 6, 0, 0, 2,},
613 {2, 6, 6, 0, 6, 6, 6, 0, 1, 2, 2, 2,},
614 {0, 6, 6, 0, 6, 4, 6, 0, 1, 2, 0, 2,},
615 {0, 6, 6, 0, 6, 7, 6, 5, 6, 0, 0, 0,},
616 {2, 6, 6, 0, 6, 6, 6, 0, 6, 0, 0, 0,},
617 {0, 6, 6, 0, 4, 0, 0, 0, 6, 0, 0, 0,},
618 {0, 6, 6, 0, 0, 5, 0, 0, 6, 5, 5, 0,}},
620 /* Level 6 */
621 {{7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
622 {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,},
623 {2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0,},
624 {0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 0,},
625 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
626 {0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1,},
627 {0, 3, 0, 0, 0, 0, 0, 0, 5, 4, 6, 0,},
628 {0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1,}},
630 /* Level 7 */
631 {{1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,},
632 {1, 1, 1, 6, 0, 0, 4, 6, 0, 1, 1, 1,},
633 {1, 1, 1, 1, 0, 1, 5, 1, 0, 1, 1, 1,},
634 {1, 1, 1, 2, 3, 3, 7, 4, 2, 6, 1, 1,},
635 {1, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1,},
636 {1, 1, 1, 1, 0, 0, 5, 0, 0, 1, 0, 1,},
637 {1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,},
638 {1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,}},
640 /* Level 8 */
641 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
642 {0, 0, 3, 3, 3, 3, 3, 4, 3, 3, 0, 0,},
643 {0, 0, 3, 3, 3, 2, 3, 3, 5, 3, 0, 0,},
644 {7, 0, 3, 3, 3, 2, 3, 3, 4, 3, 0, 0,},
645 {0, 0, 3, 3, 4, 5, 3, 3, 3, 3, 0, 0,},
646 {0, 0, 3, 3, 5, 2, 3, 3, 3, 3, 0, 0,},
647 {0, 0, 3, 3, 2, 4, 3, 3, 3, 3, 0, 0,},
648 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
650 /* Level 9 */
651 {{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
652 {0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
653 {0, 0, 0, 0, 2, 4, 4, 3, 0, 1, 1, 0,},
654 {0, 1, 0, 0, 2, 1, 0, 0, 0, 1, 1, 1,},
655 {0, 0, 0, 2, 2, 7, 1, 0, 0, 0, 0, 2,},
656 {0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 1, 1,},
657 {0, 3, 1, 0, 2, 5, 5, 0, 0, 0, 3, 0,},
658 {0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0,}},
660 /* Level 10 */
661 {{1, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0,},
662 {1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 7,},
663 {0, 0, 4, 0, 6, 6, 6, 0, 0, 0, 3, 0,},
664 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
665 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
666 {0, 0, 0, 0, 6, 6, 6, 0, 3, 0, 0, 0,},
667 {1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0,},
668 {1, 1, 1, 1, 1, 2, 1, 1, 0, 0, 0, 0,}},
670 /* Level 11 */
671 {{1, 7, 1, 0, 1, 1, 6, 0, 0, 1, 1, 0,},
672 {1, 0, 0, 0, 5, 4, 6, 6, 0, 2, 2, 0,},
673 {1, 2, 1, 2, 0, 1, 6, 0, 0, 2, 2, 0,},
674 {1, 0, 0, 2, 0, 1, 0, 0, 0, 3, 3, 0,},
675 {1, 2, 1, 0, 0, 1, 0, 1, 0, 3, 3, 0,},
676 {0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0,},
677 {0, 3, 4, 3, 0, 1, 0, 1, 0, 0, 0, 0,},
678 {0, 0, 0, 0, 2, 2, 2, 1, 1, 1, 1, 1,}},
680 /* Level 12 */
681 {{7, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,},
682 {1, 2, 1, 2, 1, 2, 1, 1, 0, 0, 0, 1,},
683 {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,},
684 {1, 2, 1, 2, 1, 2, 1, 0, 0, 0, 0, 1,},
685 {0, 0, 0, 0, 0, 0, 1, 1, 5, 5, 6, 1,},
686 {1, 2, 1, 2, 1, 2, 1, 1, 0, 2, 2, 1,},
687 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1,},
688 {1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,}},
690 /* Level 13 */
691 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
692 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
693 {0, 0, 2, 0, 5, 0, 2, 0, 4, 0, 0, 6,},
694 {7, 0, 3, 0, 4, 0, 5, 0, 4, 0, 0, 6,},
695 {0, 0, 5, 0, 4, 0, 2, 0, 4, 0, 0, 6,},
696 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
697 {0, 0, 3, 0, 3, 0, 2, 0, 4, 0, 0, 6,},
698 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
700 /* Level 14 */
701 {{1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,},
702 {1, 1, 0, 2, 0, 0, 4, 0, 0, 2, 0, 1,},
703 {1, 6, 0, 0, 5, 1, 0, 1, 1, 0, 0, 1,},
704 {1, 1, 1, 0, 0, 3, 5, 3, 0, 0, 1, 1,},
705 {1, 1, 0, 0, 1, 1, 0, 1, 5, 0, 0, 6,},
706 {1, 1, 0, 2, 0, 0, 4, 0, 0, 0, 7, 1,},
707 {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,},
708 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
710 /* Level 15 */
711 {{0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
712 {0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
713 {0, 3, 4, 6, 0, 6, 0, 6, 0, 6, 0, 2,},
714 {0, 4, 0, 6, 0, 6, 4, 6, 0, 6, 0, 1,},
715 {0, 3, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
716 {7, 0, 0, 6, 4, 6, 0, 6, 0, 6, 0, 1,},
717 {0, 0, 4, 6, 0, 6, 0, 6, 4, 6, 0, 1,},
718 {0, 0, 4, 6, 0, 6, 0, 6, 0, 6, 0, 1,}}
722 /*****************************************************************************
723 * display_text() formats and outputs text.
724 ******************************************************************************/
725 static void display_text(char *str, bool waitkey)
727 int chars_by_line;
728 int lines_by_screen;
729 int chars_for_line;
730 int current_line = 0;
731 int char_width, char_height;
732 int first_char_index = 0;
733 char *ptr_char;
734 char *ptr_line;
735 int i;
736 char line[255];
737 int key;
738 bool go_on;
740 rb->lcd_clear_display();
742 rb->lcd_getstringsize("a", &char_width, &char_height);
744 chars_by_line = LCD_WIDTH / char_width;
745 lines_by_screen = LCD_HEIGHT / char_height;
749 ptr_char = str + first_char_index;
750 chars_for_line = 0;
751 i = 0;
752 ptr_line = line;
753 while (i < chars_by_line)
755 switch (*ptr_char)
757 case '\t':
758 case ' ':
759 *(ptr_line++) = ' ';
760 case '\n':
761 case '\0':
762 chars_for_line = i;
763 break;
765 default:
766 *(ptr_line++) = *ptr_char;
768 if (*ptr_char == '\n' || *ptr_char == '\0')
769 break;
770 ptr_char++;
771 i++;
774 if (chars_for_line == 0)
775 chars_for_line = i;
777 line[chars_for_line] = '\0';
779 /* test if we have cut a word. If it is the case we don't have to */
780 /* skip the space */
781 if (i == chars_by_line && chars_for_line == chars_by_line)
782 first_char_index += chars_for_line;
783 else
784 first_char_index += chars_for_line + 1;
786 /* print the line on the screen */
787 rb->lcd_putsxy(0, current_line * char_height, line);
789 /* if the number of line showed on the screen is equals to the */
790 /* maximum number of line we can show, we wait for a key pressed to */
791 /* clear and show the remaining text. */
792 current_line++;
793 if (current_line == lines_by_screen || *ptr_char == '\0')
795 current_line = 0;
796 rb->lcd_update();
797 go_on = false;
798 while (waitkey && !go_on)
800 key = rb->button_get(true);
801 switch (key)
803 #ifdef HAVE_TOUCHSCREEN
804 case BUTTON_TOUCHSCREEN:
805 #endif
806 case PEGBOX_QUIT:
807 case PEGBOX_LEFT:
808 case PEGBOX_DOWN:
809 go_on = true;
810 break;
812 default:
813 /*if (rb->default_event_handler(key) == SYS_USB_CONNECTED)
815 usb_detected = true;
816 go_on = true;
817 break;
819 break;
822 rb->lcd_clear_display();
824 } while (*ptr_char != '\0');
827 /*****************************************************************************
828 * draw_board() draws the game's current level.
829 ******************************************************************************/
830 static void draw_board(struct game_context* pb) {
831 unsigned int r, c, type;
832 pb->num_left = 0;
833 char str[5];
835 rb->lcd_clear_display();
836 #ifdef WIDE_LAYOUT
837 rb->lcd_bitmap(pegbox_header,LCD_WIDTH-HEADER_WIDTH,0,
838 HEADER_WIDTH,LCD_HEIGHT);
839 #else
840 rb->lcd_bitmap(pegbox_header,(LCD_WIDTH-HEADER_WIDTH)/2,0,
841 HEADER_WIDTH, HEADER_HEIGHT);
842 #endif /* WIDE_LAYOUT */
844 #if ((BOARD_HEIGHT + HEADER_HEIGHT + 4) <= LCD_HEIGHT)
845 rb->lcd_drawrect(BOARD_X-2,BOARD_Y-2,BOARD_WIDTH+4,BOARD_HEIGHT+4);
846 #endif /* enough space for a frame? */
848 #ifdef HAVE_LCD_COLOR
849 rb->lcd_set_foreground(LCD_WHITE);
850 rb->lcd_fillrect(BOARD_X-1,BOARD_Y-1,BOARD_WIDTH+2,BOARD_HEIGHT+2);
851 rb->lcd_set_foreground(LCD_BLACK);
852 rb->lcd_set_background(TEXT_BG);
853 #endif
855 for (r=0 ; r < ROWS ; r++) {
856 for (c = 0 ; c < COLS ; c++) {
858 type = pb->playboard[r][c];
860 switch(type) {
861 case SPACE:
862 break;
864 default:
865 rb->lcd_bitmap_part(pegbox_pieces, 0, (type-1)*PIECE_HEIGHT,
866 PIECE_WIDTH, c * PIECE_WIDTH + BOARD_X,
867 r * PIECE_HEIGHT + BOARD_Y, PIECE_WIDTH,
868 PIECE_HEIGHT);
869 break;
872 if(pb->playboard[r][c] == PLAYER) {
873 pb->player_row=r;
874 pb->player_col=c;
876 else if (type != WALL && type != SPACE && type != HOLE)
877 pb->num_left++;
881 #ifdef WIDE_LAYOUT
882 rb->snprintf(str, 3, "%d", pb->level);
883 rb->lcd_putsxy(TEXT_X, LEVEL_TEXT_Y, str);
884 rb->snprintf(str, 3, "%d", pb->num_left);
885 rb->lcd_putsxy(TEXT_X, PEGS_TEXT_Y, str);
886 #else
887 rb->snprintf(str, 3, "%d", pb->level);
888 rb->lcd_putsxy(LEVEL_TEXT_X, TEXT_Y, str);
889 rb->snprintf(str, 3, "%d", pb->num_left);
890 rb->lcd_putsxy(PEGS_TEXT_X, TEXT_Y, str);
891 #endif /*WIDE_LAYOUT*/
893 #ifdef HAVE_LCD_COLOR
894 rb->lcd_set_background(BG_COLOR);
895 rb->lcd_set_foreground(LCD_WHITE);
896 #endif
897 /* print out the screen */
898 rb->lcd_update();
901 /*****************************************************************************
902 * load_level() loads the player's current level from the array and sets the
903 * player's position.
904 ******************************************************************************/
905 static void load_level(struct game_context* pb) {
906 int r, c;
908 for(r = 0; r < ROWS; r++)
909 for(c = 0; c < COLS; c++)
910 pb->playboard[r][c] = levels[pb->level-1][r][c];
913 /*****************************************************************************
914 * new_piece() creates a new piece at a specified location. The player
915 * navigates through the pieces and selects one.
916 ******************************************************************************/
917 static void new_piece(struct game_context* pb, unsigned int x_loc,
918 unsigned int y_loc) {
919 int button;
920 bool exit = false;
922 pb->playboard[x_loc][y_loc] = TRIANGLE;
924 while (!exit) {
925 draw_board(pb);
926 button = rb->button_get(true);
927 #ifdef HAVE_TOUCHSCREEN
928 if(button & BUTTON_TOUCHSCREEN)
930 pegbox_raster_btn.two_d_from.y = x_loc;
931 pegbox_raster_btn.two_d_from.x = y_loc;
933 struct ts_raster_button_result ret =
934 touchscreen_raster_map_button(&pegbox_raster_btn,
935 rb->button_get_data() >> 16,
936 rb->button_get_data() & 0xffff,
937 button);
938 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
940 if(ret.to.x > ret.from.x)
941 button = PEGBOX_UP;
942 else if(ret.to.x < ret.from.x)
943 button = PEGBOX_DOWN;
944 else if(ret.to.y > ret.from.y)
945 button = PEGBOX_LEFT;
946 else if(ret.to.y < ret.from.y)
947 button = PEGBOX_RIGHT;
949 else if(ret.action == TS_ACTION_CLICK
950 && (unsigned)ret.to.x == y_loc
951 && (unsigned)ret.to.y == x_loc)
952 button = PEGBOX_SAVE;
954 #endif
955 switch(button){
956 case PEGBOX_LEFT:
957 case (PEGBOX_LEFT|BUTTON_REPEAT):
958 case PEGBOX_DOWN:
959 case (PEGBOX_DOWN|BUTTON_REPEAT):
960 if (pb->playboard[x_loc][y_loc] < 5)
961 pb->playboard[x_loc][y_loc]++;
962 else
963 pb->playboard[x_loc][y_loc] = TRIANGLE;
964 break;
965 case PEGBOX_RIGHT:
966 case (PEGBOX_RIGHT|BUTTON_REPEAT):
967 case PEGBOX_UP:
968 case (PEGBOX_UP|BUTTON_REPEAT):
969 if (pb->playboard[x_loc][y_loc] > 2)
970 pb->playboard[x_loc][y_loc]--;
971 else
972 pb->playboard[x_loc][y_loc] = CIRCLE;
973 break;
974 case PEGBOX_SAVE:
975 exit = true;
976 break;
981 /*****************************************************************************
982 * move_player() moves the player and pieces and updates the board accordingly.
983 ******************************************************************************/
984 static void move_player(struct game_context* pb, signed int x_dir,
985 signed int y_dir) {
986 unsigned int type1, type2;
987 signed int r,c;
989 r = pb->player_row+y_dir;
990 c = pb->player_col+x_dir;
992 type1 = pb->playboard[r][c];
993 type2 = pb->playboard[r+y_dir][c+x_dir];
995 if (r == ROWS || c == COLS || r < 0 || c < 0 || type1 == WALL)
996 return;
997 else if(type1 != SPACE) {
998 if (type2 == WALL || r+y_dir == ROWS || c+x_dir == COLS ||
999 r+y_dir < 0 || c+x_dir < 0)
1000 return;
1004 pb->playboard[pb->player_row][pb->player_col] = SPACE;
1005 pb->player_row += y_dir;
1006 pb->player_col += x_dir;
1008 if (type1 == HOLE) {
1009 draw_board(pb);
1010 rb->splash(HZ*2, "You fell down a hole!");
1011 load_level(pb);
1013 else if (type1 == SPACE)
1014 pb->playboard[r][c] = PLAYER;
1015 else {
1016 pb->playboard[r][c] = PLAYER;
1017 if(type1 == type2) {
1018 if (type1 == TRIANGLE)
1019 pb->playboard[r+y_dir][c+x_dir] = WALL;
1020 else if (type1 == CROSS) {
1021 pb->playboard[r][c] = SPACE;
1022 new_piece(pb, r+y_dir, c+x_dir);
1023 pb->playboard[r][c] = PLAYER;
1025 else
1026 pb->playboard[r+y_dir][c+x_dir] = SPACE;
1028 else if (type2 == SPACE)
1029 pb->playboard[r+y_dir][c+x_dir] = type1;
1030 else if (type2 == HOLE) {
1031 if (type1 == SQUARE)
1032 pb->playboard[r+y_dir][c+x_dir] = SPACE;
1034 else {
1035 rb->splash(HZ*2, "Illegal Move!");
1036 load_level(pb);
1040 draw_board(pb);
1043 /*****************************************************************************
1044 * pegbox_loadgame() loads the saved game and returns load success.
1045 ******************************************************************************/
1046 static bool pegbox_loadgame(struct game_context* pb) {
1047 signed int fd;
1048 bool loaded = false;
1050 /* open game file */
1051 fd = rb->open(SAVE_FILE, O_RDONLY);
1052 if(fd < 0) return loaded;
1054 /* read in saved game */
1055 while(true) {
1056 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
1057 if(rb->read(fd, &pb->playboard, sizeof(pb->playboard)) <= 0)
1059 loaded = true;
1060 break;
1062 break;
1065 rb->close(fd);
1066 return loaded;
1069 /*****************************************************************************
1070 * pegbox_savegame() saves the current game state.
1071 ******************************************************************************/
1072 static void pegbox_savegame(struct game_context* pb) {
1073 unsigned int fd;
1075 /* write out the game state to the save file */
1076 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
1077 rb->write(fd, &pb->level, sizeof(pb->level));
1078 rb->write(fd, &pb->playboard, sizeof(pb->playboard));
1079 rb->close(fd);
1082 /*****************************************************************************
1083 * pegbox_loaddata() loads the level and highlevel and returns load success.
1084 ******************************************************************************/
1085 static void pegbox_loaddata(struct game_context* pb) {
1086 signed int fd;
1088 /* open game file */
1089 fd = rb->open(DATA_FILE, O_RDONLY);
1090 if(fd < 0) {
1091 pb->level = 1;
1092 pb->highlevel = 1;
1093 return;
1096 /* read in saved game */
1097 while(true) {
1098 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
1099 if(rb->read(fd, &pb->highlevel, sizeof(pb->highlevel)) <= 0) break;
1100 break;
1103 rb->close(fd);
1104 return;
1107 /*****************************************************************************
1108 * pegbox_savedata() saves the level and highlevel.
1109 ******************************************************************************/
1110 static void pegbox_savedata(struct game_context* pb) {
1111 unsigned int fd;
1113 /* write out the game state to the save file */
1114 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT);
1115 rb->write(fd, &pb->level, sizeof(pb->level));
1116 rb->write(fd, &pb->highlevel, sizeof(pb->highlevel));
1117 rb->close(fd);
1120 /*****************************************************************************
1121 * pegbox_callback() is the default event handler callback which is called
1122 * on usb connect and shutdown.
1123 ******************************************************************************/
1124 static void pegbox_callback(void* param) {
1125 struct game_context* pb = (struct game_context*) param;
1126 rb->splash(HZ, "Saving data...");
1127 pegbox_savedata(pb);
1130 /*****************************************************************************
1131 * pegbox_menu() is the initial menu at the start of the game.
1132 ******************************************************************************/
1133 static unsigned int pegbox_menu(struct game_context* pb) {
1134 int button;
1135 char str[30];
1136 unsigned int startlevel = 1, loc = 0;
1137 bool breakout = false, can_resume = false;
1139 if (pb->num_left > 0 || pb->save_exist)
1140 can_resume = true;
1142 while(!breakout){
1143 #if LCD_HEIGHT >= 80
1144 rb->lcd_clear_display();
1145 rb->lcd_bitmap(pegbox_menu_top,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_menu_top);
1147 /* menu bitmaps */
1148 if (loc == 0) {
1149 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT, ITEM_WIDTH,
1150 MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT);
1152 else {
1153 rb->lcd_bitmap_part(pegbox_menu_items, 0, 0, ITEM_WIDTH,
1154 MENU_X, MENU_Y, ITEM_WIDTH, ITEM_HEIGHT);
1156 if (can_resume) {
1157 if (loc == 1) {
1158 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*3, ITEM_WIDTH,
1159 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1161 else {
1162 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*2, ITEM_WIDTH,
1163 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1166 else {
1167 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*4, ITEM_WIDTH,
1168 MENU_X, MENU_Y+ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
1171 if (loc==2) {
1172 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*6, ITEM_WIDTH,
1173 MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT);
1175 else {
1176 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*5, ITEM_WIDTH,
1177 MENU_X, MENU_Y+ITEM_HEIGHT*2, ITEM_WIDTH, ITEM_HEIGHT);
1180 if (loc==3) {
1181 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*8, ITEM_WIDTH,
1182 MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT);
1184 else {
1185 rb->lcd_bitmap_part(pegbox_menu_items, 0, ITEM_HEIGHT*7, ITEM_WIDTH,
1186 MENU_X, MENU_Y+ITEM_HEIGHT*3, ITEM_WIDTH, ITEM_HEIGHT);
1188 #else
1189 unsigned int w,h;
1190 rb->lcd_clear_display();
1191 rb->lcd_getstringsize("PegBox", &w, &h);
1192 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, "PegBox");
1193 rb->lcd_putsxy((LCD_WIDTH)/4, 16, "New Game");
1194 rb->lcd_putsxy((LCD_WIDTH)/4, 24, "Resume");
1195 rb->lcd_putsxy((LCD_WIDTH)/4, 32, "Help");
1196 rb->lcd_putsxy((LCD_WIDTH)/4, 40, "Quit");
1198 if(!can_resume)
1199 rb->lcd_hline((LCD_WIDTH)/4, (LCD_WIDTH)/4+30, 28);
1201 rb->lcd_putsxy((LCD_WIDTH)/4-8, loc*8+16, "*");
1204 #endif
1205 rb->snprintf(str, 28, "Start on level %d of %d", startlevel,
1206 pb->highlevel);
1207 #if LCD_HEIGHT > 110
1208 rb->lcd_putsxy(0, MENU_Y+4*ITEM_HEIGHT+8, str);
1209 #elif LCD_HEIGHT > 64
1210 rb->lcd_putsxy(0, LCD_HEIGHT - 8, str);
1211 #else
1212 rb->lcd_puts_scroll(0, 7, str);
1213 #endif
1214 rb->lcd_update();
1216 /* handle menu button presses */
1217 button = rb->button_get(true);
1219 #ifdef HAVE_TOUCHSCREEN
1220 if(button & BUTTON_TOUCHSCREEN)
1222 unsigned int result = touchscreen_map(&main_menu,
1223 rb->button_get_data() >> 16,
1224 rb->button_get_data() & 0xffff);
1225 if(result != (unsigned)-1 && button & BUTTON_REL)
1227 if(result == 4)
1228 button = PEGBOX_LVL_UP;
1229 else
1231 if(loc == result)
1232 button = PEGBOX_RIGHT;
1233 loc = result;
1237 #endif
1239 switch(button) {
1240 case PEGBOX_SAVE: /* start playing */
1241 case PEGBOX_RIGHT:
1242 if (loc == 0) {
1243 breakout = true;
1244 pb->level = startlevel;
1245 load_level(pb);
1247 else if (loc == 1 && can_resume) {
1248 if(pb->save_exist)
1250 rb->remove(SAVE_FILE);
1251 pb->save_exist = false;
1253 breakout = true;
1255 else if (loc == 2)
1256 display_text("How to Play\nTo beat each level, you must "
1257 "destroy all of the pegs. If two like pegs are "
1258 "pushed into each other they disappear except "
1259 "for triangles which form a solid block and "
1260 "crosses which allow you to choose a "
1261 "replacement block.\n\n"
1262 "Controls\n"
1263 #if LCD_HEIGHT > 64
1264 RESTART_TEXT " to restart level\n"
1265 LVL_UP_TEXT " to go up a level\n"
1266 LVL_DOWN_TEXT " to go down a level\n"
1267 SAVE_TEXT " to select/save\n"
1268 QUIT_TEXT " to quit\n",true);
1269 #else
1270 RESTART_TEXT ": restart\n"
1271 LVL_UP_TEXT ": level up\n"
1272 LVL_DOWN_TEXT " level down\n"
1273 SAVE_TEXT " select/save\n"
1274 QUIT_TEXT " quit\n",true);
1275 #endif
1276 else if (loc == 3)
1277 return PB_QUIT;
1278 break;
1280 case PEGBOX_QUIT: /* quit program */
1281 return PB_QUIT;
1283 case (PEGBOX_UP|BUTTON_REPEAT):
1284 case PEGBOX_UP:
1285 if (loc <= 0)
1286 loc = 3;
1287 else
1288 loc--;
1289 if (!can_resume && loc == 1) {
1290 loc = 0;
1292 break;
1295 case (PEGBOX_DOWN|BUTTON_REPEAT):
1296 case PEGBOX_DOWN:
1297 if (loc >= 3)
1298 loc = 0;
1299 else
1300 loc++;
1301 if (!can_resume && loc == 1) {
1302 loc = 2;
1304 break;
1306 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1307 case PEGBOX_LVL_UP: /* increase starting level */
1308 if(startlevel >= pb->highlevel) {
1309 startlevel = 1;
1310 } else {
1311 startlevel++;
1313 break;
1315 /* only for targets with enough buttons */
1316 #ifdef PEGBOX_LVL_DOWN
1317 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1318 case PEGBOX_LVL_DOWN: /* decrease starting level */
1319 if(startlevel <= 1) {
1320 startlevel = pb->highlevel;
1321 } else {
1322 startlevel--;
1324 break;
1325 #endif
1326 default:
1327 if(rb->default_event_handler_ex(button, pegbox_callback,
1328 (void*) pb) == SYS_USB_CONNECTED)
1329 return PB_USB;
1330 break;
1334 draw_board(pb);
1336 return 0;
1339 /*****************************************************************************
1340 * pegbox() is the main game subroutine, it returns the final game status.
1341 ******************************************************************************/
1342 static int pegbox(struct game_context* pb) {
1343 int temp_var;
1345 /********************
1346 * menu *
1347 ********************/
1348 temp_var = pegbox_menu(pb);
1349 if (temp_var == PB_QUIT || temp_var == PB_USB)
1350 return temp_var;
1352 while (true) {
1353 temp_var = rb->button_get(true);
1354 #ifdef HAVE_TOUCHSCREEN
1355 if(temp_var & BUTTON_TOUCHSCREEN)
1357 pegbox_raster_btn.two_d_from.y = pb->player_row;
1358 pegbox_raster_btn.two_d_from.x = pb->player_col;
1360 struct ts_raster_button_result ret =
1361 touchscreen_raster_map_button(&pegbox_raster_btn,
1362 rb->button_get_data() >> 16,
1363 rb->button_get_data() & 0xffff,
1364 temp_var);
1365 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
1366 move_player(pb, ret.to.x - ret.from.x, ret.to.y - ret.from.y);
1368 #endif
1369 switch(temp_var){
1370 case PEGBOX_LEFT: /* move cursor left */
1371 case (PEGBOX_LEFT|BUTTON_REPEAT):
1372 move_player(pb, -1, 0);
1373 break;
1375 case PEGBOX_RIGHT: /* move cursor right */
1376 case (PEGBOX_RIGHT|BUTTON_REPEAT):
1377 move_player(pb, 1, 0);
1378 break;
1380 case PEGBOX_DOWN: /* move cursor down */
1381 case (PEGBOX_DOWN|BUTTON_REPEAT):
1382 move_player(pb, 0, 1);
1383 break;
1385 case PEGBOX_UP: /* move cursor up */
1386 case (PEGBOX_UP|BUTTON_REPEAT):
1387 move_player(pb, 0, -1);
1388 break;
1390 case PEGBOX_SAVE: /* save and end game */
1391 rb->splash(HZ, "Saving game...");
1392 pegbox_savegame(pb);
1393 /* fall through to PEGBOX_QUIT */
1395 case PEGBOX_QUIT:
1396 return PB_END;
1398 case PEGBOX_RESTART:
1399 load_level(pb);
1400 draw_board(pb);
1401 break;
1403 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1404 case PEGBOX_LVL_UP:
1405 if(pb->level >= pb->highlevel) {
1406 pb->level = 1;
1407 } else {
1408 pb->level++;
1410 load_level(pb);
1411 draw_board(pb);
1412 break;
1414 /* only for targets with enough buttons */
1415 #ifdef PEGBOX_LVL_DOWN
1416 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1417 case PEGBOX_LVL_DOWN:
1418 if(pb->level <= 1) {
1419 pb->level = pb->highlevel;
1420 } else {
1421 pb->level--;
1423 load_level(pb);
1424 draw_board(pb);
1425 break;
1426 #endif
1430 if(pb->num_left == 0) {
1431 rb->splash(HZ*2, "Nice Pegging!");
1432 if(pb->level == NUM_LEVELS) {
1433 draw_board(pb);
1434 rb->splash(HZ*2, "You Won!");
1435 break;
1437 else {
1438 pb->level++;
1439 load_level(pb);
1440 draw_board(pb);
1443 if(pb->level > pb->highlevel)
1444 pb->highlevel = pb->level;
1449 return PLUGIN_OK;
1453 /*****************************************************************************
1454 * plugin entry point.
1455 ******************************************************************************/
1456 enum plugin_status plugin_start(const void* parameter) {
1457 bool exit = false;
1458 struct game_context pb;
1460 (void)parameter;
1462 rb->lcd_setfont(FONT_SYSFIXED);
1463 #if LCD_DEPTH > 1
1464 rb->lcd_set_backdrop(NULL);
1465 #endif
1466 #ifdef HAVE_LCD_COLOR
1467 rb->lcd_set_foreground(LCD_WHITE);
1468 rb->lcd_set_background(BG_COLOR);
1469 #endif
1471 rb->splash(0, "Loading...");
1472 pegbox_loaddata(&pb);
1473 pb.save_exist = pegbox_loadgame(&pb);
1474 pb.num_left = 0;
1476 rb->lcd_clear_display();
1479 while(!exit) {
1480 switch(pegbox(&pb)){
1481 case PB_END:
1482 break;
1484 case PB_USB:
1485 rb->lcd_setfont(FONT_UI);
1486 return PLUGIN_USB_CONNECTED;
1488 case PB_QUIT:
1489 rb->splash(HZ, "Saving data...");
1490 pegbox_savedata(&pb);
1491 exit = true;
1492 break;
1494 default:
1495 break;
1499 rb->lcd_setfont(FONT_UI);
1500 return PLUGIN_OK;