Snake2: Add support for 640x480 screens
[kugel-rb.git] / apps / plugins / snake2.c
blob771e3850997f672e4be9d01e98a46d244bb9bf1c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2003 Mat Holton
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 Snake2!
25 Board consists of a WIDTHxHEIGHT grid. If board element is 0 then nothing is
26 there otherwise it is part of the snake or a wall.
28 Head and Tail are stored
32 #include "plugin.h"
33 #ifdef HAVE_LCD_BITMAP
35 PLUGIN_HEADER
37 #define WIDTH 28
38 #define HEIGHT 16
40 #if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) && (LCD_DEPTH >= 1)
41 #include "pluginbitmaps/snake2_header1.h"
42 #include "pluginbitmaps/snake2_header2.h"
43 #include "pluginbitmaps/snake2_left.h"
44 #include "pluginbitmaps/snake2_right.h"
45 #include "pluginbitmaps/snake2_bottom.h"
46 #define BMPHEIGHT_snake2_header BMPHEIGHT_snake2_header1
47 #define BMPWIDTH_snake2_header BMPWIDTH_snake2_header1
48 #endif
50 #if (LCD_WIDTH >= 640) && (LCD_HEIGHT >= 480)
51 #define MULTIPLIER 20 /*Modifier for porting on other screens*/
52 #define MODIFIER_1 20
53 #define MODIFIER_2 16
54 #define CENTER_X 40
55 #define CENTER_Y 110
56 #define TOP_X1 68 /* x-coord of the upperleft item (game type) */
57 #define TOP_X2 562 /* x-coord of the upperright item (maze type) */
58 #define TOP_X3 84 /* x-coord of the lowerleft item (speed) */
59 #define TOP_X4 548 /* x-coord of the lowerright item (hi-score) */
60 #define TOP_Y1 8 /* y-coord of the top row of items */
61 #define TOP_Y2 50 /* y-coord of the bottom row of items */
62 #elif (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240)
63 #define MULTIPLIER 10 /*Modifier for porting on other screens*/
64 #define MODIFIER_1 10
65 #define MODIFIER_2 8
66 #define CENTER_X 20
67 #define CENTER_Y 55
68 #define TOP_X1 34 /* x-coord of the upperleft item (game type) */
69 #define TOP_X2 281 /* x-coord of the upperright item (maze type) */
70 #define TOP_X3 42 /* x-coord of the lowerleft item (speed) */
71 #define TOP_X4 274 /* x-coord of the lowerright item (hi-score) */
72 #define TOP_Y1 4 /* y-coord of the top row of items */
73 #define TOP_Y2 25 /* y-coord of the bottom row of items */
74 #elif (LCD_WIDTH >= 240) && (LCD_HEIGHT >= 168)
75 #define MULTIPLIER 8
76 #define MODIFIER_1 8
77 #define MODIFIER_2 6
78 #define CENTER_X 8
79 #define CENTER_Y 34
80 #define TOP_X1 34
81 #define TOP_X2 201
82 #define TOP_X3 42
83 #define TOP_X4 194
84 #define TOP_Y1 4
85 #define TOP_Y2 25
86 #elif (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176)
87 #define MULTIPLIER 7
88 #define MODIFIER_1 7
89 #define MODIFIER_2 5
90 #define CENTER_X 12
91 #define CENTER_Y 46
92 #define TOP_X1 34
93 #define TOP_X2 181
94 #define TOP_X3 42
95 #define TOP_X4 174
96 #define TOP_Y1 4
97 #define TOP_Y2 25
98 #elif (LCD_WIDTH >= 176) && (LCD_HEIGHT >= 132)
99 #define MULTIPLIER 5
100 #define MODIFIER_1 5
101 #define MODIFIER_2 3
102 #define CENTER_X 18
103 #define CENTER_Y 40
104 #define TOP_X1 34
105 #define TOP_X2 137
106 #define TOP_X3 42
107 #define TOP_X4 130
108 #define TOP_Y1 4
109 #define TOP_Y2 25
110 #elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128)
111 #define MULTIPLIER 5
112 #define MODIFIER_1 5
113 #define MODIFIER_2 3
114 #define CENTER_X 10
115 #define CENTER_Y 38
116 #define TOP_X1 34
117 #define TOP_X2 121
118 #define TOP_X3 42
119 #define TOP_X4 114
120 #define TOP_Y1 4
121 #define TOP_Y2 25
122 #else
123 #define MULTIPLIER 4
124 #define MODIFIER_1 4
125 #define MODIFIER_2 2
126 #define CENTER_X 0
127 #define CENTER_Y 0
129 #endif
131 /* variable button definitions */
132 #if CONFIG_KEYPAD == RECORDER_PAD
133 #define SNAKE2_LEFT BUTTON_LEFT
134 #define SNAKE2_RIGHT BUTTON_RIGHT
135 #define SNAKE2_UP BUTTON_UP
136 #define SNAKE2_DOWN BUTTON_DOWN
137 #define SNAKE2_QUIT BUTTON_OFF
138 #define SNAKE2_LEVEL_UP BUTTON_UP
139 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
140 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
141 #define SNAKE2_MAZE_LAST BUTTON_LEFT
142 #define SNAKE2_SELECT_TYPE BUTTON_F3
143 #define SNAKE2_PLAYPAUSE BUTTON_PLAY
144 #define SNAKE2_PLAYPAUSE_TEXT "Play"
146 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
147 #define SNAKE2_LEFT BUTTON_LEFT
148 #define SNAKE2_RIGHT BUTTON_RIGHT
149 #define SNAKE2_UP BUTTON_UP
150 #define SNAKE2_DOWN BUTTON_DOWN
151 #define SNAKE2_QUIT BUTTON_OFF
152 #define SNAKE2_LEVEL_UP BUTTON_UP
153 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
154 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
155 #define SNAKE2_MAZE_LAST BUTTON_LEFT
156 #define SNAKE2_SELECT_TYPE BUTTON_F3
157 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
158 #define SNAKE2_PLAYPAUSE_TEXT "Select"
160 #elif CONFIG_KEYPAD == ONDIO_PAD
161 #define SNAKE2_LEFT BUTTON_LEFT
162 #define SNAKE2_RIGHT BUTTON_RIGHT
163 #define SNAKE2_UP BUTTON_UP
164 #define SNAKE2_DOWN BUTTON_DOWN
165 #define SNAKE2_QUIT BUTTON_OFF
166 #define SNAKE2_LEVEL_UP BUTTON_UP
167 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
168 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
169 #define SNAKE2_SELECT_TYPE BUTTON_LEFT
170 #define SNAKE2_PLAYPAUSE BUTTON_MENU
171 #define SNAKE2_PLAYPAUSE_TEXT "Menu"
173 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
174 (CONFIG_KEYPAD == IRIVER_H300_PAD)
175 #define SNAKE2_LEFT BUTTON_LEFT
176 #define SNAKE2_RIGHT BUTTON_RIGHT
177 #define SNAKE2_UP BUTTON_UP
178 #define SNAKE2_DOWN BUTTON_DOWN
179 #define SNAKE2_QUIT BUTTON_OFF
180 #define SNAKE2_LEVEL_UP BUTTON_UP
181 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
182 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
183 #define SNAKE2_MAZE_LAST BUTTON_LEFT
184 #define SNAKE2_SELECT_TYPE BUTTON_MODE
185 #define SNAKE2_PLAYPAUSE BUTTON_ON
186 #define SNAKE2_PLAYPAUSE_TEXT "Play"
188 #define SNAKE2_RC_QUIT BUTTON_RC_STOP
189 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
190 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
191 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
192 #define SNAKE2_LEFT BUTTON_LEFT
193 #define SNAKE2_RIGHT BUTTON_RIGHT
194 #define SNAKE2_UP BUTTON_MENU
195 #define SNAKE2_DOWN BUTTON_PLAY
196 #define SNAKE2_QUIT (BUTTON_SELECT | BUTTON_MENU)
197 #define SNAKE2_LEVEL_UP BUTTON_SCROLL_FWD
198 #define SNAKE2_LEVEL_DOWN BUTTON_SCROLL_BACK
199 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
200 #define SNAKE2_MAZE_LAST BUTTON_LEFT
201 #define SNAKE2_SELECT_TYPE BUTTON_PLAY
202 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
203 #define SNAKE2_PLAYPAUSE_TEXT "Select"
205 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
206 #define SNAKE2_LEFT BUTTON_LEFT
207 #define SNAKE2_RIGHT BUTTON_RIGHT
208 #define SNAKE2_UP BUTTON_UP
209 #define SNAKE2_DOWN BUTTON_DOWN
210 #define SNAKE2_QUIT BUTTON_POWER
211 #define SNAKE2_LEVEL_UP BUTTON_UP
212 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
213 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
214 #define SNAKE2_MAZE_LAST BUTTON_LEFT
215 #define SNAKE2_SELECT_TYPE BUTTON_PLAY
216 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
217 #define SNAKE2_PLAYPAUSE_TEXT "Select"
219 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
220 #define SNAKE2_LEFT BUTTON_LEFT
221 #define SNAKE2_RIGHT BUTTON_RIGHT
222 #define SNAKE2_UP BUTTON_UP
223 #define SNAKE2_DOWN BUTTON_DOWN
224 #define SNAKE2_QUIT BUTTON_POWER
225 #define SNAKE2_LEVEL_UP BUTTON_UP
226 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
227 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
228 #define SNAKE2_MAZE_LAST BUTTON_LEFT
229 #define SNAKE2_SELECT_TYPE BUTTON_MENU
230 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
231 #define SNAKE2_PLAYPAUSE_TEXT "Select"
233 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
234 (CONFIG_KEYPAD == SANSA_C200_PAD)
235 #define SNAKE2_LEFT BUTTON_LEFT
236 #define SNAKE2_RIGHT BUTTON_RIGHT
237 #define SNAKE2_UP BUTTON_UP
238 #define SNAKE2_DOWN BUTTON_DOWN
239 #define SNAKE2_QUIT BUTTON_POWER
240 #define SNAKE2_LEVEL_UP BUTTON_UP
241 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
242 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
243 #define SNAKE2_MAZE_LAST BUTTON_LEFT
244 #define SNAKE2_SELECT_TYPE BUTTON_REC
245 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
246 #define SNAKE2_PLAYPAUSE_TEXT "Select"
248 #elif (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
249 (CONFIG_KEYPAD == SANSA_M200_PAD)
250 #define SNAKE2_LEFT BUTTON_LEFT
251 #define SNAKE2_RIGHT BUTTON_RIGHT
252 #define SNAKE2_UP BUTTON_UP
253 #define SNAKE2_DOWN BUTTON_DOWN
254 #define SNAKE2_QUIT BUTTON_POWER
255 #define SNAKE2_LEVEL_UP BUTTON_UP
256 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
257 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
258 #define SNAKE2_MAZE_LAST BUTTON_LEFT
259 #define SNAKE2_SELECT_TYPE BUTTON_VOL_UP
260 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
261 #define SNAKE2_PLAYPAUSE_TEXT "Select"
263 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
264 #define SNAKE2_LEFT BUTTON_LEFT
265 #define SNAKE2_RIGHT BUTTON_RIGHT
266 #define SNAKE2_UP BUTTON_UP
267 #define SNAKE2_DOWN BUTTON_DOWN
268 #define SNAKE2_QUIT (BUTTON_HOME|BUTTON_REPEAT)
269 #define SNAKE2_LEVEL_UP BUTTON_UP
270 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
271 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
272 #define SNAKE2_MAZE_LAST BUTTON_LEFT
273 #define SNAKE2_SELECT_TYPE BUTTON_SELECT|BUTTON_REL
274 #define SNAKE2_PLAYPAUSE BUTTON_SELECT|BUTTON_REPEAT
275 #define SNAKE2_PLAYPAUSE_TEXT "Hold Select"
277 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
278 #define SNAKE2_LEFT BUTTON_LEFT
279 #define SNAKE2_RIGHT BUTTON_RIGHT
280 #define SNAKE2_UP BUTTON_SCROLL_UP
281 #define SNAKE2_DOWN BUTTON_SCROLL_DOWN
282 #define SNAKE2_QUIT BUTTON_POWER
283 #define SNAKE2_LEVEL_UP BUTTON_SCROLL_UP
284 #define SNAKE2_LEVEL_DOWN BUTTON_SCROLL_DOWN
285 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
286 #define SNAKE2_MAZE_LAST BUTTON_LEFT
287 #define SNAKE2_SELECT_TYPE BUTTON_PLAY
288 #define SNAKE2_PLAYPAUSE BUTTON_FF
289 #define SNAKE2_PLAYPAUSE_TEXT "FF"
291 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
292 #define SNAKE2_LEFT BUTTON_LEFT
293 #define SNAKE2_RIGHT BUTTON_RIGHT
294 #define SNAKE2_UP BUTTON_UP
295 #define SNAKE2_DOWN BUTTON_DOWN
296 #define SNAKE2_QUIT BUTTON_BACK
297 #define SNAKE2_LEVEL_UP BUTTON_UP
298 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
299 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
300 #define SNAKE2_MAZE_LAST BUTTON_LEFT
301 #define SNAKE2_SELECT_TYPE BUTTON_MENU
302 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
303 #define SNAKE2_PLAYPAUSE_TEXT "Select"
305 #elif (CONFIG_KEYPAD == MROBE100_PAD)
306 #define SNAKE2_LEFT BUTTON_LEFT
307 #define SNAKE2_RIGHT BUTTON_RIGHT
308 #define SNAKE2_UP BUTTON_UP
309 #define SNAKE2_DOWN BUTTON_DOWN
310 #define SNAKE2_QUIT BUTTON_POWER
311 #define SNAKE2_LEVEL_UP BUTTON_UP
312 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
313 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
314 #define SNAKE2_MAZE_LAST BUTTON_LEFT
315 #define SNAKE2_SELECT_TYPE BUTTON_MENU
316 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
317 #define SNAKE2_PLAYPAUSE_TEXT "Select"
319 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
320 #define SNAKE2_LEFT BUTTON_RC_REW
321 #define SNAKE2_RIGHT BUTTON_RC_FF
322 #define SNAKE2_UP BUTTON_RC_VOL_UP
323 #define SNAKE2_DOWN BUTTON_RC_VOL_DOWN
324 #define SNAKE2_QUIT BUTTON_RC_REC
325 #define SNAKE2_LEVEL_UP BUTTON_RC_VOL_UP
326 #define SNAKE2_LEVEL_DOWN BUTTON_RC_VOL_DOWN
327 #define SNAKE2_MAZE_NEXT BUTTON_RC_FF
328 #define SNAKE2_MAZE_LAST BUTTON_RC_REW
329 #define SNAKE2_SELECT_TYPE BUTTON_RC_MODE
330 #define SNAKE2_PLAYPAUSE BUTTON_RC_PLAY
331 #define SNAKE2_PLAYPAUSE_TEXT "Play"
333 #elif (CONFIG_KEYPAD == COWOND2_PAD)
334 #define SNAKE2_QUIT BUTTON_POWER
336 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
337 #define SNAKE2_LEFT BUTTON_LEFT
338 #define SNAKE2_RIGHT BUTTON_RIGHT
339 #define SNAKE2_UP BUTTON_UP
340 #define SNAKE2_DOWN BUTTON_DOWN
341 #define SNAKE2_QUIT BUTTON_BACK
342 #define SNAKE2_LEVEL_UP BUTTON_UP
343 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
344 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
345 #define SNAKE2_MAZE_LAST BUTTON_LEFT
346 #define SNAKE2_SELECT_TYPE BUTTON_MENU
347 #define SNAKE2_PLAYPAUSE BUTTON_PLAY
348 #define SNAKE2_PLAYPAUSE_TEXT "Play"
350 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
351 #define SNAKE2_LEFT BUTTON_LEFT
352 #define SNAKE2_RIGHT BUTTON_RIGHT
353 #define SNAKE2_UP BUTTON_UP
354 #define SNAKE2_DOWN BUTTON_DOWN
355 #define SNAKE2_QUIT BUTTON_POWER
356 #define SNAKE2_LEVEL_UP BUTTON_UP
357 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
358 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
359 #define SNAKE2_MAZE_LAST BUTTON_LEFT
360 #define SNAKE2_SELECT_TYPE BUTTON_MENU
361 #define SNAKE2_PLAYPAUSE BUTTON_VIEW
362 #define SNAKE2_PLAYPAUSE_TEXT "View"
364 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || CONFIG_KEYPAD == MROBE500_PAD
365 #define SNAKE2_QUIT BUTTON_POWER
367 #else
368 #error No keymap defined!
369 #endif
371 #ifdef HAVE_TOUCHSCREEN
372 #ifndef SNAKE2_LEFT
373 #define SNAKE2_LEFT BUTTON_MIDLEFT
374 #endif
375 #ifndef SNAKE2_RIGHT
376 #define SNAKE2_RIGHT BUTTON_MIDRIGHT
377 #endif
378 #ifndef SNAKE2_UP
379 #define SNAKE2_UP BUTTON_TOPMIDDLE
380 #endif
381 #ifndef SNAKE2_DOWN
382 #define SNAKE2_DOWN BUTTON_BOTTOMMIDDLE
383 #endif
384 #ifndef SNAKE2_QUIT
385 #define SNAKE2_QUIT BUTTON_TOPLEFT
386 #endif
387 #ifndef SNAKE2_LEVEL_UP
388 #define SNAKE2_LEVEL_UP BUTTON_TOPRIGHT
389 #endif
390 #ifndef SNAKE2_LEVEL_DOWN
391 #define SNAKE2_LEVEL_DOWN BUTTON_TOPLEFT
392 #endif
393 #ifndef SNAKE2_MAZE_NEXT
394 #define SNAKE2_MAZE_NEXT BUTTON_TOPMIDDLE
395 #endif
396 #ifndef SNAKE2_MAZE_LAST
397 #define SNAKE2_MAZE_LAST BUTTON_BOTTOMMIDDLE
398 #endif
399 #ifndef SNAKE2_SELECT_TYPE
400 #define SNAKE2_SELECT_TYPE BUTTON_BOTTOMLEFT
401 #endif
402 #ifndef SNAKE2_PLAYPAUSE
403 #define SNAKE2_PLAYPAUSE BUTTON_CENTER
404 #endif
405 #ifndef SNAKE2_PLAYPAUSE_TEXT
406 #define SNAKE2_PLAYPAUSE_TEXT "CENTER"
407 #endif
408 #endif
410 static int max_levels = 0;
411 static char (*level_cache)[HEIGHT][WIDTH];
413 /*Board itself - 2D int array*/
414 static int board[WIDTH][HEIGHT];
416 Buffer for sorting movement (in case user presses two movements during a
417 single frame
419 static int ardirectionbuffer[2];
420 static unsigned int score, hiscore = 0;
421 static int applex;
422 static int appley;
423 static int strwdt,strhgt; /*used for string width, height for orientation purposes*/
424 static int dir;
425 static int frames;
426 static int apple;
427 static int level = 4, speed = 5,dead = 0, quit = 0;
428 static int sillydir = 0, num_levels = 0;
429 static int level_from_file = 0;
430 static int headx, heady, tailx, taily, applecountdown = 5;
431 static int game_type = 0;
432 static int num_apples_to_get=1;
433 static int num_apples_to_got=0;
434 static int game_b_level=0;
435 static int applecount=0;
436 static char phscore[30];
438 #define NORTH 1
439 #define EAST 2
440 #define SOUTH 4
441 #define WEST 8
442 #define HEAD 16
444 #define EAST_NORTH 32
445 #define EAST_SOUTH 64
446 #define WEST_NORTH 128
447 #define WEST_SOUTH 256
449 #define NORTH_EAST 512
450 #define NORTH_WEST 1024
451 #define SOUTH_EAST 2048
452 #define SOUTH_WEST 4096
454 #define LEVELS_FILE PLUGIN_GAMES_DIR "/snake2.levels"
455 #define HISCORE_FILE PLUGIN_GAMES_DIR "/snake2.hs"
457 int load_all_levels(void)
459 int linecnt = 0;
460 int fd;
461 ssize_t size;
462 char buf[64]; /* Larger than WIDTH, to allow for whitespace after the
463 lines */
465 /* Init the level_cache pointer and
466 calculate how many levels that will fit */
467 level_cache = rb->plugin_get_buffer((size_t *)&size);
468 max_levels = size / (HEIGHT*WIDTH);
470 num_levels = 0;
472 /* open file */
473 if ((fd = rb->open(LEVELS_FILE, O_RDONLY)) < 0)
475 return -1;
478 while(rb->read_line(fd, buf, 64))
480 if(rb->strlen(buf) == 0) /* Separator? */
482 num_levels++;
483 if(num_levels > max_levels)
485 rb->splash(HZ, "Too many levels in file");
486 break;
488 continue;
491 rb->memcpy(level_cache[num_levels][linecnt], buf, WIDTH);
492 linecnt++;
493 if(linecnt == HEIGHT)
495 linecnt = 0;
499 rb->close(fd);
500 return 0;
503 /*Hi-Score reading and writing to file "/.rockbox/rocks/games/snake2.levels" function */
504 void iohiscore(void)
506 int fd;
507 unsigned int compare;
509 /* clear the buffer we're about to load the highscore data into */
510 rb->memset(phscore, 0, sizeof(phscore));
512 fd = rb->open(HISCORE_FILE,O_RDWR | O_CREAT);
514 /* highscore used to %d, is now %d\n
515 Deal with no file or bad file */
516 rb->read(fd,phscore, sizeof(phscore));
518 compare = rb->atoi(phscore);
520 if(hiscore > compare){
521 rb->lseek(fd,0,SEEK_SET);
522 rb->fdprintf(fd, "%d\n", hiscore);
524 else
525 hiscore = compare;
527 rb->close(fd);
532 ** Completely clear the board of walls and/or snake */
534 void clear_board( void)
536 int x,y;
538 for (x = 0; x < WIDTH; x++)
540 for (y = 0; y < HEIGHT; y++)
542 board[x][y] = 0;
547 int load_level( int level_number )
549 int x,y;
550 clear_board();
551 for(y = 0;y < HEIGHT;y++)
553 for(x = 0;x < WIDTH;x++)
555 switch(level_cache[level_number][y][x])
557 case '|':
558 board[x][y] = NORTH;
559 break;
561 case '-':
562 board[x][y] = EAST;
563 break;
565 case '+':
566 board[x][y] = HEAD;
567 break;
571 return 1;
575 ** Gets the currently chosen direction from the first place
576 ** in the direction buffer. If there is something in the
577 ** next part of the buffer then that is moved to the first place
579 void get_direction( void )
581 /*if 1st place is empty*/
582 if(ardirectionbuffer[0] != -1)
584 /*return this direction*/
585 dir = ardirectionbuffer[0];
586 ardirectionbuffer[0]=-1;
587 /*now see if one needs moving:*/
588 if(ardirectionbuffer[1] != -1)
590 /*there's a move waiting to be done
591 so move it into the space:*/
592 ardirectionbuffer[0] = ardirectionbuffer[1];
593 ardirectionbuffer[1] = -1;
599 ** Sets the direction
601 void set_direction(int newdir)
603 if(ardirectionbuffer[0] != newdir)
605 /*if 1st place is empty*/
606 if(ardirectionbuffer[0] == -1)
608 /*use 1st space:*/
609 ardirectionbuffer[0] = newdir;
611 else
613 /*use 2nd space:*/
614 if(ardirectionbuffer[0] != newdir) ardirectionbuffer[1] = newdir;
617 if(frames < 0) ardirectionbuffer[0] = newdir;
621 void new_level(int level)
623 load_level(level);
625 ardirectionbuffer[0] = -1;
626 ardirectionbuffer[1] = -1;
627 dir = EAST;
628 headx = WIDTH/2;
629 heady = HEIGHT/2;
630 tailx = headx - 4;
631 taily = heady;
632 applecountdown = 0;
633 /*Create a small snake to start off with*/
634 board[headx][heady] = dir;
635 board[headx-1][heady] = dir;
636 board[headx-2][heady] = dir;
637 board[headx-3][heady] = dir;
638 board[headx-4][heady] = dir;
639 num_apples_to_got=0;
642 void init_snake(void)
644 num_apples_to_get=1;
645 if(game_type == 1)
646 level_from_file = 1;
647 game_b_level=1;
648 new_level(level_from_file);
652 ** Draws the apple. If it doesn't exist then
653 ** a new one get's created.
655 void draw_apple( void )
657 int x,y;
659 #if LCD_WIDTH >= 160 && LCD_HEIGHT >= 128
660 char pscore[5], counter[4];
662 rb->lcd_bitmap(snake2_header2,0,0,BMPWIDTH_snake2_header, BMPHEIGHT_snake2_header);
663 rb->lcd_bitmap(snake2_left,0,BMPHEIGHT_snake2_header,BMPWIDTH_snake2_left, BMPHEIGHT_snake2_left);
664 rb->lcd_bitmap(snake2_right,LCD_WIDTH-BMPWIDTH_snake2_right,BMPHEIGHT_snake2_header,BMPWIDTH_snake2_right, BMPHEIGHT_snake2_right);
665 rb->lcd_bitmap(snake2_bottom,0,BMPHEIGHT_snake2_header+BMPHEIGHT_snake2_left,BMPWIDTH_snake2_bottom, BMPHEIGHT_snake2_bottom);
667 rb->snprintf(counter,sizeof(counter),"%d",applecount);
668 rb->lcd_getstringsize(counter,&strwdt,&strhgt);
669 rb->lcd_putsxy(TOP_X3-strwdt/2,TOP_Y2,counter);
671 rb->snprintf(pscore,sizeof(pscore),"%d",score);
672 rb->lcd_getstringsize(pscore,&strwdt,&strhgt);
673 rb->lcd_putsxy(TOP_X4-strwdt/2,TOP_Y2,pscore);
674 #endif
676 if (!apple)
680 x = (rb->rand() % (WIDTH-1))+1;
681 y = (rb->rand() % (HEIGHT-1))+1;
682 } while (board[x][y]);
683 apple=1;
684 board[x][y]=-1;
685 applex = x;appley = y;
687 rb->lcd_fillrect((CENTER_X+applex*MULTIPLIER)+1,CENTER_Y+appley*MULTIPLIER,MODIFIER_2,MODIFIER_1);
688 rb->lcd_fillrect(CENTER_X+applex*MULTIPLIER,(CENTER_Y+appley*MULTIPLIER)+1,MODIFIER_1,MODIFIER_2);
692 * x x *
693 * x x *
694 * x x *
695 * x x *
697 void draw_vertical_bit(int x, int y)
699 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+1,CENTER_Y+y*MULTIPLIER,MODIFIER_2,MODIFIER_1);
703 * * * *
704 X X X X
705 X X X X
706 * * * *
708 void draw_horizontal_bit(int x, int y)
710 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER,CENTER_Y+y*MULTIPLIER+1,MODIFIER_1,MODIFIER_2);
714 * * * *
715 * * X X
716 * X X X
717 * X X *
719 void draw_n_to_e_bit(int x, int y)
721 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+1,CENTER_Y+y*MULTIPLIER+2,MODIFIER_2,MODIFIER_2);
722 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+2,CENTER_Y+y*MULTIPLIER+1,MODIFIER_2,MODIFIER_2);
726 * * * *
727 * * X X
728 * X X X
729 * X X *
731 void draw_w_to_s_bit(int x, int y)
733 draw_n_to_e_bit(x,y);
737 * * * *
738 X X * *
739 X X X *
740 * X X *
742 void draw_n_to_w_bit(int x, int y)
744 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER,CENTER_Y+y*MULTIPLIER+1,MODIFIER_2,MODIFIER_2);
745 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+1,CENTER_Y+y*MULTIPLIER+2,MODIFIER_2,MODIFIER_2);
749 * * * *
750 X X * *
751 X X X *
752 * X X *
754 void draw_e_to_s_bit(int x, int y)
756 draw_n_to_w_bit(x, y);
760 * X X *
761 * X X X
762 * * X X
763 * * * *
765 void draw_s_to_e_bit(int x, int y)
767 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+1,CENTER_Y+y*MULTIPLIER,MODIFIER_2,MODIFIER_2);
768 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+2,CENTER_Y+y*MULTIPLIER+1,MODIFIER_2,MODIFIER_2);
772 * X X *
773 * X X X
774 * * X X
775 * * * *
777 void draw_w_to_n_bit(int x, int y)
779 draw_s_to_e_bit(x,y);
783 * X X *
784 X X X *
785 X X * *
786 * * * *
788 void draw_e_to_n_bit(int x, int y)
790 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER+1,CENTER_Y+y*MULTIPLIER,MODIFIER_2,MODIFIER_2);
791 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER,CENTER_Y+y*MULTIPLIER+1,MODIFIER_2,MODIFIER_2);
795 * X X *
796 X X X *
797 X X * *
798 * * * *
800 void draw_s_to_w_bit(int x, int y)
802 draw_e_to_n_bit(x, y);
806 ** Draws a wall/obsticals
808 void draw_boundary ( void )
810 int x, y;
812 /*TODO: Load levels from file!*/
814 /*top and bottom line*/
815 for(x=0; x < WIDTH; x++)
817 board[x][0] = EAST;
818 board[x][HEIGHT-1] = WEST;
821 /*left and right lines*/
822 for(y=0; y < HEIGHT; y++)
824 board[0][y] = NORTH;
825 board[WIDTH-1][y] = SOUTH;
828 /*corners:*/
829 board[0][0] = NORTH_EAST;
830 board[WIDTH-1][0] = EAST_SOUTH;
831 board[0][HEIGHT-1] = SOUTH_EAST;
832 board[WIDTH-1][HEIGHT-1] = EAST_NORTH;
836 ** Redraw the entire board
838 void redraw (void)
840 int x,y;
842 for (x = 0; x < WIDTH; x++)
844 for (y = 0; y < HEIGHT; y++)
846 switch (board[x][y])
848 case -1:
849 rb->lcd_fillrect((CENTER_X+x*MULTIPLIER)+1,CENTER_Y+y*MULTIPLIER,MODIFIER_2,MODIFIER_1);
850 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER,(CENTER_Y+y*MULTIPLIER)+1,MODIFIER_1,MODIFIER_2);
851 break;
852 case 0:
853 break;
855 case NORTH:
856 case SOUTH:
857 draw_vertical_bit(x,y);
858 break;
860 case EAST:
861 case WEST:
862 draw_horizontal_bit(x,y);
863 break;
865 default:
866 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER,CENTER_Y+y*MULTIPLIER,MODIFIER_1,MODIFIER_1);
867 break;
874 ** Draws the snake bit described by nCurrentBit at position x/y
875 ** deciding whether it's a corner bit by examing the nPrevious bit
877 void draw_snake_bit(int currentbit, int previousbit, int x, int y)
879 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
880 rb->lcd_fillrect(CENTER_X+x*MULTIPLIER,CENTER_Y+y*MULTIPLIER,MODIFIER_1,MODIFIER_1);
881 rb->lcd_set_drawmode(DRMODE_SOLID);
883 switch(currentbit)
885 case(NORTH):
886 switch(previousbit)
888 case(SOUTH):
889 case(NORTH):
890 draw_vertical_bit(x,y);
891 break;
893 case(EAST):
894 draw_e_to_n_bit(x,y);
895 break;
897 case(WEST):
898 draw_w_to_n_bit(x,y);
899 break;
901 break;
903 case(EAST):
904 switch(previousbit)
906 case(WEST):
907 case(EAST):
908 draw_horizontal_bit(x,y);
909 break;
911 case(NORTH):
912 draw_n_to_e_bit(x,y);
913 break;
915 case(SOUTH):
916 draw_s_to_e_bit(x,y);
917 break;
919 break;
921 case(SOUTH):
922 switch(previousbit)
924 case(SOUTH):
925 case(NORTH):
926 draw_vertical_bit(x,y);
927 break;
929 case(EAST):
930 draw_e_to_s_bit(x,y);
931 break;
933 case(WEST):
934 draw_w_to_s_bit(x,y);
935 break;
937 break;
939 case(WEST):
940 switch(previousbit)
942 case(EAST):
943 case(WEST):
944 draw_horizontal_bit(x,y);
945 break;
947 case(SOUTH):
948 draw_s_to_w_bit(x,y);
949 break;
951 case(NORTH):
952 draw_n_to_w_bit(x,y);
953 break;
955 break;
960 ** Death 'sequence' and end game stuff.
962 void die (void)
964 int button;
965 bool done=false;
966 char pscore[20];
968 rb->splash(HZ*2, "Oops!");
970 rb->lcd_clear_display();
972 applecount=0;
974 rb->lcd_getstringsize("You died!",&strwdt,&strhgt);
975 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt,"You died!");
977 rb->snprintf(pscore,sizeof(pscore),"Your score: %d",score);
978 rb->lcd_getstringsize(pscore,&strwdt,&strhgt);
979 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt * 2 + 2,pscore);
981 if (score>hiscore)
983 hiscore=score;
984 rb->lcd_getstringsize("New high score!",&strwdt,&strhgt);
985 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt * 4 + 2,"New high score!");
987 else
989 rb->snprintf(phscore,sizeof(phscore),"High score: %d",hiscore);
990 rb->lcd_getstringsize(phscore,&strwdt,&strhgt);
991 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt * 5,phscore);
994 rb->snprintf(phscore,sizeof(phscore),"Press %s...",SNAKE2_PLAYPAUSE_TEXT);
995 rb->lcd_getstringsize(phscore,&strwdt,&strhgt);
996 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt * 7,phscore);
998 rb->lcd_update();
1000 while(!done)
1002 button=rb->button_get(true);
1003 switch(button)
1005 case SNAKE2_PLAYPAUSE:
1006 done = true;
1007 break;
1011 dead=1;
1015 ** Check for collision. TODO: Currently this
1016 ** sets of the death sequence. What we want is it to only return a true/false
1017 ** depending on whether a collision occured.
1019 void collision ( int x, int y )
1021 int bdeath=0;
1024 switch (board[x][y])
1026 case 0:
1028 break;
1029 case -1:
1030 score = score + (1 * level);
1031 apple=0;
1032 applecountdown=2;
1033 applecount++;
1035 if(game_type==1)
1037 if(num_apples_to_get == num_apples_to_got)
1039 level_from_file++;
1040 if(level_from_file >= num_levels)
1042 level_from_file = 1;
1043 /*and increase the number of apples to pick up
1044 before level changes*/
1045 num_apples_to_get+=2;
1046 game_b_level++;
1048 rb->splash(HZ, "Level Completed!");
1049 rb->lcd_clear_display();
1050 new_level(level_from_file);
1051 rb->lcd_clear_display();
1052 redraw();
1053 rb->lcd_update();
1055 else
1056 num_apples_to_got++;
1058 break;
1059 default:
1060 bdeath=1;
1061 break;
1064 if(bdeath==1)
1066 die();
1067 sillydir = dir;
1068 frames = -110;
1072 void move( void )
1074 int taildir;
1075 /*this actually sets the dir variable.*/
1076 get_direction();
1077 /*draw head*/
1078 switch (dir)
1080 case (NORTH):
1081 board[headx][heady]=NORTH;
1082 heady--;
1083 break;
1084 case (EAST):
1085 board[headx][heady]=EAST;
1086 headx++;
1087 break;
1088 case (SOUTH):
1089 board[headx][heady]=SOUTH;
1090 heady++;
1091 break;
1092 case (WEST):
1093 board[headx][heady]=WEST;
1094 headx--;
1095 break;
1098 if(headx == WIDTH)
1099 headx = 0;
1100 else if(headx < 0)
1101 headx = WIDTH-1;
1103 if(heady == HEIGHT)
1104 heady = 0;
1105 else if(heady < 0)
1106 heady = HEIGHT-1;
1108 rb->lcd_fillrect(CENTER_X+headx*MULTIPLIER,CENTER_Y+heady*MULTIPLIER,MODIFIER_1,MODIFIER_1);
1110 /*clear tail*/
1111 if(applecountdown <= 0)
1113 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
1114 rb->lcd_fillrect(CENTER_X+tailx*MULTIPLIER,CENTER_Y+taily*MULTIPLIER,MODIFIER_1,MODIFIER_1);
1115 rb->lcd_set_drawmode(DRMODE_SOLID);
1117 taildir = board[tailx][taily];
1118 board[tailx][taily] = 0;
1120 switch (taildir)
1122 case(NORTH):
1123 taily--;
1124 break;
1126 case(EAST):
1127 tailx++;
1128 break;
1130 case(SOUTH):
1131 taily++;
1132 break;
1134 case(WEST):
1135 tailx--;
1136 break;
1139 if(tailx == WIDTH)
1140 tailx = 0;
1141 else if(tailx < 0)
1142 tailx = WIDTH-1;
1144 if(taily == HEIGHT)
1145 taily = 0;
1146 else if(taily < 0)
1147 taily = HEIGHT-1;
1149 else
1150 applecountdown--;
1153 void frame (void)
1155 int olddir, noldx, noldy, temp;
1156 noldx = headx;
1157 noldy = heady;
1158 olddir = 0;
1159 switch(dir)
1161 case(NORTH):
1162 if(heady == HEIGHT-1)
1163 temp = 0;
1164 else
1165 temp = heady + 1;
1167 olddir = board[headx][temp];
1168 break;
1170 case(EAST):
1171 if(headx == 0)
1172 temp = WIDTH-1;
1173 else
1174 temp = headx - 1;
1176 olddir = board[temp][heady];
1177 break;
1179 case(SOUTH):
1180 if(heady == 0)
1181 temp = HEIGHT-1;
1182 else
1183 temp = heady - 1;
1185 olddir = board[headx][temp];
1186 break;
1188 case(WEST):
1189 if(headx == WIDTH-1)
1190 temp = 0;
1191 else
1192 temp = headx + 1;
1194 olddir = board[temp][heady];
1195 break;
1198 move();
1201 now redraw the bit that was
1202 the tail, to something snake-like:
1204 draw_snake_bit(dir, olddir, noldx, noldy);
1206 collision(headx, heady);
1208 rb->lcd_update();
1211 void game_pause (void)
1213 int button;
1215 rb->lcd_clear_display();
1216 rb->lcd_getstringsize("Paused",&strwdt,&strhgt);
1217 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,LCD_HEIGHT/2,"Paused");
1219 rb->lcd_update();
1220 while (1)
1222 button = rb->button_get(true);
1223 switch (button)
1225 case SNAKE2_PLAYPAUSE:
1226 rb->lcd_clear_display();
1227 redraw();
1228 rb->lcd_update();
1229 rb->sleep(HZ/2);
1230 return;
1232 #ifdef SNAKE2_RC_QUIT
1233 case SNAKE2_RC_QUIT:
1234 #endif
1235 case SNAKE2_QUIT:
1236 dead = 1;
1237 quit = 1;
1238 return;
1240 default:
1241 if (rb->default_event_handler(button)==SYS_USB_CONNECTED) {
1242 dead = 1;
1243 quit = 2;
1244 return;
1246 break;
1251 void game (void)
1253 int button;
1255 rb->lcd_clear_display();
1256 redraw();
1257 rb->lcd_update();
1258 /*main loop:*/
1259 while (1)
1261 if(frames==5)
1263 frame();
1264 if(frames>0) frames=0;
1266 frames++;
1268 if(frames == 0)
1270 die();
1272 else
1274 if(frames < 0)
1276 if(sillydir != dir)
1278 /*it has, great set frames to a positive value again:*/
1279 frames = 1;
1284 if (dead) return;
1286 draw_apple();
1288 rb->sleep(HZ/speed);
1290 button = rb->button_get(false);
1292 #ifdef HAS_BUTTON_HOLD
1293 if (rb->button_hold())
1294 button = SNAKE2_PLAYPAUSE;
1295 #endif
1297 switch (button)
1299 case SNAKE2_UP:
1300 case SNAKE2_UP | BUTTON_REPEAT:
1301 if (dir != SOUTH) set_direction(NORTH);
1302 break;
1304 case SNAKE2_RIGHT:
1305 case SNAKE2_RIGHT | BUTTON_REPEAT:
1306 if (dir != WEST) set_direction(EAST);
1307 break;
1309 case SNAKE2_DOWN:
1310 case SNAKE2_DOWN | BUTTON_REPEAT:
1311 if (dir != NORTH) set_direction(SOUTH);
1312 break;
1314 case SNAKE2_LEFT:
1315 case SNAKE2_LEFT | BUTTON_REPEAT:
1316 if (dir != EAST) set_direction(WEST);
1317 break;
1319 #ifdef SNAKE2_RC_QUIT
1320 case SNAKE2_RC_QUIT:
1321 #endif
1322 case SNAKE2_QUIT:
1323 dead=1;
1324 return;
1326 case SNAKE2_PLAYPAUSE:
1327 game_pause();
1328 break;
1330 default:
1331 if (rb->default_event_handler(button)==SYS_USB_CONNECTED) {
1332 quit = 2;
1333 return;
1335 break;
1341 void game_init(void)
1343 int button;
1344 char plevel[30];
1346 dead=0;
1347 apple=0;
1348 score=0;
1349 applecount=0;
1351 clear_board();
1352 load_level( level_from_file );
1353 rb->lcd_clear_display();
1354 redraw();
1355 rb->lcd_update();
1357 while (1)
1359 #if LCD_WIDTH >= 160 && LCD_HEIGHT >= 128
1361 rb->lcd_bitmap(snake2_header1,0,0,BMPWIDTH_snake2_header, BMPHEIGHT_snake2_header);
1362 rb->lcd_bitmap(snake2_left,0,BMPHEIGHT_snake2_header,BMPWIDTH_snake2_left, BMPHEIGHT_snake2_left);
1363 rb->lcd_bitmap(snake2_right,LCD_WIDTH-BMPWIDTH_snake2_right,BMPHEIGHT_snake2_header,BMPWIDTH_snake2_right, BMPHEIGHT_snake2_right);
1364 rb->lcd_bitmap(snake2_bottom,0,BMPHEIGHT_snake2_header+BMPHEIGHT_snake2_left,BMPWIDTH_snake2_bottom, BMPHEIGHT_snake2_bottom);
1366 rb->snprintf(plevel,sizeof(plevel),"%d",level);
1367 rb->lcd_getstringsize(plevel,&strwdt,&strhgt);
1368 rb->lcd_putsxy(TOP_X3-strwdt/2,TOP_Y2, plevel);
1370 rb->snprintf(plevel,sizeof(plevel),"%d",level_from_file);
1371 rb->lcd_getstringsize(plevel,&strwdt,&strhgt);
1372 rb->lcd_putsxy(TOP_X2-strwdt/2,TOP_Y1, plevel);
1374 if(game_type==0){
1375 rb->lcd_getstringsize("A",&strwdt,&strhgt);
1376 rb->lcd_putsxy(TOP_X1,TOP_Y1,"A");
1378 else{
1379 rb->lcd_getstringsize("B",&strwdt,&strhgt);
1380 rb->lcd_putsxy(TOP_X1,TOP_Y1,"B");
1383 rb->snprintf(phscore,sizeof(phscore),"%d",hiscore);
1384 rb->lcd_getstringsize(phscore,&strwdt,&strhgt);
1385 rb->lcd_putsxy(TOP_X4-strwdt/2,TOP_Y2, phscore);
1387 #else
1388 rb->snprintf(plevel,sizeof(plevel),"Speed: %02d",level);
1389 rb->lcd_getstringsize("Speed: 00",&strwdt,&strhgt);
1390 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt+4, plevel);
1392 rb->snprintf(plevel,sizeof(plevel),"Maze: %d",level_from_file);
1393 rb->lcd_getstringsize(plevel,&strwdt,&strhgt);
1394 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt*2+4, plevel);
1396 if(game_type==0){
1397 rb->lcd_getstringsize("Game Type: A ",&strwdt,&strhgt);
1398 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt*3+4,"Game Type: A");
1400 else{
1401 rb->lcd_getstringsize("Game Type: B ",&strwdt,&strhgt);
1402 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt*3+4,"Game Type: B");
1405 rb->snprintf(phscore,sizeof(phscore),"Hi Score: %d",hiscore);
1406 rb->lcd_getstringsize(phscore,&strwdt,&strhgt);
1407 rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt*4+4, phscore);
1408 #endif
1410 rb->lcd_update();
1412 button=rb->button_get(true);
1413 switch (button)
1415 case SNAKE2_LEVEL_UP:
1416 case SNAKE2_LEVEL_UP|BUTTON_REPEAT:
1417 if (level<10)
1418 level+=1;
1419 break;
1420 case SNAKE2_LEVEL_DOWN:
1421 case SNAKE2_LEVEL_DOWN|BUTTON_REPEAT:
1422 if (level>1)
1423 level-=1;
1424 break;
1425 case SNAKE2_QUIT:
1426 quit=1;
1427 return;
1428 break;
1429 case SNAKE2_PLAYPAUSE:
1430 speed = level*20;
1431 return;
1432 break;
1433 case SNAKE2_SELECT_TYPE:
1434 if(game_type==0)game_type=1; else game_type=0;
1435 break;
1436 case SNAKE2_MAZE_NEXT:
1437 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
1438 rb->lcd_fillrect(CENTER_X, CENTER_Y, CENTER_X+WIDTH*MULTIPLIER,
1439 CENTER_Y+HEIGHT*MULTIPLIER);
1440 rb->lcd_set_drawmode(DRMODE_SOLID);
1441 if(level_from_file < num_levels)
1442 level_from_file++;
1443 else
1444 level_from_file = 0;
1445 load_level( level_from_file );
1446 redraw();
1447 break;
1448 #ifdef SNAKE2_MAZE_LAST
1449 case SNAKE2_MAZE_LAST:
1450 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
1451 rb->lcd_fillrect(CENTER_X, CENTER_Y, CENTER_X+WIDTH*MULTIPLIER,
1452 CENTER_Y+HEIGHT*MULTIPLIER);
1453 rb->lcd_set_drawmode(DRMODE_SOLID);
1454 if(level_from_file > 0)
1455 level_from_file--;
1456 else
1457 level_from_file = num_levels;
1458 load_level( level_from_file );
1459 redraw();
1460 break;
1461 #endif
1462 default:
1463 if (rb->default_event_handler(button)==SYS_USB_CONNECTED) {
1464 quit = 2;
1465 return;
1467 break;
1473 enum plugin_status plugin_start(const void* parameter)
1475 (void)(parameter);
1477 /* Lets use the default font */
1478 rb->lcd_setfont(FONT_SYSFIXED);
1479 #if LCD_DEPTH > 1
1480 rb->lcd_set_backdrop(NULL);
1481 #endif
1482 #ifdef HAVE_LCD_COLOR
1483 rb->lcd_set_foreground(LCD_BLACK);
1484 rb->lcd_set_background(LCD_WHITE);
1485 #endif
1487 load_all_levels();
1489 if (num_levels == 0) {
1490 rb->splash(HZ*2, "Failed loading levels!");
1491 return PLUGIN_OK;
1494 iohiscore();
1496 while(quit==0)
1498 game_init();
1499 rb->lcd_clear_display();
1500 frames=1;
1502 if(quit==0)
1504 init_snake();
1506 /*Start Game:*/
1507 game();
1511 iohiscore();
1512 return (quit==1) ? PLUGIN_OK : PLUGIN_USB_CONNECTED;
1515 #endif