grr.. typo
[Rockbox.git] / apps / plugins / pegbox.c
blob45c830a5a0b50e4123c715766e19698583886737
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_SAVE BUTTON_ON
55 #define PEGBOX_QUIT BUTTON_OFF
56 #define PEGBOX_RESTART BUTTON_F2
57 #define PEGBOX_LVL_UP BUTTON_F1
58 #define PEGBOX_LVL_DOWN BUTTON_F3
59 #define PEGBOX_UP BUTTON_UP
60 #define PEGBOX_DOWN BUTTON_DOWN
61 #define PEGBOX_RIGHT BUTTON_RIGHT
62 #define PEGBOX_LEFT BUTTON_LEFT
64 #define SAVE_TEXT "ON"
65 #define QUIT_TEXT "OFF"
66 #define RESTART_TEXT "F2"
67 #define LVL_UP_TEXT "F1"
68 #define LVL_DOWN_TEXT "F3"
70 #elif CONFIG_KEYPAD == ONDIO_PAD
71 #define PEGBOX_SAVE BUTTON_OFF
72 #define PEGBOX_QUIT (BUTTON_MENU | BUTTON_LEFT)
73 #define PEGBOX_RESTART (BUTTON_MENU | BUTTON_RIGHT)
74 #define PEGBOX_LVL_UP (BUTTON_MENU | BUTTON_UP)
75 #define PEGBOX_LVL_DOWN (BUTTON_MENU | BUTTON_DOWN)
76 #define PEGBOX_UP BUTTON_UP
77 #define PEGBOX_DOWN BUTTON_DOWN
78 #define PEGBOX_RIGHT BUTTON_RIGHT
79 #define PEGBOX_LEFT BUTTON_LEFT
81 #define SAVE_TEXT "OFF"
82 #define QUIT_TEXT "M+LEFT"
83 #define RESTART_TEXT "M+RIGHT"
84 #define LVL_UP_TEXT "M+UP"
85 #define LVL_DOWN_TEXT "M+DOWN"
87 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
88 (CONFIG_KEYPAD == IRIVER_H300_PAD)
89 #define PEGBOX_SAVE BUTTON_SELECT
90 #define PEGBOX_QUIT BUTTON_OFF
91 #define PEGBOX_RESTART BUTTON_ON
92 #define PEGBOX_LVL_UP BUTTON_MODE
93 #define PEGBOX_LVL_DOWN BUTTON_REC
94 #define PEGBOX_UP BUTTON_UP
95 #define PEGBOX_DOWN BUTTON_DOWN
96 #define PEGBOX_RIGHT BUTTON_RIGHT
97 #define PEGBOX_LEFT BUTTON_LEFT
99 #define SAVE_TEXT "NAVI"
100 #define QUIT_TEXT "OFF"
101 #define RESTART_TEXT "ON"
102 #define LVL_UP_TEXT "AB"
103 #define LVL_DOWN_TEXT "REC"
105 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
106 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
107 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
108 #define PEGBOX_SAVE (BUTTON_SELECT|BUTTON_RIGHT)
109 #define PEGBOX_QUIT (BUTTON_SELECT|BUTTON_PLAY)
110 #define PEGBOX_RESTART (BUTTON_SELECT|BUTTON_LEFT)
111 #define PEGBOX_LVL_UP (BUTTON_SELECT|BUTTON_MENU)
112 #define PEGBOX_UP BUTTON_MENU
113 #define PEGBOX_DOWN BUTTON_PLAY
114 #define PEGBOX_RIGHT BUTTON_RIGHT
115 #define PEGBOX_LEFT BUTTON_LEFT
117 #define SAVE_TEXT "SELECT+RIGHT"
118 #define QUIT_TEXT "SELECT+PLAY"
119 #define RESTART_TEXT "SELECT+LEFT"
120 #define LVL_UP_TEXT "SELECT+MENU"
121 #define LVL_DOWN_TEXT "-"
123 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
124 #define PEGBOX_SAVE BUTTON_SELECT
125 #define PEGBOX_QUIT BUTTON_POWER
126 #define PEGBOX_RESTART BUTTON_REC
127 #define PEGBOX_LVL_UP BUTTON_PLAY
128 #define PEGBOX_UP BUTTON_UP
129 #define PEGBOX_DOWN BUTTON_DOWN
130 #define PEGBOX_RIGHT BUTTON_RIGHT
131 #define PEGBOX_LEFT BUTTON_LEFT
133 #define SAVE_TEXT "SELECT"
134 #define QUIT_TEXT "OFF"
135 #define RESTART_TEXT "REC"
136 #define LVL_UP_TEXT "PLAY"
137 #define LVL_DOWN_TEXT "-"
139 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
140 #define PEGBOX_SAVE BUTTON_MODE
141 #define PEGBOX_QUIT BUTTON_PLAY
142 #define PEGBOX_RESTART (BUTTON_EQ|BUTTON_MODE)
143 #define PEGBOX_LVL_UP (BUTTON_EQ|BUTTON_UP)
144 #define PEGBOX_LVL_DOWN (BUTTON_EQ|BUTTON_DOWN)
145 #define PEGBOX_UP BUTTON_UP
146 #define PEGBOX_DOWN BUTTON_DOWN
147 #define PEGBOX_RIGHT BUTTON_RIGHT
148 #define PEGBOX_LEFT BUTTON_LEFT
150 #define SAVE_TEXT "MODE"
151 #define QUIT_TEXT "PLAY"
152 #define RESTART_TEXT "EQ+MODE"
153 #define LVL_UP_TEXT "EQ+UP"
154 #define LVL_DOWN_TEXT "EQ+DOWN"
156 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
157 #define PEGBOX_SAVE BUTTON_PLAY
158 #define PEGBOX_QUIT BUTTON_POWER
159 #define PEGBOX_RESTART (BUTTON_FF|BUTTON_REPEAT)
160 #define PEGBOX_LVL_UP (BUTTON_FF|BUTTON_SCROLL_UP)
161 #define PEGBOX_LVL_DOWN (BUTTON_FF|BUTTON_SCROLL_DOWN)
162 #define PEGBOX_UP BUTTON_SCROLL_UP
163 #define PEGBOX_DOWN BUTTON_SCROLL_DOWN
164 #define PEGBOX_RIGHT BUTTON_RIGHT
165 #define PEGBOX_LEFT BUTTON_LEFT
167 #define SAVE_TEXT "PLAY"
168 #define QUIT_TEXT "OFF"
169 #define RESTART_TEXT "LONG FF"
170 #define LVL_UP_TEXT "FF+SCROLL_UP"
171 #define LVL_DOWN_TEXT "FF+SCROLL_DOWN"
173 #elif CONFIG_KEYPAD == SANSA_E200_PAD
174 #define PEGBOX_SAVE BUTTON_SELECT
175 #define PEGBOX_QUIT BUTTON_POWER
176 #define PEGBOX_RESTART BUTTON_REC
177 #define PEGBOX_LVL_UP BUTTON_SCROLL_BACK
178 #define PEGBOX_LVL_DOWN BUTTON_SCROLL_FWD
179 #define PEGBOX_UP BUTTON_UP
180 #define PEGBOX_DOWN BUTTON_DOWN
181 #define PEGBOX_RIGHT BUTTON_RIGHT
182 #define PEGBOX_LEFT BUTTON_LEFT
184 #define SAVE_TEXT "SELECT"
185 #define QUIT_TEXT "POWER"
186 #define RESTART_TEXT "REC"
187 #define LVL_UP_TEXT "SCROLL BACK"
188 #define LVL_DOWN_TEXT "SCROLL FWD"
190 #elif CONFIG_KEYPAD == GIGABEAT_PAD
191 #define PEGBOX_SAVE BUTTON_SELECT
192 #define PEGBOX_QUIT BUTTON_POWER
193 #define PEGBOX_RESTART BUTTON_A
194 #define PEGBOX_LVL_UP BUTTON_VOL_UP
195 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
196 #define PEGBOX_UP BUTTON_UP
197 #define PEGBOX_DOWN BUTTON_DOWN
198 #define PEGBOX_RIGHT BUTTON_RIGHT
199 #define PEGBOX_LEFT BUTTON_LEFT
201 #define SAVE_TEXT "SELECT"
202 #define QUIT_TEXT "POWER"
203 #define RESTART_TEXT "A"
204 #define LVL_UP_TEXT "VOL+"
205 #define LVL_DOWN_TEXT "VOL-"
207 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
208 #define PEGBOX_SAVE BUTTON_SELECT
209 #define PEGBOX_QUIT BUTTON_BACK
210 #define PEGBOX_RESTART BUTTON_MENU
211 #define PEGBOX_LVL_UP BUTTON_VOL_UP
212 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
213 #define PEGBOX_UP BUTTON_UP
214 #define PEGBOX_DOWN BUTTON_DOWN
215 #define PEGBOX_RIGHT BUTTON_RIGHT
216 #define PEGBOX_LEFT BUTTON_LEFT
218 #define SAVE_TEXT "SELECT"
219 #define QUIT_TEXT "BACK"
220 #define RESTART_TEXT "MENU"
221 #define LVL_UP_TEXT "VOL+"
222 #define LVL_DOWN_TEXT "VOL-"
224 #elif CONFIG_KEYPAD == MROBE100_PAD
225 #define PEGBOX_SAVE BUTTON_SELECT
226 #define PEGBOX_QUIT BUTTON_POWER
227 #define PEGBOX_RESTART BUTTON_PLAY
228 #define PEGBOX_LVL_UP BUTTON_MENU
229 #define PEGBOX_LVL_DOWN BUTTON_DISPLAY
230 #define PEGBOX_UP BUTTON_UP
231 #define PEGBOX_DOWN BUTTON_DOWN
232 #define PEGBOX_RIGHT BUTTON_RIGHT
233 #define PEGBOX_LEFT BUTTON_LEFT
235 #define SAVE_TEXT "SELECT"
236 #define QUIT_TEXT "POWER"
237 #define RESTART_TEXT "PLAY"
238 #define LVL_UP_TEXT "MENU"
239 #define LVL_DOWN_TEXT "DISPLAY"
241 #elif CONFIG_KEYPAD == SANSA_C200_PAD
242 #define PEGBOX_SAVE BUTTON_SELECT
243 #define PEGBOX_QUIT BUTTON_POWER
244 #define PEGBOX_RESTART BUTTON_REC
245 #define PEGBOX_LVL_UP BUTTON_VOL_UP
246 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
247 #define PEGBOX_UP BUTTON_UP
248 #define PEGBOX_DOWN BUTTON_DOWN
249 #define PEGBOX_RIGHT BUTTON_RIGHT
250 #define PEGBOX_LEFT BUTTON_LEFT
252 #define SAVE_TEXT "SELECT"
253 #define QUIT_TEXT "POWER"
254 #define RESTART_TEXT "REC"
255 #define LVL_UP_TEXT "VOL+"
256 #define LVL_DOWN_TEXT "VOL-"
258 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
259 #define PEGBOX_SAVE BUTTON_RC_PLAY
260 #define PEGBOX_QUIT BUTTON_RC_REC
261 #define PEGBOX_RESTART BUTTON_RC_MODE
262 #define PEGBOX_LVL_UP BUTTON_VOL_UP
263 #define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
264 #define PEGBOX_UP BUTTON_RC_VOL_UP
265 #define PEGBOX_DOWN BUTTON_RC_VOL_DOWN
266 #define PEGBOX_RIGHT BUTTON_RC_FF
267 #define PEGBOX_LEFT BUTTON_RC_REW
269 #define SAVE_TEXT "REM. PLAY"
270 #define QUIT_TEXT "REM. REC"
271 #define RESTART_TEXT "REM. MODE"
272 #define LVL_UP_TEXT "VOL+"
273 #define LVL_DOWN_TEXT "VOL-"
275 #elif CONFIG_KEYPAD == COWOND2_PAD
276 #define PEGBOX_SAVE BUTTON_SELECT
277 #define PEGBOX_QUIT BUTTON_POWER
278 #define PEGBOX_RESTART BUTTON_MENU
279 #define PEGBOX_LVL_UP BUTTON_PLUS
280 #define PEGBOX_LVL_DOWN BUTTON_MINUS
281 #define PEGBOX_UP BUTTON_UP
282 #define PEGBOX_DOWN BUTTON_DOWN
283 #define PEGBOX_RIGHT BUTTON_RIGHT
284 #define PEGBOX_LEFT BUTTON_LEFT
286 #define SAVE_TEXT "SELECT"
287 #define QUIT_TEXT "POWER"
288 #define RESTART_TEXT "MENU"
289 #define LVL_UP_TEXT "PLUS"
290 #define LVL_DOWN_TEXT "MINUS"
291 #else
292 #error Unsupported keymap!
293 #endif
295 #if (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240)
296 #define LEVEL_TEXT_X 59
297 #define PEGS_TEXT_X 276
298 #define TEXT_Y 28
299 #elif (LCD_WIDTH >= 240) && (LCD_HEIGHT >= 192)
300 #define LEVEL_TEXT_X 59
301 #define PEGS_TEXT_X 196
302 #define TEXT_Y 28
303 #elif (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176)
304 #define LEVEL_TEXT_X 49
305 #define PEGS_TEXT_X 186
306 #define TEXT_Y 28
307 #elif (LCD_WIDTH >= 176) && (LCD_HEIGHT >= 132)
308 #define LEVEL_TEXT_X 38
309 #define PEGS_TEXT_X 155
310 #define TEXT_Y 17
311 #elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128)
312 #define LEVEL_TEXT_X 37
313 #define PEGS_TEXT_X 140
314 #define TEXT_Y 13
315 #elif (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
316 #define LEVEL_TEXT_X 28
317 #define PEGS_TEXT_X 119
318 #define TEXT_Y 15
319 #elif (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 128)
320 #define LEVEL_TEXT_X 28
321 #define PEGS_TEXT_X 119
322 #define TEXT_Y 15
323 #endif
325 #ifdef HAVE_LCD_COLOR
326 #define BG_COLOR LCD_BLACK
327 #define TEXT_BG LCD_RGBPACK(189,189,189)
328 #endif
330 #define BOARD_X (LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2
332 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
333 #define BOARD_Y BMPHEIGHT_pegbox_header+2
334 #else
335 #define BOARD_Y 0
336 #endif
338 struct game_context {
339 unsigned int level;
340 unsigned int highlevel;
341 signed int player_row;
342 signed int player_col;
343 unsigned int num_left;
344 bool save_exist;
345 unsigned int playboard[ROWS][COLS];
348 char levels[NUM_LEVELS][ROWS][COLS] = {
349 /* Level 1 */
350 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
351 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
352 {1, 0, 0, 0, 7, 0, 0, 5, 0, 0, 0, 1,},
353 {1, 0, 0, 0, 0, 3, 3, 2, 0, 0, 0, 1,},
354 {1, 0, 0, 0, 4, 6, 0, 5, 0, 0, 0, 1,},
355 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
356 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
357 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
359 /* Level 2 */
360 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
361 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,},
362 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
363 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
364 {7, 0, 0, 0, 2, 2, 5, 5, 0, 0, 0, 1,},
365 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
366 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
367 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,}},
369 /* Level 3 */
370 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
371 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
372 {1, 0, 0, 0, 0, 0, 2, 0, 7, 0, 0, 0,},
373 {1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 2, 1,},
374 {1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1,},
375 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,},
376 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
377 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
379 /* Level 4 */
380 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
381 {6, 0, 4, 0, 2, 0, 2, 0, 0, 0, 0, 1,},
382 {6, 0, 3, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
383 {6, 0, 5, 0, 4, 7, 2, 0, 0, 0, 0, 1,},
384 {6, 0, 2, 0, 4, 0, 2, 0, 3, 0, 0, 1,},
385 {6, 0, 4, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
386 {6, 0, 5, 0, 4, 0, 2, 0, 0, 0, 0, 1,},
387 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
389 /* Level 5 */
390 {{0, 6, 6, 0, 4, 6, 0, 0, 6, 0, 0, 0,},
391 {0, 6, 6, 0, 4, 4, 0, 0, 6, 0, 0, 2,},
392 {2, 6, 6, 0, 6, 6, 6, 0, 1, 2, 2, 2,},
393 {0, 6, 6, 0, 6, 4, 6, 0, 1, 2, 0, 2,},
394 {0, 6, 6, 0, 6, 7, 6, 5, 6, 0, 0, 0,},
395 {2, 6, 6, 0, 6, 6, 6, 0, 6, 0, 0, 0,},
396 {0, 6, 6, 0, 4, 0, 0, 0, 6, 0, 0, 0,},
397 {0, 6, 6, 0, 0, 5, 0, 0, 6, 5, 5, 0,}},
399 /* Level 6 */
400 {{7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
401 {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,},
402 {2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0,},
403 {0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 0,},
404 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
405 {0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1,},
406 {0, 3, 0, 0, 0, 0, 0, 0, 5, 4, 6, 0,},
407 {0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1,}},
409 /* Level 7 */
410 {{1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,},
411 {1, 1, 1, 6, 0, 0, 4, 6, 0, 1, 1, 1,},
412 {1, 1, 1, 1, 0, 1, 5, 1, 0, 1, 1, 1,},
413 {1, 1, 1, 2, 3, 3, 7, 4, 2, 6, 1, 1,},
414 {1, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1,},
415 {1, 1, 1, 1, 0, 0, 5, 0, 0, 1, 0, 1,},
416 {1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,},
417 {1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,}},
419 /* Level 8 */
420 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
421 {0, 0, 3, 3, 3, 3, 3, 4, 3, 3, 0, 0,},
422 {0, 0, 3, 3, 3, 2, 3, 3, 5, 3, 0, 0,},
423 {7, 0, 3, 3, 3, 2, 3, 3, 4, 3, 0, 0,},
424 {0, 0, 3, 3, 4, 5, 3, 3, 3, 3, 0, 0,},
425 {0, 0, 3, 3, 5, 2, 3, 3, 3, 3, 0, 0,},
426 {0, 0, 3, 3, 2, 4, 3, 3, 3, 3, 0, 0,},
427 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
429 /* Level 9 */
430 {{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
431 {0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
432 {0, 0, 0, 0, 2, 4, 4, 3, 0, 1, 1, 0,},
433 {0, 1, 0, 0, 2, 1, 0, 0, 0, 1, 1, 1,},
434 {0, 0, 0, 2, 2, 7, 1, 0, 0, 0, 0, 2,},
435 {0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 1, 1,},
436 {0, 3, 1, 0, 2, 5, 5, 0, 0, 0, 3, 0,},
437 {0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0,}},
439 /* Level 10 */
440 {{1, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0,},
441 {1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 7,},
442 {0, 0, 4, 0, 6, 6, 6, 0, 0, 0, 3, 0,},
443 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
444 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
445 {0, 0, 0, 0, 6, 6, 6, 0, 3, 0, 0, 0,},
446 {1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0,},
447 {1, 1, 1, 1, 1, 2, 1, 1, 0, 0, 0, 0,}},
449 /* Level 11 */
450 {{1, 7, 1, 0, 1, 1, 6, 0, 0, 1, 1, 0,},
451 {1, 0, 0, 0, 5, 4, 6, 6, 0, 2, 2, 0,},
452 {1, 2, 1, 2, 0, 1, 6, 0, 0, 2, 2, 0,},
453 {1, 0, 0, 2, 0, 1, 0, 0, 0, 3, 3, 0,},
454 {1, 2, 1, 0, 0, 1, 0, 1, 0, 3, 3, 0,},
455 {0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0,},
456 {0, 3, 4, 3, 0, 1, 0, 1, 0, 0, 0, 0,},
457 {0, 0, 0, 0, 2, 2, 2, 1, 1, 1, 1, 1,}},
459 /* Level 12 */
460 {{7, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,},
461 {1, 2, 1, 2, 1, 2, 1, 1, 0, 0, 0, 1,},
462 {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,},
463 {1, 2, 1, 2, 1, 2, 1, 0, 0, 0, 0, 1,},
464 {0, 0, 0, 0, 0, 0, 1, 1, 5, 5, 6, 1,},
465 {1, 2, 1, 2, 1, 2, 1, 1, 0, 2, 2, 1,},
466 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1,},
467 {1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,}},
469 /* Level 13 */
470 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
471 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
472 {0, 0, 2, 0, 5, 0, 2, 0, 4, 0, 0, 6,},
473 {7, 0, 3, 0, 4, 0, 5, 0, 4, 0, 0, 6,},
474 {0, 0, 5, 0, 4, 0, 2, 0, 4, 0, 0, 6,},
475 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
476 {0, 0, 3, 0, 3, 0, 2, 0, 4, 0, 0, 6,},
477 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
479 /* Level 14 */
480 {{1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,},
481 {1, 1, 0, 2, 0, 0, 4, 0, 0, 2, 0, 1,},
482 {1, 6, 0, 0, 5, 1, 0, 1, 1, 0, 0, 1,},
483 {1, 1, 1, 0, 0, 3, 5, 3, 0, 0, 1, 1,},
484 {1, 1, 0, 0, 1, 1, 0, 1, 5, 0, 0, 6,},
485 {1, 1, 0, 2, 0, 0, 4, 0, 0, 0, 7, 1,},
486 {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,},
487 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
489 /* Level 15 */
490 {{0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
491 {0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
492 {0, 3, 4, 6, 0, 6, 0, 6, 0, 6, 0, 2,},
493 {0, 4, 0, 6, 0, 6, 4, 6, 0, 6, 0, 1,},
494 {0, 3, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
495 {7, 0, 0, 6, 4, 6, 0, 6, 0, 6, 0, 1,},
496 {0, 0, 4, 6, 0, 6, 0, 6, 4, 6, 0, 1,},
497 {0, 0, 4, 6, 0, 6, 0, 6, 0, 6, 0, 1,}}
501 /*****************************************************************************
502 * display_text() formats and outputs text.
503 ******************************************************************************/
504 static void display_text(char *str, bool waitkey)
506 int chars_by_line;
507 int lines_by_screen;
508 int chars_for_line;
509 int current_line = 0;
510 int char_width, char_height;
511 int first_char_index = 0;
512 char *ptr_char;
513 char *ptr_line;
514 int i;
515 char line[255];
516 int key;
517 bool go_on;
519 rb->lcd_clear_display();
521 rb->lcd_getstringsize("a", &char_width, &char_height);
523 chars_by_line = LCD_WIDTH / char_width;
524 lines_by_screen = LCD_HEIGHT / char_height;
528 ptr_char = str + first_char_index;
529 chars_for_line = 0;
530 i = 0;
531 ptr_line = line;
532 while (i < chars_by_line)
534 switch (*ptr_char)
536 case '\t':
537 case ' ':
538 *(ptr_line++) = ' ';
539 case '\n':
540 case '\0':
541 chars_for_line = i;
542 break;
544 default:
545 *(ptr_line++) = *ptr_char;
547 if (*ptr_char == '\n' || *ptr_char == '\0')
548 break;
549 ptr_char++;
550 i++;
553 if (chars_for_line == 0)
554 chars_for_line = i;
556 line[chars_for_line] = '\0';
558 /* test if we have cut a word. If it is the case we don't have to */
559 /* skip the space */
560 if (i == chars_by_line && chars_for_line == chars_by_line)
561 first_char_index += chars_for_line;
562 else
563 first_char_index += chars_for_line + 1;
565 /* print the line on the screen */
566 rb->lcd_putsxy(0, current_line * char_height, line);
568 /* if the number of line showed on the screen is equals to the */
569 /* maximum number of line we can show, we wait for a key pressed to */
570 /* clear and show the remaining text. */
571 current_line++;
572 if (current_line == lines_by_screen || *ptr_char == '\0')
574 current_line = 0;
575 rb->lcd_update();
576 go_on = false;
577 while (waitkey && !go_on)
579 key = rb->button_get(true);
580 switch (key)
582 case PEGBOX_QUIT:
583 case PEGBOX_LEFT:
584 case PEGBOX_DOWN:
585 go_on = true;
586 break;
588 default:
589 /*if (rb->default_event_handler(key) == SYS_USB_CONNECTED)
591 usb_detected = true;
592 go_on = true;
593 break;
595 break;
598 rb->lcd_clear_display();
600 } while (*ptr_char != '\0');
603 /*****************************************************************************
604 * draw_board() draws the game's current level.
605 ******************************************************************************/
606 static void draw_board(struct game_context* pb) {
607 unsigned int r, c, type;
608 pb->num_left = 0;
609 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
610 char str[5];
612 rb->lcd_clear_display();
613 rb->lcd_bitmap(pegbox_header,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_header);
614 rb->lcd_drawrect((LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2-2,
615 BMPHEIGHT_pegbox_header,
616 12*BMPWIDTH_pegbox_pieces+4,8*BMPWIDTH_pegbox_pieces+4);
618 #ifdef HAVE_LCD_COLOR
619 rb->lcd_set_foreground(LCD_WHITE);
620 rb->lcd_fillrect((LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2-1,BMPHEIGHT_pegbox_header+1,
621 12*BMPWIDTH_pegbox_pieces+2,8*BMPWIDTH_pegbox_pieces+2);
622 rb->lcd_set_foreground(LCD_BLACK);
623 rb->lcd_set_background(TEXT_BG);
624 #endif
626 #else
627 rb->lcd_clear_display();
629 #ifdef HAVE_LCD_COLOR
630 rb->lcd_set_foreground(LCD_WHITE);
631 rb->lcd_fillrect((LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2-1,0,
632 12*BMPWIDTH_pegbox_pieces+2,8*BMPWIDTH_pegbox_pieces+1);
633 rb->lcd_set_foreground(LCD_BLACK);
634 rb->lcd_set_background(TEXT_BG);
635 #endif
637 #endif
639 for (r=0 ; r < ROWS ; r++) {
640 for (c = 0 ; c < COLS ; c++) {
642 type = pb->playboard[r][c];
644 switch(type) {
645 case SPACE:
646 break;
648 default:
649 rb->lcd_bitmap_part(pegbox_pieces, 0,
650 (type-1)*BMPWIDTH_pegbox_pieces,
651 BMPWIDTH_pegbox_pieces,
652 c * BMPWIDTH_pegbox_pieces + BOARD_X,
653 r * BMPWIDTH_pegbox_pieces + BOARD_Y,
654 BMPWIDTH_pegbox_pieces,
655 BMPWIDTH_pegbox_pieces);
656 break;
659 if(pb->playboard[r][c] == PLAYER) {
660 pb->player_row=r;
661 pb->player_col=c;
663 else if (type != WALL && type != SPACE && type != HOLE)
664 pb->num_left++;
667 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
668 rb->snprintf(str, 3, "%d", pb->level);
669 rb->lcd_putsxy(LEVEL_TEXT_X, TEXT_Y, str);
670 rb->snprintf(str, 3, "%d", pb->num_left);
671 rb->lcd_putsxy(PEGS_TEXT_X, TEXT_Y, str);
672 #endif
674 #ifdef HAVE_LCD_COLOR
675 rb->lcd_set_background(BG_COLOR);
676 rb->lcd_set_foreground(LCD_WHITE);
677 #endif
678 /* print out the screen */
679 rb->lcd_update();
682 /*****************************************************************************
683 * load_level() loads the player's current level from the array and sets the
684 * player's position.
685 ******************************************************************************/
686 static void load_level(struct game_context* pb) {
687 int r, c;
689 for(r = 0; r < ROWS; r++)
690 for(c = 0; c < COLS; c++)
691 pb->playboard[r][c] = levels[pb->level-1][r][c];
694 /*****************************************************************************
695 * new_piece() creates a new piece at a specified location. The player
696 * navigates through the pieces and selects one.
697 ******************************************************************************/
698 static void new_piece(struct game_context* pb, unsigned int x_loc,
699 unsigned int y_loc) {
700 int button;
701 bool exit = false;
703 pb->playboard[x_loc][y_loc] = TRIANGLE;
705 while (!exit) {
706 draw_board(pb);
707 button = rb->button_get(true);
708 switch(button){
709 case PEGBOX_LEFT:
710 case (PEGBOX_LEFT|BUTTON_REPEAT):
711 case PEGBOX_DOWN:
712 case (PEGBOX_DOWN|BUTTON_REPEAT):
713 if (pb->playboard[x_loc][y_loc] < 5)
714 pb->playboard[x_loc][y_loc]++;
715 else
716 pb->playboard[x_loc][y_loc] = TRIANGLE;
717 break;
718 case PEGBOX_RIGHT:
719 case (PEGBOX_RIGHT|BUTTON_REPEAT):
720 case PEGBOX_UP:
721 case (PEGBOX_UP|BUTTON_REPEAT):
722 if (pb->playboard[x_loc][y_loc] > 2)
723 pb->playboard[x_loc][y_loc]--;
724 else
725 pb->playboard[x_loc][y_loc] = CIRCLE;
726 break;
727 case PEGBOX_SAVE:
728 exit = true;
729 break;
734 /*****************************************************************************
735 * move_player() moves the player and pieces and updates the board accordingly.
736 ******************************************************************************/
737 static void move_player(struct game_context* pb, signed int x_dir,
738 signed int y_dir) {
739 unsigned int type1, type2;
740 signed int r,c;
742 r = pb->player_row+y_dir;
743 c = pb->player_col+x_dir;
745 type1 = pb->playboard[r][c];
746 type2 = pb->playboard[r+y_dir][c+x_dir];
748 if (r == ROWS || c == COLS || r < 0 || c < 0 || type1 == WALL)
749 return;
750 else if(type1 != SPACE) {
751 if (type2 == WALL || r+y_dir == ROWS || c+x_dir == COLS ||
752 r+y_dir < 0 || c+x_dir < 0)
753 return;
757 pb->playboard[pb->player_row][pb->player_col] = SPACE;
758 pb->player_row += y_dir;
759 pb->player_col += x_dir;
761 if (type1 == HOLE) {
762 draw_board(pb);
763 rb->splash(HZ*2, "You fell down a hole!");
764 load_level(pb);
766 else if (type1 == SPACE)
767 pb->playboard[r][c] = PLAYER;
768 else {
769 pb->playboard[r][c] = PLAYER;
770 if(type1 == type2) {
771 if (type1 == TRIANGLE)
772 pb->playboard[r+y_dir][c+x_dir] = WALL;
773 else if (type1 == CROSS) {
774 pb->playboard[r][c] = SPACE;
775 new_piece(pb, r+y_dir, c+x_dir);
776 pb->playboard[r][c] = PLAYER;
778 else
779 pb->playboard[r+y_dir][c+x_dir] = SPACE;
781 else if (type2 == SPACE)
782 pb->playboard[r+y_dir][c+x_dir] = type1;
783 else if (type2 == HOLE) {
784 if (type1 == SQUARE)
785 pb->playboard[r+y_dir][c+x_dir] = SPACE;
787 else {
788 rb->splash(HZ*2, "Illegal Move!");
789 load_level(pb);
793 draw_board(pb);
796 /*****************************************************************************
797 * pegbox_loadgame() loads the saved game and returns load success.
798 ******************************************************************************/
799 static bool pegbox_loadgame(struct game_context* pb) {
800 signed int fd;
801 bool loaded = false;
803 /* open game file */
804 fd = rb->open(SAVE_FILE, O_RDONLY);
805 if(fd < 0) return loaded;
807 /* read in saved game */
808 while(true) {
809 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
810 if(rb->read(fd, &pb->playboard, sizeof(pb->playboard)) <= 0)
812 loaded = true;
813 break;
815 break;
818 rb->close(fd);
819 return loaded;
822 /*****************************************************************************
823 * pegbox_savegame() saves the current game state.
824 ******************************************************************************/
825 static void pegbox_savegame(struct game_context* pb) {
826 unsigned int fd;
828 /* write out the game state to the save file */
829 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
830 rb->write(fd, &pb->level, sizeof(pb->level));
831 rb->write(fd, &pb->playboard, sizeof(pb->playboard));
832 rb->close(fd);
835 /*****************************************************************************
836 * pegbox_loaddata() loads the level and highlevel and returns load success.
837 ******************************************************************************/
838 static void pegbox_loaddata(struct game_context* pb) {
839 signed int fd;
841 /* open game file */
842 fd = rb->open(DATA_FILE, O_RDONLY);
843 if(fd < 0) {
844 pb->level = 1;
845 pb->highlevel = 1;
846 return;
849 /* read in saved game */
850 while(true) {
851 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
852 if(rb->read(fd, &pb->highlevel, sizeof(pb->highlevel)) <= 0) break;
853 break;
856 rb->close(fd);
857 return;
860 /*****************************************************************************
861 * pegbox_savedata() saves the level and highlevel.
862 ******************************************************************************/
863 static void pegbox_savedata(struct game_context* pb) {
864 unsigned int fd;
866 /* write out the game state to the save file */
867 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT);
868 rb->write(fd, &pb->level, sizeof(pb->level));
869 rb->write(fd, &pb->highlevel, sizeof(pb->highlevel));
870 rb->close(fd);
873 /*****************************************************************************
874 * pegbox_callback() is the default event handler callback which is called
875 * on usb connect and shutdown.
876 ******************************************************************************/
877 static void pegbox_callback(void* param) {
878 struct game_context* pb = (struct game_context*) param;
879 rb->splash(HZ, "Saving data...");
880 pegbox_savedata(pb);
883 /*****************************************************************************
884 * pegbox_menu() is the initial menu at the start of the game.
885 ******************************************************************************/
886 static unsigned int pegbox_menu(struct game_context* pb) {
887 int button;
888 char str[30];
889 unsigned int startlevel = 1, loc = 0;
890 bool breakout = false, can_resume = false;
892 if (pb->num_left > 0 || pb->save_exist)
893 can_resume = true;
895 while(!breakout){
896 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
897 rb->lcd_clear_display();
898 rb->lcd_bitmap(pegbox_menu_top,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_menu_top);
900 /* menu bitmaps */
901 if (loc == 0) {
902 rb->lcd_bitmap_part(pegbox_menu_items, 0,
903 (BMPHEIGHT_pegbox_menu_items/9),
904 BMPWIDTH_pegbox_menu_items,
905 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
906 BMPHEIGHT_pegbox_menu_top,
907 BMPWIDTH_pegbox_menu_items,
908 (BMPHEIGHT_pegbox_menu_items/9));
910 else {
911 rb->lcd_bitmap_part(pegbox_menu_items, 0, 0,
912 BMPWIDTH_pegbox_menu_items,
913 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
914 BMPHEIGHT_pegbox_menu_top,
915 BMPWIDTH_pegbox_menu_items,
916 (BMPHEIGHT_pegbox_menu_items/9));
918 if (can_resume) {
919 if (loc == 1) {
920 rb->lcd_bitmap_part(pegbox_menu_items, 0,
921 (BMPHEIGHT_pegbox_menu_items/9)*3,
922 BMPWIDTH_pegbox_menu_items,
923 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
924 BMPHEIGHT_pegbox_menu_top+
925 (BMPHEIGHT_pegbox_menu_items/9),
926 BMPWIDTH_pegbox_menu_items,
927 (BMPHEIGHT_pegbox_menu_items/9));
929 else {
930 rb->lcd_bitmap_part(pegbox_menu_items, 0,
931 (BMPHEIGHT_pegbox_menu_items/9)*2,
932 BMPWIDTH_pegbox_menu_items,
933 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
934 BMPHEIGHT_pegbox_menu_top+
935 (BMPHEIGHT_pegbox_menu_items/9),
936 BMPWIDTH_pegbox_menu_items,
937 (BMPHEIGHT_pegbox_menu_items/9));
940 else {
941 rb->lcd_bitmap_part(pegbox_menu_items, 0,
942 (BMPHEIGHT_pegbox_menu_items/9)*4,
943 BMPWIDTH_pegbox_menu_items,
944 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
945 BMPHEIGHT_pegbox_menu_top+
946 (BMPHEIGHT_pegbox_menu_items/9),
947 BMPWIDTH_pegbox_menu_items,
948 (BMPHEIGHT_pegbox_menu_items/9));
951 if (loc==2) {
952 rb->lcd_bitmap_part(pegbox_menu_items, 0,
953 (BMPHEIGHT_pegbox_menu_items/9)*6,
954 BMPWIDTH_pegbox_menu_items,
955 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
956 BMPHEIGHT_pegbox_menu_top+
957 (BMPHEIGHT_pegbox_menu_items/9)*2,
958 BMPWIDTH_pegbox_menu_items,
959 (BMPHEIGHT_pegbox_menu_items/9));
961 else {
962 rb->lcd_bitmap_part(pegbox_menu_items, 0,
963 (BMPHEIGHT_pegbox_menu_items/9)*5,
964 BMPWIDTH_pegbox_menu_items,
965 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
966 BMPHEIGHT_pegbox_menu_top+
967 (BMPHEIGHT_pegbox_menu_items/9)*2,
968 BMPWIDTH_pegbox_menu_items,
969 (BMPHEIGHT_pegbox_menu_items/9));
972 if (loc==3) {
973 rb->lcd_bitmap_part(pegbox_menu_items, 0,
974 (BMPHEIGHT_pegbox_menu_items/9)*8,
975 BMPWIDTH_pegbox_menu_items,
976 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
977 BMPHEIGHT_pegbox_menu_top+
978 (BMPHEIGHT_pegbox_menu_items/9)*3,
979 BMPWIDTH_pegbox_menu_items,
980 (BMPHEIGHT_pegbox_menu_items/9));
982 else {
983 rb->lcd_bitmap_part(pegbox_menu_items, 0,
984 (BMPHEIGHT_pegbox_menu_items/9)*7,
985 BMPWIDTH_pegbox_menu_items,
986 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
987 BMPHEIGHT_pegbox_menu_top+
988 (BMPHEIGHT_pegbox_menu_items/9)*3,
989 BMPWIDTH_pegbox_menu_items,
990 (BMPHEIGHT_pegbox_menu_items/9));
992 #else
993 unsigned int w,h;
994 rb->lcd_clear_display();
995 rb->lcd_getstringsize("PegBox", &w, &h);
996 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, "PegBox");
997 rb->lcd_putsxy((LCD_WIDTH)/4, 16, "New Game");
998 rb->lcd_putsxy((LCD_WIDTH)/4, 24, "Resume");
999 rb->lcd_putsxy((LCD_WIDTH)/4, 32, "Help");
1000 rb->lcd_putsxy((LCD_WIDTH)/4, 40, "Quit");
1002 if(!can_resume)
1003 rb->lcd_hline((LCD_WIDTH)/4, (LCD_WIDTH)/4+30, 28);
1005 rb->lcd_putsxy((LCD_WIDTH)/4-8, loc*8+16, "*");
1008 #endif
1009 rb->snprintf(str, 28, "Start on level %d of %d", startlevel,
1010 pb->highlevel);
1011 #if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
1012 rb->lcd_putsxy(0, BMPHEIGHT_pegbox_menu_top+4*
1013 (BMPHEIGHT_pegbox_menu_items/9)+8, str);
1014 #elif LCD_WIDTH > 112
1015 rb->lcd_putsxy(0, LCD_HEIGHT - 8, str);
1016 #else
1017 rb->lcd_puts_scroll(0, 7, str);
1018 #endif
1019 rb->lcd_update();
1021 /* handle menu button presses */
1022 button = rb->button_get(true);
1024 switch(button) {
1025 case PEGBOX_SAVE: /* start playing */
1026 case PEGBOX_RIGHT:
1027 if (loc == 0) {
1028 breakout = true;
1029 pb->level = startlevel;
1030 load_level(pb);
1032 else if (loc == 1 && can_resume) {
1033 if(pb->save_exist)
1035 rb->remove(SAVE_FILE);
1036 pb->save_exist = false;
1038 breakout = true;
1040 else if (loc == 2)
1041 display_text("How to Play\nTo beat each level, you must "
1042 "destroy all of the pegs. If two like pegs are "
1043 "pushed into each other they disappear except "
1044 "for triangles which form a solid block and "
1045 "crosses which allow you to choose a "
1046 "replacement block.\n\n"
1047 "Controls\n"
1048 #if LCD_HEIGHT > 64
1049 RESTART_TEXT " to restart level\n"
1050 LVL_UP_TEXT " to go up a level\n"
1051 LVL_DOWN_TEXT " to go down a level\n"
1052 SAVE_TEXT " to select/save\n"
1053 QUIT_TEXT " to quit\n",true);
1054 #else
1055 RESTART_TEXT ": restart\n"
1056 LVL_UP_TEXT ": level up\n"
1057 LVL_DOWN_TEXT " level down\n"
1058 SAVE_TEXT " select/save\n"
1059 QUIT_TEXT " quit\n",true);
1060 #endif
1061 else if (loc == 3)
1062 return PB_QUIT;
1063 break;
1065 case PEGBOX_QUIT: /* quit program */
1066 return PB_QUIT;
1068 case (PEGBOX_UP|BUTTON_REPEAT):
1069 case PEGBOX_UP:
1070 if (loc <= 0)
1071 loc = 3;
1072 else
1073 loc--;
1074 if (!can_resume && loc == 1) {
1075 loc = 0;
1077 break;
1080 case (PEGBOX_DOWN|BUTTON_REPEAT):
1081 case PEGBOX_DOWN:
1082 if (loc >= 3)
1083 loc = 0;
1084 else
1085 loc++;
1086 if (!can_resume && loc == 1) {
1087 loc = 2;
1089 break;
1091 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1092 case PEGBOX_LVL_UP: /* increase starting level */
1093 if(startlevel >= pb->highlevel) {
1094 startlevel = 1;
1095 } else {
1096 startlevel++;
1098 break;
1100 /* only for targets with enough buttons */
1101 #ifdef PEGBOX_LVL_DOWN
1102 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1103 case PEGBOX_LVL_DOWN: /* decrease starting level */
1104 if(startlevel <= 1) {
1105 startlevel = pb->highlevel;
1106 } else {
1107 startlevel--;
1109 break;
1110 #endif
1111 default:
1112 if(rb->default_event_handler_ex(button, pegbox_callback,
1113 (void*) pb) == SYS_USB_CONNECTED)
1114 return PB_USB;
1115 break;
1119 draw_board(pb);
1121 return 0;
1124 /*****************************************************************************
1125 * pegbox() is the main game subroutine, it returns the final game status.
1126 ******************************************************************************/
1127 static int pegbox(struct game_context* pb) {
1128 int temp_var;
1130 /********************
1131 * menu *
1132 ********************/
1133 temp_var = pegbox_menu(pb);
1134 if (temp_var == PB_QUIT || temp_var == PB_USB)
1135 return temp_var;
1137 while (true) {
1138 temp_var = rb->button_get(true);
1139 switch(temp_var){
1140 case PEGBOX_LEFT: /* move cursor left */
1141 case (PEGBOX_LEFT|BUTTON_REPEAT):
1142 move_player(pb, -1, 0);
1143 break;
1145 case PEGBOX_RIGHT: /* move cursor right */
1146 case (PEGBOX_RIGHT|BUTTON_REPEAT):
1147 move_player(pb, 1, 0);
1148 break;
1150 case PEGBOX_DOWN: /* move cursor down */
1151 case (PEGBOX_DOWN|BUTTON_REPEAT):
1152 move_player(pb, 0, 1);
1153 break;
1155 case PEGBOX_UP: /* move cursor up */
1156 case (PEGBOX_UP|BUTTON_REPEAT):
1157 move_player(pb, 0, -1);
1158 break;
1160 case PEGBOX_SAVE: /* save and end game */
1161 rb->splash(HZ, "Saving game...");
1162 pegbox_savegame(pb);
1163 /* fall through to PEGBOX_QUIT */
1165 case PEGBOX_QUIT:
1166 return PB_END;
1168 case PEGBOX_RESTART:
1169 load_level(pb);
1170 draw_board(pb);
1171 break;
1173 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1174 case PEGBOX_LVL_UP:
1175 if(pb->level >= pb->highlevel) {
1176 pb->level = 1;
1177 } else {
1178 pb->level++;
1180 load_level(pb);
1181 draw_board(pb);
1182 break;
1184 /* only for targets with enough buttons */
1185 #ifdef PEGBOX_LVL_DOWN
1186 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1187 case PEGBOX_LVL_DOWN:
1188 if(pb->level <= 1) {
1189 pb->level = pb->highlevel;
1190 } else {
1191 pb->level--;
1193 load_level(pb);
1194 draw_board(pb);
1195 break;
1196 #endif
1200 if(pb->num_left == 0) {
1201 rb->splash(HZ*2, "Nice Pegging!");
1202 if(pb->level == NUM_LEVELS) {
1203 draw_board(pb);
1204 rb->splash(HZ*2, "You Won!");
1205 break;
1207 else {
1208 pb->level++;
1209 load_level(pb);
1210 draw_board(pb);
1213 if(pb->level > pb->highlevel)
1214 pb->highlevel = pb->level;
1219 return PLUGIN_OK;
1223 /*****************************************************************************
1224 * plugin entry point.
1225 ******************************************************************************/
1226 enum plugin_status plugin_start(struct plugin_api* api, void* parameter) {
1227 bool exit = false;
1228 struct game_context pb;
1230 (void)parameter;
1231 rb = api;
1233 rb->lcd_setfont(FONT_SYSFIXED);
1234 #if LCD_DEPTH > 1
1235 rb->lcd_set_backdrop(NULL);
1236 #endif
1237 #ifdef HAVE_LCD_COLOR
1238 rb->lcd_set_foreground(LCD_WHITE);
1239 rb->lcd_set_background(BG_COLOR);
1240 #endif
1242 rb->splash(0, "Loading...");
1243 pegbox_loaddata(&pb);
1244 pb.save_exist = pegbox_loadgame(&pb);
1245 pb.num_left = 0;
1247 rb->lcd_clear_display();
1250 while(!exit) {
1251 switch(pegbox(&pb)){
1252 case PB_END:
1253 break;
1255 case PB_USB:
1256 rb->lcd_setfont(FONT_UI);
1257 return PLUGIN_USB_CONNECTED;
1259 case PB_QUIT:
1260 rb->splash(HZ, "Saving data...");
1261 pegbox_savedata(&pb);
1262 exit = true;
1263 break;
1265 default:
1266 break;
1270 rb->lcd_setfont(FONT_UI);
1271 return PLUGIN_OK;