Fix red, moved around a bit to much.
[kugel-rb.git] / apps / plugins / brickmania.c
blob400ee022fcb8da4549926a8ea5f177986db202ac
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005, 2006 Ben Basha (Paprica)
11 * Copyright (C) 2009 Karl Kurbjun
12 * check_lines is based off an explanation and expanded math presented by Paul
13 * Bourke: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
25 #include "plugin.h"
26 #include "lib/configfile.h"
27 #include "lib/display_text.h"
28 #include "lib/helper.h"
29 #include "lib/highscore.h"
30 #include "lib/playback_control.h"
32 PLUGIN_HEADER
34 /* If there are three fractional bits, the smallest screen size that will scale
35 * properly is 28x22. If you have a smaller screen increase the fractional
36 * precision. If you have a precision of 4 the smallest screen size would be
37 * 14x11. Note though that this will decrease the maximum resolution due to
38 * the line intersection tests. These defines are used for all of the fixed
39 * point calculations/conversions.
41 #define FIXED3(x) ((x)<<3)
42 #define FIXED3_MUL(x, y) ((long long)((x)*(y))>>3)
43 #define FIXED3_DIV(x, y) (((x)<<3)/(y))
44 #define INT3(x) ((x)>>3)
46 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
47 (CONFIG_KEYPAD == IRIVER_H300_PAD)
48 #define CONTINUE_TEXT "Press NAVI To Continue"
49 #define QUIT BUTTON_OFF
50 #define LEFT BUTTON_LEFT
51 #define RIGHT BUTTON_RIGHT
52 #define SELECT BUTTON_SELECT
53 #define UP BUTTON_UP
54 #define DOWN BUTTON_DOWN
55 #define RC_QUIT BUTTON_RC_STOP
57 #elif CONFIG_KEYPAD == ONDIO_PAD
58 #define CONTINUE_TEXT "MENU To Continue"
59 #define QUIT BUTTON_OFF
60 #define LEFT BUTTON_LEFT
61 #define RIGHT BUTTON_RIGHT
62 #define SELECT BUTTON_MENU
63 #define UP BUTTON_UP
64 #define DOWN BUTTON_DOWN
66 #elif CONFIG_KEYPAD == RECORDER_PAD
67 #define QUIT BUTTON_OFF
68 #define LEFT BUTTON_LEFT
69 #define RIGHT BUTTON_RIGHT
70 #define SELECT BUTTON_PLAY
71 #define UP BUTTON_UP
72 #define DOWN BUTTON_DOWN
74 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
75 #define QUIT BUTTON_OFF
76 #define LEFT BUTTON_LEFT
77 #define RIGHT BUTTON_RIGHT
78 #define SELECT BUTTON_SELECT
79 #define UP BUTTON_UP
80 #define DOWN BUTTON_DOWN
82 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
83 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
84 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
85 #define QUIT BUTTON_MENU
86 #define LEFT BUTTON_LEFT
87 #define RIGHT BUTTON_RIGHT
88 #define SELECT BUTTON_SELECT
89 #define UP BUTTON_SCROLL_BACK
90 #define DOWN BUTTON_SCROLL_FWD
91 #define SCROLL_FWD(x) ((x) & BUTTON_SCROLL_FWD)
92 #define SCROLL_BACK(x) ((x) & BUTTON_SCROLL_BACK)
94 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
95 #define QUIT BUTTON_POWER
96 #define LEFT BUTTON_LEFT
97 #define RIGHT BUTTON_RIGHT
98 #define SELECT BUTTON_SELECT
99 #define UP BUTTON_UP
100 #define DOWN BUTTON_DOWN
102 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
103 #define QUIT BUTTON_POWER
104 #define LEFT BUTTON_LEFT
105 #define RIGHT BUTTON_RIGHT
106 #define SELECT BUTTON_PLAY
107 #define UP BUTTON_UP
108 #define DOWN BUTTON_DOWN
110 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
111 #define QUIT BUTTON_POWER
112 #define LEFT BUTTON_LEFT
113 #define RIGHT BUTTON_RIGHT
114 #define SELECT BUTTON_SELECT
115 #define UP BUTTON_UP
116 #define DOWN BUTTON_DOWN
117 #define SCROLL_FWD(x) ((x) & BUTTON_SCROLL_FWD)
118 #define SCROLL_BACK(x) ((x) & BUTTON_SCROLL_BACK)
121 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
122 #define QUIT (BUTTON_HOME|BUTTON_REPEAT)
123 #define LEFT BUTTON_LEFT
124 #define RIGHT BUTTON_RIGHT
125 #define SELECT BUTTON_SELECT
126 #define UP BUTTON_UP
127 #define DOWN BUTTON_DOWN
129 #define SCROLL_FWD(x) ((x) & BUTTON_SCROLL_FWD)
130 #define SCROLL_BACK(x) ((x) & BUTTON_SCROLL_BACK)
133 #elif CONFIG_KEYPAD == SANSA_C200_PAD || \
134 CONFIG_KEYPAD == SANSA_CLIP_PAD || \
135 CONFIG_KEYPAD == SANSA_M200_PAD
136 #define QUIT BUTTON_POWER
137 #define LEFT BUTTON_LEFT
138 #define RIGHT BUTTON_RIGHT
139 #define ALTLEFT BUTTON_VOL_DOWN
140 #define ALTRIGHT BUTTON_VOL_UP
141 #define SELECT BUTTON_SELECT
142 #define UP BUTTON_UP
143 #define DOWN BUTTON_DOWN
145 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
146 #define QUIT BUTTON_POWER
147 #define LEFT BUTTON_LEFT
148 #define RIGHT BUTTON_RIGHT
149 #define SELECT BUTTON_PLAY
150 #define UP BUTTON_SCROLL_UP
151 #define DOWN BUTTON_SCROLL_DOWN
153 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
154 #define QUIT BUTTON_BACK
155 #define LEFT BUTTON_LEFT
156 #define RIGHT BUTTON_RIGHT
157 #define SELECT BUTTON_SELECT
158 #define UP BUTTON_UP
159 #define DOWN BUTTON_DOWN
161 #elif (CONFIG_KEYPAD == MROBE100_PAD)
162 #define QUIT BUTTON_POWER
163 #define LEFT BUTTON_LEFT
164 #define RIGHT BUTTON_RIGHT
165 #define SELECT BUTTON_SELECT
166 #define UP BUTTON_UP
167 #define DOWN BUTTON_DOWN
169 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
170 #define CONTINUE_TEXT "PLAY To Continue"
171 #define QUIT BUTTON_RC_REC
172 #define LEFT BUTTON_RC_REW
173 #define RIGHT BUTTON_RC_FF
174 #define SELECT BUTTON_RC_PLAY
175 #define UP BUTTON_RC_VOL_UP
176 #define DOWN BUTTON_RC_VOL_DOWN
177 #define RC_QUIT BUTTON_REC
179 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
180 #define QUIT BUTTON_BACK
181 #define LEFT BUTTON_LEFT
182 #define RIGHT BUTTON_RIGHT
183 #define SELECT BUTTON_SELECT
184 #define UP BUTTON_UP
185 #define DOWN BUTTON_DOWN
187 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
188 #define QUIT BUTTON_POWER
189 #define LEFT BUTTON_LEFT
190 #define RIGHT BUTTON_RIGHT
191 #define SELECT BUTTON_SELECT
192 #define UP BUTTON_UP
193 #define DOWN BUTTON_DOWN
195 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
196 #define QUIT BUTTON_POWER
197 #define LEFT BUTTON_PREV
198 #define RIGHT BUTTON_NEXT
199 #define SELECT BUTTON_PLAY
200 #define UP BUTTON_UP
201 #define DOWN BUTTON_DOWN
203 #elif CONFIG_KEYPAD == COWON_D2_PAD
204 #define QUIT BUTTON_POWER
206 #elif CONFIG_KEYPAD == ONDAVX747_PAD
207 #define QUIT BUTTON_POWER
208 #define LEFT BUTTON_VOL_DOWN
209 #define RIGHT BUTTON_VOL_UP
210 #define SELECT BUTTON_MENU
211 #elif CONFIG_KEYPAD == ONDAVX777_PAD
212 #define QUIT BUTTON_POWER
214 #elif CONFIG_KEYPAD == MROBE500_PAD
215 #define QUIT BUTTON_POWER
217 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
218 #define QUIT BUTTON_FFWD
219 #define SELECT BUTTON_PLAY
220 #define LEFT BUTTON_LEFT
221 #define RIGHT BUTTON_RIGHT
222 #define UP BUTTON_UP
223 #define DOWN BUTTON_DOWN
226 #else
227 #error No keymap defined!
228 #endif
230 #ifdef HAVE_TOUCHSCREEN
231 #ifndef LEFT
232 #define LEFT BUTTON_BOTTOMLEFT
233 #endif
234 #ifndef RIGHT
235 #define RIGHT BUTTON_BOTTOMRIGHT
236 #endif
237 #ifndef SELECT
238 #define SELECT BUTTON_CENTER
239 #endif
240 #ifndef UP
241 #define UP BUTTON_TOPMIDDLE
242 #endif
243 #ifndef DOWN
244 #define DOWN BUTTON_BOTTOMMIDDLE
245 #endif
246 #endif
248 /* Continue text is used as a string later when the game is paused. This allows
249 * targets to specify their own text if needed.
251 #if !defined(CONTINUE_TEXT)
252 #define CONTINUE_TEXT "Press SELECT To Continue"
253 #endif
255 #ifndef SCROLL_FWD /* targets without scroll wheel*/
256 #define SCROLL_FWD(x) (0)
257 #define SCROLL_BACK(x) (0)
258 #endif
260 #include "pluginbitmaps/brickmania_pads.h"
261 #include "pluginbitmaps/brickmania_short_pads.h"
262 #include "pluginbitmaps/brickmania_long_pads.h"
263 #include "pluginbitmaps/brickmania_bricks.h"
264 #include "pluginbitmaps/brickmania_powerups.h"
265 #include "pluginbitmaps/brickmania_ball.h"
266 #include "pluginbitmaps/brickmania_gameover.h"
268 #define GAMESCREEN_WIDTH FIXED3(LCD_WIDTH)
269 #define GAMESCREEN_HEIGHT FIXED3(LCD_HEIGHT)
271 #define PAD_WIDTH FIXED3(BMPWIDTH_brickmania_pads)
272 #define PAD_HEIGHT FIXED3(BMPHEIGHT_brickmania_pads/3)
273 #define SHORT_PAD_WIDTH FIXED3(BMPWIDTH_brickmania_short_pads)
274 #define LONG_PAD_WIDTH FIXED3(BMPWIDTH_brickmania_long_pads)
275 #define BRICK_HEIGHT FIXED3(BMPHEIGHT_brickmania_bricks/7)
276 #define BRICK_WIDTH FIXED3(BMPWIDTH_brickmania_bricks)
277 #define LEFTMARGIN ((GAMESCREEN_WIDTH-10*BRICK_WIDTH)/2)
278 #define NUMBER_OF_POWERUPS 9
279 #define POWERUP_HEIGHT FIXED3(BMPHEIGHT_brickmania_powerups/NUMBER_OF_POWERUPS)
280 #define POWERUP_WIDTH FIXED3(BMPWIDTH_brickmania_powerups)
281 #define BALL FIXED3(BMPHEIGHT_brickmania_ball)
282 #define HALFBALL (BALL / 2)
284 #define GAMEOVER_WIDTH FIXED3(BMPWIDTH_brickmania_gameover)
285 #define GAMEOVER_HEIGHT FIXED3(BMPHEIGHT_brickmania_gameover)
287 #ifdef HAVE_LCD_COLOR /* currently no transparency for non-colour */
288 #include "pluginbitmaps/brickmania_break.h"
289 #endif
291 /* The time (in ms) for one iteration through the game loop - decrease this
292 * to speed up the game - note that current_tick is (currently) only accurate
293 * to 10ms.
295 #define CYCLETIME 30
297 #define TOPMARGIN MAX(BRICK_HEIGHT, FIXED3(8))
299 #define STRINGPOS_FINISH (GAMESCREEN_HEIGHT - (GAMESCREEN_HEIGHT / 6))
300 #define STRINGPOS_CONGRATS (STRINGPOS_FINISH - 20)
301 #define STRINGPOS_NAVI (STRINGPOS_FINISH - 10)
302 #define STRINGPOS_FLIP (STRINGPOS_FINISH - 10)
304 /* Brickmania was originally designed for the H300, other targets should scale
305 * the speed up/down as needed based on the screen height.
307 #define SPEED_SCALE_H(y) FIXED3_DIV(GAMESCREEN_HEIGHT, FIXED3(176)/(y) )
308 #define SPEED_SCALE_W(x) FIXED3_DIV(GAMESCREEN_WIDTH, FIXED3(220)/(x) )
310 /* These are all used as ball speeds depending on where the ball hit the
311 * paddle.
313 * Note that all of these speeds (including pad, power, and fire)
314 * could be made variable and could be raised to be much higher to add
315 * additional difficulty to the game. The line intersection tests allow this
316 * to be drastically increased without the collision detection failing
317 * (ideally).
319 #define SPEED_1Q_X SPEED_SCALE_W( 6)
320 #define SPEED_1Q_Y SPEED_SCALE_H(-2)
322 #define SPEED_2Q_X SPEED_SCALE_W( 4)
323 #define SPEED_2Q_Y SPEED_SCALE_H(-3)
325 #define SPEED_3Q_X SPEED_SCALE_W( 3)
326 #define SPEED_3Q_Y SPEED_SCALE_H(-4)
328 #define SPEED_4Q_X SPEED_SCALE_W( 2)
329 #define SPEED_4Q_Y SPEED_SCALE_H(-4)
331 /* This is used to determine the speed of the paddle */
332 #define SPEED_PAD SPEED_SCALE_W( 8)
334 /* This defines the speed that the powerups drop */
335 #define SPEED_POWER SPEED_SCALE_H( 2)
337 /* This defines the speed that the shot moves */
338 #define SPEED_FIRE SPEED_SCALE_H( 4)
339 #define FIRE_LENGTH SPEED_SCALE_H( 7)
341 /*calculate paddle y-position */
342 #define PAD_POS_Y (GAMESCREEN_HEIGHT - PAD_HEIGHT - 1)
344 /* change to however many levels there are, i.e. how many arrays there are total */
345 int levels_num = 40;
347 /* change the first number in [ ] to however many levels there are (levels_num) */
348 static unsigned char levels[40][8][10] =
349 /* You can set up new levels with the level editor
350 ( http://plugbox.rockbox-lounge.com/brickmania.htm ).
351 With 0x1, it refers to the first brick in the bitmap, 0x2 would refer to the
352 second, ect., 0x0 leaves a empty space. If you add a 2 before the 2nd number,
353 it will take two hits to break, and 3 hits if you add a 3. That is 0x24, will
354 result with the fourth brick being displayed and having take 2 hits to break.
355 You could do the same with the 3, just replace the 2 with a 3 for it to take
356 three hits to break it apart. */
358 { /* level1 */
359 {0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1},
360 {0x2,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x2},
361 {0x0,0x2,0x1,0x0,0x0,0x0,0x0,0x1,0x2,0x0},
362 {0x0,0x0,0x2,0x1,0x0,0x0,0x1,0x2,0x0,0x0},
363 {0x0,0x0,0x0,0x2,0x1,0x1,0x2,0x0,0x0,0x0},
364 {0x7,0x0,0x0,0x7,0x2,0x2,0x7,0x0,0x0,0x7},
365 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
366 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
368 { /* level2 */
369 {0x0,0x0,0x7,0x7,0x1,0x1,0x7,0x7,0x0,0x0},
370 {0x0,0x1,0x0,0x0,0x1,0x1,0x0,0x0,0x1,0x0},
371 {0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1},
372 {0x1,0x1,0x1,0x1,0x0,0x0,0x1,0x1,0x1,0x1},
373 {0x1,0x1,0x2,0x1,0x0,0x0,0x1,0x2,0x1,0x1},
374 {0x1,0x2,0x0,0x2,0x2,0x2,0x2,0x0,0x2,0x1},
375 {0x0,0x1,0x2,0x0,0x0,0x0,0x0,0x2,0x1,0x0},
376 {0x0,0x0,0x1,0x2,0x2,0x2,0x2,0x1,0x0,0x0}
378 { /* level3 */
379 {0x3,0x3,0x3,0x3,0x0,0x0,0x2,0x2,0x2,0x2},
380 {0x3,0x23,0x23,0x3,0x0,0x0,0x2,0x22,0x22,0x2},
381 {0x3,0x3,0x3,0x3,0x0,0x0,0x2,0x2,0x2,0x2},
382 {0x0,0x0,0x0,0x0,0x37,0x37,0x0,0x0,0x0,0x0},
383 {0x0,0x0,0x0,0x0,0x37,0x37,0x0,0x0,0x0,0x0},
384 {0x5,0x5,0x5,0x5,0x0,0x0,0x6,0x6,0x6,0x6},
385 {0x5,0x25,0x25,0x5,0x0,0x0,0x6,0x26,0x26,0x6},
386 {0x5,0x5,0x5,0x5,0x0,0x0,0x6,0x6,0x6,0x6}
388 { /* level4 */
389 {0x0,0x0,0x0,0x27,0x27,0x27,0x27,0x0,0x0,0x0},
390 {0x0,0x0,0x0,0x27,0x7,0x7,0x27,0x0,0x0,0x0},
391 {0x22,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x22},
392 {0x22,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x22},
393 {0x26,0x6,0x0,0x2,0x2,0x2,0x2,0x0,0x6,0x26},
394 {0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0},
395 {0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0},
396 {0x1,0x1,0x1,0x1,0x0,0x0,0x1,0x1,0x1,0x1}
398 { /* level5 */
399 {0x1,0x0,0x2,0x2,0x0,0x3,0x3,0x0,0x4,0x4},
400 {0x0,0x2,0x2,0x0,0x3,0x3,0x0,0x4,0x4,0x0},
401 {0x2,0x2,0x0,0x3,0x3,0x0,0x4,0x4,0x0,0x5},
402 {0x2,0x0,0x3,0x3,0x0,0x4,0x4,0x0,0x5,0x5},
403 {0x0,0x33,0x3,0x0,0x4,0x4,0x0,0x5,0x5,0x0},
404 {0x3,0x33,0x0,0x4,0x4,0x0,0x5,0x5,0x0,0x36},
405 {0x3,0x0,0x4,0x4,0x0,0x5,0x5,0x0,0x6,0x36},
406 {0x0,0x24,0x24,0x0,0x25,0x25,0x0,0x26,0x26,0x0}
408 { /* level6 */
409 {0x0,0x1,0x3,0x7,0x7,0x7,0x7,0x3,0x1,0x0},
410 {0x3,0x1,0x3,0x7,0x0,0x0,0x7,0x3,0x1,0x3},
411 {0x3,0x1,0x3,0x7,0x7,0x7,0x7,0x3,0x1,0x3},
412 {0x0,0x0,0x0,0x2,0x2,0x2,0x2,0x0,0x0,0x0},
413 {0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5},
414 {0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x5},
415 {0x0,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x0},
416 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
418 { /* level7 */
419 {0x0,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x0},
420 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
421 {0x6,0x0,0x0,0x2,0x2,0x2,0x2,0x0,0x0,0x6},
422 {0x6,0x0,0x0,0x2,0x2,0x2,0x2,0x0,0x0,0x6},
423 {0x6,0x6,0x6,0x0,0x0,0x0,0x0,0x6,0x6,0x6},
424 {0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0},
425 {0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0},
426 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
428 { /* level8 */
429 {0x0,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x0},
430 {0x0,0x0,0x0,0x4,0x0,0x0,0x4,0x0,0x0,0x0},
431 {0x6,0x6,0x0,0x2,0x32,0x32,0x2,0x0,0x6,0x6},
432 {0x0,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x0,0x0},
433 {0x0,0x6,0x6,0x0,0x0,0x0,0x0,0x6,0x6,0x0},
434 {0x0,0x0,0x0,0x5,0x25,0x25,0x5,0x0,0x0,0x0},
435 {0x0,0x5,0x5,0x25,0x5,0x5,0x25,0x5,0x5,0x0},
436 {0x5,0x5,0x25,0x5,0x5,0x5,0x5,0x25,0x5,0x5}
438 { /* level9 */
439 {0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2},
440 {0x2,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x2},
441 {0x2,0x0,0x3,0x0,0x1,0x1,0x0,0x3,0x0,0x2},
442 {0x2,0x0,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x2},
443 {0x2,0x0,0x1,0x0,0x3,0x3,0x0,0x1,0x0,0x2},
444 {0x2,0x0,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x2},
445 {0x2,0x2,0x0,0x0,0x1,0x1,0x0,0x0,0x2,0x2},
446 {0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2}
448 { /* level10 */
449 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
450 {0x0,0x5,0x0,0x5,0x0,0x5,0x0,0x5,0x0,0x5},
451 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
452 {0x0,0x0,0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0},
453 {0x0,0x0,0x0,0x4,0x1,0x1,0x4,0x0,0x0,0x0},
454 {0x0,0x0,0x3,0x4,0x1,0x1,0x4,0x3,0x0,0x0},
455 {0x0,0x2,0x3,0x4,0x1,0x1,0x4,0x3,0x2,0x0},
456 {0x1,0x2,0x3,0x4,0x1,0x1,0x4,0x3,0x2,0x1}
458 { /* level11 */
459 {0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3},
460 {0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x2},
461 {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2},
462 {0x2,0x0,0x0,0x0,0x7,0x7,0x0,0x0,0x0,0x2},
463 {0x2,0x0,0x0,0x7,0x7,0x7,0x7,0x0,0x0,0x2},
464 {0x0,0x0,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x0},
465 {0x0,0x2,0x0,0x1,0x0,0x0,0x1,0x0,0x2,0x0},
466 {0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5}
468 { /* level 12 */
469 {0x2,0x1,0x3,0x1,0x0,0x0,0x1,0x3,0x1,0x2},
470 {0x1,0x1,0x1,0x1,0x0,0x0,0x1,0x1,0x1,0x1},
471 {0x1,0x1,0x1,0x0,0x1,0x1,0x0,0x1,0x1,0x1},
472 {0x0,0x1,0x0,0x1,0x6,0x6,0x1,0x0,0x1,0x0},
473 {0x0,0x0,0x1,0x1,0x6,0x6,0x1,0x1,0x0,0x0},
474 {0x1,0x1,0x1,0x7,0x0,0x0,0x7,0x1,0x1,0x1},
475 {0x1,0x1,0x7,0x1,0x0,0x0,0x1,0x7,0x1,0x1},
476 {0x2,0x2,0x0,0x2,0x2,0x2,0x2,0x0,0x2,0x2}
478 {/* levell13 */
479 {0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2},
480 {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2},
481 {0x2,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x0,0x2},
482 {0x2,0x0,0x2,0x3,0x3,0x3,0x3,0x3,0x0,0x2},
483 {0x2,0x0,0x2,0x4,0x4,0x4,0x4,0x4,0x0,0x2},
484 {0x2,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2},
485 {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
486 {0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2}
488 {/* level14 */
489 {0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1},
490 {0x4,0x4,0x4,0x4,0x2,0x2,0x4,0x4,0x4,0x4},
491 {0x4,0x0,0x0,0x0,0x2,0x2,0x0,0x0,0x0,0x4},
492 {0x4,0x0,0x0,0x2,0x3,0x3,0x2,0x0,0x0,0x4},
493 {0x4,0x0,0x2,0x23,0x3,0x3,0x23,0x2,0x0,0x4},
494 {0x4,0x0,0x2,0x22,0x2,0x2,0x22,0x2,0x0,0x4},
495 {0x4,0x0,0x6,0x21,0x5,0x5,0x21,0x6,0x0,0x4},
496 {0x4,0x6,0x1,0x1,0x5,0x5,0x1,0x1,0x6,0x4}
498 {/* level 15 */
499 {0x4,0x4,0x4,0x4,0x4,0x3,0x3,0x3,0x3,0x3},
500 {0x2,0x2,0x1,0x1,0x1,0x1,0x1,0x5,0x0,0x0},
501 {0x2,0x2,0x1,0x1,0x1,0x0,0x1,0x6,0x0,0x0},
502 {0x2,0x1,0x1,0x2,0x1,0x1,0x1,0x5,0x0,0x0},
503 {0x2,0x1,0x2,0x2,0x2,0x1,0x1,0x6,0x0,0x0},
504 {0x2,0x1,0x2,0x2,0x2,0x1,0x3,0x5,0x3,0x0},
505 {0x2,0x1,0x1,0x2,0x1,0x1,0x1,0x6,0x0,0x0},
506 {0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2}
508 {/* level 16 (Rockbox) by ts-x */
509 {0x2,0x2,0x3,0x3,0x3,0x4,0x4,0x5,0x0,0x5},
510 {0x2,0x0,0x3,0x0,0x3,0x4,0x0,0x5,0x5,0x0},
511 {0x2,0x0,0x3,0x3,0x3,0x4,0x4,0x5,0x0,0x5},
512 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
513 {0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
514 {0x7,0x7,0x7,0x1,0x1,0x1,0x2,0x0,0x2,0x0},
515 {0x7,0x0,0x7,0x1,0x0,0x1,0x0,0x2,0x0,0x0},
516 {0x7,0x7,0x7,0x1,0x1,0x1,0x2,0x0,0x2,0x0}
518 {/* level 17 (Alien) by ts-x */
519 {0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1},
520 {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2},
521 {0x1,0x0,0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x1},
522 {0x2,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x2},
523 {0x1,0x0,0x1,0x2,0x2,0x2,0x2,0x1,0x0,0x1},
524 {0x2,0x0,0x0,0x1,0x2,0x2,0x1,0x0,0x0,0x2},
525 {0x2,0x1,0x0,0x0,0x1,0x1,0x0,0x0,0x1,0x2},
526 {0x2,0x2,0x1,0x0,0x1,0x1,0x0,0x1,0x2,0x2}
528 {/* level 18 (Tetris) by ts-x */
529 {0x0,0x2,0x0,0x0,0x3,0x4,0x0,0x2,0x2,0x0},
530 {0x0,0x2,0x7,0x0,0x3,0x4,0x0,0x2,0x2,0x0},
531 {0x2,0x2,0x7,0x0,0x3,0x4,0x0,0x6,0x2,0x2},
532 {0x2,0x2,0x7,0x7,0x3,0x4,0x0,0x6,0x2,0x2},
533 {0x2,0x1,0x7,0x7,0x3,0x4,0x4,0x6,0x5,0x5},
534 {0x2,0x1,0x0,0x7,0x3,0x4,0x4,0x6,0x5,0x5},
535 {0x1,0x1,0x1,0x7,0x3,0x0,0x6,0x6,0x5,0x5},
536 {0x1,0x1,0x1,0x0,0x3,0x0,0x6,0x6,0x5,0x5}
538 { /* level 19 (Stalactites) by ts-x */
539 {0x5,0x2,0x6,0x3,0x4,0x7,0x5,0x3,0x1,0x2},
540 {0x5,0x2,0x6,0x3,0x4,0x7,0x5,0x3,0x1,0x2},
541 {0x5,0x0,0x6,0x3,0x4,0x7,0x5,0x0,0x1,0x2},
542 {0x5,0x2,0x6,0x3,0x4,0x0,0x5,0x3,0x1,0x2},
543 {0x5,0x0,0x6,0x0,0x4,0x7,0x5,0x0,0x1,0x0},
544 {0x5,0x0,0x0,0x3,0x4,0x0,0x0,0x0,0x1,0x2},
545 {0x0,0x0,0x6,0x0,0x0,0x0,0x5,0x0,0x0,0x0},
546 {0x5,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0}
548 { /* level 20 (Maze) by ts-x */
549 {0x1,0x1,0x21,0x1,0x1,0x1,0x1,0x1,0x1,0x21},
550 {0x1,0x0,0x0,0x3,0x0,0x0,0x3,0x1,0x31,0x1},
551 {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x31,0x0,0x1},
552 {0x21,0x0,0x21,0x3,0x0,0x3,0x0,0x3,0x0,0x2},
553 {0x1,0x0,0x1,0x21,0x0,0x12,0x0,0x0,0x0,0x0},
554 {0x31,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x3,0x0},
555 {0x1,0x0,0x1,0x0,0x1,0x1,0x31,0x1,0x1,0x2},
556 {0x22,0x0,0x2,0x1,0x1,0x1,0x1,0x1,0x1,0x21}
558 { /* level 21 (Dentist) by ts-x */
559 {0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x0},
560 {0x2,0x2,0x0,0x6,0x0,0x6,0x0,0x6,0x2,0x2},
561 {0x2,0x6,0x0,0x6,0x0,0x6,0x0,0x6,0x0,0x2},
562 {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x2},
563 {0x2,0x0,0x6,0x0,0x6,0x0,0x0,0x0,0x0,0x2},
564 {0x2,0x0,0x6,0x0,0x6,0x0,0x6,0x0,0x6,0x2},
565 {0x2,0x2,0x6,0x0,0x6,0x0,0x6,0x0,0x2,0x2},
566 {0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x0}
568 { /* level 22 (Spider) by ts-x */
569 {0x31,0x3,0x1,0x1,0x0,0x0,0x1,0x1,0x3,0x31},
570 {0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0},
571 {0x33,0x1,0x1,0x36,0x1,0x1,0x36,0x1,0x1,0x33},
572 {0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0},
573 {0x0,0x0,0x1,0x1,0x0,0x0,0x1,0x1,0x0,0x0},
574 {0x21,0x3,0x1,0x21,0x2,0x2,0x21,0x1,0x3,0x21},
575 {0x0,0x0,0x0,0x1,0x21,0x1,0x1,0x0,0x0,0x0},
576 {0x3,0x1,0x3,0x1,0x0,0x0,0x1,0x3,0x1,0x3}
578 { /* level 23 (Pool) by ts-x */
579 {0x0,0x7,0x7,0x7,0x0,0x7,0x7,0x7,0x7,0x0},
580 {0x0,0x0,0x5,0x0,0x2,0x0,0x0,0x0,0x2,0x0},
581 {0x7,0x3,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x7},
582 {0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x5,0x0,0x7},
583 {0x7,0x0,0x4,0x0,0x0,0x3,0x0,0x0,0x0,0x7},
584 {0x7,0x0,0x0,0x6,0x0,0x0,0x0,0x0,0x4,0x7},
585 {0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
586 {0x0,0x7,0x7,0x7,0x7,0x0,0x7,0x7,0x7,0x0}
588 { /* level 24 (Vorbis Fish) by ts-x */
589 {0x0,0x0,0x4,0x4,0x5,0x5,0x5,0x0,0x0,0x5},
590 {0x0,0x4,0x6,0x4,0x4,0x5,0x5,0x5,0x0,0x5},
591 {0x5,0x6,0x0,0x6,0x4,0x4,0x4,0x5,0x5,0x5},
592 {0x5,0x6,0x0,0x6,0x4,0x4,0x4,0x4,0x5,0x5},
593 {0x0,0x5,0x6,0x4,0x4,0x5,0x5,0x4,0x5,0x0},
594 {0x5,0x5,0x4,0x4,0x5,0x5,0x5,0x4,0x5,0x5},
595 {0x5,0x4,0x4,0x4,0x5,0x5,0x4,0x4,0x5,0x5},
596 {0x0,0x0,0x4,0x4,0x4,0x4,0x4,0x5,0x0,0x5}
598 {/* level 25 (Rainbow) by ts-x */
599 {0x0,0x4,0x1,0x0,0x0,0x0,0x0,0x1,0x4,0x0},
600 {0x24,0x1,0x3,0x1,0x0,0x0,0x21,0x3,0x1,0x24},
601 {0x1,0x23,0x5,0x3,0x1,0x21,0x3,0x5,0x3,0x21},
602 {0x3,0x5,0x6,0x5,0x3,0x3,0x5,0x6,0x5,0x3},
603 {0x5,0x6,0x7,0x6,0x5,0x5,0x6,0x7,0x6,0x5},
604 {0x6,0x7,0x2,0x27,0x6,0x6,0x27,0x2,0x7,0x6},
605 {0x7,0x2,0x0,0x2,0x27,0x27,0x2,0x0,0x2,0x7},
606 {0x32,0x0,0x0,0x0,0x2,0x2,0x0,0x0,0x0,0x32}
608 { /* level 26 (Bowtie) by ts-x */
609 {0x5,0x1,0x5,0x1,0x0,0x0,0x1,0x5,0x1,0x5},
610 {0x1,0x0,0x0,0x1,0x5,0x5,0x1,0x0,0x0,0x1},
611 {0x5,0x0,0x6,0x0,0x1,0x1,0x0,0x6,0x0,0x5},
612 {0x1,0x0,0x6,0x6,0x0,0x0,0x6,0x6,0x0,0x1},
613 {0x1,0x0,0x6,0x6,0x0,0x0,0x6,0x6,0x0,0x1},
614 {0x5,0x0,0x6,0x0,0x1,0x1,0x0,0x6,0x0,0x5},
615 {0x1,0x0,0x0,0x1,0x5,0x5,0x1,0x0,0x0,0x1},
616 {0x5,0x1,0x5,0x1,0x0,0x0,0x1,0x5,0x1,0x5}
618 { /* level 27 (Frog) by ts-x */
619 {0x0,0x5,0x25,0x0,0x0,0x0,0x0,0x25,0x5,0x0},
620 {0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5},
621 {0x25,0x0,0x0,0x5,0x6,0x6,0x5,0x0,0x0,0x25},
622 {0x5,0x0,0x3,0x0,0x6,0x6,0x0,0x3,0x0,0x5},
623 {0x5,0x0,0x31,0x0,0x6,0x6,0x0,0x31,0x0,0x5},
624 {0x5,0x0,0x0,0x5,0x6,0x6,0x5,0x0,0x0,0x5},
625 {0x5,0x5,0x5,0x35,0x0,0x0,0x35,0x5,0x5,0x5},
626 {0x0,0x25,0x5,0x0,0x4,0x4,0x0,0x5,0x25,0x0}
628 { /* level 28 (DigDug) by ts-x */
629 {0x35,0x5,0x5,0x25,0x0,0x25,0x25,0x5,0x5,0x35},
630 {0x6,0x0,0x0,0x6,0x0,0x6,0x6,0x0,0x0,0x6},
631 {0x7,0x0,0x37,0x37,0x0,0x37,0x37,0x7,0x0,0x7},
632 {0x7,0x0,0x7,0x0,0x0,0x0,0x7,0x7,0x7,0x7},
633 {0x4,0x4,0x4,0x24,0x0,0x24,0x4,0x0,0x0,0x4},
634 {0x4,0x4,0x0,0x0,0x0,0x4,0x4,0x0,0x4,0x4},
635 {0x24,0x24,0x4,0x4,0x4,0x4,0x0,0x0,0x24,0x4},
636 {0x1,0x1,0x1,0x1,0x1,0x1,0x21,0x21,0x1,0x1}
638 { /* level 29 UK Flag by Seth Opgenorth */
639 {0x32,0x0,0x3,0x3,0x2,0x2,0x3,0x3,0x0,0x32},
640 {0x0,0x2,0x0,0x3,0x32,0x22,0x33,0x0,0x32,0x0},
641 {0x33,0x0,0x22,0x0,0x2,0x2,0x0,0x2,0x0,0x33},
642 {0x22,0x32,0x2,0x2,0x2,0x2,0x2,0x2,0x22,0x2},
643 {0x3,0x0,0x0,0x32,0x22,0x2,0x2,0x0,0x0,0x3},
644 {0x23,0x0,0x32,0x0,0x32,0x2,0x0,0x2,0x0,0x3},
645 {0x0,0x2,0x0,0x3,0x2,0x2,0x3,0x0,0x22,0x0},
646 {0x32,0x0,0x3,0x23,0x2,0x2,0x23,0x33,0x0,0x32}
648 { /* level 30 Win-Logo by Seth Opgenorth */
649 {0x0,0x0,0x0,0x22,0x0,0x0,0x0,0x0,0x0,0x0},
650 {0x0,0x0,0x32,0x2,0x2,0x25,0x0,0x5,0x0,0x0},
651 {0x0,0x0,0x2,0x22,0x2,0x5,0x5,0x35,0x0,0x0},
652 {0x0,0x0,0x2,0x1,0x2,0x5,0x5,0x25,0x0,0x0},
653 {0x0,0x0,0x21,0x1,0x1,0x36,0x7,0x26,0x0,0x0},
654 {0x0,0x0,0x1,0x1,0x1,0x6,0x6,0x6,0x0,0x0},
655 {0x0,0x0,0x21,0x0,0x21,0x6,0x6,0x26,0x0,0x0},
656 {0x0,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x0,0x0}
658 { /* level 31 Color wave/V by Seth Opgenorth */
659 {0x25,0x34,0x2,0x31,0x33,0x23,0x1,0x2,0x34,0x5},
660 {0x3,0x5,0x24,0x2,0x1,0x1,0x2,0x4,0x5,0x3},
661 {0x1,0x3,0x5,0x4,0x2,0x2,0x4,0x5,0x3,0x1},
662 {0x2,0x1,0x33,0x35,0x4,0x4,0x5,0x33,0x1,0x22},
663 {0x31,0x22,0x1,0x3,0x5,0x25,0x3,0x1,0x2,0x31},
664 {0x3,0x1,0x2,0x1,0x3,0x3,0x1,0x2,0x21,0x3},
665 {0x5,0x23,0x1,0x32,0x1,0x1,0x2,0x1,0x3,0x5},
666 {0x4,0x35,0x3,0x1,0x2,0x22,0x31,0x3,0x5,0x4}
668 { /* level 32 Sweedish Flag by Seth Opgenorth */
669 {0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
670 {0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
671 {0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
672 {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36},
673 {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36},
674 {0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
675 {0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
676 {0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3}
678 { /* level 33 Color Pyramid by Seth Opgenorth */
679 {0x0,0x0,0x0,0x0,0x2,0x2,0x0,0x0,0x0,0x0},
680 {0x0,0x0,0x0,0x4,0x24,0x4,0x24,0x0,0x0,0x0},
681 {0x0,0x0,0x23,0x3,0x3,0x3,0x23,0x3,0x0,0x0},
682 {0x0,0x0,0x25,0x5,0x25,0x35,0x5,0x35,0x0,0x0},
683 {0x0,0x36,0x6,0x6,0x6,0x6,0x26,0x6,0x6,0x0},
684 {0x0,0x7,0x7,0x7,0x7,0x25,0x27,0x7,0x27,0x0},
685 {0x2,0x2,0x22,0x2,0x2,0x2,0x22,0x2,0x2,0x2},
686 {0x21,0x1,0x1,0x31,0x1,0x21,0x1,0x1,0x31,0x1}
688 { /* level 34 Rhombus by Seth Opgenorth */
689 {0x0,0x0,0x0,0x0,0x3,0x33,0x0,0x0,0x0,0x0},
690 {0x0,0x0,0x0,0x3,0x32,0x22,0x23,0x0,0x0,0x0},
691 {0x0,0x0,0x3,0x2,0x24,0x4,0x2,0x23,0x0,0x0},
692 {0x26,0x3,0x2,0x4,0x5,0x5,0x4,0x22,0x3,0x6},
693 {0x36,0x3,0x2,0x34,0x5,0x5,0x4,0x2,0x3,0x36},
694 {0x0,0x0,0x3,0x2,0x4,0x34,0x2,0x23,0x0,0x0},
695 {0x0,0x0,0x0,0x23,0x2,0x2,0x3,0x0,0x0,0x0},
696 {0x0,0x0,0x0,0x0,0x3,0x33,0x0,0x0,0x0,0x0}
698 { /* level 35 PacMan Ghost by Seth Opgenorth */
699 {0x0,0x0,0x0,0x0,0x2,0x32,0x2,0x0,0x0,0x0},
700 {0x0,0x0,0x0,0x2,0x2,0x2,0x2,0x2,0x0,0x0},
701 {0x0,0x0,0x2,0x24,0x4,0x2,0x4,0x4,0x32,0x0},
702 {0x0,0x0,0x2,0x24,0x0,0x22,0x24,0x0,0x22,0x0},
703 {0x0,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x0},
704 {0x0,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x0},
705 {0x0,0x0,0x2,0x32,0x2,0x2,0x22,0x2,0x32,0x0},
706 {0x0,0x0,0x0,0x22,0x0,0x32,0x0,0x22,0x0,0x0}
708 { /* level 36 Star by Seth Opgenorth */
709 {0x3,0x4,0x3,0x4,0x6,0x24,0x3,0x24,0x3,0x0},
710 {0x24,0x0,0x0,0x6,0x6,0x6,0x0,0x0,0x4,0x0},
711 {0x3,0x26,0x6,0x2,0x6,0x2,0x6,0x26,0x23,0x0},
712 {0x4,0x0,0x6,0x6,0x36,0x6,0x6,0x0,0x4,0x0},
713 {0x3,0x0,0x0,0x26,0x6,0x26,0x0,0x0,0x33,0x0},
714 {0x34,0x0,0x6,0x6,0x0,0x6,0x6,0x0,0x4,0x0},
715 {0x3,0x26,0x6,0x0,0x0,0x0,0x6,0x6,0x3,0x0},
716 {0x4,0x3,0x4,0x23,0x24,0x3,0x4,0x33,0x4,0x0}
718 { /* level 37 It's 8-Bit by Seth Opgenorth */
719 {0x26,0x26,0x6,0x6,0x5,0x6,0x26,0x6,0x26,0x6},
720 {0x2,0x2,0x22,0x3,0x3,0x0,0x0,0x0,0x4,0x0},
721 {0x2,0x0,0x2,0x33,0x3,0x3,0x5,0x0,0x24,0x0},
722 {0x32,0x2,0x2,0x33,0x0,0x23,0x0,0x4,0x4,0x4},
723 {0x2,0x22,0x2,0x3,0x3,0x0,0x5,0x4,0x4,0x24},
724 {0x2,0x0,0x2,0x23,0x0,0x3,0x25,0x0,0x4,0x0},
725 {0x22,0x2,0x2,0x3,0x23,0x0,0x5,0x0,0x4,0x0},
726 {0x6,0x26,0x6,0x36,0x6,0x36,0x6,0x6,0x6,0x6}
728 { /* level 38 Linux by Seth Opgenorth */
729 {0x27,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
730 {0x7,0x0,0x0,0x0,0x33,0x0,0x23,0x0,0x0,0x0},
731 {0x7,0x32,0x0,0x0,0x3,0x0,0x23,0x6,0x0,0x6},
732 {0x37,0x0,0x0,0x0,0x23,0x0,0x3,0x6,0x0,0x26},
733 {0x7,0x22,0x24,0x0,0x3,0x33,0x3,0x0,0x26,0x0},
734 {0x37,0x22,0x24,0x24,0x4,0x0,0x0,0x0,0x26,0x0},
735 {0x7,0x2,0x4,0x0,0x4,0x0,0x0,0x6,0x0,0x26},
736 {0x7,0x27,0x4,0x0,0x34,0x0,0x0,0x6,0x0,0x26}
738 { /* level 39 Colorful Squares by Seth Opgenorth*/
739 {0x0,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x0},
740 {0x0,0x4,0x5,0x5,0x5,0x5,0x5,0x5,0x4,0x0},
741 {0x0,0x4,0x5,0x3,0x3,0x3,0x3,0x5,0x4,0x0},
742 {0x0,0x4,0x5,0x3,0x4,0x4,0x3,0x5,0x4,0x0},
743 {0x0,0x4,0x5,0x3,0x4,0x4,0x3,0x5,0x4,0x0},
744 {0x0,0x4,0x5,0x3,0x3,0x3,0x3,0x5,0x4,0x0},
745 {0x0,0x4,0x5,0x5,0x5,0x5,0x5,0x5,0x4,0x0},
746 {0x0,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x0}
748 { /* TheEnd */
749 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
750 {0x32,0x32,0x36,0x0,0x0,0x36,0x34,0x34,0x0,0x0},
751 {0x32,0x0,0x36,0x36,0x0,0x36,0x34,0x0,0x34,0x0},
752 {0x32,0x32,0x36,0x36,0x0,0x36,0x34,0x0,0x34,0x0},
753 {0x32,0x32,0x36,0x0,0x36,0x36,0x34,0x0,0x34,0x0},
754 {0x32,0x0,0x36,0x0,0x36,0x36,0x34,0x0,0x34,0x0},
755 {0x32,0x32,0x36,0x0,0x0,0x36,0x34,0x34,0x0,0x0},
756 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
760 #define MAX_BALLS 10
762 enum difficulty_options {
763 EASY, NORMAL
766 int pad_pos_x;
767 int life;
768 enum { ST_READY, ST_START, ST_PAUSE } game_state = ST_READY;
770 enum {
771 PLAIN = 0,
772 STICKY = 1,
773 SHOOTER = 2
774 } pad_type;
776 int score=0,vscore=0;
777 bool flip_sides=false;
778 int level=0;
779 int brick_on_board=0;
780 int used_balls=1;
781 int difficulty = NORMAL;
782 int pad_width;
783 int num_count;
784 bool resume = false;
785 bool resume_file = false;
787 typedef struct cube
789 int powertop; /* Stores the powerup Y top pos, it is a fixed point num */
790 int power; /* What powerup is in the brick? */
791 bool poweruse; /* Stores whether a powerup is falling or not */
792 bool used; /* Is the brick still in play? */
793 int color;
794 int hits; /* How many hits can this brick take? */
795 int hiteffect;
796 } cube;
797 cube brick[80];
799 typedef struct balls
801 /* pos_x and y store the current center position of the ball */
802 int pos_x;
803 int pos_y;
804 /* tempx and tempy store an absolute position the ball should be in. If
805 * they are equal to 0, they are not used when positioning the ball.
807 int tempx;
808 int tempy;
809 /* speedx and speedy store the current speed of the ball */
810 int speedx;
811 int speedy;
812 bool glue; /* Is the ball stuck to the paddle? */
813 } balls;
815 balls ball[MAX_BALLS];
817 typedef struct sfire {
818 int top; /* This stores the fire y position, it is a fixed point num */
819 int x_pos; /* This stores the fire x position, it is a whole number */
820 } sfire;
821 sfire fire[30];
823 #define CONFIG_FILE_NAME "brickmania.cfg"
824 #define SAVE_FILE PLUGIN_GAMES_DIR "/brickmania.save"
825 #define HIGH_SCORE PLUGIN_GAMES_DIR "/brickmania.score"
826 #define NUM_SCORES 5
828 static struct configdata config[] = {
829 {TYPE_INT, 0, 1, { .int_p = &difficulty }, "difficulty", NULL},
832 struct highscore highest[NUM_SCORES];
834 typedef struct point
836 int x;
837 int y;
838 } point;
840 typedef struct line
842 point p1;
843 point p2;
844 } line;
847 * check_lines:
848 * This is based off an explanation and expanded math presented by Paul Bourke:
849 * http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
851 * It takes two lines as inputs and returns 1 if they intersect, 0 if they do
852 * not. hitp returns the point where the two lines intersected.
854 * This function expects fixed point inputs with a precision of 3. When a
855 * collision occurs hitp is updated with a fixed point location (precision 3)
856 * where the collision happened. The internal calculations are fixed
857 * point with a 7 bit fractional precision.
859 * If you choose 10 bits of precision a screen size of about 640x480 is the
860 * largest this can go. 7 bits allows for an accurate intersection calculation
861 * with a line length of about 64 and a rougher line lenght of 128 which is
862 * larger than any target currently needs (the pad is the longest line and it
863 * only needs an accuracy of 2^4 at most to figure out which section of the pad
864 * the ball hit). A precision of 7 gives breathing room for larger screens.
865 * Longer line sizes that need accurate intersection points will need more
866 * precision, but will decrease the maximum screen resolution.
869 #define LINE_PREC 7
870 int check_lines(line *line1, line *line2, point *hitp)
872 /* Introduction:
873 * This code is based on the solution of these two input equations:
874 * Pa = P1 + ua (P2-P1)
875 * Pb = P3 + ub (P4-P3)
877 * Where line one is composed of points P1 and P2 and line two is composed
878 * of points P3 and P4.
880 * ua/b is the fractional value you can multiply the x and y legs of the
881 * triangle formed by each line to find a point on the line.
883 * The two equations can be expanded to their x/y components:
884 * Pa.x = p1.x + ua(p2.x - p1.x)
885 * Pa.y = p1.y + ua(p2.y - p1.y)
887 * Pb.x = p3.x + ub(p4.x - p3.x)
888 * Pb.y = p3.y + ub(p4.y - p3.y)
890 * When Pa.x == Pb.x and Pa.y == Pb.y the lines intersect so you can come
891 * up with two equations (one for x and one for y):
893 * p1.x + ua(p2.x - p1.x) = p3.x + ub(p4.x - p3.x)
894 * p1.y + ua(p2.y - p1.y) = p3.y + ub(p4.y - p3.y)
896 * ua and ub can then be individually solved for. This results in the
897 * equations used in the following code.
900 /* Denominator for ua and ub are the same so store this calculation */
901 int d = FIXED3_MUL((line2->p2.y - line2->p1.y),(line1->p2.x-line1->p1.x))
902 -FIXED3_MUL((line2->p2.x - line2->p1.x),(line1->p2.y-line1->p1.y));
904 /* n_a and n_b are calculated as seperate values for readability */
905 int n_a = FIXED3_MUL((line2->p2.x - line2->p1.x),(line1->p1.y-line2->p1.y))
906 -FIXED3_MUL((line2->p2.y - line2->p1.y),(line1->p1.x-line2->p1.x));
908 int n_b = FIXED3_MUL((line1->p2.x - line1->p1.x),(line1->p1.y-line2->p1.y))
909 -FIXED3_MUL((line1->p2.y - line1->p1.y),(line1->p1.x-line2->p1.x));
911 /* Make sure there is not a division by zero - this also indicates that
912 * the lines are parallel.
914 * If n_a and n_b were both equal to zero the lines would be on top of each
915 * other (coincidental). This check is not done because it is not
916 * necessary for this implementation (the parallel check accounts for this).
918 if(d == 0)
919 return 0;
921 /* Calculate the intermediate fractional point that the lines potentially
922 * intersect.
924 int ua = (n_a << LINE_PREC)/d;
925 int ub = (n_b << LINE_PREC)/d;
927 /* The fractional point will be between 0 and 1 inclusive if the lines
928 * intersect. If the fractional calculation is larger than 1 or smaller
929 * than 0 the lines would need to be longer to intersect.
931 if(ua >=0 && ua <= (1<<LINE_PREC) && ub >= 0 && ub <= (1<<LINE_PREC))
933 hitp->x = line1->p1.x + ((ua * (line1->p2.x - line1->p1.x))>>LINE_PREC);
934 hitp->y = line1->p1.y + ((ua * (line1->p2.y - line1->p1.y))>>LINE_PREC);
935 return 1;
937 return 0;
940 static void brickmania_init_game(bool new_game)
942 int i,j;
944 pad_pos_x = GAMESCREEN_WIDTH/2 - PAD_WIDTH/2;
946 for(i=0;i<MAX_BALLS;i++)
948 ball[i].speedx = 0;
949 ball[i].speedy = 0;
950 ball[i].tempy = 0;
951 ball[i].tempx = 0;
952 ball[i].pos_y = PAD_POS_Y - HALFBALL;
953 ball[i].pos_x = GAMESCREEN_WIDTH/2;
954 ball[i].glue = false;
957 used_balls = 1;
958 game_state = ST_READY;
959 pad_type = PLAIN;
960 pad_width = PAD_WIDTH;
961 flip_sides = false;
962 num_count = 10;
964 if (new_game) {
965 brick_on_board=0;
966 /* add one life per achieved level */
967 if (difficulty==EASY && life<2) {
968 score-=100;
969 life++;
973 for(i=0;i<30;i++) {
974 /* No fire should be active */
975 fire[i].top=-1;
978 for(i=0;i<=7;i++) {
979 for(j=0;j<=9;j++) {
980 int bnum = i*10+j;
981 brick[bnum].poweruse = false;
982 if (new_game) {
983 brick[bnum].power=rb->rand()%25;
984 /* +8 make the game with less powerups */
986 brick[bnum].hits=levels[level][i][j]>=10?
987 levels[level][i][j]/16-1:0;
988 brick[bnum].hiteffect=0;
989 brick[bnum].powertop = TOPMARGIN + i*BRICK_HEIGHT;
990 brick[bnum].used=!(levels[level][i][j]==0);
991 brick[bnum].color=(levels[level][i][j]>=10?
992 levels[level][i][j]%16:
993 levels[level][i][j])-1;
994 if (levels[level][i][j]!=0)
995 brick_on_board++;
1001 static void brickmania_loadgame(void)
1003 int fd;
1005 resume = false;
1007 /* open game file */
1008 fd = rb->open(SAVE_FILE, O_RDONLY);
1009 if(fd < 0) return;
1011 /* read in saved game */
1012 while(true) {
1013 if(rb->read(fd, &pad_pos_x, sizeof(pad_pos_x)) <= 0) break;
1014 if(rb->read(fd, &life, sizeof(life)) <= 0) break;
1015 if(rb->read(fd, &game_state, sizeof(game_state)) <= 0) break;
1016 if(rb->read(fd, &pad_type, sizeof(pad_type)) <= 0) break;
1017 if(rb->read(fd, &score, sizeof(score)) <= 0) break;
1018 if(rb->read(fd, &flip_sides, sizeof(flip_sides)) <= 0) break;
1019 if(rb->read(fd, &level, sizeof(level)) <= 0) break;
1020 if(rb->read(fd, &brick_on_board, sizeof(brick_on_board)) <= 0) break;
1021 if(rb->read(fd, &used_balls, sizeof(used_balls)) <= 0) break;
1022 if(rb->read(fd, &pad_width, sizeof(pad_width)) <= 0) break;
1023 if(rb->read(fd, &num_count, sizeof(num_count)) <= 0) break;
1024 if(rb->read(fd, &brick, sizeof(brick)) <= 0) break;
1025 if(rb->read(fd, &ball, sizeof(ball)) <= 0) break;
1026 if(rb->read(fd, &fire, sizeof(fire)) <= 0) break;
1027 vscore = score;
1028 resume = true;
1029 break;
1032 rb->close(fd);
1034 return;
1037 static void brickmania_savegame(void)
1039 int fd;
1041 /* write out the game state to the save file */
1042 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
1043 if(fd < 0) return;
1045 rb->write(fd, &pad_pos_x, sizeof(pad_pos_x));
1046 rb->write(fd, &life, sizeof(life));
1047 rb->write(fd, &game_state, sizeof(game_state));
1048 rb->write(fd, &pad_type, sizeof(pad_type));
1049 rb->write(fd, &score, sizeof(score));
1050 rb->write(fd, &flip_sides, sizeof(flip_sides));
1051 rb->write(fd, &level, sizeof(level));
1052 rb->write(fd, &brick_on_board, sizeof(brick_on_board));
1053 rb->write(fd, &used_balls, sizeof(used_balls));
1054 rb->write(fd, &pad_width, sizeof(pad_width));
1055 rb->write(fd, &num_count, sizeof(num_count));
1056 rb->write(fd, &brick, sizeof(brick));
1057 rb->write(fd, &ball, sizeof(ball));
1058 rb->write(fd, &fire, sizeof(fire));
1059 rb->close(fd);
1062 /* brickmania_sleep timer counting the score */
1063 static void brickmania_sleep(int secs)
1065 bool done=false;
1066 char s[20];
1067 int count=0;
1068 int sw, w;
1070 while (!done)
1072 if (count == 0)
1073 count = *rb->current_tick + HZ*secs;
1074 if ( (TIME_AFTER(*rb->current_tick, count)) && (vscore == score) )
1075 done = true;
1077 if(vscore != score)
1079 if (vscore<score)
1080 vscore++;
1081 if (vscore>score)
1082 vscore--;
1083 rb->snprintf(s, sizeof(s), "%d", vscore);
1084 rb->lcd_getstringsize(s, &sw, &w);
1085 rb->lcd_putsxy(LCD_WIDTH/2-sw/2, 0, s);
1086 rb->lcd_update_rect(0,0,LCD_WIDTH,w+2);
1088 rb->yield();
1092 static int brickmania_help(void)
1094 #define WORDS (sizeof help_text / sizeof (char*))
1095 static char *help_text[] = {
1096 "Brickmania", "", "Aim", "",
1097 "Destroy", "all", "the", "bricks", "by", "bouncing",
1098 "the", "ball", "of", "them", "using", "the", "paddle.", "", "",
1099 "Controls", "",
1100 "< & >", "Moves", "the", "paddle", "",
1101 #if CONFIG_KEYPAD == ONDIO_PAD
1102 "MENU:",
1103 #elif (CONFIG_KEYPAD == RECORDER_PAD) || (CONFIG_KEYPAD == IAUDIO_M3_PAD)
1104 "PLAY:",
1105 #elif CONFIG_KEYPAD == IRIVER_H300_PAD
1106 "NAVI:",
1107 #else
1108 "SELECT:",
1109 #endif
1110 "Releases", "the", "ball/Fire!", "",
1111 #if CONFIG_KEYPAD == IAUDIO_M3_PAD
1112 "REC:",
1113 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \
1114 (CONFIG_KEYPAD == CREATIVEZVM_PAD)
1115 "BACK:",
1116 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
1117 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
1118 (CONFIG_KEYPAD == IPOD_1G2G_PAD) || \
1119 (CONFIG_KEYPAD == SANSA_FUZE_PAD)
1120 "MENU:",
1121 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
1122 (CONFIG_KEYPAD == IRIVER_H300_PAD) || \
1123 (CONFIG_KEYPAD == ONDIO_PAD) || \
1124 (CONFIG_KEYPAD == RECORDER_PAD) || \
1125 (CONFIG_KEYPAD == ARCHOS_AV300_PAD)
1126 "STOP:",
1127 #else
1128 "POWER:",
1129 #endif
1130 "Returns", "to", "menu", "", "",
1131 "Specials", "",
1132 "N", "Normal:", "returns", "paddle", "to", "normal", "",
1133 "D", "DIE!:", "loses", "a", "life", "",
1134 "L", "Life:", "gains", "a", "life/power", "up", "",
1135 "F", "Fire:", "allows", "you", "to", "shoot", "bricks", "",
1136 "G", "Glue:", "ball", "sticks", "to", "paddle", "",
1137 "B", "Ball:", "generates", "another", "ball", "",
1138 "FL", "Flip:", "flips", "left / right", "movement", "",
1139 "<->", "or", "<E>:", "enlarges", "the", "paddle", "",
1140 ">-<", "or", ">S<:", "shrinks", "the", "paddle", "",
1142 static struct style_text formation[]={
1143 { 0, TEXT_CENTER|TEXT_UNDERLINE },
1144 { 2, C_RED },
1145 { 19, C_RED },
1146 { 37, C_RED },
1147 { 39, C_BLUE },
1148 { 46, C_RED },
1149 { 52, C_GREEN },
1150 { 59, C_ORANGE },
1151 { 67, C_GREEN },
1152 { 74, C_YELLOW },
1153 { 80, C_RED },
1154 { -1, 0 }
1156 int button;
1158 rb->lcd_setfont(FONT_UI);
1159 #ifdef HAVE_LCD_COLOR
1160 rb->lcd_set_background(LCD_BLACK);
1161 rb->lcd_set_foreground(LCD_WHITE);
1162 #endif
1164 if (display_text(WORDS, help_text, formation, NULL))
1165 return 1;
1166 do {
1167 button = rb->button_get(true);
1168 if (rb->default_event_handler(button) == SYS_USB_CONNECTED) {
1169 return 1;
1171 } while( ( button == BUTTON_NONE )
1172 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
1173 rb->lcd_setfont(FONT_SYSFIXED);
1174 return 0;
1177 static int brickmania_menu_cb(int action, const struct menu_item_ex *this_item)
1179 int i = ((intptr_t)this_item);
1180 if(action == ACTION_REQUEST_MENUITEM
1181 && !resume && (i==0 || i==6))
1182 return ACTION_EXIT_MENUITEM;
1183 return action;
1186 static int brickmania_menu(void)
1188 int selected = 0;
1190 static struct opt_items options[] = {
1191 { "Easy", -1 },
1192 { "Normal", -1 },
1195 #ifdef HAVE_TOUCHSCREEN
1196 /* Entering Menu, set the touchscreen to the global setting */
1197 rb->touchscreen_set_mode(rb->global_settings->touch_mode);
1198 #endif
1200 MENUITEM_STRINGLIST(main_menu, "Brickmania Menu", brickmania_menu_cb,
1201 "Resume Game", "Start New Game",
1202 "Difficulty", "Help", "High Scores",
1203 "Playback Control",
1204 "Quit without Saving", "Quit");
1206 rb->button_clear_queue();
1207 while (true) {
1208 switch (rb->do_menu(&main_menu, &selected, NULL, false)) {
1209 case 0:
1210 if(game_state!=ST_READY)
1211 game_state = ST_PAUSE;
1212 if(resume_file)
1213 rb->remove(SAVE_FILE);
1214 return 0;
1215 case 1:
1216 score=0;
1217 vscore=0;
1218 life=2;
1219 level=0;
1220 brickmania_init_game(true);
1221 return 0;
1222 case 2:
1223 rb->set_option("Difficulty", &difficulty, INT,
1224 options, 2, NULL);
1225 break;
1226 case 3:
1227 if (brickmania_help())
1228 return 1;
1229 break;
1230 case 4:
1231 highscore_show(NUM_SCORES, highest, NUM_SCORES, true);
1232 break;
1233 case 5:
1234 if (playback_control(NULL))
1235 return 1;
1236 break;
1237 case 6:
1238 return 1;
1239 case 7:
1240 if (resume) {
1241 rb->splash(HZ*1, "Saving game ...");
1242 brickmania_savegame();
1244 return 1;
1245 case MENU_ATTACHED_USB:
1246 return 1;
1247 default:
1248 break;
1251 #ifdef HAVE_TOUCHSCREEN
1252 rb->touchscreen_set_mode(TOUCHSCREEN_POINT);
1253 #endif
1256 /* Find an unused fire position */
1257 static int brickmania_find_empty_fire(void)
1259 int t;
1260 for(t=0;t<30;t++)
1261 if (fire[t].top < 0)
1262 return t;
1264 return 0;
1267 void brick_hit(int brick_number)
1269 if(!brick[brick_number].used)
1270 return;
1272 /* if this is a crackable brick hits starts as
1273 * greater than 0.
1275 if (brick[brick_number].hits > 0) {
1276 brick[brick_number].hits--;
1277 brick[brick_number].hiteffect++;
1278 score+=2;
1280 else {
1281 brick[brick_number].used=false;
1282 /* Was there a powerup on the brick? */
1283 if (brick[brick_number].power<NUMBER_OF_POWERUPS) {
1284 /* Activate the powerup */
1285 brick[brick_number].poweruse = true;
1287 brick_on_board--;
1288 score+=8;
1292 static int brickmania_game_loop(void)
1294 int j,i,k;
1295 int sw;
1296 char s[30];
1297 int sec_count=0;
1298 int end;
1300 /* pad_line used for powerup/ball checks */
1301 line pad_line;
1302 /* This is used for various lines that are checked (ball and powerup) */
1303 line misc_line;
1305 /* This stores the point that the two lines intersected in a test */
1306 point pt_hit;
1308 if (brickmania_menu()) {
1309 return 1;
1311 resume = false;
1312 resume_file = false;
1314 #ifdef HAVE_LCD_COLOR
1315 rb->lcd_set_background(LCD_BLACK);
1316 rb->lcd_set_foreground(LCD_WHITE);
1317 rb->lcd_set_drawmode(DRMODE_SOLID);
1318 rb->lcd_clear_display();
1319 #endif
1321 while(true) {
1322 /* Convert CYCLETIME (in ms) to HZ */
1323 end = *rb->current_tick + (CYCLETIME * HZ) / 1000;
1325 if (life >= 0) {
1326 rb->lcd_clear_display();
1328 if (flip_sides)
1330 if (TIME_AFTER(*rb->current_tick, sec_count))
1332 sec_count=*rb->current_tick+HZ;
1333 if (num_count!=0)
1334 num_count--;
1335 else
1336 flip_sides=false;
1338 rb->snprintf(s, sizeof(s), "%d", num_count);
1339 rb->lcd_getstringsize(s, &sw, NULL);
1340 rb->lcd_putsxy(LCD_WIDTH/2-2, INT3(STRINGPOS_FLIP), s);
1343 /* write life num */
1344 #if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
1345 rb->snprintf(s, sizeof(s), "L:%d", life);
1346 #else
1347 rb->snprintf(s, sizeof(s), "Life: %d", life);
1348 #endif
1349 rb->lcd_putsxy(0, 0, s);
1351 #if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
1352 rb->snprintf(s, sizeof(s), "L%d", level+1);
1353 #else
1354 rb->snprintf(s, sizeof(s), "Level %d", level+1);
1355 #endif
1357 rb->lcd_getstringsize(s, &sw, NULL);
1358 rb->lcd_putsxy(LCD_WIDTH-sw, 0, s);
1360 if (vscore<score) vscore++;
1361 rb->snprintf(s, sizeof(s), "%d", vscore);
1362 rb->lcd_getstringsize(s, &sw, NULL);
1363 rb->lcd_putsxy(LCD_WIDTH/2-sw/2, 0, s);
1365 /* continue game */
1366 if (game_state == ST_PAUSE)
1368 rb->snprintf(s, sizeof(s), CONTINUE_TEXT);
1369 rb->lcd_getstringsize(s, &sw, NULL);
1370 rb->lcd_putsxy(LCD_WIDTH/2-sw/2, INT3(STRINGPOS_NAVI), s);
1372 sec_count=*rb->current_tick+HZ;
1375 /* draw the ball */
1376 for(i=0;i<used_balls;i++)
1377 rb->lcd_bitmap(brickmania_ball,
1378 INT3(ball[i].pos_x - HALFBALL),
1379 INT3(ball[i].pos_y - HALFBALL),
1380 INT3(BALL), INT3(BALL));
1382 if (brick_on_board==0)
1383 brick_on_board--;
1385 /* if the pad is fire */
1386 for(i=0; i<30; i++)
1388 /* If the projectile is active (>0 inactive) */
1389 if (fire[i].top >= 0)
1391 if (game_state!=ST_PAUSE)
1392 fire[i].top -= SPEED_FIRE;
1393 /* Draw the projectile */
1394 rb->lcd_vline( INT3(fire[i].x_pos), INT3(fire[i].top),
1395 INT3(fire[i].top + FIRE_LENGTH));
1399 /* Setup the pad line-later used in intersection test */
1400 pad_line.p1.x = pad_pos_x;
1401 pad_line.p1.y = PAD_POS_Y;
1403 pad_line.p2.x = pad_pos_x + pad_width;
1404 pad_line.p2.y = PAD_POS_Y;
1406 /* handle all of the bricks/powerups */
1407 for (i=0; i<=7; i++)
1409 for (j=0; j<=9 ;j++)
1411 int brickx;
1412 int bnum = i*10+j;
1414 /* This brick is not really a brick, it is a powerup if
1415 * poweruse is set. Perform appropriate powerup checks.
1417 if(brick[bnum].poweruse)
1419 brickx = LEFTMARGIN + j*BRICK_WIDTH +
1420 (BRICK_WIDTH - POWERUP_WIDTH) / 2;
1422 /* Update powertop if the game is not paused */
1423 if (game_state!=ST_PAUSE)
1424 brick[bnum].powertop+=SPEED_POWER;
1426 /* Draw the powerup */
1427 rb->lcd_bitmap_part(brickmania_powerups,0,
1428 INT3(POWERUP_HEIGHT)*brick[bnum].power,
1429 STRIDE( SCREEN_MAIN,
1430 BMPWIDTH_brickmania_powerups,
1431 BMPHEIGHT_brickmania_powerups),
1432 INT3(brickx),
1433 INT3(brick[bnum].powertop),
1434 INT3(POWERUP_WIDTH),
1435 INT3(POWERUP_HEIGHT) );
1437 /* Use misc_line to check if the center of the powerup
1438 * hit the paddle.
1440 misc_line.p1.x = brickx + (POWERUP_WIDTH >> 1);
1441 misc_line.p1.y = brick[bnum].powertop + POWERUP_HEIGHT;
1443 misc_line.p2.x = brickx + (POWERUP_WIDTH >> 1);
1444 misc_line.p2.y = SPEED_POWER + brick[bnum].powertop +
1445 POWERUP_HEIGHT;
1447 /* Check if the powerup will hit the paddle */
1448 if ( check_lines(&misc_line, &pad_line, &pt_hit) )
1450 switch(brick[bnum].power) {
1451 case 0: /* Extra Life */
1452 life++;
1453 score += 50;
1454 break;
1455 case 1: /* Loose a life */
1456 life--;
1457 if (life>=0)
1459 brickmania_init_game(false);
1460 brickmania_sleep(2);
1462 break;
1463 case 2: /* Make the paddle sticky */
1464 score += 34;
1465 pad_type = STICKY;
1466 break;
1467 case 3: /* Give the paddle shooter */
1468 score += 47;
1469 pad_type = SHOOTER;
1470 for(k=0;k<used_balls;k++)
1471 ball[k].glue=false;
1472 break;
1473 case 4: /* Normal brick */
1474 score += 23;
1475 pad_type = PLAIN;
1476 for(k=0;k<used_balls;k++)
1477 ball[k].glue=false;
1478 flip_sides=false;
1480 pad_pos_x += (pad_width-PAD_WIDTH)/2;
1481 pad_width = PAD_WIDTH;
1482 break;
1483 case 5: /* Flip the paddle */
1484 score += 23;
1485 sec_count = *rb->current_tick+HZ;
1486 num_count = 10;
1487 flip_sides = true;
1488 break;
1489 case 6: /* Extra Ball */
1490 score += 23;
1491 if(used_balls<MAX_BALLS)
1493 /* Set the speed */
1494 if(rb->rand()%2 == 0)
1495 ball[used_balls].speedx=-SPEED_4Q_X;
1496 else
1497 ball[used_balls].speedx= SPEED_4Q_X;
1499 ball[used_balls].speedy= SPEED_4Q_Y;
1501 /* Ball is not glued */
1502 ball[used_balls].glue= false;
1503 used_balls++;
1505 break;
1506 case 7: /* Long paddle */
1507 score+=23;
1508 if (pad_width==PAD_WIDTH)
1510 pad_width = LONG_PAD_WIDTH;
1511 pad_pos_x -= (LONG_PAD_WIDTH -
1512 PAD_WIDTH)/2;
1514 else if (pad_width==SHORT_PAD_WIDTH)
1516 pad_width = PAD_WIDTH;
1517 pad_pos_x-=(PAD_WIDTH-
1518 SHORT_PAD_WIDTH)/2;
1521 if (pad_pos_x < 0)
1522 pad_pos_x = 0;
1523 else if(pad_pos_x + pad_width >
1524 GAMESCREEN_WIDTH)
1525 pad_pos_x = GAMESCREEN_WIDTH-pad_width;
1526 break;
1527 case 8: /* Short Paddle */
1528 if (pad_width==PAD_WIDTH)
1530 pad_width=SHORT_PAD_WIDTH;
1531 pad_pos_x+=(PAD_WIDTH-
1532 SHORT_PAD_WIDTH)/2;
1534 else if (pad_width==LONG_PAD_WIDTH)
1536 pad_width=PAD_WIDTH;
1537 pad_pos_x+=(LONG_PAD_WIDTH-PAD_WIDTH)/2;
1539 break;
1541 /* Disable the powerup (it was picked up) */
1542 brick[bnum].poweruse = false;
1545 if (brick[bnum].powertop>PAD_POS_Y)
1547 /* Disable the powerup (it was missed) */
1548 brick[bnum].poweruse = false;
1551 /* The brick is a brick, but it may or may not be in use */
1552 else if(brick[bnum].used)
1554 /* these lines are used to describe the brick */
1555 line bot_brick, top_brick, left_brick, rght_brick;
1556 brickx = LEFTMARGIN + j*BRICK_WIDTH;
1558 /* Describe the brick for later collision checks */
1559 /* Setup the bottom of the brick */
1560 bot_brick.p1.x = brickx;
1561 bot_brick.p1.y = brick[bnum].powertop + BRICK_HEIGHT;
1563 bot_brick.p2.x = brickx + BRICK_WIDTH;
1564 bot_brick.p2.y = brick[bnum].powertop + BRICK_HEIGHT;
1566 /* Setup the top of the brick */
1567 top_brick.p1.x = brickx;
1568 top_brick.p1.y = brick[bnum].powertop;
1570 top_brick.p2.x = brickx + BRICK_WIDTH;
1571 top_brick.p2.y = brick[bnum].powertop;
1573 /* Setup the left of the brick */
1574 left_brick.p1.x = brickx;
1575 left_brick.p1.y = brick[bnum].powertop;
1577 left_brick.p2.x = brickx;
1578 left_brick.p2.y = brick[bnum].powertop + BRICK_HEIGHT;
1580 /* Setup the right of the brick */
1581 rght_brick.p1.x = brickx + BRICK_WIDTH;
1582 rght_brick.p1.y = brick[bnum].powertop;
1584 rght_brick.p2.x = brickx + BRICK_WIDTH;
1585 rght_brick.p2.y = brick[bnum].powertop + BRICK_HEIGHT;
1587 /* Check if any of the active fires hit a brick */
1588 for (k=0;k<30;k++)
1590 if(fire[k].top > 0)
1592 /* Use misc_line to check if fire hit brick */
1593 misc_line.p1.x = fire[k].x_pos;
1594 misc_line.p1.y = fire[k].top;
1596 misc_line.p2.x = fire[k].x_pos;
1597 misc_line.p2.y = fire[k].top + SPEED_FIRE;
1599 /* If the fire hit the brick take care of it */
1600 if (check_lines(&misc_line, &bot_brick,
1601 &pt_hit))
1603 score+=13;
1604 /* De-activate the fire */
1605 fire[k].top=-1;
1606 brick_hit(bnum);
1611 /* Draw the brick */
1612 rb->lcd_bitmap_part(brickmania_bricks,0,
1613 INT3(BRICK_HEIGHT)*brick[bnum].color,
1614 STRIDE( SCREEN_MAIN,
1615 BMPWIDTH_brickmania_bricks,
1616 BMPHEIGHT_brickmania_bricks),
1617 INT3(brickx),
1618 INT3(brick[bnum].powertop),
1619 INT3(BRICK_WIDTH), INT3(BRICK_HEIGHT) );
1621 #ifdef HAVE_LCD_COLOR /* No transparent effect for greyscale lcds for now */
1622 if (brick[bnum].hiteffect > 0)
1623 rb->lcd_bitmap_transparent_part(brickmania_break,0,
1624 INT3(BRICK_HEIGHT)*brick[bnum].hiteffect,
1625 STRIDE( SCREEN_MAIN,
1626 BMPWIDTH_brickmania_break,
1627 BMPHEIGHT_brickmania_break),
1628 INT3(brickx),
1629 INT3(brick[bnum].powertop),
1630 INT3(BRICK_WIDTH), INT3(BRICK_HEIGHT) );
1631 #endif
1633 /* Check if any balls collided with the brick */
1634 for(k=0; k<used_balls; k++)
1636 /* Setup the ball path to describe the current ball
1637 * position and the line it makes to its next
1638 * position.
1640 misc_line.p1.x = ball[k].pos_x;
1641 misc_line.p1.y = ball[k].pos_y;
1643 misc_line.p2.x = ball[k].pos_x + ball[k].speedx;
1644 misc_line.p2.y = ball[k].pos_y + ball[k].speedy;
1646 /* Check to see if the ball and the bottom hit. If
1647 * the ball is moving down we don't want to
1648 * include the bottom line intersection.
1650 * The order that the sides are checked matters.
1652 * Note that tempx/tempy store the next position
1653 * that the ball should be drawn.
1655 if(ball[k].speedy <= 0 &&
1656 check_lines(&misc_line, &bot_brick, &pt_hit))
1658 ball[k].speedy = -ball[k].speedy;
1659 ball[k].tempy = pt_hit.y;
1660 ball[k].tempx = pt_hit.x;
1661 brick_hit(bnum);
1663 /* Check the top, if the ball is moving up dont
1664 * count it as a hit.
1666 else if(ball[k].speedy > 0 &&
1667 check_lines(&misc_line, &top_brick, &pt_hit))
1669 ball[k].speedy = -ball[k].speedy;
1670 ball[k].tempy = pt_hit.y;
1671 ball[k].tempx = pt_hit.x;
1672 brick_hit(bnum);
1674 /* Check the left side of the brick */
1675 else if(
1676 check_lines(&misc_line, &left_brick, &pt_hit))
1678 ball[k].speedx = -ball[k].speedx;
1679 ball[k].tempy = pt_hit.y;
1680 ball[k].tempx = pt_hit.x;
1681 brick_hit(bnum);
1683 /* Check the right side of the brick */
1684 else if(
1685 check_lines(&misc_line, &rght_brick, &pt_hit))
1687 ball[k].speedx = -ball[k].speedx;
1688 ball[k].tempy = pt_hit.y;
1689 ball[k].tempx = pt_hit.x;
1690 brick_hit(bnum);
1692 } /* for k */
1693 } /* if(used) */
1695 } /* for j */
1696 } /* for i */
1698 /* draw the paddle according to the PAD_WIDTH */
1699 if( pad_width == PAD_WIDTH ) /* Normal width */
1701 rb->lcd_bitmap_part(
1702 brickmania_pads,
1703 0, pad_type*INT3(PAD_HEIGHT),
1704 STRIDE( SCREEN_MAIN, BMPWIDTH_brickmania_pads,
1705 BMPHEIGHT_brickmania_pads),
1706 INT3(pad_pos_x), INT3(PAD_POS_Y),
1707 INT3(pad_width), INT3(PAD_HEIGHT) );
1709 else if( pad_width == LONG_PAD_WIDTH ) /* Long Pad */
1711 rb->lcd_bitmap_part(
1712 brickmania_long_pads,
1713 0,pad_type*INT3(PAD_HEIGHT),
1714 STRIDE( SCREEN_MAIN, BMPWIDTH_brickmania_long_pads,
1715 BMPHEIGHT_brickmania_long_pads),
1716 INT3(pad_pos_x), INT3(PAD_POS_Y),
1717 INT3(pad_width), INT3(PAD_HEIGHT) );
1719 else /* Short pad */
1721 rb->lcd_bitmap_part(
1722 brickmania_short_pads,
1723 0,pad_type*INT3(PAD_HEIGHT),
1724 STRIDE( SCREEN_MAIN, BMPWIDTH_brickmania_short_pads,
1725 BMPHEIGHT_brickmania_short_pads),
1726 INT3(pad_pos_x), INT3(PAD_POS_Y),
1727 INT3(pad_width), INT3(PAD_HEIGHT) );
1730 /* If the game is not paused continue */
1731 if (game_state!=ST_PAUSE)
1733 /* Loop through all of the balls in play */
1734 for(k=0;k<used_balls;k++)
1736 line screen_edge;
1738 /* Describe the ball movement for the edge collision detection */
1739 misc_line.p1.x = ball[k].pos_x;
1740 misc_line.p1.y = ball[k].pos_y;
1742 misc_line.p2.x = ball[k].pos_x + ball[k].speedx;
1743 misc_line.p2.y = ball[k].pos_y + ball[k].speedy;
1745 /* Did the Ball hit the top of the screen? */
1746 screen_edge.p1.x = 0;
1747 screen_edge.p1.y = 0;
1749 screen_edge.p2.x = FIXED3(LCD_WIDTH);
1750 screen_edge.p2.y = 0;
1751 if (check_lines(&misc_line, &screen_edge, &pt_hit))
1753 ball[k].tempy = pt_hit.y + 1;
1754 ball[k].tempx = pt_hit.x;
1755 /* Reverse the direction */
1756 ball[k].speedy = -ball[k].speedy;
1759 /* Player missed the ball and hit bottom of screen */
1760 if (ball[k].pos_y >= GAMESCREEN_HEIGHT)
1762 /* Player had balls to spare, so handle the removal */
1763 if (used_balls>1)
1765 /* decrease number of balls in play */
1766 used_balls--;
1767 /* Replace removed ball with the last ball */
1768 ball[k].pos_x = ball[used_balls].pos_x;
1769 ball[k].pos_y = ball[used_balls].pos_y;
1770 ball[k].speedy = ball[used_balls].speedy;
1771 ball[k].tempy = ball[used_balls].tempy;
1772 ball[k].speedx = ball[used_balls].speedx;
1773 ball[k].tempx = ball[used_balls].tempx;
1774 ball[k].glue = ball[used_balls].glue;
1776 /* Reset the last ball that was removed */
1777 ball[used_balls].speedx=0;
1778 ball[used_balls].speedy=0;
1779 ball[used_balls].tempy=0;
1780 ball[used_balls].tempx=0;
1781 ball[used_balls].pos_y=PAD_POS_Y-BALL;
1782 ball[used_balls].pos_x=pad_pos_x+(pad_width/2)-2;
1784 k--;
1785 continue;
1787 else
1789 /* Player lost a life */
1790 life--;
1791 if (life>=0)
1793 /* No lives left reset game */
1794 brickmania_init_game(false);
1795 brickmania_sleep(2);
1796 rb->button_clear_queue();
1801 /* Check if the ball hit the left side */
1802 screen_edge.p1.x = 0;
1803 screen_edge.p1.y = 0;
1805 screen_edge.p2.x = 0;
1806 screen_edge.p2.y = FIXED3(LCD_HEIGHT);
1807 if ( check_lines(&misc_line, &screen_edge, &pt_hit))
1809 /* Reverse direction */
1810 ball[k].speedx = -ball[k].speedx;
1812 /* Re-position ball in gameboard */
1813 ball[k].tempy = pt_hit.y;
1814 ball[k].tempx = 0;
1817 /* Check if the ball hit the right side */
1818 screen_edge.p1.x = FIXED3(LCD_WIDTH);
1819 screen_edge.p1.y = 0;
1821 screen_edge.p2.x = FIXED3(LCD_WIDTH);
1822 screen_edge.p2.y = FIXED3(LCD_HEIGHT);
1823 if ( check_lines(&misc_line, &screen_edge, &pt_hit))
1825 /* Reverse direction */
1826 ball[k].speedx = -ball[k].speedx;
1828 /* Re-position ball in gameboard */
1829 ball[k].tempy = pt_hit.y;
1830 ball[k].tempx = FIXED3(LCD_WIDTH - 1);
1833 /* Did the ball hit the paddle? Depending on where the ball
1834 * Hit set the x/y speed appropriately.
1836 if( game_state!=ST_READY && !ball[k].glue &&
1837 check_lines(&misc_line, &pad_line, &pt_hit) )
1839 /* Re-position ball based on collision */
1840 ball[k].tempy = pt_hit.y - 1;
1841 ball[k].tempx = pt_hit.x;
1843 /* Calculate the ball position relative to the paddle width */
1844 int ball_repos = pt_hit.x - pad_pos_x;
1845 /* If the ball hits the right half of paddle, x speed
1846 * should be positive, if it hits the left half it
1847 * should be negative.
1849 int x_direction = -1;
1851 /* Comparisons are done with respect to 1/2 pad_width */
1852 if(ball_repos > pad_width/2)
1854 /* flip the relative position */
1855 ball_repos -= ((ball_repos - pad_width/2) << 1);
1856 /* Ball hit the right half so X speed calculations
1857 * should be positive.
1859 x_direction = 1;
1862 /* Figure out where the ball hit relative to 1/2 pad
1863 * and in divisions of 4.
1865 ball_repos = ball_repos / (pad_width/2/4);
1867 switch(ball_repos)
1869 /* Ball hit the outer edge of the paddle */
1870 case 0:
1871 ball[k].speedy = SPEED_1Q_Y;
1872 ball[k].speedx = SPEED_1Q_X * x_direction;
1873 break;
1874 /* Ball hit the next fourth of the paddle */
1875 case 1:
1876 ball[k].speedy = SPEED_2Q_Y;
1877 ball[k].speedx = SPEED_2Q_X * x_direction;
1878 break;
1879 /* Ball hit the third fourth of the paddle */
1880 case 2:
1881 ball[k].speedy = SPEED_3Q_Y;
1882 ball[k].speedx = SPEED_3Q_X * x_direction;
1883 break;
1884 /* Ball hit the fourth fourth of the paddle or dead
1885 * center.
1887 case 3:
1888 case 4:
1889 ball[k].speedy = SPEED_4Q_Y;
1890 /* Since this is the middle we don't want to
1891 * force the ball in a different direction.
1892 * Just keep it going in the same direction
1893 * with a specific speed.
1895 if(ball[k].speedx > 0)
1897 ball[k].speedx = SPEED_4Q_X;
1899 else
1901 ball[k].speedx = -SPEED_4Q_X;
1903 break;
1905 default:
1906 ball[k].speedy = SPEED_4Q_Y;
1907 break;
1910 if(pad_type == STICKY)
1912 ball[k].speedy = -ball[k].speedy;
1913 ball[k].glue=true;
1915 /* X location should not be forced since that is moved with the paddle. The Y
1916 * position should be forced to keep the ball at the paddle.
1918 ball[k].tempx = 0;
1919 ball[k].tempy = pt_hit.y - BALL;
1923 /* Update the ball position */
1924 if (!ball[k].glue)
1926 if(ball[k].tempx)
1927 ball[k].pos_x = ball[k].tempx;
1928 else
1929 ball[k].pos_x += ball[k].speedx;
1931 if(ball[k].tempy)
1932 ball[k].pos_y = ball[k].tempy;
1933 else
1934 ball[k].pos_y += ball[k].speedy;
1936 ball[k].tempy=0;
1937 ball[k].tempx=0;
1939 } /* for k */
1942 rb->lcd_update();
1944 if (brick_on_board < 0)
1946 if (level+1<levels_num)
1948 level++;
1949 if (difficulty==NORMAL)
1950 score+=100;
1951 brickmania_init_game(true);
1952 brickmania_sleep(2);
1953 rb->button_clear_queue();
1955 else
1957 rb->lcd_getstringsize("Congratulations!", &sw, NULL);
1958 rb->lcd_putsxy(LCD_WIDTH/2-sw/2, INT3(STRINGPOS_CONGRATS),
1959 "Congratulations!");
1960 #if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
1961 rb->lcd_getstringsize("No more levels", &sw, NULL);
1962 rb->lcd_putsxy(LCD_WIDTH/2-sw/2, INT3(STRINGPOS_FINISH),
1963 "No more levels");
1964 #else
1965 rb->lcd_getstringsize("You have finished the game!",
1966 &sw, NULL);
1967 rb->lcd_putsxy(LCD_WIDTH/2-sw/2, INT3(STRINGPOS_FINISH),
1968 "You have finished the game!");
1969 #endif
1970 vscore=score;
1971 rb->lcd_update();
1972 brickmania_sleep(2);
1973 return 0;
1977 int button=rb->button_get(false);
1978 int move_button = rb->button_status();
1980 #if defined(HAS_BUTTON_HOLD) && !defined(HAVE_REMOTE_LCD_AS_MAIN)
1981 /* FIXME: Should probably check remote hold here */
1982 if (rb->button_hold())
1983 button = QUIT;
1984 #endif
1986 #ifdef HAVE_TOUCHSCREEN
1987 if( move_button & BUTTON_TOUCHSCREEN)
1989 int data;
1990 short touch_x, touch_y;
1991 rb->button_status_wdata(&data);
1992 touch_x = FIXED3(data >> 16);
1993 touch_y = FIXED3(data & 0xffff);
1995 if(flip_sides)
1997 pad_pos_x = GAMESCREEN_WIDTH - (touch_x + pad_width/2);
1999 else
2001 pad_pos_x = (touch_x - pad_width/2);
2004 if(pad_pos_x < 0)
2005 pad_pos_x = 0;
2006 else if(pad_pos_x + pad_width > GAMESCREEN_WIDTH)
2007 pad_pos_x = GAMESCREEN_WIDTH-pad_width;
2008 for(k=0; k<used_balls; k++)
2009 if (game_state==ST_READY || ball[k].glue)
2010 ball[k].pos_x = pad_pos_x + pad_width/2;
2012 else
2013 #endif
2015 int button_right, button_left;
2016 #ifdef ALTRIGHT
2017 button_right = move_button & (RIGHT | ALTRIGHT);
2018 button_left = move_button & (LEFT | ALTLEFT);
2019 #else
2020 button_right =((move_button & RIGHT)|| SCROLL_FWD(button));
2021 button_left =((move_button & LEFT) ||SCROLL_BACK(button));
2022 #endif
2023 if ((game_state==ST_PAUSE) && (button_right || button_left))
2024 continue;
2025 if ((button_right && !flip_sides) ||
2026 (button_left && flip_sides))
2028 if (pad_pos_x+SPEED_PAD+pad_width > GAMESCREEN_WIDTH)
2030 for(k=0;k<used_balls;k++)
2031 if (game_state==ST_READY || ball[k].glue)
2032 ball[k].pos_x += GAMESCREEN_WIDTH-pad_pos_x -
2033 pad_width;
2034 pad_pos_x += GAMESCREEN_WIDTH - pad_pos_x - pad_width;
2036 else {
2037 for(k=0;k<used_balls;k++)
2038 if ((game_state==ST_READY || ball[k].glue))
2039 ball[k].pos_x+=SPEED_PAD;
2040 pad_pos_x+=SPEED_PAD;
2043 else if ((button_left && !flip_sides) ||
2044 (button_right && flip_sides))
2046 if (pad_pos_x-SPEED_PAD < 0)
2048 for(k=0;k<used_balls;k++)
2049 if (game_state==ST_READY || ball[k].glue)
2050 ball[k].pos_x-=pad_pos_x;
2051 pad_pos_x -= pad_pos_x;
2053 else
2055 for(k=0;k<used_balls;k++)
2056 if (game_state==ST_READY || ball[k].glue)
2057 ball[k].pos_x-=SPEED_PAD;
2058 pad_pos_x-=SPEED_PAD;
2063 switch(button)
2065 #if defined(HAVE_TOUCHSCREEN)
2066 case (BUTTON_REL | BUTTON_TOUCHSCREEN):
2067 #endif
2068 case UP:
2069 case SELECT:
2070 if (game_state==ST_READY)
2072 /* Initialize used balls starting speed */
2073 for(k=0 ; k < used_balls ; k++)
2075 ball[k].speedy = SPEED_4Q_Y;
2076 if(pad_pos_x + (pad_width/2) >= GAMESCREEN_WIDTH/2)
2078 ball[k].speedx = SPEED_4Q_X;
2080 else
2082 ball[k].speedx = -SPEED_4Q_X;
2085 game_state=ST_START;
2087 else if (game_state==ST_PAUSE)
2089 game_state=ST_START;
2091 else if (pad_type == STICKY)
2093 for(k=0;k<used_balls;k++)
2095 if (ball[k].glue)
2097 ball[k].glue=false;
2098 ball[k].speedy = -ball[k].speedy;
2102 else if (pad_type == SHOOTER)
2104 k=brickmania_find_empty_fire();
2105 fire[k].top=PAD_POS_Y - FIRE_LENGTH;
2106 fire[k].x_pos = pad_pos_x + 1; /* Add 1 for edge */
2108 k=brickmania_find_empty_fire();
2109 fire[k].top=PAD_POS_Y - FIRE_LENGTH;
2110 fire[k].x_pos = pad_pos_x + pad_width -1; /* Sub1 edge*/
2112 break;
2113 #ifdef RC_QUIT
2114 case RC_QUIT:
2115 #endif
2116 case QUIT:
2117 resume = true;
2118 return 0;
2119 break;
2121 default:
2122 if(rb->default_event_handler(button) == SYS_USB_CONNECTED)
2123 return 1;
2124 break;
2127 else
2129 #ifdef HAVE_LCD_COLOR
2130 rb->lcd_bitmap_transparent(brickmania_gameover,
2131 (LCD_WIDTH - INT3(GAMEOVER_WIDTH))/2,
2132 INT3(GAMESCREEN_HEIGHT - GAMEOVER_HEIGHT)/2,
2133 INT3(GAMEOVER_WIDTH),INT3(GAMEOVER_HEIGHT));
2134 #else /* greyscale and mono */
2135 rb->lcd_bitmap(brickmania_gameover,(LCD_WIDTH -
2136 INT3(GAMEOVER_WIDTH))/2,
2137 INT3(GAMESCREEN_HEIGHT - GAMEOVER_HEIGHT)/2,
2138 INT3(GAMEOVER_WIDTH),INT3(GAMEOVER_HEIGHT) );
2139 #endif
2140 rb->lcd_update();
2141 brickmania_sleep(2);
2142 return 0;
2145 /* Game always needs to yield for other threads */
2146 rb->yield();
2148 /* Sleep for a bit if there is time to spare */
2149 if (TIME_BEFORE(*rb->current_tick, end))
2150 rb->sleep(end-*rb->current_tick);
2152 return 0;
2155 /* this is the plugin entry point */
2156 enum plugin_status plugin_start(const void* parameter)
2158 (void)parameter;
2159 int last_difficulty;
2161 highscore_load(HIGH_SCORE,highest,NUM_SCORES);
2162 configfile_load(CONFIG_FILE_NAME,config,1,0);
2163 last_difficulty = difficulty;
2165 #ifdef HAVE_TOUCHSCREEN
2166 rb->touchscreen_set_mode(TOUCHSCREEN_POINT);
2167 #endif
2169 rb->lcd_setfont(FONT_SYSFIXED);
2170 #if LCD_DEPTH > 1
2171 rb->lcd_set_backdrop(NULL);
2172 #endif
2173 /* Turn off backlight timeout */
2174 backlight_force_on(); /* backlight control in lib/helper.c */
2176 /* now go ahead and have fun! */
2177 rb->srand( *rb->current_tick );
2178 brickmania_loadgame();
2179 resume_file = resume;
2180 while(!brickmania_game_loop())
2182 if(!resume)
2184 int position = highscore_update(score, level+1, "", highest,
2185 NUM_SCORES);
2186 if (position == 0)
2188 rb->splash(HZ*2, "New High Score");
2191 if (position != -1)
2193 highscore_show(position, highest, NUM_SCORES, true);
2195 else
2197 brickmania_sleep(3);
2202 highscore_save(HIGH_SCORE,highest,NUM_SCORES);
2203 if(last_difficulty != difficulty)
2204 configfile_save(CONFIG_FILE_NAME,config,1,0);
2205 /* Restore user's original backlight setting */
2206 rb->lcd_setfont(FONT_UI);
2207 /* Turn on backlight timeout (revert to settings) */
2208 backlight_use_settings(); /* backlight control in lib/helper.c */
2210 return PLUGIN_OK;