Add another delay in the AMSv2 sd controller driver as a work-around for SD initialis...
[maemo-rb.git] / apps / plugins / pong.c
blobbae1703db587a078104f6e99bbc1dbc19a52070f
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2004 Daniel Stenberg
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 ****************************************************************************/
21 #include "plugin.h"
22 #include "lib/helper.h"
24 #define PAD_HEIGHT LCD_HEIGHT / 6 /* Recorder: 10 iRiver: 21 */
25 #define PAD_WIDTH LCD_WIDTH / 50 /* Recorder: 2 iRiver: 2 */
27 #define BALL_HEIGHT LCD_HEIGHT / 32 /* Recorder: 2 iRiver: 4 */
28 #define BALL_WIDTH LCD_HEIGHT / 32 /* We want a square ball */
30 #define SPEEDX ( LCD_WIDTH * 3 ) / 2 /* Recorder: 168 iRiver: 240 */
31 #define SPEEDY LCD_HEIGHT * 2 /* Recorder: 128 iRiver: 256 */
32 /* This is the width of the dead spot where the
33 * cpu player doesnt care about the ball -- 3/8 of the screen */
34 #define CPU_PLAYER_RIGHT_DIST ( (LCD_WIDTH/8 ) * 5 )
35 #define CPU_PLAYER_LEFT_DIST ( (LCD_WIDTH/8 ) * 3 )
37 #define RES 100
39 #define MOVE_STEP LCD_HEIGHT / 32 /* move pad this many steps up/down each move */
41 /* variable button definitions */
42 #if CONFIG_KEYPAD == RECORDER_PAD
43 #define PONG_QUIT BUTTON_OFF
44 #define PONG_PAUSE BUTTON_ON
45 #define PONG_LEFT_UP BUTTON_F1
46 #define PONG_LEFT_DOWN BUTTON_LEFT
47 #define PONG_RIGHT_UP BUTTON_F3
48 #define PONG_RIGHT_DOWN BUTTON_RIGHT
50 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
51 #define PONG_QUIT BUTTON_OFF
52 #define PONG_PAUSE BUTTON_ON
53 #define PONG_LEFT_UP BUTTON_F1
54 #define PONG_LEFT_DOWN BUTTON_LEFT
55 #define PONG_RIGHT_UP BUTTON_F3
56 #define PONG_RIGHT_DOWN BUTTON_RIGHT
58 #elif CONFIG_KEYPAD == ONDIO_PAD
59 #define PONG_QUIT BUTTON_OFF
60 #define PONG_PAUSE BUTTON_RIGHT
61 #define PONG_LEFT_UP BUTTON_LEFT
62 #define PONG_LEFT_DOWN BUTTON_MENU
63 #define PONG_RIGHT_UP BUTTON_UP
64 #define PONG_RIGHT_DOWN BUTTON_DOWN
66 #elif CONFIG_KEYPAD == IRIVER_H100_PAD
67 #define PONG_QUIT BUTTON_OFF
68 #define PONG_LEFT_UP BUTTON_UP
69 #define PONG_LEFT_DOWN BUTTON_DOWN
70 #define PONG_RIGHT_UP BUTTON_ON
71 #define PONG_RIGHT_DOWN BUTTON_MODE
72 #define PONG_RC_QUIT BUTTON_RC_STOP
74 #elif CONFIG_KEYPAD == IRIVER_H300_PAD
75 #define PONG_QUIT BUTTON_OFF
76 #define PONG_LEFT_UP BUTTON_UP
77 #define PONG_LEFT_DOWN BUTTON_DOWN
78 #define PONG_RIGHT_UP BUTTON_REC
79 #define PONG_RIGHT_DOWN BUTTON_MODE
80 #define PONG_RC_QUIT BUTTON_RC_STOP
82 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
83 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
84 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
85 #define PONG_QUIT BUTTON_SELECT
86 #define PONG_LEFT_UP BUTTON_MENU
87 #define PONG_LEFT_DOWN BUTTON_LEFT
88 #define PONG_RIGHT_UP BUTTON_RIGHT
89 #define PONG_RIGHT_DOWN BUTTON_PLAY
91 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
92 #define PONG_QUIT BUTTON_POWER
93 #define PONG_LEFT_UP BUTTON_UP
94 #define PONG_LEFT_DOWN BUTTON_DOWN
95 #define PONG_RIGHT_UP BUTTON_REC
96 #define PONG_RIGHT_DOWN BUTTON_PLAY
98 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
99 #define PONG_QUIT BUTTON_POWER
100 #define PONG_PAUSE BUTTON_SELECT
101 #define PONG_LEFT_UP BUTTON_UP
102 #define PONG_LEFT_DOWN BUTTON_DOWN
103 #define PONG_RIGHT_UP BUTTON_VOL_UP
104 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
106 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
107 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
108 (CONFIG_KEYPAD == SANSA_M200_PAD)
109 #define PONG_QUIT BUTTON_POWER
110 #define PONG_PAUSE BUTTON_SELECT
111 #define PONG_LEFT_UP BUTTON_LEFT
112 #define PONG_LEFT_DOWN BUTTON_DOWN
113 #define PONG_RIGHT_UP BUTTON_UP
114 #define PONG_RIGHT_DOWN BUTTON_RIGHT
116 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
117 #define PONG_QUIT BUTTON_HOME
118 #define PONG_PAUSE BUTTON_SELECT
119 #define PONG_LEFT_UP BUTTON_LEFT
120 #define PONG_LEFT_DOWN BUTTON_DOWN
121 #define PONG_RIGHT_UP BUTTON_UP
122 #define PONG_RIGHT_DOWN BUTTON_RIGHT
124 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
125 #define PONG_QUIT BUTTON_POWER
126 #define PONG_PAUSE BUTTON_SELECT
127 #define PONG_LEFT_UP BUTTON_VOL_UP
128 #define PONG_LEFT_DOWN BUTTON_VOL_DOWN
129 #define PONG_RIGHT_UP BUTTON_UP
130 #define PONG_RIGHT_DOWN BUTTON_DOWN
132 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
133 #define PONG_QUIT BUTTON_POWER
134 #define PONG_LEFT_UP BUTTON_SCROLL_UP
135 #define PONG_LEFT_DOWN BUTTON_SCROLL_DOWN
136 #define PONG_RIGHT_UP BUTTON_REW
137 #define PONG_RIGHT_DOWN BUTTON_FF
139 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
140 #define PONG_QUIT BUTTON_BACK
141 #define PONG_LEFT_UP BUTTON_UP
142 #define PONG_LEFT_DOWN BUTTON_DOWN
143 #define PONG_RIGHT_UP BUTTON_VOL_UP
144 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
146 #elif (CONFIG_KEYPAD == MROBE100_PAD)
147 #define PONG_QUIT BUTTON_POWER
148 #define PONG_PAUSE BUTTON_SELECT
149 #define PONG_LEFT_UP BUTTON_MENU
150 #define PONG_LEFT_DOWN BUTTON_LEFT
151 #define PONG_RIGHT_UP BUTTON_PLAY
152 #define PONG_RIGHT_DOWN BUTTON_RIGHT
154 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
155 #define PONG_QUIT BUTTON_RC_REC
156 #define PONG_PAUSE BUTTON_RC_PLAY
157 #define PONG_LEFT_UP BUTTON_RC_VOL_UP
158 #define PONG_LEFT_DOWN BUTTON_RC_VOL_DOWN
159 #define PONG_RIGHT_UP BUTTON_VOL_UP
160 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
162 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
163 #define PONG_QUIT BUTTON_POWER
165 #elif CONFIG_KEYPAD == IAUDIO67_PAD
166 #define PONG_QUIT BUTTON_POWER
167 #define PONG_PAUSE BUTTON_MENU
168 #define PONG_LEFT_UP BUTTON_VOLUP
169 #define PONG_LEFT_DOWN BUTTON_VOLDOWN
170 #define PONG_RIGHT_UP BUTTON_RIGHT
171 #define PONG_RIGHT_DOWN BUTTON_LEFT
173 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
174 #define PONG_QUIT BUTTON_BACK
175 #define PONG_LEFT_UP BUTTON_UP
176 #define PONG_LEFT_DOWN BUTTON_DOWN
177 #define PONG_RIGHT_UP BUTTON_PLAY
178 #define PONG_RIGHT_DOWN BUTTON_MENU
180 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
181 #define PONG_QUIT BUTTON_POWER
182 #define PONG_PAUSE BUTTON_MENU
183 #define PONG_LEFT_UP BUTTON_UP
184 #define PONG_LEFT_DOWN BUTTON_DOWN
185 #define PONG_RIGHT_UP BUTTON_VOL_UP
186 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
188 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
189 #define PONG_QUIT BUTTON_POWER
190 #define PONG_PAUSE BUTTON_MENU
191 #define PONG_LEFT_UP BUTTON_UP
192 #define PONG_LEFT_DOWN BUTTON_DOWN
193 #define PONG_RIGHT_UP BUTTON_VOL_UP
194 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
196 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
197 #define PONG_QUIT BUTTON_POWER
198 #define PONG_PAUSE BUTTON_MENU
199 #define PONG_LEFT_UP BUTTON_UP
200 #define PONG_LEFT_DOWN BUTTON_DOWN
201 #define PONG_RIGHT_UP BUTTON_VOL_UP
202 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
204 #elif CONFIG_KEYPAD == ONDAVX747_PAD || \
205 CONFIG_KEYPAD == ONDAVX777_PAD || \
206 CONFIG_KEYPAD == MROBE500_PAD
207 #define PONG_QUIT BUTTON_POWER
209 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
210 #define PONG_QUIT BUTTON_REC
211 #define PONG_PAUSE BUTTON_PLAY
212 #define PONG_LEFT_UP BUTTON_UP
213 #define PONG_LEFT_DOWN BUTTON_DOWN
214 #define PONG_RIGHT_UP BUTTON_FFWD
215 #define PONG_RIGHT_DOWN BUTTON_REW
217 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
218 #define PONG_QUIT BUTTON_REC
219 #define PONG_PAUSE BUTTON_OK
220 #define PONG_LEFT_UP BUTTON_MENU
221 #define PONG_LEFT_DOWN BUTTON_PREV
222 #define PONG_RIGHT_UP BUTTON_PLAY
223 #define PONG_RIGHT_DOWN BUTTON_NEXT
225 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
226 #define PONG_QUIT (BUTTON_REC|BUTTON_PLAY)
227 #define PONG_LEFT_UP BUTTON_REW
228 #define PONG_LEFT_DOWN BUTTON_FF
229 #define PONG_RIGHT_UP BUTTON_VOL_UP
230 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
232 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
233 #define PONG_QUIT (BUTTON_REC|BUTTON_REPEAT)
234 #define PONG_LEFT_UP BUTTON_FF
235 #define PONG_LEFT_DOWN BUTTON_REW
236 #define PONG_RIGHT_UP BUTTON_UP
237 #define PONG_RIGHT_DOWN BUTTON_DOWN
239 #else
240 #error No keymap defined!
241 #endif
243 #ifdef HAVE_TOUCHSCREEN
244 #ifndef PONG_QUIT
245 #define PONG_QUIT BUTTON_TOPMIDDLE
246 #endif
247 #ifndef PONG_LEFT_UP
248 #define PONG_LEFT_UP BUTTON_TOPLEFT
249 #endif
250 #ifndef PONG_LEFT_DOWN
251 #define PONG_LEFT_DOWN BUTTON_BOTTOMLEFT
252 #endif
253 #ifndef PONG_RIGHT_UP
254 #define PONG_RIGHT_UP BUTTON_TOPRIGHT
255 #endif
256 #ifndef PONG_RIGHT_DOWN
257 #define PONG_RIGHT_DOWN BUTTON_BOTTOMRIGHT
258 #endif
259 #ifndef PONG_PAUSE
260 #define PONG_PAUSE BUTTON_CENTER
261 #endif
262 #endif
264 struct player {
265 int xpos; /* X position of pad */
266 int w_pad; /* wanted current Y position of pad */
267 int e_pad; /* existing current Y position of pad */
268 int score;
269 bool iscpu; /* Status of AI player */
272 struct ball {
273 int x; /* current X*RES position of the ball */
274 int y; /* current Y*RES position of the ball */
275 int speedx; /* */
276 int speedy; /* */
279 struct pong {
280 struct ball ball;
281 struct player player[2];
284 void singlepad(int x, int y, int set)
286 if(set) {
287 rb->lcd_fillrect(x, y, PAD_WIDTH, PAD_HEIGHT);
289 else {
290 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
291 rb->lcd_fillrect(x, y, PAD_WIDTH, PAD_HEIGHT);
292 rb->lcd_set_drawmode(DRMODE_SOLID);
296 void pad(struct pong *p, int pad)
298 struct player *player = &p->player[pad];
299 /* clear existing pad */
300 singlepad(player->xpos, player->e_pad, 0);
302 /* draw wanted pad */
303 singlepad(player->xpos, player->w_pad, 1);
305 /* existing is now the wanted */
306 player->e_pad = player->w_pad;
309 bool wallcollide(struct pong *p, int pad)
311 /* we have already checked for pad-collision, just check if this hits
312 the wall */
313 if(pad) {
314 /* right-side */
315 if(p->ball.x > ( LCD_WIDTH*RES ) - PAD_WIDTH )
316 return true;
318 else {
319 if(p->ball.x + ( BALL_WIDTH*RES ) < PAD_WIDTH )
320 return true;
322 return false;
325 /* returns true if the ball has hit a pad, and then the info variable
326 will have extra angle info */
328 bool padcollide(struct pong *p, int pad, int *info)
330 struct player *player = &p->player[pad];
331 int x = p->ball.x/RES;
332 int y = p->ball.y/RES;
334 if((y < (player->e_pad+PAD_HEIGHT)) &&
335 (y + BALL_HEIGHT > player->e_pad)) {
336 /* Y seems likely right */
338 /* store the delta between ball-middle MINUS pad-middle, so
339 it returns:
340 0 when the ball hits exactly the middle of the pad
341 positive numbers when the ball is below the middle of the pad
342 negative numbers when the ball is above the middle of the pad
344 max number is +- PAD_HEIGHT/2
347 *info = (y+BALL_HEIGHT/2) - (player->e_pad + PAD_HEIGHT/2);
349 if(pad) {
350 /* right-side */
351 if((x + BALL_WIDTH) >= (LCD_WIDTH - PAD_WIDTH))
352 return true; /* phump */
354 else {
355 if(x <= PAD_WIDTH)
356 return true;
359 return false; /* nah */
362 void bounce(struct pong *p, int pad, int info)
364 p->ball.speedx = -p->ball.speedx;
366 /* Give ball a little push to keep it from getting stuck between wall and pad */
367 if(pad) {
368 /* right side */
369 p->ball.x -= PAD_WIDTH*RES/4;
371 else {
372 p->ball.x += PAD_WIDTH*RES/4;
375 /* info is the hit-angle into the pad */
376 if(p->ball.speedy > 0) {
377 /* downwards */
378 if(info > 0) {
379 /* below the middle of the pad */
380 p->ball.speedy += info * RES/3;
382 else if(info < 0) {
383 /* above the middle */
384 p->ball.speedy = info * RES/2;
387 else {
388 /* upwards */
389 if(info > 0) {
390 /* below the middle of the pad */
391 p->ball.speedy = info * RES/2;
393 else if(info < 0) {
394 /* above the middle */
395 p->ball.speedy += info * RES/3;
399 p->ball.speedy += rb->rand()%21-10;
401 #if 0
402 fprintf(stderr, "INFO: %d YSPEED: %d\n", info, p->ball.speedy);
403 #endif
406 void score(struct pong *p, int pad)
408 if(pad)
409 rb->splash(HZ/4, "right scores!");
410 else
411 rb->splash(HZ/4, "left scores!");
412 rb->lcd_clear_display();
413 p->player[pad].score++;
415 /* then move the X-speed of the ball and give it a random Y position */
416 p->ball.speedx = -p->ball.speedx;
417 p->ball.y = rb->rand()%((LCD_HEIGHT-BALL_HEIGHT)*RES);
419 /* avoid hitting the pad with the new ball */
420 p->ball.x = (p->ball.x < 0) ?
421 (RES * PAD_WIDTH) : (RES * (LCD_WIDTH - PAD_WIDTH - BALL_WIDTH));
423 /* restore Y-speed to default */
424 p->ball.speedy = (p->ball.speedy > 0) ? SPEEDY : -SPEEDY;
426 /* set the existing pad positions to something weird to force pad
427 updates */
428 p->player[0].e_pad = -1;
429 p->player[1].e_pad = -1;
432 void ball(struct pong *p)
434 int oldx = p->ball.x/RES;
435 int oldy = p->ball.y/RES;
437 int newx;
438 int newy;
440 int info;
442 /* movement */
443 p->ball.x += p->ball.speedx;
444 p->ball.y += p->ball.speedy;
446 newx = p->ball.x/RES;
447 newy = p->ball.y/RES;
449 /* detect if ball hits a wall */
450 if(newy + BALL_HEIGHT > LCD_HEIGHT) {
451 /* hit floor, bounce */
452 p->ball.speedy = -p->ball.speedy;
453 p->ball.y = (LCD_HEIGHT - BALL_HEIGHT) * RES;
455 else if(newy < 0) {
456 /* hit ceiling, bounce */
457 p->ball.speedy = -p->ball.speedy;
458 p->ball.y = 0;
461 /* detect if ball hit pads */
462 if(padcollide(p, 0, &info))
463 bounce(p, 0, info);
464 else if(padcollide(p, 1, &info))
465 bounce(p, 1, info);
466 else if(wallcollide(p, 0))
467 score(p, 1);
468 else if(wallcollide(p, 1))
469 score(p, 0);
471 newx = p->ball.x/RES;
472 newy = p->ball.y/RES;
474 /* clear old position */
475 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
476 rb->lcd_fillrect(oldx, oldy, BALL_WIDTH, BALL_HEIGHT);
477 rb->lcd_set_drawmode(DRMODE_SOLID);
479 /* draw the new ball position */
480 rb->lcd_fillrect(newx, newy, BALL_WIDTH, BALL_HEIGHT);
483 void padmove(int *pos, int dir)
485 *pos += dir;
486 if(*pos > (LCD_HEIGHT-PAD_HEIGHT))
487 *pos = (LCD_HEIGHT-PAD_HEIGHT);
488 else if(*pos < 0)
489 *pos = 0;
492 void key_pad(struct pong *p, int pad, int up, int down)
494 struct player *player = &p->player[pad];
495 if(player->iscpu) {
496 if((pad && (p->ball.x/RES > CPU_PLAYER_RIGHT_DIST)) /* cpu right */
497 || (!pad && (p->ball.x/RES < CPU_PLAYER_LEFT_DIST)) /* cpu left */)
499 if(p->ball.y/RES > player->w_pad) /* player goes down */
500 padmove(&player->w_pad, MOVE_STEP);
502 if(p->ball.y/RES < player->w_pad) /* player goes up */
503 padmove(&player->w_pad, -MOVE_STEP);
506 if(down || up) {
507 /* if player presses control keys stop cpu player */
508 player->iscpu = false;
509 p->player[0].score = p->player[1].score = 0; /* reset the score */
510 rb->lcd_clear_display(); /* get rid of the text */
513 else {
514 if(down) /* player goes down */
515 padmove(&player->w_pad, MOVE_STEP);
517 if(up) /* player goes up */
518 padmove(&player->w_pad, -MOVE_STEP);
522 int keys(struct pong *p)
524 int key;
525 #ifdef PONG_PAUSE
526 static bool pause = false;
527 #endif
529 /* number of ticks this function will loop reading keys */
530 #ifndef HAVE_TOUCHSCREEN
531 int time = 4;
532 #else
533 int time = 1;
534 #endif
535 int start = *rb->current_tick;
536 int end = start + time;
538 while(TIME_BEFORE(*rb->current_tick, end)) {
539 key = rb->button_get_w_tmo(end - *rb->current_tick);
541 #ifdef HAVE_TOUCHSCREEN
542 short touch_x, touch_y;
543 if(key & BUTTON_TOUCHSCREEN)
545 struct player *player;
546 touch_x = rb->button_get_data() >> 16;
547 touch_y = rb->button_get_data() & 0xFFFF;
549 player = &p->player[0];
550 if(touch_x >= player->xpos && touch_x <= player->xpos+(PAD_WIDTH*4))
552 padmove(&player->w_pad, touch_y-(player->e_pad*2+PAD_HEIGHT)/2);
553 if (player->iscpu) {
554 /* if left player presses control keys stop cpu player */
555 player->iscpu = false;
556 p->player[0].score = p->player[1].score = 0; /* reset the score */
557 rb->lcd_clear_display(); /* get rid of the text */
561 player = &p->player[1];
562 if(touch_x >= player->xpos-(PAD_WIDTH*4) && touch_x <= player->xpos)
564 padmove(&player->w_pad, touch_y-(player->e_pad*2+PAD_HEIGHT)/2);
565 if (player->iscpu) {
566 /* if right player presses control keys stop cpu player */
567 player->iscpu = false;
568 p->player[0].score = p->player[1].score = 0; /* reset the score */
569 rb->lcd_clear_display(); /* get rid of the text */
573 #endif
575 #ifdef HAS_BUTTON_HOLD
576 if (rb->button_hold())
577 return 2; /* Pause game */
578 #endif
580 if(key & PONG_QUIT
581 #ifdef PONG_RC_QUIT
582 || key & PONG_RC_QUIT
583 #endif
585 return 0; /* exit game NOW */
587 #ifdef PONG_PAUSE
588 if(key == PONG_PAUSE)
589 pause = !pause;
590 if(pause)
591 return 2; /* Pause game */
592 #endif
594 key = rb->button_status(); /* ignore BUTTON_REPEAT */
596 key_pad(p, 0, (key & PONG_LEFT_UP), (key & PONG_LEFT_DOWN));
597 key_pad(p, 1, (key & PONG_RIGHT_UP), (key & PONG_RIGHT_DOWN));
599 if(rb->default_event_handler(key) == SYS_USB_CONNECTED)
600 return -1; /* exit game because of USB */
602 return 1; /* return 0 to exit game */
605 void showscore(struct pong *p)
607 static char buffer[20];
608 int w;
610 rb->snprintf(buffer, sizeof(buffer), "%d - %d",
611 p->player[0].score, p->player[1].score);
612 w = rb->lcd_getstringsize((unsigned char *)buffer, NULL, NULL);
613 rb->lcd_putsxy( (LCD_WIDTH / 2) - (w / 2), 0, (unsigned char *)buffer);
616 void blink_demo(void)
618 static char buffer[30];
619 int w;
621 rb->snprintf(buffer, sizeof(buffer), "Press Key To Play");
622 w = rb->lcd_getstringsize((unsigned char *)buffer, NULL, NULL);
623 if(LCD_WIDTH > ( (w/8)*7 ) ) /* make sure text isn't too long for screen */
624 rb->lcd_putsxy( (LCD_WIDTH / 2) - (w / 2), (LCD_HEIGHT / 2),
625 (unsigned char *)buffer);
628 /* this is the plugin entry point */
629 enum plugin_status plugin_start(const void* parameter)
631 struct pong pong;
632 int game = 1;
634 int blink_timer = 0;
635 int blink_rate = 20;
636 bool blink = true;
638 /* init the struct with some silly values to start with */
640 pong.ball.x = 20*RES;
641 pong.ball.y = 20*RES;
642 pong.ball.speedx = SPEEDX;
643 pong.ball.speedy = SPEEDY;
645 pong.player[0].xpos = 0;
646 pong.player[0].e_pad = 0;
647 pong.player[0].w_pad = 7;
648 pong.player[1].xpos = LCD_WIDTH-PAD_WIDTH;
649 pong.player[1].e_pad = 0;
650 pong.player[1].w_pad = 40;
652 /* start every game in demo mode */
653 pong.player[0].iscpu = pong.player[1].iscpu = true;
655 pong.player[0].score = pong.player[1].score = 0; /* lets start at 0 - 0 ;-) */
657 /* if you don't use the parameter, you can do like
658 this to avoid the compiler warning about it */
659 (void)parameter;
661 /* Turn off backlight timeout */
662 backlight_ignore_timeout();
663 /* Clear screen */
664 rb->lcd_clear_display();
666 /* go go go */
667 while(game > 0) {
668 if (game == 2) { /* Game Paused */
669 rb->splash(0, "PAUSED");
670 while(game == 2)
671 game = keys(&pong); /* short circuit */
672 rb->lcd_clear_display();
675 if( pong.player[0].iscpu && pong.player[1].iscpu ) {
676 if(blink_timer<blink_rate) {
677 ++blink_timer;
679 else {
680 blink_timer=0;
681 blink = !blink;
684 if(blink==true) {
685 blink_demo();
687 else {
688 rb->lcd_clear_display();
692 showscore(&pong);
693 pad(&pong, 0); /* draw left pad */
694 pad(&pong, 1); /* draw right pad */
695 ball(&pong); /* move and draw ball */
697 rb->lcd_update();
699 game = keys(&pong); /* deal with keys */
702 /* Turn on backlight timeout (revert to settings) */
703 backlight_use_settings();
704 return (game == 0) ? PLUGIN_OK : PLUGIN_USB_CONNECTED;