blob: 4ba8156e8bb8e337b6e5fb8ecc86ba3c7660296c [file] [log] [blame]
Robert Kuklab411ce62008-04-03 22:43:39 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 Tom Ross
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Robert Kuklab411ce62008-04-03 22:43:39 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "plugin.h"
22
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +000023#if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
Robert Kuklab411ce62008-04-03 22:43:39 +000024#include "pegbox_menu_top.h"
25#include "pegbox_menu_items.h"
26#include "pegbox_header.h"
27#endif
28#include "pegbox_pieces.h"
29
Steve Bavin65265772008-05-13 09:57:56 +000030static const struct plugin_api* rb;
Robert Kuklab411ce62008-04-03 22:43:39 +000031
32PLUGIN_HEADER
33
34/* final game return status */
35#define PB_END 3
36#define PB_USB 2
37#define PB_QUIT 1
38
39#define DATA_FILE PLUGIN_DIR "/games/pegbox.data"
40#define SAVE_FILE PLUGIN_DIR "/games/pegbox.save"
41
42#define ROWS 8 /* Number of rows on each board */
43#define COLS 12 /* Number of columns on each board */
44#define NUM_LEVELS 15 /* Number of levels */
45
46#define SPACE 0
47#define WALL 1
48#define TRIANGLE 2
49#define CROSS 3
50#define SQUARE 4
51#define CIRCLE 5
52#define HOLE 6
53#define PLAYER 7
54
55#if CONFIG_KEYPAD == RECORDER_PAD
Robert Kukla1b335ae2008-04-04 17:54:29 +000056#define PEGBOX_SAVE BUTTON_ON
Robert Kuklab411ce62008-04-03 22:43:39 +000057#define PEGBOX_QUIT BUTTON_OFF
Robert Kukla1b335ae2008-04-04 17:54:29 +000058#define PEGBOX_RESTART BUTTON_F2
Robert Kuklab411ce62008-04-03 22:43:39 +000059#define PEGBOX_LVL_UP BUTTON_F1
60#define PEGBOX_LVL_DOWN BUTTON_F3
61#define PEGBOX_UP BUTTON_UP
62#define PEGBOX_DOWN BUTTON_DOWN
63#define PEGBOX_RIGHT BUTTON_RIGHT
64#define PEGBOX_LEFT BUTTON_LEFT
65
Robert Kukla1b335ae2008-04-04 17:54:29 +000066#define SAVE_TEXT "ON"
67#define QUIT_TEXT "OFF"
68#define RESTART_TEXT "F2"
Robert Kuklab411ce62008-04-03 22:43:39 +000069#define LVL_UP_TEXT "F1"
70#define LVL_DOWN_TEXT "F3"
Robert Kuklab411ce62008-04-03 22:43:39 +000071
72#elif CONFIG_KEYPAD == ONDIO_PAD
Robert Kukla1b335ae2008-04-04 17:54:29 +000073#define PEGBOX_SAVE BUTTON_OFF
74#define PEGBOX_QUIT (BUTTON_MENU | BUTTON_LEFT)
75#define PEGBOX_RESTART (BUTTON_MENU | BUTTON_RIGHT)
76#define PEGBOX_LVL_UP (BUTTON_MENU | BUTTON_UP)
77#define PEGBOX_LVL_DOWN (BUTTON_MENU | BUTTON_DOWN)
Robert Kuklab411ce62008-04-03 22:43:39 +000078#define PEGBOX_UP BUTTON_UP
79#define PEGBOX_DOWN BUTTON_DOWN
80#define PEGBOX_RIGHT BUTTON_RIGHT
81#define PEGBOX_LEFT BUTTON_LEFT
82
Robert Kukla1b335ae2008-04-04 17:54:29 +000083#define SAVE_TEXT "OFF"
84#define QUIT_TEXT "M+LEFT"
85#define RESTART_TEXT "M+RIGHT"
86#define LVL_UP_TEXT "M+UP"
87#define LVL_DOWN_TEXT "M+DOWN"
Robert Kuklab411ce62008-04-03 22:43:39 +000088
89#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
90 (CONFIG_KEYPAD == IRIVER_H300_PAD)
Robert Kukla1b335ae2008-04-04 17:54:29 +000091#define PEGBOX_SAVE BUTTON_SELECT
Robert Kuklab411ce62008-04-03 22:43:39 +000092#define PEGBOX_QUIT BUTTON_OFF
Robert Kukla1b335ae2008-04-04 17:54:29 +000093#define PEGBOX_RESTART BUTTON_ON
94#define PEGBOX_LVL_UP BUTTON_MODE
Robert Kuklab411ce62008-04-03 22:43:39 +000095#define PEGBOX_LVL_DOWN BUTTON_REC
96#define PEGBOX_UP BUTTON_UP
97#define PEGBOX_DOWN BUTTON_DOWN
98#define PEGBOX_RIGHT BUTTON_RIGHT
99#define PEGBOX_LEFT BUTTON_LEFT
100
Robert Kukla1b335ae2008-04-04 17:54:29 +0000101#define SAVE_TEXT "NAVI"
Robert Kuklab411ce62008-04-03 22:43:39 +0000102#define QUIT_TEXT "OFF"
Robert Kukla1b335ae2008-04-04 17:54:29 +0000103#define RESTART_TEXT "ON"
104#define LVL_UP_TEXT "AB"
105#define LVL_DOWN_TEXT "REC"
Robert Kuklab411ce62008-04-03 22:43:39 +0000106
107#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
108 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
109 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
Robert Kuklab411ce62008-04-03 22:43:39 +0000110#define PEGBOX_SAVE (BUTTON_SELECT|BUTTON_RIGHT)
Robert Kukla1b335ae2008-04-04 17:54:29 +0000111#define PEGBOX_QUIT (BUTTON_SELECT|BUTTON_PLAY)
Robert Kuklab411ce62008-04-03 22:43:39 +0000112#define PEGBOX_RESTART (BUTTON_SELECT|BUTTON_LEFT)
Robert Kukla1b335ae2008-04-04 17:54:29 +0000113#define PEGBOX_LVL_UP (BUTTON_SELECT|BUTTON_MENU)
Robert Kuklab411ce62008-04-03 22:43:39 +0000114#define PEGBOX_UP BUTTON_MENU
115#define PEGBOX_DOWN BUTTON_PLAY
116#define PEGBOX_RIGHT BUTTON_RIGHT
117#define PEGBOX_LEFT BUTTON_LEFT
118
Robert Kuklab411ce62008-04-03 22:43:39 +0000119#define SAVE_TEXT "SELECT+RIGHT"
Robert Kukla1b335ae2008-04-04 17:54:29 +0000120#define QUIT_TEXT "SELECT+PLAY"
121#define RESTART_TEXT "SELECT+LEFT"
122#define LVL_UP_TEXT "SELECT+MENU"
123#define LVL_DOWN_TEXT "-"
Robert Kuklab411ce62008-04-03 22:43:39 +0000124
125#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
Robert Kukla1b335ae2008-04-04 17:54:29 +0000126#define PEGBOX_SAVE BUTTON_SELECT
Robert Kuklab411ce62008-04-03 22:43:39 +0000127#define PEGBOX_QUIT BUTTON_POWER
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +0000128#define PEGBOX_RESTART BUTTON_REC
Robert Kukla1b335ae2008-04-04 17:54:29 +0000129#define PEGBOX_LVL_UP BUTTON_PLAY
Robert Kuklab411ce62008-04-03 22:43:39 +0000130#define PEGBOX_UP BUTTON_UP
131#define PEGBOX_DOWN BUTTON_DOWN
132#define PEGBOX_RIGHT BUTTON_RIGHT
133#define PEGBOX_LEFT BUTTON_LEFT
134
Robert Kukla1b335ae2008-04-04 17:54:29 +0000135#define SAVE_TEXT "SELECT"
Robert Kuklab411ce62008-04-03 22:43:39 +0000136#define QUIT_TEXT "OFF"
Robert Kukla1b335ae2008-04-04 17:54:29 +0000137#define RESTART_TEXT "REC"
138#define LVL_UP_TEXT "PLAY"
139#define LVL_DOWN_TEXT "-"
Robert Kuklab411ce62008-04-03 22:43:39 +0000140
141#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
Robert Kukla1b335ae2008-04-04 17:54:29 +0000142#define PEGBOX_SAVE BUTTON_MODE
Robert Kuklab411ce62008-04-03 22:43:39 +0000143#define PEGBOX_QUIT BUTTON_PLAY
Robert Kukla1b335ae2008-04-04 17:54:29 +0000144#define PEGBOX_RESTART (BUTTON_EQ|BUTTON_MODE)
Robert Kuklab411ce62008-04-03 22:43:39 +0000145#define PEGBOX_LVL_UP (BUTTON_EQ|BUTTON_UP)
146#define PEGBOX_LVL_DOWN (BUTTON_EQ|BUTTON_DOWN)
147#define PEGBOX_UP BUTTON_UP
148#define PEGBOX_DOWN BUTTON_DOWN
149#define PEGBOX_RIGHT BUTTON_RIGHT
150#define PEGBOX_LEFT BUTTON_LEFT
151
Robert Kukla1b335ae2008-04-04 17:54:29 +0000152#define SAVE_TEXT "MODE"
153#define QUIT_TEXT "PLAY"
154#define RESTART_TEXT "EQ+MODE"
Robert Kuklab411ce62008-04-03 22:43:39 +0000155#define LVL_UP_TEXT "EQ+UP"
156#define LVL_DOWN_TEXT "EQ+DOWN"
Robert Kuklab411ce62008-04-03 22:43:39 +0000157
158#elif CONFIG_KEYPAD == IRIVER_H10_PAD
Robert Kukla1b335ae2008-04-04 17:54:29 +0000159#define PEGBOX_SAVE BUTTON_PLAY
Robert Kuklab411ce62008-04-03 22:43:39 +0000160#define PEGBOX_QUIT BUTTON_POWER
Robert Kuklab411ce62008-04-03 22:43:39 +0000161#define PEGBOX_RESTART (BUTTON_FF|BUTTON_REPEAT)
162#define PEGBOX_LVL_UP (BUTTON_FF|BUTTON_SCROLL_UP)
163#define PEGBOX_LVL_DOWN (BUTTON_FF|BUTTON_SCROLL_DOWN)
164#define PEGBOX_UP BUTTON_SCROLL_UP
165#define PEGBOX_DOWN BUTTON_SCROLL_DOWN
166#define PEGBOX_RIGHT BUTTON_RIGHT
167#define PEGBOX_LEFT BUTTON_LEFT
168
Robert Kukla1b335ae2008-04-04 17:54:29 +0000169#define SAVE_TEXT "PLAY"
170#define QUIT_TEXT "OFF"
Robert Kuklab411ce62008-04-03 22:43:39 +0000171#define RESTART_TEXT "LONG FF"
172#define LVL_UP_TEXT "FF+SCROLL_UP"
173#define LVL_DOWN_TEXT "FF+SCROLL_DOWN"
Robert Kuklab411ce62008-04-03 22:43:39 +0000174
175#elif CONFIG_KEYPAD == SANSA_E200_PAD
Robert Kukla1b335ae2008-04-04 17:54:29 +0000176#define PEGBOX_SAVE BUTTON_SELECT
Robert Kuklab411ce62008-04-03 22:43:39 +0000177#define PEGBOX_QUIT BUTTON_POWER
Robert Kukla1b335ae2008-04-04 17:54:29 +0000178#define PEGBOX_RESTART BUTTON_REC
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +0000179#define PEGBOX_LVL_UP BUTTON_SCROLL_BACK
180#define PEGBOX_LVL_DOWN BUTTON_SCROLL_FWD
Robert Kuklab411ce62008-04-03 22:43:39 +0000181#define PEGBOX_UP BUTTON_UP
182#define PEGBOX_DOWN BUTTON_DOWN
183#define PEGBOX_RIGHT BUTTON_RIGHT
184#define PEGBOX_LEFT BUTTON_LEFT
185
Robert Kukla1b335ae2008-04-04 17:54:29 +0000186#define SAVE_TEXT "SELECT"
Robert Kuklab411ce62008-04-03 22:43:39 +0000187#define QUIT_TEXT "POWER"
Robert Kukla1b335ae2008-04-04 17:54:29 +0000188#define RESTART_TEXT "REC"
189#define LVL_UP_TEXT "SCROLL BACK"
190#define LVL_DOWN_TEXT "SCROLL FWD"
Robert Kuklab411ce62008-04-03 22:43:39 +0000191
192#elif CONFIG_KEYPAD == GIGABEAT_PAD
Robert Kukla1b335ae2008-04-04 17:54:29 +0000193#define PEGBOX_SAVE BUTTON_SELECT
Robert Kuklab411ce62008-04-03 22:43:39 +0000194#define PEGBOX_QUIT BUTTON_POWER
Robert Kuklab411ce62008-04-03 22:43:39 +0000195#define PEGBOX_RESTART BUTTON_A
196#define PEGBOX_LVL_UP BUTTON_VOL_UP
197#define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
198#define PEGBOX_UP BUTTON_UP
199#define PEGBOX_DOWN BUTTON_DOWN
200#define PEGBOX_RIGHT BUTTON_RIGHT
201#define PEGBOX_LEFT BUTTON_LEFT
202
Robert Kukla1b335ae2008-04-04 17:54:29 +0000203#define SAVE_TEXT "SELECT"
204#define QUIT_TEXT "POWER"
205#define RESTART_TEXT "A"
Robert Kuklab411ce62008-04-03 22:43:39 +0000206#define LVL_UP_TEXT "VOL+"
207#define LVL_DOWN_TEXT "VOL-"
Robert Kuklab411ce62008-04-03 22:43:39 +0000208
Michael Sevakis5d230522008-04-06 23:25:21 +0000209#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
210#define PEGBOX_SAVE BUTTON_SELECT
211#define PEGBOX_QUIT BUTTON_BACK
212#define PEGBOX_RESTART BUTTON_MENU
213#define PEGBOX_LVL_UP BUTTON_VOL_UP
214#define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
215#define PEGBOX_UP BUTTON_UP
216#define PEGBOX_DOWN BUTTON_DOWN
217#define PEGBOX_RIGHT BUTTON_RIGHT
218#define PEGBOX_LEFT BUTTON_LEFT
219
220#define SAVE_TEXT "SELECT"
221#define QUIT_TEXT "BACK"
222#define RESTART_TEXT "MENU"
223#define LVL_UP_TEXT "VOL+"
224#define LVL_DOWN_TEXT "VOL-"
225
Robert Kuklab411ce62008-04-03 22:43:39 +0000226#elif CONFIG_KEYPAD == MROBE100_PAD
Robert Kukla1b335ae2008-04-04 17:54:29 +0000227#define PEGBOX_SAVE BUTTON_SELECT
Robert Kuklab411ce62008-04-03 22:43:39 +0000228#define PEGBOX_QUIT BUTTON_POWER
Robert Kuklab411ce62008-04-03 22:43:39 +0000229#define PEGBOX_RESTART BUTTON_PLAY
Robert Kukla1b335ae2008-04-04 17:54:29 +0000230#define PEGBOX_LVL_UP BUTTON_MENU
231#define PEGBOX_LVL_DOWN BUTTON_DISPLAY
Robert Kuklab411ce62008-04-03 22:43:39 +0000232#define PEGBOX_UP BUTTON_UP
233#define PEGBOX_DOWN BUTTON_DOWN
234#define PEGBOX_RIGHT BUTTON_RIGHT
235#define PEGBOX_LEFT BUTTON_LEFT
236
Robert Kukla1b335ae2008-04-04 17:54:29 +0000237#define SAVE_TEXT "SELECT"
Robert Kuklab411ce62008-04-03 22:43:39 +0000238#define QUIT_TEXT "POWER"
Robert Kukla1b335ae2008-04-04 17:54:29 +0000239#define RESTART_TEXT "PLAY"
240#define LVL_UP_TEXT "MENU"
241#define LVL_DOWN_TEXT "DISPLAY"
Robert Kuklab411ce62008-04-03 22:43:39 +0000242
243#elif CONFIG_KEYPAD == SANSA_C200_PAD
Robert Kukla1b335ae2008-04-04 17:54:29 +0000244#define PEGBOX_SAVE BUTTON_SELECT
Robert Kuklab411ce62008-04-03 22:43:39 +0000245#define PEGBOX_QUIT BUTTON_POWER
Robert Kukla1b335ae2008-04-04 17:54:29 +0000246#define PEGBOX_RESTART BUTTON_REC
Robert Kuklab411ce62008-04-03 22:43:39 +0000247#define PEGBOX_LVL_UP BUTTON_VOL_UP
248#define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
249#define PEGBOX_UP BUTTON_UP
250#define PEGBOX_DOWN BUTTON_DOWN
251#define PEGBOX_RIGHT BUTTON_RIGHT
252#define PEGBOX_LEFT BUTTON_LEFT
253
Robert Kukla1b335ae2008-04-04 17:54:29 +0000254#define SAVE_TEXT "SELECT"
255#define QUIT_TEXT "POWER"
Robert Kuklab411ce62008-04-03 22:43:39 +0000256#define RESTART_TEXT "REC"
257#define LVL_UP_TEXT "VOL+"
258#define LVL_DOWN_TEXT "VOL-"
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +0000259
260#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
Robert Kukla1b335ae2008-04-04 17:54:29 +0000261#define PEGBOX_SAVE BUTTON_RC_PLAY
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +0000262#define PEGBOX_QUIT BUTTON_RC_REC
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +0000263#define PEGBOX_RESTART BUTTON_RC_MODE
264#define PEGBOX_LVL_UP BUTTON_VOL_UP
265#define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
266#define PEGBOX_UP BUTTON_RC_VOL_UP
267#define PEGBOX_DOWN BUTTON_RC_VOL_DOWN
268#define PEGBOX_RIGHT BUTTON_RC_FF
269#define PEGBOX_LEFT BUTTON_RC_REW
270
Robert Kukla1b335ae2008-04-04 17:54:29 +0000271#define SAVE_TEXT "REM. PLAY"
272#define QUIT_TEXT "REM. REC"
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +0000273#define RESTART_TEXT "REM. MODE"
274#define LVL_UP_TEXT "VOL+"
275#define LVL_DOWN_TEXT "VOL-"
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +0000276
277#elif CONFIG_KEYPAD == COWOND2_PAD
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +0000278#define PEGBOX_QUIT BUTTON_POWER
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +0000279
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +0000280#define QUIT_TEXT "POWER"
Michael Sevakis5d230522008-04-06 23:25:21 +0000281#else
282#error Unsupported keymap!
Robert Kuklab411ce62008-04-03 22:43:39 +0000283#endif
284
Rob Purchase297e0502008-04-27 15:30:19 +0000285#ifdef HAVE_TOUCHPAD
286#ifndef PEGBOX_QUIT
287#define PEGBOX_QUIT BUTTON_TOPLEFT
288#endif
289#ifndef PEGBOX_SAVE
290#define PEGBOX_SAVE BUTTON_CENTER
291#endif
292#ifndef PEGBOX_RESTART
293#define PEGBOX_RESTART BUTTON_TOPRIGHT
294#endif
295#ifndef PEGBOX_LVL_UP
296#define PEGBOX_LVL_UP BUTTON_BOTTOMLEFT
297#endif
298#ifndef PEGBOX_LVL_DOWN
299#define PEGBOX_LVL_DOWN BUTTON_BOTTOMRIGHT
300#endif
301#ifndef PEGBOX_UP
302#define PEGBOX_UP BUTTON_TOPMIDDLE
303#endif
304#ifndef PEGBOX_DOWN
305#define PEGBOX_DOWN BUTTON_BOTTOMMIDDLE
306#endif
307#ifndef PEGBOX_RIGHT
308#define PEGBOX_RIGHT BUTTON_MIDRIGHT
309#endif
310#ifndef PEGBOX_LEFT
311#define PEGBOX_LEFT BUTTON_MIDLEFT
312#endif
313#ifndef SAVE_TEXT
314#define SAVE_TEXT "CENTER"
315#endif
316#ifndef QUIT_TEXT
317#define QUIT_TEXT "TOPLEFT"
318#endif
319#ifndef RESTART_TEXT
320#define RESTART_TEXT "TOPRIGHT"
321#endif
322#ifndef LVL_UP_TEXT
323#define LVL_UP_TEXT "BOTTOMLEFT"
324#endif
325#ifndef LVL_DOWN_TEXT
326#define LVL_DOWN_TEXT "BOTTOMRIGHT"
327#endif
328#endif
329
Robert Kuklab411ce62008-04-03 22:43:39 +0000330#if (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240)
331#define LEVEL_TEXT_X 59
332#define PEGS_TEXT_X 276
333#define TEXT_Y 28
334#elif (LCD_WIDTH >= 240) && (LCD_HEIGHT >= 192)
335#define LEVEL_TEXT_X 59
336#define PEGS_TEXT_X 196
337#define TEXT_Y 28
338#elif (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176)
339#define LEVEL_TEXT_X 49
340#define PEGS_TEXT_X 186
341#define TEXT_Y 28
342#elif (LCD_WIDTH >= 176) && (LCD_HEIGHT >= 132)
343#define LEVEL_TEXT_X 38
344#define PEGS_TEXT_X 155
345#define TEXT_Y 17
346#elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128)
347#define LEVEL_TEXT_X 37
348#define PEGS_TEXT_X 140
349#define TEXT_Y 13
350#elif (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
351#define LEVEL_TEXT_X 28
352#define PEGS_TEXT_X 119
353#define TEXT_Y 15
354#elif (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 128)
355#define LEVEL_TEXT_X 28
356#define PEGS_TEXT_X 119
357#define TEXT_Y 15
358#endif
359
360#ifdef HAVE_LCD_COLOR
361#define BG_COLOR LCD_BLACK
362#define TEXT_BG LCD_RGBPACK(189,189,189)
363#endif
364
365#define BOARD_X (LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2
366
367#if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
368#define BOARD_Y BMPHEIGHT_pegbox_header+2
369#else
370#define BOARD_Y 0
371#endif
372
Maurus Cuelenaeree1753de2008-06-06 18:29:46 +0000373#ifdef HAVE_TOUCHPAD
374#include "lib/touchscreen.h"
375
376static struct ts_mapping main_menu_items[5] =
377{
378{(LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, BMPHEIGHT_pegbox_menu_top, BMPWIDTH_pegbox_menu_items, (BMPHEIGHT_pegbox_menu_items/9)},
379{(LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, BMPHEIGHT_pegbox_menu_top+(BMPHEIGHT_pegbox_menu_items/9), BMPWIDTH_pegbox_menu_items, (BMPHEIGHT_pegbox_menu_items/9)},
380{(LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, BMPHEIGHT_pegbox_menu_top+(BMPHEIGHT_pegbox_menu_items/9)*2, BMPWIDTH_pegbox_menu_items, (BMPHEIGHT_pegbox_menu_items/9)},
381{(LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, BMPHEIGHT_pegbox_menu_top+(BMPHEIGHT_pegbox_menu_items/9)*3, BMPWIDTH_pegbox_menu_items, (BMPHEIGHT_pegbox_menu_items/9)},
382{
383#if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
3840, BMPHEIGHT_pegbox_menu_top+4*(BMPHEIGHT_pegbox_menu_items/9)+8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
385#elif LCD_WIDTH > 112
3860, LCD_HEIGHT - 8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT
387#else
388#error "Touchpad isn't supported on non-bitmap screens!"
389#endif
390}
391
392};
393static struct ts_mappings main_menu = {main_menu_items, 5};
394
395static struct ts_raster pegbox_raster = { BOARD_X, BOARD_Y, COLS*BMPWIDTH_pegbox_pieces, ROWS*BMPWIDTH_pegbox_pieces, BMPWIDTH_pegbox_pieces, BMPWIDTH_pegbox_pieces };
396static struct ts_raster_button_mapping pegbox_raster_btn = { &pegbox_raster, false, false, true, false, true, {0, 0}, 0, 0, 0 };
397#endif
398
Robert Kuklab411ce62008-04-03 22:43:39 +0000399struct game_context {
400 unsigned int level;
401 unsigned int highlevel;
402 signed int player_row;
403 signed int player_col;
404 unsigned int num_left;
405 bool save_exist;
406 unsigned int playboard[ROWS][COLS];
407};
408
409char levels[NUM_LEVELS][ROWS][COLS] = {
410 /* Level 1 */
411 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
412 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
413 {1, 0, 0, 0, 7, 0, 0, 5, 0, 0, 0, 1,},
414 {1, 0, 0, 0, 0, 3, 3, 2, 0, 0, 0, 1,},
415 {1, 0, 0, 0, 4, 6, 0, 5, 0, 0, 0, 1,},
416 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
417 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,},
418 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
419
420 /* Level 2 */
421 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
422 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,},
423 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
424 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
425 {7, 0, 0, 0, 2, 2, 5, 5, 0, 0, 0, 1,},
426 {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,},
427 {1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,},
428 {1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 1,}},
429
430 /* Level 3 */
431 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
432 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
433 {1, 0, 0, 0, 0, 0, 2, 0, 7, 0, 0, 0,},
434 {1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 2, 1,},
435 {1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1,},
436 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,},
437 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
438 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
439
440 /* Level 4 */
441 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
442 {6, 0, 4, 0, 2, 0, 2, 0, 0, 0, 0, 1,},
443 {6, 0, 3, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
444 {6, 0, 5, 0, 4, 7, 2, 0, 0, 0, 0, 1,},
445 {6, 0, 2, 0, 4, 0, 2, 0, 3, 0, 0, 1,},
446 {6, 0, 4, 0, 5, 0, 2, 0, 0, 0, 0, 1,},
447 {6, 0, 5, 0, 4, 0, 2, 0, 0, 0, 0, 1,},
448 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
449
450 /* Level 5 */
451 {{0, 6, 6, 0, 4, 6, 0, 0, 6, 0, 0, 0,},
452 {0, 6, 6, 0, 4, 4, 0, 0, 6, 0, 0, 2,},
453 {2, 6, 6, 0, 6, 6, 6, 0, 1, 2, 2, 2,},
454 {0, 6, 6, 0, 6, 4, 6, 0, 1, 2, 0, 2,},
455 {0, 6, 6, 0, 6, 7, 6, 5, 6, 0, 0, 0,},
456 {2, 6, 6, 0, 6, 6, 6, 0, 6, 0, 0, 0,},
457 {0, 6, 6, 0, 4, 0, 0, 0, 6, 0, 0, 0,},
458 {0, 6, 6, 0, 0, 5, 0, 0, 6, 5, 5, 0,}},
459
460 /* Level 6 */
461 {{7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
462 {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,},
463 {2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0,},
464 {0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 0,},
465 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
466 {0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1,},
467 {0, 3, 0, 0, 0, 0, 0, 0, 5, 4, 6, 0,},
468 {0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1,}},
469
470 /* Level 7 */
471 {{1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,},
472 {1, 1, 1, 6, 0, 0, 4, 6, 0, 1, 1, 1,},
473 {1, 1, 1, 1, 0, 1, 5, 1, 0, 1, 1, 1,},
474 {1, 1, 1, 2, 3, 3, 7, 4, 2, 6, 1, 1,},
475 {1, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1,},
476 {1, 1, 1, 1, 0, 0, 5, 0, 0, 1, 0, 1,},
477 {1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,},
478 {1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,}},
479
480 /* Level 8 */
481 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
482 {0, 0, 3, 3, 3, 3, 3, 4, 3, 3, 0, 0,},
483 {0, 0, 3, 3, 3, 2, 3, 3, 5, 3, 0, 0,},
484 {7, 0, 3, 3, 3, 2, 3, 3, 4, 3, 0, 0,},
485 {0, 0, 3, 3, 4, 5, 3, 3, 3, 3, 0, 0,},
486 {0, 0, 3, 3, 5, 2, 3, 3, 3, 3, 0, 0,},
487 {0, 0, 3, 3, 2, 4, 3, 3, 3, 3, 0, 0,},
488 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
489
490 /* Level 9 */
491 {{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
492 {0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,},
493 {0, 0, 0, 0, 2, 4, 4, 3, 0, 1, 1, 0,},
494 {0, 1, 0, 0, 2, 1, 0, 0, 0, 1, 1, 1,},
495 {0, 0, 0, 2, 2, 7, 1, 0, 0, 0, 0, 2,},
496 {0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 1, 1,},
497 {0, 3, 1, 0, 2, 5, 5, 0, 0, 0, 3, 0,},
498 {0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0,}},
499
500 /* Level 10 */
501 {{1, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0,},
502 {1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 7,},
503 {0, 0, 4, 0, 6, 6, 6, 0, 0, 0, 3, 0,},
504 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
505 {0, 3, 3, 0, 6, 6, 6, 0, 4, 3, 4, 0,},
506 {0, 0, 0, 0, 6, 6, 6, 0, 3, 0, 0, 0,},
507 {1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0,},
508 {1, 1, 1, 1, 1, 2, 1, 1, 0, 0, 0, 0,}},
509
510 /* Level 11 */
511 {{1, 7, 1, 0, 1, 1, 6, 0, 0, 1, 1, 0,},
512 {1, 0, 0, 0, 5, 4, 6, 6, 0, 2, 2, 0,},
513 {1, 2, 1, 2, 0, 1, 6, 0, 0, 2, 2, 0,},
514 {1, 0, 0, 2, 0, 1, 0, 0, 0, 3, 3, 0,},
515 {1, 2, 1, 0, 0, 1, 0, 1, 0, 3, 3, 0,},
516 {0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0,},
517 {0, 3, 4, 3, 0, 1, 0, 1, 0, 0, 0, 0,},
518 {0, 0, 0, 0, 2, 2, 2, 1, 1, 1, 1, 1,}},
519
520 /* Level 12 */
521 {{7, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,},
522 {1, 2, 1, 2, 1, 2, 1, 1, 0, 0, 0, 1,},
523 {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,},
524 {1, 2, 1, 2, 1, 2, 1, 0, 0, 0, 0, 1,},
525 {0, 0, 0, 0, 0, 0, 1, 1, 5, 5, 6, 1,},
526 {1, 2, 1, 2, 1, 2, 1, 1, 0, 2, 2, 1,},
527 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1,},
528 {1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,}},
529
530 /* Level 13 */
531 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
532 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
533 {0, 0, 2, 0, 5, 0, 2, 0, 4, 0, 0, 6,},
534 {7, 0, 3, 0, 4, 0, 5, 0, 4, 0, 0, 6,},
535 {0, 0, 5, 0, 4, 0, 2, 0, 4, 0, 0, 6,},
536 {0, 0, 4, 0, 2, 0, 5, 0, 4, 0, 0, 6,},
537 {0, 0, 3, 0, 3, 0, 2, 0, 4, 0, 0, 6,},
538 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
539
540 /* Level 14 */
541 {{1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,},
542 {1, 1, 0, 2, 0, 0, 4, 0, 0, 2, 0, 1,},
543 {1, 6, 0, 0, 5, 1, 0, 1, 1, 0, 0, 1,},
544 {1, 1, 1, 0, 0, 3, 5, 3, 0, 0, 1, 1,},
545 {1, 1, 0, 0, 1, 1, 0, 1, 5, 0, 0, 6,},
546 {1, 1, 0, 2, 0, 0, 4, 0, 0, 0, 7, 1,},
547 {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,},
548 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,}},
549
550 /* Level 15 */
551 {{0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
552 {0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
553 {0, 3, 4, 6, 0, 6, 0, 6, 0, 6, 0, 2,},
554 {0, 4, 0, 6, 0, 6, 4, 6, 0, 6, 0, 1,},
555 {0, 3, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1,},
556 {7, 0, 0, 6, 4, 6, 0, 6, 0, 6, 0, 1,},
557 {0, 0, 4, 6, 0, 6, 0, 6, 4, 6, 0, 1,},
558 {0, 0, 4, 6, 0, 6, 0, 6, 0, 6, 0, 1,}}
559};
560
561
562/*****************************************************************************
563* display_text() formats and outputs text.
564******************************************************************************/
565static void display_text(char *str, bool waitkey)
566{
567 int chars_by_line;
568 int lines_by_screen;
569 int chars_for_line;
570 int current_line = 0;
571 int char_width, char_height;
572 int first_char_index = 0;
573 char *ptr_char;
574 char *ptr_line;
575 int i;
576 char line[255];
577 int key;
578 bool go_on;
579
580 rb->lcd_clear_display();
581
582 rb->lcd_getstringsize("a", &char_width, &char_height);
583
584 chars_by_line = LCD_WIDTH / char_width;
585 lines_by_screen = LCD_HEIGHT / char_height;
586
587 do
588 {
589 ptr_char = str + first_char_index;
590 chars_for_line = 0;
591 i = 0;
592 ptr_line = line;
593 while (i < chars_by_line)
594 {
595 switch (*ptr_char)
596 {
597 case '\t':
598 case ' ':
599 *(ptr_line++) = ' ';
600 case '\n':
601 case '\0':
602 chars_for_line = i;
603 break;
604
605 default:
606 *(ptr_line++) = *ptr_char;
607 }
608 if (*ptr_char == '\n' || *ptr_char == '\0')
609 break;
610 ptr_char++;
611 i++;
612 }
613
614 if (chars_for_line == 0)
615 chars_for_line = i;
616
617 line[chars_for_line] = '\0';
618
619 /* test if we have cut a word. If it is the case we don't have to */
620 /* skip the space */
621 if (i == chars_by_line && chars_for_line == chars_by_line)
622 first_char_index += chars_for_line;
623 else
624 first_char_index += chars_for_line + 1;
625
626 /* print the line on the screen */
627 rb->lcd_putsxy(0, current_line * char_height, line);
628
629 /* if the number of line showed on the screen is equals to the */
630 /* maximum number of line we can show, we wait for a key pressed to */
631 /* clear and show the remaining text. */
632 current_line++;
633 if (current_line == lines_by_screen || *ptr_char == '\0')
634 {
635 current_line = 0;
636 rb->lcd_update();
637 go_on = false;
638 while (waitkey && !go_on)
639 {
640 key = rb->button_get(true);
641 switch (key)
642 {
Maurus Cuelenaeree1753de2008-06-06 18:29:46 +0000643#ifdef HAVE_TOUCHPAD
644 case BUTTON_TOUCHPAD:
645#endif
Robert Kuklab411ce62008-04-03 22:43:39 +0000646 case PEGBOX_QUIT:
647 case PEGBOX_LEFT:
648 case PEGBOX_DOWN:
649 go_on = true;
650 break;
651
652 default:
653 /*if (rb->default_event_handler(key) == SYS_USB_CONNECTED)
654 {
655 usb_detected = true;
656 go_on = true;
657 break;
658 }*/
659 break;
660 }
661 }
662 rb->lcd_clear_display();
663 }
664 } while (*ptr_char != '\0');
665}
666
667/*****************************************************************************
668* draw_board() draws the game's current level.
669******************************************************************************/
670static void draw_board(struct game_context* pb) {
671 unsigned int r, c, type;
672 pb->num_left = 0;
673#if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
674 char str[5];
675
676 rb->lcd_clear_display();
677 rb->lcd_bitmap(pegbox_header,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_header);
678 rb->lcd_drawrect((LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2-2,
679 BMPHEIGHT_pegbox_header,
680 12*BMPWIDTH_pegbox_pieces+4,8*BMPWIDTH_pegbox_pieces+4);
681
682#ifdef HAVE_LCD_COLOR
683 rb->lcd_set_foreground(LCD_WHITE);
684 rb->lcd_fillrect((LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2-1,BMPHEIGHT_pegbox_header+1,
685 12*BMPWIDTH_pegbox_pieces+2,8*BMPWIDTH_pegbox_pieces+2);
686 rb->lcd_set_foreground(LCD_BLACK);
687 rb->lcd_set_background(TEXT_BG);
688#endif
689
690#else
691 rb->lcd_clear_display();
Robert Kukla1b335ae2008-04-04 17:54:29 +0000692
693#ifdef HAVE_LCD_COLOR
694 rb->lcd_set_foreground(LCD_WHITE);
695 rb->lcd_fillrect((LCD_WIDTH-12*BMPWIDTH_pegbox_pieces)/2-1,0,
696 12*BMPWIDTH_pegbox_pieces+2,8*BMPWIDTH_pegbox_pieces+1);
697 rb->lcd_set_foreground(LCD_BLACK);
698 rb->lcd_set_background(TEXT_BG);
699#endif
700
Robert Kuklab411ce62008-04-03 22:43:39 +0000701#endif
702
703 for (r=0 ; r < ROWS ; r++) {
704 for (c = 0 ; c < COLS ; c++) {
705
706 type = pb->playboard[r][c];
707
708 switch(type) {
709 case SPACE:
710 break;
711
712 default:
713 rb->lcd_bitmap_part(pegbox_pieces, 0,
714 (type-1)*BMPWIDTH_pegbox_pieces,
715 BMPWIDTH_pegbox_pieces,
716 c * BMPWIDTH_pegbox_pieces + BOARD_X,
717 r * BMPWIDTH_pegbox_pieces + BOARD_Y,
718 BMPWIDTH_pegbox_pieces,
719 BMPWIDTH_pegbox_pieces);
720 break;
721 }
722
723 if(pb->playboard[r][c] == PLAYER) {
724 pb->player_row=r;
725 pb->player_col=c;
726 }
727 else if (type != WALL && type != SPACE && type != HOLE)
728 pb->num_left++;
729 }
730 }
731#if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
732 rb->snprintf(str, 3, "%d", pb->level);
733 rb->lcd_putsxy(LEVEL_TEXT_X, TEXT_Y, str);
734 rb->snprintf(str, 3, "%d", pb->num_left);
735 rb->lcd_putsxy(PEGS_TEXT_X, TEXT_Y, str);
736#endif
737
738#ifdef HAVE_LCD_COLOR
739 rb->lcd_set_background(BG_COLOR);
740 rb->lcd_set_foreground(LCD_WHITE);
741#endif
742 /* print out the screen */
743 rb->lcd_update();
744}
745
746/*****************************************************************************
747* load_level() loads the player's current level from the array and sets the
748* player's position.
749******************************************************************************/
750static void load_level(struct game_context* pb) {
751 int r, c;
752
753 for(r = 0; r < ROWS; r++)
754 for(c = 0; c < COLS; c++)
755 pb->playboard[r][c] = levels[pb->level-1][r][c];
756}
757
758/*****************************************************************************
759* new_piece() creates a new piece at a specified location. The player
760* navigates through the pieces and selects one.
761******************************************************************************/
762static void new_piece(struct game_context* pb, unsigned int x_loc,
763 unsigned int y_loc) {
764 int button;
765 bool exit = false;
766
767 pb->playboard[x_loc][y_loc] = TRIANGLE;
768
769 while (!exit) {
770 draw_board(pb);
771 button = rb->button_get(true);
Maurus Cuelenaeree1753de2008-06-06 18:29:46 +0000772#ifdef HAVE_TOUCHPAD
773 if(button & BUTTON_TOUCHPAD)
774 {
775 pegbox_raster_btn.two_d_from.y = x_loc;
776 pegbox_raster_btn.two_d_from.x = y_loc;
777
778 struct ts_raster_button_result ret = touchscreen_raster_map_button(&pegbox_raster_btn, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff, button);
779 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
780 {
781 if(ret.to.x > ret.from.x)
782 button = PEGBOX_UP;
783 else if(ret.to.x < ret.from.x)
784 button = PEGBOX_DOWN;
785 else if(ret.to.y > ret.from.y)
786 button = PEGBOX_LEFT;
787 else if(ret.to.y < ret.from.y)
788 button = PEGBOX_RIGHT;
789 }
790 else if(ret.action == TS_ACTION_CLICK && (unsigned)ret.to.x == y_loc && (unsigned)ret.to.y == x_loc)
791 button = PEGBOX_SAVE;
792 }
793#endif
Robert Kuklab411ce62008-04-03 22:43:39 +0000794 switch(button){
795 case PEGBOX_LEFT:
796 case (PEGBOX_LEFT|BUTTON_REPEAT):
797 case PEGBOX_DOWN:
798 case (PEGBOX_DOWN|BUTTON_REPEAT):
799 if (pb->playboard[x_loc][y_loc] < 5)
800 pb->playboard[x_loc][y_loc]++;
801 else
802 pb->playboard[x_loc][y_loc] = TRIANGLE;
803 break;
804 case PEGBOX_RIGHT:
805 case (PEGBOX_RIGHT|BUTTON_REPEAT):
806 case PEGBOX_UP:
807 case (PEGBOX_UP|BUTTON_REPEAT):
808 if (pb->playboard[x_loc][y_loc] > 2)
809 pb->playboard[x_loc][y_loc]--;
810 else
811 pb->playboard[x_loc][y_loc] = CIRCLE;
812 break;
Robert Kukla1b335ae2008-04-04 17:54:29 +0000813 case PEGBOX_SAVE:
Robert Kuklab411ce62008-04-03 22:43:39 +0000814 exit = true;
815 break;
816 }
817 }
818}
819
820/*****************************************************************************
821* move_player() moves the player and pieces and updates the board accordingly.
822******************************************************************************/
823static void move_player(struct game_context* pb, signed int x_dir,
824 signed int y_dir) {
825 unsigned int type1, type2;
826 signed int r,c;
827
828 r = pb->player_row+y_dir;
829 c = pb->player_col+x_dir;
830
831 type1 = pb->playboard[r][c];
832 type2 = pb->playboard[r+y_dir][c+x_dir];
833
834 if (r == ROWS || c == COLS || r < 0 || c < 0 || type1 == WALL)
835 return;
836 else if(type1 != SPACE) {
837 if (type2 == WALL || r+y_dir == ROWS || c+x_dir == COLS ||
838 r+y_dir < 0 || c+x_dir < 0)
839 return;
840 }
841
842
843 pb->playboard[pb->player_row][pb->player_col] = SPACE;
844 pb->player_row += y_dir;
845 pb->player_col += x_dir;
846
847 if (type1 == HOLE) {
848 draw_board(pb);
849 rb->splash(HZ*2, "You fell down a hole!");
850 load_level(pb);
851 }
852 else if (type1 == SPACE)
853 pb->playboard[r][c] = PLAYER;
854 else {
855 pb->playboard[r][c] = PLAYER;
856 if(type1 == type2) {
857 if (type1 == TRIANGLE)
858 pb->playboard[r+y_dir][c+x_dir] = WALL;
859 else if (type1 == CROSS) {
860 pb->playboard[r][c] = SPACE;
861 new_piece(pb, r+y_dir, c+x_dir);
862 pb->playboard[r][c] = PLAYER;
863 }
864 else
865 pb->playboard[r+y_dir][c+x_dir] = SPACE;
866 }
867 else if (type2 == SPACE)
868 pb->playboard[r+y_dir][c+x_dir] = type1;
869 else if (type2 == HOLE) {
870 if (type1 == SQUARE)
871 pb->playboard[r+y_dir][c+x_dir] = SPACE;
872 }
873 else {
874 rb->splash(HZ*2, "Illegal Move!");
875 load_level(pb);
876 }
877 }
878
879 draw_board(pb);
880}
881
882/*****************************************************************************
883* pegbox_loadgame() loads the saved game and returns load success.
884******************************************************************************/
885static bool pegbox_loadgame(struct game_context* pb) {
886 signed int fd;
887 bool loaded = false;
888
889 /* open game file */
890 fd = rb->open(SAVE_FILE, O_RDONLY);
891 if(fd < 0) return loaded;
892
893 /* read in saved game */
894 while(true) {
895 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
896 if(rb->read(fd, &pb->playboard, sizeof(pb->playboard)) <= 0)
897 {
898 loaded = true;
899 break;
900 }
901 break;
902 }
903
904 rb->close(fd);
905 return loaded;
906}
907
908/*****************************************************************************
909* pegbox_savegame() saves the current game state.
910******************************************************************************/
911static void pegbox_savegame(struct game_context* pb) {
912 unsigned int fd;
913
914 /* write out the game state to the save file */
915 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
916 rb->write(fd, &pb->level, sizeof(pb->level));
917 rb->write(fd, &pb->playboard, sizeof(pb->playboard));
918 rb->close(fd);
919}
920
921/*****************************************************************************
922* pegbox_loaddata() loads the level and highlevel and returns load success.
923******************************************************************************/
924static void pegbox_loaddata(struct game_context* pb) {
925 signed int fd;
926
927 /* open game file */
928 fd = rb->open(DATA_FILE, O_RDONLY);
929 if(fd < 0) {
930 pb->level = 1;
931 pb->highlevel = 1;
932 return;
933 }
934
935 /* read in saved game */
936 while(true) {
937 if(rb->read(fd, &pb->level, sizeof(pb->level)) <= 0) break;
938 if(rb->read(fd, &pb->highlevel, sizeof(pb->highlevel)) <= 0) break;
939 break;
940 }
941
942 rb->close(fd);
943 return;
944}
945
946/*****************************************************************************
947* pegbox_savedata() saves the level and highlevel.
948******************************************************************************/
949static void pegbox_savedata(struct game_context* pb) {
950 unsigned int fd;
951
952 /* write out the game state to the save file */
953 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT);
954 rb->write(fd, &pb->level, sizeof(pb->level));
955 rb->write(fd, &pb->highlevel, sizeof(pb->highlevel));
956 rb->close(fd);
957}
958
959/*****************************************************************************
960* pegbox_callback() is the default event handler callback which is called
961* on usb connect and shutdown.
962******************************************************************************/
963static void pegbox_callback(void* param) {
964 struct game_context* pb = (struct game_context*) param;
965 rb->splash(HZ, "Saving data...");
966 pegbox_savedata(pb);
967}
968
969/*****************************************************************************
970* pegbox_menu() is the initial menu at the start of the game.
971******************************************************************************/
972static unsigned int pegbox_menu(struct game_context* pb) {
973 int button;
974 char str[30];
975 unsigned int startlevel = 1, loc = 0;
976 bool breakout = false, can_resume = false;
977
978 if (pb->num_left > 0 || pb->save_exist)
979 can_resume = true;
980
981 while(!breakout){
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +0000982#if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
Robert Kuklab411ce62008-04-03 22:43:39 +0000983 rb->lcd_clear_display();
984 rb->lcd_bitmap(pegbox_menu_top,0,0,LCD_WIDTH, BMPHEIGHT_pegbox_menu_top);
985
986 /* menu bitmaps */
987 if (loc == 0) {
988 rb->lcd_bitmap_part(pegbox_menu_items, 0,
989 (BMPHEIGHT_pegbox_menu_items/9),
990 BMPWIDTH_pegbox_menu_items,
991 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
992 BMPHEIGHT_pegbox_menu_top,
993 BMPWIDTH_pegbox_menu_items,
994 (BMPHEIGHT_pegbox_menu_items/9));
995 }
996 else {
997 rb->lcd_bitmap_part(pegbox_menu_items, 0, 0,
998 BMPWIDTH_pegbox_menu_items,
999 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
1000 BMPHEIGHT_pegbox_menu_top,
1001 BMPWIDTH_pegbox_menu_items,
1002 (BMPHEIGHT_pegbox_menu_items/9));
1003 }
1004 if (can_resume) {
1005 if (loc == 1) {
1006 rb->lcd_bitmap_part(pegbox_menu_items, 0,
1007 (BMPHEIGHT_pegbox_menu_items/9)*3,
1008 BMPWIDTH_pegbox_menu_items,
1009 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
1010 BMPHEIGHT_pegbox_menu_top+
1011 (BMPHEIGHT_pegbox_menu_items/9),
1012 BMPWIDTH_pegbox_menu_items,
1013 (BMPHEIGHT_pegbox_menu_items/9));
1014 }
1015 else {
1016 rb->lcd_bitmap_part(pegbox_menu_items, 0,
1017 (BMPHEIGHT_pegbox_menu_items/9)*2,
1018 BMPWIDTH_pegbox_menu_items,
1019 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
1020 BMPHEIGHT_pegbox_menu_top+
1021 (BMPHEIGHT_pegbox_menu_items/9),
1022 BMPWIDTH_pegbox_menu_items,
1023 (BMPHEIGHT_pegbox_menu_items/9));
1024 }
1025 }
1026 else {
1027 rb->lcd_bitmap_part(pegbox_menu_items, 0,
1028 (BMPHEIGHT_pegbox_menu_items/9)*4,
1029 BMPWIDTH_pegbox_menu_items,
1030 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
1031 BMPHEIGHT_pegbox_menu_top+
1032 (BMPHEIGHT_pegbox_menu_items/9),
1033 BMPWIDTH_pegbox_menu_items,
1034 (BMPHEIGHT_pegbox_menu_items/9));
1035 }
1036
1037 if (loc==2) {
1038 rb->lcd_bitmap_part(pegbox_menu_items, 0,
1039 (BMPHEIGHT_pegbox_menu_items/9)*6,
1040 BMPWIDTH_pegbox_menu_items,
1041 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
1042 BMPHEIGHT_pegbox_menu_top+
1043 (BMPHEIGHT_pegbox_menu_items/9)*2,
1044 BMPWIDTH_pegbox_menu_items,
1045 (BMPHEIGHT_pegbox_menu_items/9));
1046 }
1047 else {
1048 rb->lcd_bitmap_part(pegbox_menu_items, 0,
1049 (BMPHEIGHT_pegbox_menu_items/9)*5,
1050 BMPWIDTH_pegbox_menu_items,
1051 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
1052 BMPHEIGHT_pegbox_menu_top+
1053 (BMPHEIGHT_pegbox_menu_items/9)*2,
1054 BMPWIDTH_pegbox_menu_items,
1055 (BMPHEIGHT_pegbox_menu_items/9));
1056 }
1057
1058 if (loc==3) {
1059 rb->lcd_bitmap_part(pegbox_menu_items, 0,
1060 (BMPHEIGHT_pegbox_menu_items/9)*8,
1061 BMPWIDTH_pegbox_menu_items,
1062 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
1063 BMPHEIGHT_pegbox_menu_top+
1064 (BMPHEIGHT_pegbox_menu_items/9)*3,
1065 BMPWIDTH_pegbox_menu_items,
1066 (BMPHEIGHT_pegbox_menu_items/9));
1067 }
1068 else {
1069 rb->lcd_bitmap_part(pegbox_menu_items, 0,
1070 (BMPHEIGHT_pegbox_menu_items/9)*7,
1071 BMPWIDTH_pegbox_menu_items,
1072 (LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2,
1073 BMPHEIGHT_pegbox_menu_top+
1074 (BMPHEIGHT_pegbox_menu_items/9)*3,
1075 BMPWIDTH_pegbox_menu_items,
1076 (BMPHEIGHT_pegbox_menu_items/9));
1077 }
1078#else
1079 unsigned int w,h;
1080 rb->lcd_clear_display();
1081 rb->lcd_getstringsize("PegBox", &w, &h);
1082 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, "PegBox");
1083 rb->lcd_putsxy((LCD_WIDTH)/4, 16, "New Game");
1084 rb->lcd_putsxy((LCD_WIDTH)/4, 24, "Resume");
1085 rb->lcd_putsxy((LCD_WIDTH)/4, 32, "Help");
1086 rb->lcd_putsxy((LCD_WIDTH)/4, 40, "Quit");
1087
1088 if(!can_resume)
Jens Arnoldfef82552008-04-12 09:51:16 +00001089 rb->lcd_hline((LCD_WIDTH)/4, (LCD_WIDTH)/4+30, 28);
Robert Kuklab411ce62008-04-03 22:43:39 +00001090
1091 rb->lcd_putsxy((LCD_WIDTH)/4-8, loc*8+16, "*");
1092
1093
1094#endif
1095 rb->snprintf(str, 28, "Start on level %d of %d", startlevel,
1096 pb->highlevel);
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +00001097#if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110)
Robert Kuklab411ce62008-04-03 22:43:39 +00001098 rb->lcd_putsxy(0, BMPHEIGHT_pegbox_menu_top+4*
1099 (BMPHEIGHT_pegbox_menu_items/9)+8, str);
1100#elif LCD_WIDTH > 112
1101 rb->lcd_putsxy(0, LCD_HEIGHT - 8, str);
1102#else
1103 rb->lcd_puts_scroll(0, 7, str);
1104#endif
1105 rb->lcd_update();
1106
1107 /* handle menu button presses */
1108 button = rb->button_get(true);
Maurus Cuelenaeree1753de2008-06-06 18:29:46 +00001109
1110#ifdef HAVE_TOUCHPAD
1111 if(button & BUTTON_TOUCHPAD)
1112 {
1113 unsigned int result = touchscreen_map(&main_menu, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff);
1114 if(result != (unsigned)-1 && button & BUTTON_REL)
1115 {
1116 if(result == 4)
1117 button = PEGBOX_LVL_UP;
1118 else
1119 {
1120 if(loc == result)
1121 button = PEGBOX_RIGHT;
1122 loc = result;
1123 }
1124 }
1125 }
1126#endif
Robert Kuklab411ce62008-04-03 22:43:39 +00001127
1128 switch(button) {
Robert Kukla1b335ae2008-04-04 17:54:29 +00001129 case PEGBOX_SAVE: /* start playing */
1130 case PEGBOX_RIGHT:
Robert Kuklab411ce62008-04-03 22:43:39 +00001131 if (loc == 0) {
1132 breakout = true;
1133 pb->level = startlevel;
1134 load_level(pb);
1135 }
1136 else if (loc == 1 && can_resume) {
1137 if(pb->save_exist)
1138 {
1139 rb->remove(SAVE_FILE);
1140 pb->save_exist = false;
1141 }
1142 breakout = true;
1143 }
1144 else if (loc == 2)
1145 display_text("How to Play\nTo beat each level, you must "
1146 "destroy all of the pegs. If two like pegs are "
1147 "pushed into each other they disappear except "
1148 "for triangles which form a solid block and "
1149 "crosses which allow you to choose a "
1150 "replacement block.\n\n"
1151 "Controls\n"
1152#if LCD_HEIGHT > 64
1153 RESTART_TEXT " to restart level\n"
1154 LVL_UP_TEXT " to go up a level\n"
1155 LVL_DOWN_TEXT " to go down a level\n"
Robert Kukla1b335ae2008-04-04 17:54:29 +00001156 SAVE_TEXT " to select/save\n"
Robert Kuklab411ce62008-04-03 22:43:39 +00001157 QUIT_TEXT " to quit\n",true);
1158#else
1159 RESTART_TEXT ": restart\n"
1160 LVL_UP_TEXT ": level up\n"
1161 LVL_DOWN_TEXT " level down\n"
Robert Kukla1b335ae2008-04-04 17:54:29 +00001162 SAVE_TEXT " select/save\n"
Robert Kuklab411ce62008-04-03 22:43:39 +00001163 QUIT_TEXT " quit\n",true);
1164#endif
1165 else if (loc == 3)
1166 return PB_QUIT;
1167 break;
1168
1169 case PEGBOX_QUIT: /* quit program */
1170 return PB_QUIT;
1171
1172 case (PEGBOX_UP|BUTTON_REPEAT):
1173 case PEGBOX_UP:
1174 if (loc <= 0)
1175 loc = 3;
1176 else
1177 loc--;
1178 if (!can_resume && loc == 1) {
1179 loc = 0;
1180 }
1181 break;
1182
1183
1184 case (PEGBOX_DOWN|BUTTON_REPEAT):
1185 case PEGBOX_DOWN:
1186 if (loc >= 3)
1187 loc = 0;
1188 else
1189 loc++;
1190 if (!can_resume && loc == 1) {
1191 loc = 2;
1192 }
1193 break;
1194
Robert Kukla1b335ae2008-04-04 17:54:29 +00001195 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
1196 case PEGBOX_LVL_UP: /* increase starting level */
Robert Kuklab411ce62008-04-03 22:43:39 +00001197 if(startlevel >= pb->highlevel) {
1198 startlevel = 1;
1199 } else {
1200 startlevel++;
1201 }
1202 break;
1203
Robert Kukla1b335ae2008-04-04 17:54:29 +00001204/* only for targets with enough buttons */
1205#ifdef PEGBOX_LVL_DOWN
1206 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
1207 case PEGBOX_LVL_DOWN: /* decrease starting level */
Robert Kuklab411ce62008-04-03 22:43:39 +00001208 if(startlevel <= 1) {
1209 startlevel = pb->highlevel;
1210 } else {
1211 startlevel--;
1212 }
1213 break;
Robert Kukla1b335ae2008-04-04 17:54:29 +00001214#endif
Robert Kuklab411ce62008-04-03 22:43:39 +00001215 default:
1216 if(rb->default_event_handler_ex(button, pegbox_callback,
1217 (void*) pb) == SYS_USB_CONNECTED)
1218 return PB_USB;
1219 break;
1220 }
1221
1222 }
1223 draw_board(pb);
1224
1225 return 0;
1226}
1227
1228/*****************************************************************************
1229* pegbox() is the main game subroutine, it returns the final game status.
1230******************************************************************************/
1231static int pegbox(struct game_context* pb) {
1232 int temp_var;
1233
1234 /********************
1235 * menu *
1236 ********************/
1237 temp_var = pegbox_menu(pb);
1238 if (temp_var == PB_QUIT || temp_var == PB_USB)
1239 return temp_var;
1240
1241 while (true) {
1242 temp_var = rb->button_get(true);
Maurus Cuelenaeree1753de2008-06-06 18:29:46 +00001243#ifdef HAVE_TOUCHPAD
1244 if(temp_var & BUTTON_TOUCHPAD)
1245 {
1246 pegbox_raster_btn.two_d_from.y = pb->player_row;
1247 pegbox_raster_btn.two_d_from.x = pb->player_col;
1248
1249 struct ts_raster_button_result ret = touchscreen_raster_map_button(&pegbox_raster_btn, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff, temp_var);
1250 if(ret.action == TS_ACTION_TWO_D_MOVEMENT)
1251 move_player(pb, ret.to.x - ret.from.x, ret.to.y - ret.from.y);
1252 }
1253#endif
Robert Kuklab411ce62008-04-03 22:43:39 +00001254 switch(temp_var){
1255 case PEGBOX_LEFT: /* move cursor left */
1256 case (PEGBOX_LEFT|BUTTON_REPEAT):
1257 move_player(pb, -1, 0);
1258 break;
1259
1260 case PEGBOX_RIGHT: /* move cursor right */
1261 case (PEGBOX_RIGHT|BUTTON_REPEAT):
1262 move_player(pb, 1, 0);
1263 break;
1264
1265 case PEGBOX_DOWN: /* move cursor down */
1266 case (PEGBOX_DOWN|BUTTON_REPEAT):
1267 move_player(pb, 0, 1);
1268 break;
1269
1270 case PEGBOX_UP: /* move cursor up */
1271 case (PEGBOX_UP|BUTTON_REPEAT):
1272 move_player(pb, 0, -1);
1273 break;
1274
1275 case PEGBOX_SAVE: /* save and end game */
1276 rb->splash(HZ, "Saving game...");
1277 pegbox_savegame(pb);
1278 /* fall through to PEGBOX_QUIT */
1279
1280 case PEGBOX_QUIT:
1281 return PB_END;
1282
1283 case PEGBOX_RESTART:
1284 load_level(pb);
1285 draw_board(pb);
1286 break;
1287
Robert Kukla1b335ae2008-04-04 17:54:29 +00001288 case (PEGBOX_LVL_UP|BUTTON_REPEAT):
Robert Kuklab411ce62008-04-03 22:43:39 +00001289 case PEGBOX_LVL_UP:
Robert Kukla1b335ae2008-04-04 17:54:29 +00001290 if(pb->level >= pb->highlevel) {
1291 pb->level = 1;
1292 } else {
Robert Kuklab411ce62008-04-03 22:43:39 +00001293 pb->level++;
Robert Kuklab411ce62008-04-03 22:43:39 +00001294 }
Robert Kukla1b335ae2008-04-04 17:54:29 +00001295 load_level(pb);
1296 draw_board(pb);
Robert Kuklab411ce62008-04-03 22:43:39 +00001297 break;
1298
Robert Kukla1b335ae2008-04-04 17:54:29 +00001299/* only for targets with enough buttons */
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +00001300#ifdef PEGBOX_LVL_DOWN
Robert Kukla1b335ae2008-04-04 17:54:29 +00001301 case (PEGBOX_LVL_DOWN|BUTTON_REPEAT):
Robert Kuklab411ce62008-04-03 22:43:39 +00001302 case PEGBOX_LVL_DOWN:
Robert Kukla1b335ae2008-04-04 17:54:29 +00001303 if(pb->level <= 1) {
1304 pb->level = pb->highlevel;
1305 } else {
Robert Kuklab411ce62008-04-03 22:43:39 +00001306 pb->level--;
Robert Kuklab411ce62008-04-03 22:43:39 +00001307 }
Robert Kukla1b335ae2008-04-04 17:54:29 +00001308 load_level(pb);
1309 draw_board(pb);
Robert Kuklab411ce62008-04-03 22:43:39 +00001310 break;
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +00001311#endif
1312
Robert Kuklab411ce62008-04-03 22:43:39 +00001313 }
1314
1315 if(pb->num_left == 0) {
1316 rb->splash(HZ*2, "Nice Pegging!");
1317 if(pb->level == NUM_LEVELS) {
1318 draw_board(pb);
1319 rb->splash(HZ*2, "You Won!");
1320 break;
1321 }
1322 else {
1323 pb->level++;
1324 load_level(pb);
1325 draw_board(pb);
1326 }
1327
1328 if(pb->level > pb->highlevel)
1329 pb->highlevel = pb->level;
1330
1331 }
1332 }
1333
1334 return PLUGIN_OK;
1335}
1336
1337
1338/*****************************************************************************
1339* plugin entry point.
1340******************************************************************************/
Steve Bavin65265772008-05-13 09:57:56 +00001341enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter) {
Robert Kuklab411ce62008-04-03 22:43:39 +00001342 bool exit = false;
1343 struct game_context pb;
1344
1345 (void)parameter;
1346 rb = api;
1347
1348 rb->lcd_setfont(FONT_SYSFIXED);
Robert Kuklaf6f0c2f2008-04-04 00:33:59 +00001349#if LCD_DEPTH > 1
1350 rb->lcd_set_backdrop(NULL);
1351#endif
Robert Kuklab411ce62008-04-03 22:43:39 +00001352#ifdef HAVE_LCD_COLOR
1353 rb->lcd_set_foreground(LCD_WHITE);
1354 rb->lcd_set_background(BG_COLOR);
1355#endif
1356
1357 rb->splash(0, "Loading...");
1358 pegbox_loaddata(&pb);
1359 pb.save_exist = pegbox_loadgame(&pb);
1360 pb.num_left = 0;
1361
1362 rb->lcd_clear_display();
1363
1364
1365 while(!exit) {
1366 switch(pegbox(&pb)){
1367 case PB_END:
1368 break;
1369
1370 case PB_USB:
1371 rb->lcd_setfont(FONT_UI);
1372 return PLUGIN_USB_CONNECTED;
1373
1374 case PB_QUIT:
1375 rb->splash(HZ, "Saving data...");
1376 pegbox_savedata(&pb);
1377 exit = true;
1378 break;
1379
1380 default:
1381 break;
1382 }
1383 }
1384
1385 rb->lcd_setfont(FONT_UI);
1386 return PLUGIN_OK;
1387}