fixing red:
[Rockbox.git] / apps / plugins / pegbox.c
blob1ca3a0a058ac48169eb1e77e425dc8d1e0d1b4a3
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Tom Ross
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include "plugin.h"
21 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
22 #include "pegbox_menu_top.h"
23 #include "pegbox_menu_items.h"
24 #include "pegbox_header.h"
25 #endif
26 #include "pegbox_pieces.h"
28 static struct plugin_api* rb;
30 PLUGIN_HEADER
32 /* final game return status */
33 #define PB_END 3
34 #define PB_USB 2
35 #define PB_QUIT 1
37 #define DATA_FILE PLUGIN_DIR "/games/pegbox.data"
38 #define SAVE_FILE PLUGIN_DIR "/games/pegbox.save"
40 #define ROWS 8 /* Number of rows on each board */
41 #define COLS 12 /* Number of columns on each board */
42 #define NUM_LEVELS 15 /* Number of levels */
44 #define SPACE 0
45 #define WALL 1
46 #define TRIANGLE 2
47 #define CROSS 3
48 #define SQUARE 4
49 #define CIRCLE 5
50 #define HOLE 6
51 #define PLAYER 7
53 #if CONFIG_KEYPAD == RECORDER_PAD
54 #define PEGBOX_SELECT BUTTON_ON
55 #define PEGBOX_QUIT BUTTON_OFF
56 #define PEGBOX_SAVE BUTTON_F2
57 #define PEGBOX_RESTART BUTTON_ON
58 #define PEGBOX_LVL_UP BUTTON_F1
59 #define PEGBOX_LVL_DOWN BUTTON_F3
60 #define PEGBOX_UP BUTTON_UP
61 #define PEGBOX_DOWN BUTTON_DOWN
62 #define PEGBOX_RIGHT BUTTON_RIGHT
63 #define PEGBOX_LEFT BUTTON_LEFT
65 #define RESTART_TEXT "ON"
66 #define LVL_UP_TEXT "F1"
67 #define LVL_DOWN_TEXT "F3"
68 #define SAVE_TEXT "F2"
69 #define QUIT_TEXT "OFF"
71 #elif CONFIG_KEYPAD == ONDIO_PAD
72 #define PEGBOX_SELECT BUTTON_MENU
73 #define PEGBOX_QUIT BUTTON_OFF
74 #define PEGBOX_SAVE (BUTTON_MENU | BUTTON_UP)
75 #define PEGBOX_RESTART (BUTTON_MENU | BUTTON_DOWN)
76 #define PEGBOX_LVL_UP (BUTTON_MENU | BUTTON_LEFT)
77 #define PEGBOX_LVL_DOWN (BUTTON_MENU | BUTTON_RIGHT)
78 #define PEGBOX_UP BUTTON_UP
79 #define PEGBOX_DOWN BUTTON_DOWN
80 #define PEGBOX_RIGHT BUTTON_RIGHT
81 #define PEGBOX_LEFT BUTTON_LEFT
83 #define RESTART_TEXT "M+DOWN"
84 #define LVL_UP_TEXT "M+RIGHT"
85 #define LVL_DOWN_TEXT "M+LEFT"
86 #define SAVE_TEXT "M+UP"
87 #define QUIT_TEXT "OFF"
89 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
90 (CONFIG_KEYPAD == IRIVER_H300_PAD)
91 #define PEGBOX_SELECT BUTTON_SELECT
92 #define PEGBOX_QUIT BUTTON_OFF
93 #define PEGBOX_SAVE BUTTON_MODE
94 #define PEGBOX_RESTART BUTTON_SELECT
95 #define PEGBOX_LVL_UP BUTTON_ON
96 #define PEGBOX_LVL_DOWN BUTTON_REC
97 #define PEGBOX_UP BUTTON_UP
98 #define PEGBOX_DOWN BUTTON_DOWN
99 #define PEGBOX_RIGHT BUTTON_RIGHT
100 #define PEGBOX_LEFT BUTTON_LEFT
102 #define RESTART_TEXT "NAVI"
103 #define LVL_UP_TEXT "PLAY"
104 #define LVL_DOWN_TEXT "REC"
105 #define SAVE_TEXT "AB"
106 #define QUIT_TEXT "OFF"
108 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
109 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
110 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
111 #define PEGBOX_SELECT (BUTTON_SELECT|BUTTON_REL)
112 #define PEGBOX_QUIT (BUTTON_SELECT|BUTTON_MENU)
113 #define PEGBOX_SAVE (BUTTON_SELECT|BUTTON_RIGHT)
114 #define PEGBOX_RESTART (BUTTON_SELECT|BUTTON_LEFT)
115 #define PEGBOX_LVL_UP BUTTON_SCROLL_BACK
116 #define PEGBOX_LVL_DOWN BUTTON_SCROLL_FWD
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 RESTART_TEXT "SELECT+LEFT"
123 #define LVL_UP_TEXT "SCROLL BACK"
124 #define LVL_DOWN_TEXT "SCROLL FWD"
125 #define SAVE_TEXT "SELECT+RIGHT"
126 #define QUIT_TEXT "SELECT+MENU"
128 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
129 #define PEGBOX_SELECT BUTTON_SELECT
130 #define PEGBOX_QUIT BUTTON_POWER
131 #define PEGBOX_SAVE BUTTON_PLAY
132 #define PEGBOX_RESTART BUTTON_REC
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 RESTART_TEXT "REC"
139 #define LVL_UP_TEXT "-"
140 #define LVL_DOWN_TEXT "-"
141 #define SAVE_TEXT "PLAY"
142 #define QUIT_TEXT "OFF"
144 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
145 #define PEGBOX_SELECT BUTTON_MODE
146 #define PEGBOX_QUIT BUTTON_PLAY
147 #define PEGBOX_SAVE (BUTTON_EQ|BUTTON_MODE)
148 #define PEGBOX_RESTART BUTTON_MODE
149 #define PEGBOX_LVL_UP (BUTTON_EQ|BUTTON_UP)
150 #define PEGBOX_LVL_DOWN (BUTTON_EQ|BUTTON_DOWN)
151 #define PEGBOX_UP BUTTON_UP
152 #define PEGBOX_DOWN BUTTON_DOWN
153 #define PEGBOX_RIGHT BUTTON_RIGHT
154 #define PEGBOX_LEFT BUTTON_LEFT
156 #define RESTART_TEXT "MODE"
157 #define LVL_UP_TEXT "EQ+UP"
158 #define LVL_DOWN_TEXT "EQ+DOWN"
159 #define SAVE_TEXT "EQ+MODE"
160 #define QUIT_TEXT "PLAY"
162 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
163 #define PEGBOX_SELECT BUTTON_PLAY
164 #define PEGBOX_QUIT BUTTON_POWER
165 #define PEGBOX_SAVE BUTTON_FF
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 RESTART_TEXT "LONG FF"
175 #define LVL_UP_TEXT "FF+SCROLL_UP"
176 #define LVL_DOWN_TEXT "FF+SCROLL_DOWN"
177 #define SAVE_TEXT "FF"
178 #define QUIT_TEXT "OFF"
180 #elif CONFIG_KEYPAD == SANSA_E200_PAD
181 #define PEGBOX_SELECT BUTTON_SELECT
182 #define PEGBOX_QUIT BUTTON_POWER
183 #define PEGBOX_SAVE BUTTON_REC
184 #define PEGBOX_RESTART BUTTON_SELECT
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 RESTART_TEXT "SELECT"
193 #define LVL_UP_TEXT "SCROLL_UP"
194 #define LVL_DOWN_TEXT "SCROLL_DOWN"
195 #define SAVE_TEXT "REC"
196 #define QUIT_TEXT "POWER"
198 #elif CONFIG_KEYPAD == GIGABEAT_PAD
199 #define PEGBOX_SELECT BUTTON_SELECT
200 #define PEGBOX_QUIT BUTTON_POWER
201 #define PEGBOX_SAVE BUTTON_MENU
202 #define PEGBOX_RESTART BUTTON_A
203 #define PEGBOX_LVL_UP BUTTON_VOL_UP
204 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
205 #define PEGBOX_UP BUTTON_UP
206 #define PEGBOX_DOWN BUTTON_DOWN
207 #define PEGBOX_RIGHT BUTTON_RIGHT
208 #define PEGBOX_LEFT BUTTON_LEFT
210 #define RESTART_TEXT "POWER"
211 #define LVL_UP_TEXT "VOL+"
212 #define LVL_DOWN_TEXT "VOL-"
213 #define SAVE_TEXT "MENU"
214 #define QUIT_TEXT "A"
216 #elif CONFIG_KEYPAD == MROBE100_PAD
217 #define PEGBOX_SELECT BUTTON_SELECT
218 #define PEGBOX_QUIT BUTTON_POWER
219 #define PEGBOX_SAVE BUTTON_MENU
220 #define PEGBOX_RESTART BUTTON_PLAY
221 #define PEGBOX_LVL_UP (BUTTON_DISPLAY | BUTTON_REL)
222 #define PEGBOX_LVL_DOWN (BUTTON_DISPLAY | BUTTON_REPEAT)
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 RESTART_TEXT "PLAY"
229 #define LVL_UP_TEXT "DISPLAY+UP"
230 #define LVL_DOWN_TEXT "DISPLAY+DOWN"
231 #define SAVE_TEXT "MENU"
232 #define QUIT_TEXT "POWER"
234 #elif CONFIG_KEYPAD == SANSA_C200_PAD
235 #define PEGBOX_SELECT BUTTON_SELECT
236 #define PEGBOX_QUIT BUTTON_POWER
237 #define PEGBOX_SAVE (BUTTON_REC | BUTTON_SELECT)
238 #define PEGBOX_RESTART (BUTTON_REC | BUTTON_REL)
239 #define PEGBOX_LVL_UP BUTTON_VOL_UP
240 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
241 #define PEGBOX_UP BUTTON_UP
242 #define PEGBOX_DOWN BUTTON_DOWN
243 #define PEGBOX_RIGHT BUTTON_RIGHT
244 #define PEGBOX_LEFT BUTTON_LEFT
246 #define RESTART_TEXT "REC"
247 #define LVL_UP_TEXT "VOL+"
248 #define LVL_DOWN_TEXT "VOL-"
249 #define SAVE_TEXT "REC+SELECT"
250 #define QUIT_TEXT "POWER"
252 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
253 #define PEGBOX_SELECT BUTTON_RC_PLAY
254 #define PEGBOX_QUIT BUTTON_RC_REC
255 #define PEGBOX_SAVE BUTTON_RC_MENU
256 #define PEGBOX_RESTART BUTTON_RC_MODE
257 #define PEGBOX_LVL_UP BUTTON_VOL_UP
258 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
259 #define PEGBOX_UP BUTTON_RC_VOL_UP
260 #define PEGBOX_DOWN BUTTON_RC_VOL_DOWN
261 #define PEGBOX_RIGHT BUTTON_RC_FF
262 #define PEGBOX_LEFT BUTTON_RC_REW
264 #define RESTART_TEXT "REM. MODE"
265 #define LVL_UP_TEXT "VOL+"
266 #define LVL_DOWN_TEXT "VOL-"
267 #define SAVE_TEXT "REM. PLAY"
268 #define QUIT_TEXT "REM. REC"
270 #elif CONFIG_KEYPAD == COWOND2_PAD
271 #define PEGBOX_SELECT BUTTON_SELECT
272 #define PEGBOX_QUIT BUTTON_POWER
273 #define PEGBOX_SAVE BUTTON_MENU
274 #define PEGBOX_RESTART BUTTON_MINUS
275 #define PEGBOX_LVL_UP BUTTON_PLUS
276 #define PEGBOX_UP BUTTON_UP
277 #define PEGBOX_DOWN BUTTON_DOWN
278 #define PEGBOX_RIGHT BUTTON_RIGHT
279 #define PEGBOX_LEFT BUTTON_LEFT
281 #define RESTART_TEXT "MINUS"
282 #define LVL_UP_TEXT "PLUS"
283 #define LVL_DOWN_TEXT "-"
284 #define SAVE_TEXT "MENU"
285 #define QUIT_TEXT "POWER"
286 #endif
288 #if (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240)
289 #define LEVEL_TEXT_X 59
290 #define PEGS_TEXT_X 276
291 #define TEXT_Y 28
292 #elif (LCD_WIDTH >= 240) && (LCD_HEIGHT >= 192)
293 #define LEVEL_TEXT_X 59
294 #define PEGS_TEXT_X 196
295 #define TEXT_Y 28
296 #elif (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176)
297 #define LEVEL_TEXT_X 49
298 #define PEGS_TEXT_X 186
299 #define TEXT_Y 28
300 #elif (LCD_WIDTH >= 176) && (LCD_HEIGHT >= 132)
301 #define LEVEL_TEXT_X 38
302 #define PEGS_TEXT_X 155
303 #define TEXT_Y 17
304 #elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128)
305 #define LEVEL_TEXT_X 37
306 #define PEGS_TEXT_X 140
307 #define TEXT_Y 13
308 #elif (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
309 #define LEVEL_TEXT_X 28
310 #define PEGS_TEXT_X 119
311 #define TEXT_Y 15
312 #elif (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 128)
313 #define LEVEL_TEXT_X 28
314 #define PEGS_TEXT_X 119
315 #define TEXT_Y 15
316 #endif
318 #ifdef HAVE_LCD_COLOR
319 #define BG_COLOR LCD_BLACK
320 #define TEXT_BG LCD_RGBPACK(189,189,189)
321 #endif
323 #define BOARD_X (LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2
325 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
326 #define BOARD_Y BMPHEIGHT_pegbox_header+2
327 #else
328 #define BOARD_Y 0
329 #endif
331 struct game_context {
332 unsigned int level;
333 unsigned int highlevel;
334 signed int player_row;
335 signed int player_col;
336 unsigned int num_left;
337 bool save_exist;
338 unsigned int playboard[ROWS][COLS];
341 char levels[NUM_LEVELS][ROWS][COLS] = {
342 /* Level 1 */
343 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
344 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
345 {1, 0, 0, 0, 7, 0, 0, 5, 0, 0, 0, 1,},
346 {1, 0, 0, 0, 0, 3, 3, 2, 0, 0, 0, 1,},
347 {1, 0, 0, 0, 4, 6, 0, 5, 0, 0, 0, 1,},
348 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
349 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
350 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
352 /* Level 2 */
353 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
354 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,},
355 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
356 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
357 {7, 0, 0, 0, 2, 2, 5, 5, 0, 0, 0, 1,},
358 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
359 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
360 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,}},
362 /* Level 3 */
363 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
364 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
365 {1, 0, 0, 0, 0, 0, 2, 0, 7, 0, 0, 0,},
366 {1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 2, 1,},
367 {1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1,},
368 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,},
369 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
370 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
372 /* Level 4 */
373 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
374 {6, 0, 4, 0, 2, 0, 2, 0, 0, 0, 0, 1,},
375 {6, 0, 3, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
376 {6, 0, 5, 0, 4, 7, 2, 0, 0, 0, 0, 1,},
377 {6, 0, 2, 0, 4, 0, 2, 0, 3, 0, 0, 1,},
378 {6, 0, 4, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
379 {6, 0, 5, 0, 4, 0, 2, 0, 0, 0, 0, 1,},
380 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
382 /* Level 5 */
383 {{0, 6, 6, 0, 4, 6, 0, 0, 6, 0, 0, 0,},
384 {0, 6, 6, 0, 4, 4, 0, 0, 6, 0, 0, 2,},
385 {2, 6, 6, 0, 6, 6, 6, 0, 1, 2, 2, 2,},
386 {0, 6, 6, 0, 6, 4, 6, 0, 1, 2, 0, 2,},
387 {0, 6, 6, 0, 6, 7, 6, 5, 6, 0, 0, 0,},
388 {2, 6, 6, 0, 6, 6, 6, 0, 6, 0, 0, 0,},
389 {0, 6, 6, 0, 4, 0, 0, 0, 6, 0, 0, 0,},
390 {0, 6, 6, 0, 0, 5, 0, 0, 6, 5, 5, 0,}},
392 /* Level 6 */
393 {{7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
394 {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,},
395 {2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0,},
396 {0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 0,},
397 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
398 {0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1,},
399 {0, 3, 0, 0, 0, 0, 0, 0, 5, 4, 6, 0,},
400 {0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1,}},
402 /* Level 7 */
403 {{1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,},
404 {1, 1, 1, 6, 0, 0, 4, 6, 0, 1, 1, 1,},
405 {1, 1, 1, 1, 0, 1, 5, 1, 0, 1, 1, 1,},
406 {1, 1, 1, 2, 3, 3, 7, 4, 2, 6, 1, 1,},
407 {1, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1,},
408 {1, 1, 1, 1, 0, 0, 5, 0, 0, 1, 0, 1,},
409 {1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,},
410 {1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,}},
412 /* Level 8 */
413 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
414 {0, 0, 3, 3, 3, 3, 3, 4, 3, 3, 0, 0,},
415 {0, 0, 3, 3, 3, 2, 3, 3, 5, 3, 0, 0,},
416 {7, 0, 3, 3, 3, 2, 3, 3, 4, 3, 0, 0,},
417 {0, 0, 3, 3, 4, 5, 3, 3, 3, 3, 0, 0,},
418 {0, 0, 3, 3, 5, 2, 3, 3, 3, 3, 0, 0,},
419 {0, 0, 3, 3, 2, 4, 3, 3, 3, 3, 0, 0,},
420 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
422 /* Level 9 */
423 {{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
424 {0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
425 {0, 0, 0, 0, 2, 4, 4, 3, 0, 1, 1, 0,},
426 {0, 1, 0, 0, 2, 1, 0, 0, 0, 1, 1, 1,},
427 {0, 0, 0, 2, 2, 7, 1, 0, 0, 0, 0, 2,},
428 {0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 1, 1,},
429 {0, 3, 1, 0, 2, 5, 5, 0, 0, 0, 3, 0,},
430 {0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0,}},
432 /* Level 10 */
433 {{1, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0,},
434 {1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 7,},
435 {0, 0, 4, 0, 6, 6, 6, 0, 0, 0, 3, 0,},
436 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
437 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
438 {0, 0, 0, 0, 6, 6, 6, 0, 3, 0, 0, 0,},
439 {1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0,},
440 {1, 1, 1, 1, 1, 2, 1, 1, 0, 0, 0, 0,}},
442 /* Level 11 */
443 {{1, 7, 1, 0, 1, 1, 6, 0, 0, 1, 1, 0,},
444 {1, 0, 0, 0, 5, 4, 6, 6, 0, 2, 2, 0,},
445 {1, 2, 1, 2, 0, 1, 6, 0, 0, 2, 2, 0,},
446 {1, 0, 0, 2, 0, 1, 0, 0, 0, 3, 3, 0,},
447 {1, 2, 1, 0, 0, 1, 0, 1, 0, 3, 3, 0,},
448 {0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0,},
449 {0, 3, 4, 3, 0, 1, 0, 1, 0, 0, 0, 0,},
450 {0, 0, 0, 0, 2, 2, 2, 1, 1, 1, 1, 1,}},
452 /* Level 12 */
453 {{7, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,},
454 {1, 2, 1, 2, 1, 2, 1, 1, 0, 0, 0, 1,},
455 {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,},
456 {1, 2, 1, 2, 1, 2, 1, 0, 0, 0, 0, 1,},
457 {0, 0, 0, 0, 0, 0, 1, 1, 5, 5, 6, 1,},
458 {1, 2, 1, 2, 1, 2, 1, 1, 0, 2, 2, 1,},
459 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1,},
460 {1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,}},
462 /* Level 13 */
463 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
464 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
465 {0, 0, 2, 0, 5, 0, 2, 0, 4, 0, 0, 6,},
466 {7, 0, 3, 0, 4, 0, 5, 0, 4, 0, 0, 6,},
467 {0, 0, 5, 0, 4, 0, 2, 0, 4, 0, 0, 6,},
468 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
469 {0, 0, 3, 0, 3, 0, 2, 0, 4, 0, 0, 6,},
470 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
472 /* Level 14 */
473 {{1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,},
474 {1, 1, 0, 2, 0, 0, 4, 0, 0, 2, 0, 1,},
475 {1, 6, 0, 0, 5, 1, 0, 1, 1, 0, 0, 1,},
476 {1, 1, 1, 0, 0, 3, 5, 3, 0, 0, 1, 1,},
477 {1, 1, 0, 0, 1, 1, 0, 1, 5, 0, 0, 6,},
478 {1, 1, 0, 2, 0, 0, 4, 0, 0, 0, 7, 1,},
479 {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,},
480 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
482 /* Level 15 */
483 {{0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
484 {0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
485 {0, 3, 4, 6, 0, 6, 0, 6, 0, 6, 0, 2,},
486 {0, 4, 0, 6, 0, 6, 4, 6, 0, 6, 0, 1,},
487 {0, 3, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
488 {7, 0, 0, 6, 4, 6, 0, 6, 0, 6, 0, 1,},
489 {0, 0, 4, 6, 0, 6, 0, 6, 4, 6, 0, 1,},
490 {0, 0, 4, 6, 0, 6, 0, 6, 0, 6, 0, 1,}}
494 /*****************************************************************************
495 * display_text() formats and outputs text.
496 ******************************************************************************/
497 static void display_text(char *str, bool waitkey)
499 int chars_by_line;
500 int lines_by_screen;
501 int chars_for_line;
502 int current_line = 0;
503 int char_width, char_height;
504 int first_char_index = 0;
505 char *ptr_char;
506 char *ptr_line;
507 int i;
508 char line[255];
509 int key;
510 bool go_on;
512 rb->lcd_clear_display();
514 rb->lcd_getstringsize("a", &char_width, &char_height);
516 chars_by_line = LCD_WIDTH / char_width;
517 lines_by_screen = LCD_HEIGHT / char_height;
521 ptr_char = str + first_char_index;
522 chars_for_line = 0;
523 i = 0;
524 ptr_line = line;
525 while (i < chars_by_line)
527 switch (*ptr_char)
529 case '\t':
530 case ' ':
531 *(ptr_line++) = ' ';
532 case '\n':
533 case '\0':
534 chars_for_line = i;
535 break;
537 default:
538 *(ptr_line++) = *ptr_char;
540 if (*ptr_char == '\n' || *ptr_char == '\0')
541 break;
542 ptr_char++;
543 i++;
546 if (chars_for_line == 0)
547 chars_for_line = i;
549 line[chars_for_line] = '\0';
551 /* test if we have cut a word. If it is the case we don't have to */
552 /* skip the space */
553 if (i == chars_by_line && chars_for_line == chars_by_line)
554 first_char_index += chars_for_line;
555 else
556 first_char_index += chars_for_line + 1;
558 /* print the line on the screen */
559 rb->lcd_putsxy(0, current_line * char_height, line);
561 /* if the number of line showed on the screen is equals to the */
562 /* maximum number of line we can show, we wait for a key pressed to */
563 /* clear and show the remaining text. */
564 current_line++;
565 if (current_line == lines_by_screen || *ptr_char == '\0')
567 current_line = 0;
568 rb->lcd_update();
569 go_on = false;
570 while (waitkey && !go_on)
572 key = rb->button_get(true);
573 switch (key)
575 case PEGBOX_QUIT:
576 case PEGBOX_LEFT:
577 case PEGBOX_DOWN:
578 go_on = true;
579 break;
581 default:
582 /*if (rb->default_event_handler(key) == SYS_USB_CONNECTED)
584 usb_detected = true;
585 go_on = true;
586 break;
588 break;
591 rb->lcd_clear_display();
593 } while (*ptr_char != '\0');
596 /*****************************************************************************
597 * draw_board() draws the game's current level.
598 ******************************************************************************/
599 static void draw_board(struct game_context* pb) {
600 unsigned int r, c, type;
601 pb->num_left = 0;
602 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
603 char str[5];
605 rb->lcd_clear_display();
606 rb->lcd_bitmap(pegbox_header,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_header);
607 rb->lcd_drawrect((LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2-2,
608 BMPHEIGHT_pegbox_header,
609 12*BMPWIDTH_pegbox_pieces+4,8*BMPWIDTH_pegbox_pieces+4);
611 #ifdef HAVE_LCD_COLOR
612 rb->lcd_set_foreground(LCD_WHITE);
613 rb->lcd_fillrect((LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2-1,BMPHEIGHT_pegbox_header+1,
614 12*BMPWIDTH_pegbox_pieces+2,8*BMPWIDTH_pegbox_pieces+2);
615 rb->lcd_set_foreground(LCD_BLACK);
616 rb->lcd_set_background(TEXT_BG);
617 #endif
619 #else
620 rb->lcd_clear_display();
621 #endif
623 for (r=0 ; r < ROWS ; r++) {
624 for (c = 0 ; c < COLS ; c++) {
626 type = pb->playboard[r][c];
628 switch(type) {
629 case SPACE:
630 break;
632 default:
633 rb->lcd_bitmap_part(pegbox_pieces, 0,
634 (type-1)*BMPWIDTH_pegbox_pieces,
635 BMPWIDTH_pegbox_pieces,
636 c * BMPWIDTH_pegbox_pieces + BOARD_X,
637 r * BMPWIDTH_pegbox_pieces + BOARD_Y,
638 BMPWIDTH_pegbox_pieces,
639 BMPWIDTH_pegbox_pieces);
640 break;
643 if(pb->playboard[r][c] == PLAYER) {
644 pb->player_row=r;
645 pb->player_col=c;
647 else if (type != WALL && type != SPACE && type != HOLE)
648 pb->num_left++;
651 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
652 rb->snprintf(str, 3, "%d", pb->level);
653 rb->lcd_putsxy(LEVEL_TEXT_X, TEXT_Y, str);
654 rb->snprintf(str, 3, "%d", pb->num_left);
655 rb->lcd_putsxy(PEGS_TEXT_X, TEXT_Y, str);
656 #endif
658 #ifdef HAVE_LCD_COLOR
659 rb->lcd_set_background(BG_COLOR);
660 rb->lcd_set_foreground(LCD_WHITE);
661 #endif
662 /* print out the screen */
663 rb->lcd_update();
666 /*****************************************************************************
667 * load_level() loads the player's current level from the array and sets the
668 * player's position.
669 ******************************************************************************/
670 static void load_level(struct game_context* pb) {
671 int r, c;
673 for(r = 0; r < ROWS; r++)
674 for(c = 0; c < COLS; c++)
675 pb->playboard[r][c] = levels[pb->level-1][r][c];
678 /*****************************************************************************
679 * new_piece() creates a new piece at a specified location. The player
680 * navigates through the pieces and selects one.
681 ******************************************************************************/
682 static void new_piece(struct game_context* pb, unsigned int x_loc,
683 unsigned int y_loc) {
684 int button;
685 bool exit = false;
687 pb->playboard[x_loc][y_loc] = TRIANGLE;
689 while (!exit) {
690 draw_board(pb);
691 button = rb->button_get(true);
692 switch(button){
693 case PEGBOX_LEFT:
694 case (PEGBOX_LEFT|BUTTON_REPEAT):
695 case PEGBOX_DOWN:
696 case (PEGBOX_DOWN|BUTTON_REPEAT):
697 if (pb->playboard[x_loc][y_loc] < 5)
698 pb->playboard[x_loc][y_loc]++;
699 else
700 pb->playboard[x_loc][y_loc] = TRIANGLE;
701 break;
702 case PEGBOX_RIGHT:
703 case (PEGBOX_RIGHT|BUTTON_REPEAT):
704 case PEGBOX_UP:
705 case (PEGBOX_UP|BUTTON_REPEAT):
706 if (pb->playboard[x_loc][y_loc] > 2)
707 pb->playboard[x_loc][y_loc]--;
708 else
709 pb->playboard[x_loc][y_loc] = CIRCLE;
710 break;
711 case PEGBOX_SELECT:
712 exit = true;
713 break;
718 /*****************************************************************************
719 * move_player() moves the player and pieces and updates the board accordingly.
720 ******************************************************************************/
721 static void move_player(struct game_context* pb, signed int x_dir,
722 signed int y_dir) {
723 unsigned int type1, type2;
724 signed int r,c;
726 r = pb->player_row+y_dir;
727 c = pb->player_col+x_dir;
729 type1 = pb->playboard[r][c];
730 type2 = pb->playboard[r+y_dir][c+x_dir];
732 if (r == ROWS || c == COLS || r < 0 || c < 0 || type1 == WALL)
733 return;
734 else if(type1 != SPACE) {
735 if (type2 == WALL || r+y_dir == ROWS || c+x_dir == COLS ||
736 r+y_dir < 0 || c+x_dir < 0)
737 return;
741 pb->playboard[pb->player_row][pb->player_col] = SPACE;
742 pb->player_row += y_dir;
743 pb->player_col += x_dir;
745 if (type1 == HOLE) {
746 draw_board(pb);
747 rb->splash(HZ*2, "You fell down a hole!");
748 load_level(pb);
750 else if (type1 == SPACE)
751 pb->playboard[r][c] = PLAYER;
752 else {
753 pb->playboard[r][c] = PLAYER;
754 if(type1 == type2) {
755 if (type1 == TRIANGLE)
756 pb->playboard[r+y_dir][c+x_dir] = WALL;
757 else if (type1 == CROSS) {
758 pb->playboard[r][c] = SPACE;
759 new_piece(pb, r+y_dir, c+x_dir);
760 pb->playboard[r][c] = PLAYER;
762 else
763 pb->playboard[r+y_dir][c+x_dir] = SPACE;
765 else if (type2 == SPACE)
766 pb->playboard[r+y_dir][c+x_dir] = type1;
767 else if (type2 == HOLE) {
768 if (type1 == SQUARE)
769 pb->playboard[r+y_dir][c+x_dir] = SPACE;
771 else {
772 rb->splash(HZ*2, "Illegal Move!");
773 load_level(pb);
777 draw_board(pb);
780 /*****************************************************************************
781 * pegbox_loadgame() loads the saved game and returns load success.
782 ******************************************************************************/
783 static bool pegbox_loadgame(struct game_context* pb) {
784 signed int fd;
785 bool loaded = false;
787 /* open game file */
788 fd = rb->open(SAVE_FILE, O_RDONLY);
789 if(fd < 0) return loaded;
791 /* read in saved game */
792 while(true) {
793 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
794 if(rb->read(fd, &pb->playboard, sizeof(pb->playboard)) <= 0)
796 loaded = true;
797 break;
799 break;
802 rb->close(fd);
803 return loaded;
806 /*****************************************************************************
807 * pegbox_savegame() saves the current game state.
808 ******************************************************************************/
809 static void pegbox_savegame(struct game_context* pb) {
810 unsigned int fd;
812 /* write out the game state to the save file */
813 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
814 rb->write(fd, &pb->level, sizeof(pb->level));
815 rb->write(fd, &pb->playboard, sizeof(pb->playboard));
816 rb->close(fd);
819 /*****************************************************************************
820 * pegbox_loaddata() loads the level and highlevel and returns load success.
821 ******************************************************************************/
822 static void pegbox_loaddata(struct game_context* pb) {
823 signed int fd;
825 /* open game file */
826 fd = rb->open(DATA_FILE, O_RDONLY);
827 if(fd < 0) {
828 pb->level = 1;
829 pb->highlevel = 1;
830 return;
833 /* read in saved game */
834 while(true) {
835 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
836 if(rb->read(fd, &pb->highlevel, sizeof(pb->highlevel)) <= 0) break;
837 break;
840 rb->close(fd);
841 return;
844 /*****************************************************************************
845 * pegbox_savedata() saves the level and highlevel.
846 ******************************************************************************/
847 static void pegbox_savedata(struct game_context* pb) {
848 unsigned int fd;
850 /* write out the game state to the save file */
851 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT);
852 rb->write(fd, &pb->level, sizeof(pb->level));
853 rb->write(fd, &pb->highlevel, sizeof(pb->highlevel));
854 rb->close(fd);
857 /*****************************************************************************
858 * pegbox_callback() is the default event handler callback which is called
859 * on usb connect and shutdown.
860 ******************************************************************************/
861 static void pegbox_callback(void* param) {
862 struct game_context* pb = (struct game_context*) param;
863 rb->splash(HZ, "Saving data...");
864 pegbox_savedata(pb);
867 /*****************************************************************************
868 * pegbox_menu() is the initial menu at the start of the game.
869 ******************************************************************************/
870 static unsigned int pegbox_menu(struct game_context* pb) {
871 int button;
872 char str[30];
873 unsigned int startlevel = 1, loc = 0;
874 bool breakout = false, can_resume = false;
876 if (pb->num_left > 0 || pb->save_exist)
877 can_resume = true;
879 while(!breakout){
880 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
881 rb->lcd_clear_display();
882 rb->lcd_bitmap(pegbox_menu_top,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_menu_top);
884 /* menu bitmaps */
885 if (loc == 0) {
886 rb->lcd_bitmap_part(pegbox_menu_items, 0,
887 (BMPHEIGHT_pegbox_menu_items/9),
888 BMPWIDTH_pegbox_menu_items,
889 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
890 BMPHEIGHT_pegbox_menu_top,
891 BMPWIDTH_pegbox_menu_items,
892 (BMPHEIGHT_pegbox_menu_items/9));
894 else {
895 rb->lcd_bitmap_part(pegbox_menu_items, 0, 0,
896 BMPWIDTH_pegbox_menu_items,
897 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
898 BMPHEIGHT_pegbox_menu_top,
899 BMPWIDTH_pegbox_menu_items,
900 (BMPHEIGHT_pegbox_menu_items/9));
902 if (can_resume) {
903 if (loc == 1) {
904 rb->lcd_bitmap_part(pegbox_menu_items, 0,
905 (BMPHEIGHT_pegbox_menu_items/9)*3,
906 BMPWIDTH_pegbox_menu_items,
907 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
908 BMPHEIGHT_pegbox_menu_top+
909 (BMPHEIGHT_pegbox_menu_items/9),
910 BMPWIDTH_pegbox_menu_items,
911 (BMPHEIGHT_pegbox_menu_items/9));
913 else {
914 rb->lcd_bitmap_part(pegbox_menu_items, 0,
915 (BMPHEIGHT_pegbox_menu_items/9)*2,
916 BMPWIDTH_pegbox_menu_items,
917 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
918 BMPHEIGHT_pegbox_menu_top+
919 (BMPHEIGHT_pegbox_menu_items/9),
920 BMPWIDTH_pegbox_menu_items,
921 (BMPHEIGHT_pegbox_menu_items/9));
924 else {
925 rb->lcd_bitmap_part(pegbox_menu_items, 0,
926 (BMPHEIGHT_pegbox_menu_items/9)*4,
927 BMPWIDTH_pegbox_menu_items,
928 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
929 BMPHEIGHT_pegbox_menu_top+
930 (BMPHEIGHT_pegbox_menu_items/9),
931 BMPWIDTH_pegbox_menu_items,
932 (BMPHEIGHT_pegbox_menu_items/9));
935 if (loc==2) {
936 rb->lcd_bitmap_part(pegbox_menu_items, 0,
937 (BMPHEIGHT_pegbox_menu_items/9)*6,
938 BMPWIDTH_pegbox_menu_items,
939 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
940 BMPHEIGHT_pegbox_menu_top+
941 (BMPHEIGHT_pegbox_menu_items/9)*2,
942 BMPWIDTH_pegbox_menu_items,
943 (BMPHEIGHT_pegbox_menu_items/9));
945 else {
946 rb->lcd_bitmap_part(pegbox_menu_items, 0,
947 (BMPHEIGHT_pegbox_menu_items/9)*5,
948 BMPWIDTH_pegbox_menu_items,
949 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
950 BMPHEIGHT_pegbox_menu_top+
951 (BMPHEIGHT_pegbox_menu_items/9)*2,
952 BMPWIDTH_pegbox_menu_items,
953 (BMPHEIGHT_pegbox_menu_items/9));
956 if (loc==3) {
957 rb->lcd_bitmap_part(pegbox_menu_items, 0,
958 (BMPHEIGHT_pegbox_menu_items/9)*8,
959 BMPWIDTH_pegbox_menu_items,
960 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
961 BMPHEIGHT_pegbox_menu_top+
962 (BMPHEIGHT_pegbox_menu_items/9)*3,
963 BMPWIDTH_pegbox_menu_items,
964 (BMPHEIGHT_pegbox_menu_items/9));
966 else {
967 rb->lcd_bitmap_part(pegbox_menu_items, 0,
968 (BMPHEIGHT_pegbox_menu_items/9)*7,
969 BMPWIDTH_pegbox_menu_items,
970 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
971 BMPHEIGHT_pegbox_menu_top+
972 (BMPHEIGHT_pegbox_menu_items/9)*3,
973 BMPWIDTH_pegbox_menu_items,
974 (BMPHEIGHT_pegbox_menu_items/9));
976 #else
977 unsigned int w,h;
978 rb->lcd_clear_display();
979 rb->lcd_getstringsize("PegBox", &w, &h);
980 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, "PegBox");
981 rb->lcd_putsxy((LCD_WIDTH)/4, 16, "New Game");
982 rb->lcd_putsxy((LCD_WIDTH)/4, 24, "Resume");
983 rb->lcd_putsxy((LCD_WIDTH)/4, 32, "Help");
984 rb->lcd_putsxy((LCD_WIDTH)/4, 40, "Quit");
986 if(!can_resume)
987 rb->lcd_drawline((LCD_WIDTH)/4, 28, (LCD_WIDTH)/4+30, 28);
989 rb->lcd_putsxy((LCD_WIDTH)/4-8, loc*8+16, "*");
992 #endif
993 rb->snprintf(str, 28, "Start on level %d of %d", startlevel,
994 pb->highlevel);
995 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
996 rb->lcd_putsxy(0, BMPHEIGHT_pegbox_menu_top+4*
997 (BMPHEIGHT_pegbox_menu_items/9)+8, str);
998 #elif LCD_WIDTH > 112
999 rb->lcd_putsxy(0, LCD_HEIGHT - 8, str);
1000 #else
1001 rb->lcd_puts_scroll(0, 7, str);
1002 #endif
1003 rb->lcd_update();
1005 /* handle menu button presses */
1006 button = rb->button_get(true);
1008 switch(button) {
1009 case PEGBOX_SELECT: /* start playing */
1010 if (loc == 0) {
1011 breakout = true;
1012 pb->level = startlevel;
1013 load_level(pb);
1015 else if (loc == 1 && can_resume) {
1016 if(pb->save_exist)
1018 rb->remove(SAVE_FILE);
1019 pb->save_exist = false;
1021 breakout = true;
1023 else if (loc == 2)
1024 display_text("How to Play\nTo beat each level, you must "
1025 "destroy all of the pegs. If two like pegs are "
1026 "pushed into each other they disappear except "
1027 "for triangles which form a solid block and "
1028 "crosses which allow you to choose a "
1029 "replacement block.\n\n"
1030 "Controls\n"
1031 #if LCD_HEIGHT > 64
1032 RESTART_TEXT " to restart level\n"
1033 LVL_UP_TEXT " to go up a level\n"
1034 LVL_DOWN_TEXT " to go down a level\n"
1035 SAVE_TEXT " to save\n"
1036 QUIT_TEXT " to quit\n",true);
1037 #else
1038 RESTART_TEXT ": restart\n"
1039 LVL_UP_TEXT ": level up\n"
1040 LVL_DOWN_TEXT " level down\n"
1041 SAVE_TEXT " save game\n"
1042 QUIT_TEXT " quit\n",true);
1043 #endif
1044 else if (loc == 3)
1045 return PB_QUIT;
1046 break;
1048 case PEGBOX_QUIT: /* quit program */
1049 return PB_QUIT;
1051 case (PEGBOX_UP|BUTTON_REPEAT):
1052 case PEGBOX_UP:
1053 if (loc <= 0)
1054 loc = 3;
1055 else
1056 loc--;
1057 if (!can_resume && loc == 1) {
1058 loc = 0;
1060 break;
1063 case (PEGBOX_DOWN|BUTTON_REPEAT):
1064 case PEGBOX_DOWN:
1065 if (loc >= 3)
1066 loc = 0;
1067 else
1068 loc++;
1069 if (!can_resume && loc == 1) {
1070 loc = 2;
1072 break;
1074 case (PEGBOX_RIGHT|BUTTON_REPEAT):
1075 case PEGBOX_RIGHT: /* increase starting level */
1076 if(startlevel >= pb->highlevel) {
1077 startlevel = 1;
1078 } else {
1079 startlevel++;
1081 break;
1083 case (PEGBOX_LEFT|BUTTON_REPEAT):
1084 case PEGBOX_LEFT: /* decrease starting level */
1085 if(startlevel <= 1) {
1086 startlevel = pb->highlevel;
1087 } else {
1088 startlevel--;
1090 break;
1092 default:
1093 if(rb->default_event_handler_ex(button, pegbox_callback,
1094 (void*) pb) == SYS_USB_CONNECTED)
1095 return PB_USB;
1096 break;
1100 draw_board(pb);
1102 return 0;
1105 /*****************************************************************************
1106 * pegbox() is the main game subroutine, it returns the final game status.
1107 ******************************************************************************/
1108 static int pegbox(struct game_context* pb) {
1109 int temp_var;
1111 /********************
1112 * menu *
1113 ********************/
1114 temp_var = pegbox_menu(pb);
1115 if (temp_var == PB_QUIT || temp_var == PB_USB)
1116 return temp_var;
1118 while (true) {
1119 temp_var = rb->button_get(true);
1120 switch(temp_var){
1121 case PEGBOX_LEFT: /* move cursor left */
1122 case (PEGBOX_LEFT|BUTTON_REPEAT):
1123 move_player(pb, -1, 0);
1124 break;
1126 case PEGBOX_RIGHT: /* move cursor right */
1127 case (PEGBOX_RIGHT|BUTTON_REPEAT):
1128 move_player(pb, 1, 0);
1129 break;
1131 case PEGBOX_DOWN: /* move cursor down */
1132 case (PEGBOX_DOWN|BUTTON_REPEAT):
1133 move_player(pb, 0, 1);
1134 break;
1136 case PEGBOX_UP: /* move cursor up */
1137 case (PEGBOX_UP|BUTTON_REPEAT):
1138 move_player(pb, 0, -1);
1139 break;
1141 case PEGBOX_SAVE: /* save and end game */
1142 rb->splash(HZ, "Saving game...");
1143 pegbox_savegame(pb);
1144 /* fall through to PEGBOX_QUIT */
1146 case PEGBOX_QUIT:
1147 return PB_END;
1149 case PEGBOX_RESTART:
1150 load_level(pb);
1151 draw_board(pb);
1152 break;
1154 #ifdef PEGBOX_LVL_UP
1155 case PEGBOX_LVL_UP:
1156 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1157 if(pb->level < pb->highlevel) {
1158 pb->level++;
1159 load_level(pb);
1160 draw_board(pb);
1162 break;
1163 #endif
1165 #ifdef PEGBOX_LVL_DOWN
1166 case PEGBOX_LVL_DOWN:
1167 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1168 if(pb->level > 1) {
1169 pb->level--;
1170 load_level(pb);
1171 draw_board(pb);
1173 break;
1174 #endif
1178 if(pb->num_left == 0) {
1179 rb->splash(HZ*2, "Nice Pegging!");
1180 if(pb->level == NUM_LEVELS) {
1181 draw_board(pb);
1182 rb->splash(HZ*2, "You Won!");
1183 break;
1185 else {
1186 pb->level++;
1187 load_level(pb);
1188 draw_board(pb);
1191 if(pb->level > pb->highlevel)
1192 pb->highlevel = pb->level;
1197 return PLUGIN_OK;
1201 /*****************************************************************************
1202 * plugin entry point.
1203 ******************************************************************************/
1204 enum plugin_status plugin_start(struct plugin_api* api, void* parameter) {
1205 bool exit = false;
1206 struct game_context pb;
1208 (void)parameter;
1209 rb = api;
1211 rb->lcd_setfont(FONT_SYSFIXED);
1212 #if LCD_DEPTH > 1
1213 rb->lcd_set_backdrop(NULL);
1214 #endif
1215 #ifdef HAVE_LCD_COLOR
1216 rb->lcd_set_foreground(LCD_WHITE);
1217 rb->lcd_set_background(BG_COLOR);
1218 #endif
1220 rb->splash(0, "Loading...");
1221 pegbox_loaddata(&pb);
1222 pb.save_exist = pegbox_loadgame(&pb);
1223 pb.num_left = 0;
1225 rb->lcd_clear_display();
1228 while(!exit) {
1229 switch(pegbox(&pb)){
1230 case PB_END:
1231 break;
1233 case PB_USB:
1234 rb->lcd_setfont(FONT_UI);
1235 return PLUGIN_USB_CONNECTED;
1237 case PB_QUIT:
1238 rb->splash(HZ, "Saving data...");
1239 pegbox_savedata(&pb);
1240 exit = true;
1241 break;
1243 default:
1244 break;
1248 rb->lcd_setfont(FONT_UI);
1249 return PLUGIN_OK;