1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Originally by Joshua Oreman, improved by Prashant Varanasi
11 * Ported to Rockbox by Ben Basha (Paprica)
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
25 #include "configfile.h"
32 - Make original speed and further increases in speed depend more on screen size
33 - attempt to make the tunnels get narrower as the game goes on
34 - make the chopper look better, maybe a picture, and scale according
36 - use textures for the color screens for background and terrain,
37 eg stars on background
38 - allow choice of different levels [later: different screen themes]
39 - better high score handling, improved screen etc.
42 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
44 #define QUIT BUTTON_OFF
45 #define ACTION BUTTON_UP
46 #define ACTION2 BUTTON_SELECT
47 #define ACTIONTEXT "SELECT"
49 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
50 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
51 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
53 #define QUIT BUTTON_MENU
54 #define ACTION BUTTON_SELECT
55 #define ACTIONTEXT "SELECT"
57 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD /* grayscale at the moment */
59 #define QUIT BUTTON_POWER
60 #define ACTION BUTTON_UP
61 #define ACTION2 BUTTON_SELECT
62 #define ACTIONTEXT "SELECT"
64 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
65 #define QUIT BUTTON_POWER
66 #define ACTION BUTTON_RIGHT
67 #define ACTIONTEXT "RIGHT"
69 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
70 (CONFIG_KEYPAD == SANSA_C200_PAD)
71 #define QUIT BUTTON_POWER
72 #define ACTION BUTTON_SELECT
73 #define ACTIONTEXT "SELECT"
75 #elif CONFIG_KEYPAD == GIGABEAT_PAD
76 #define QUIT BUTTON_MENU
77 #define ACTION BUTTON_SELECT
78 #define ACTIONTEXT "SELECT"
80 #elif CONFIG_KEYPAD == RECORDER_PAD
81 #define QUIT BUTTON_OFF
82 #define ACTION BUTTON_PLAY
83 #define ACTIONTEXT "PLAY"
85 #elif CONFIG_KEYPAD == ONDIO_PAD
86 #define QUIT BUTTON_OFF
87 #define ACTION BUTTON_UP
88 #define ACTION2 BUTTON_MENU
89 #define ACTIONTEXT "UP"
91 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
92 #define QUIT BUTTON_BACK
93 #define ACTION BUTTON_SELECT
94 #define ACTION2 BUTTON_MENU
95 #define ACTIONTEXT "SELECT"
97 #elif CONFIG_KEYPAD == MROBE100_PAD
98 #define QUIT BUTTON_POWER
99 #define ACTION BUTTON_SELECT
100 #define ACTIONTEXT "SELECT"
102 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
103 #define QUIT BUTTON_RC_REC
104 #define ACTION BUTTON_RC_PLAY
105 #define ACTION2 BUTTON_RC_MODE
106 #define ACTIONTEXT "PLAY"
108 #elif CONFIG_KEYPAD == COWOND2_PAD
109 #define QUIT BUTTON_POWER
112 #error No keymap defined!
117 #define QUIT BUTTON_TOPLEFT
120 #define ACTION BUTTON_BOTTOMLEFT
123 #define ACTION2 BUTTON_BOTTOMRIGHT
126 #define ACTIONTEXT "BOTTOMRIGHT"
130 static const struct plugin_api
* rb
;
132 #define NUMBER_OF_BLOCKS 8
133 #define NUMBER_OF_PARTICLES 3
134 #define MAX_TERRAIN_NODES 15
136 #define LEVEL_MODE_NORMAL 0
137 #define LEVEL_MODE_STEEP 1
140 #define CYCLETIME 100
141 #define SCALE(x) ((x)==1 ? (x) : ((x) >> 1))
149 /*Chopper's local variables to track the terrain position etc*/
150 static int chopCounter
;
151 static int iRotorOffset
;
154 static int iPlayerPosX
;
155 static int iPlayerPosY
;
156 static int iCameraPosX
;
157 static int iPlayerSpeedX
;
158 static int iPlayerSpeedY
;
159 static int iLastBlockPlacedPosX
;
160 static int iGravityTimerCountdown
;
161 static int iPlayerAlive
;
162 static int iLevelMode
;
163 static int blockh
,blockw
;
164 static int highscore
;
167 #define CFG_FILE "chopper.cfg"
168 #define MAX_POINTS 50000
169 static struct configdata config
[] =
171 {TYPE_INT
, 0, MAX_POINTS
, &highscore
, "highscore", NULL
, NULL
}
204 struct CTerrainNode mNodes
[MAX_TERRAIN_NODES
];
206 int iLastNodePlacedPosX
;
209 struct CBlock mBlocks
[NUMBER_OF_BLOCKS
];
210 struct CParticle mParticles
[NUMBER_OF_PARTICLES
];
212 struct CTerrain mGround
;
213 struct CTerrain mRoof
;
215 /*Function declarations*/
216 static void chopDrawParticle(struct CParticle
*mParticle
);
217 static void chopDrawBlock(struct CBlock
*mBlock
);
218 static void chopRenderTerrain(struct CTerrain
*ter
);
219 void chopper_load(bool newgame
);
220 void cleanup_chopper(void);
222 static void chopDrawPlayer(int x
,int y
) /* These are SCREEN coords, not world!*/
226 rb
->lcd_set_foreground(LCD_RGBPACK(50,50,200));
228 rb
->lcd_set_foreground(LCD_DARKGRAY
);
230 rb
->lcd_fillrect(SCALE(x
+6), SCALE(y
+2), SCALE(12), SCALE(9));
231 rb
->lcd_fillrect(SCALE(x
-3), SCALE(y
+6), SCALE(20), SCALE(3));
234 rb
->lcd_set_foreground(LCD_RGBPACK(50,50,50));
236 rb
->lcd_set_foreground(LCD_DARKGRAY
);
238 rb
->lcd_fillrect(SCALE(x
+10), SCALE(y
), SCALE(2), SCALE(3));
239 rb
->lcd_fillrect(SCALE(x
+10), SCALE(y
), SCALE(1), SCALE(3));
242 rb
->lcd_set_foreground(LCD_RGBPACK(40,40,100));
244 rb
->lcd_set_foreground(LCD_BLACK
);
246 rb
->lcd_drawline(SCALE(x
), SCALE(y
+iRotorOffset
), SCALE(x
+20),
247 SCALE(y
-iRotorOffset
));
250 rb
->lcd_set_foreground(LCD_RGBPACK(20,20,50));
252 rb
->lcd_set_foreground(LCD_BLACK
);
254 rb
->lcd_fillrect(SCALE(x
- 2), SCALE(y
+ 5), SCALE(2), SCALE(5));
258 static void chopClearTerrain(struct CTerrain
*ter
)
260 ter
->iNodesCount
= 0;
264 int iR(int low
,int high
)
266 return low
+rb
->rand()%(high
-low
+1);
269 static void chopCopyTerrain(struct CTerrain
*src
, struct CTerrain
*dest
,
270 int xOffset
,int yOffset
)
274 while(i
< src
->iNodesCount
)
276 dest
->mNodes
[i
].x
= src
->mNodes
[i
].x
+ xOffset
;
277 dest
->mNodes
[i
].y
= src
->mNodes
[i
].y
+ yOffset
;
282 dest
->iNodesCount
= src
->iNodesCount
;
283 dest
->iLastNodePlacedPosX
= src
->iLastNodePlacedPosX
;
287 static void chopAddTerrainNode(struct CTerrain
*ter
, int x
, int y
)
291 if(ter
->iNodesCount
+ 1 >= MAX_TERRAIN_NODES
)
293 /* DEBUGF("ERROR: Not enough nodes!\n"); */
299 i
= ter
->iNodesCount
- 1;
301 ter
->mNodes
[i
].x
= x
;
304 ter
->iLastNodePlacedPosX
= x
;
308 static void chopTerrainNodeDeleteAndShift(struct CTerrain
*ter
,int nodeIndex
)
312 while( i
< ter
->iNodesCount
)
314 ter
->mNodes
[i
- 1] = ter
->mNodes
[i
];
323 int chopUpdateTerrainRecycling(struct CTerrain
*ter
)
328 while(i
< ter
->iNodesCount
)
331 if( iCameraPosX
> ter
->mNodes
[i
].x
)
334 chopTerrainNodeDeleteAndShift(ter
,i
);
336 iNewNodePos
= ter
->iLastNodePlacedPosX
+ 50;
342 if(iLevelMode
== LEVEL_MODE_STEEP
)
345 chopAddTerrainNode(ter
,iNewNodePos
,g
- iR(-v
,v
));
357 int chopTerrainHeightAtPoint(struct CTerrain
*ter
, int pX
)
360 int iNodeIndexOne
=0,iNodeIndexTwo
=0, h
, terY1
, terY2
, terX1
, terX2
, a
, b
;
364 for(i
=1;i
<MAX_TERRAIN_NODES
;i
++)
366 if(ter
->mNodes
[i
].x
> pX
)
368 iNodeIndexOne
= i
- 1;
374 iNodeIndexTwo
= iNodeIndexOne
+ 1;
375 terY1
= ter
->mNodes
[iNodeIndexOne
].y
;
376 terY2
= ter
->mNodes
[iNodeIndexTwo
].y
;
379 terX2
= ter
->mNodes
[iNodeIndexTwo
].x
- ter
->mNodes
[iNodeIndexOne
].x
;
381 pX
-= ter
->mNodes
[iNodeIndexOne
].x
;
394 int chopPointInTerrain(struct CTerrain
*ter
, int pX
, int pY
, int iTestType
)
396 int h
= chopTerrainHeightAtPoint(ter
, pX
);
404 static void chopAddBlock(int x
,int y
,int sx
,int sy
, int indexOverride
)
408 if(indexOverride
< 0)
410 while(mBlocks
[i
].bIsActive
&& i
< NUMBER_OF_BLOCKS
)
412 if(i
==NUMBER_OF_BLOCKS
)
414 DEBUGF("No blocks!\n");
421 mBlocks
[i
].bIsActive
= 1;
422 mBlocks
[i
].iWorldX
= x
;
423 mBlocks
[i
].iWorldY
= y
;
424 mBlocks
[i
].iSizeX
= sx
;
425 mBlocks
[i
].iSizeY
= sy
;
427 iLastBlockPlacedPosX
= x
;
430 static void chopAddParticle(int x
,int y
,int sx
,int sy
)
434 while(mParticles
[i
].bIsActive
&& i
< NUMBER_OF_PARTICLES
)
437 if(i
==NUMBER_OF_PARTICLES
)
440 mParticles
[i
].bIsActive
= 1;
441 mParticles
[i
].iWorldX
= x
;
442 mParticles
[i
].iWorldY
= y
;
443 mParticles
[i
].iSpeedX
= sx
;
444 mParticles
[i
].iSpeedY
= sy
;
447 static void chopGenerateBlockIfNeeded(void)
450 int DistSpeedX
= iPlayerSpeedX
* 5;
451 if(DistSpeedX
<200) DistSpeedX
= 200;
453 while(i
< NUMBER_OF_BLOCKS
)
455 if(!mBlocks
[i
].bIsActive
)
459 iX
= iLastBlockPlacedPosX
+ (350-DistSpeedX
);
463 sY
= blockh
+ iR(1,blockh
/3);
465 chopAddBlock(iX
,iY
,sX
,sY
,i
);
473 static int chopBlockCollideWithPlayer(struct CBlock
*mBlock
)
475 int px
= iPlayerPosX
;
476 int py
= iPlayerPosY
;
478 int x
= mBlock
->iWorldX
-17;
479 int y
= mBlock
->iWorldY
-11;
481 int x2
= x
+ mBlock
->iSizeX
+17;
482 int y2
= y
+ mBlock
->iSizeY
+11;
495 static int chopBlockOffscreen(struct CBlock
*mBlock
)
497 if(mBlock
->iWorldX
+ mBlock
->iSizeX
< iCameraPosX
)
503 static int chopParticleOffscreen(struct CParticle
*mParticle
)
505 if (mParticle
->iWorldX
< iCameraPosX
|| mParticle
->iWorldY
< 0 ||
506 mParticle
->iWorldY
> iScreenY
|| mParticle
->iWorldX
> iCameraPosX
+
515 static void chopKillPlayer(void)
519 for (i
= 0; i
< NUMBER_OF_PARTICLES
; i
++) {
520 mParticles
[i
].bIsActive
= 0;
521 chopAddParticle(iPlayerPosX
+ iR(0,20), iPlayerPosY
+ iR(0,20),
527 if (iPlayerAlive
== 0) {
528 rb
->lcd_set_drawmode(DRMODE_FG
);
530 rb
->lcd_set_foreground(LCD_LIGHTGRAY
);
532 rb
->splash(HZ
, "Game Over");
534 if (score
> highscore
) {
537 rb
->snprintf(scoretext
, sizeof(scoretext
), "New High Score: %d",
539 rb
->splash(HZ
*2, scoretext
);
542 rb
->splash(HZ
/4, "Press " ACTIONTEXT
" to continue");
545 rb
->lcd_set_drawmode(DRMODE_SOLID
);
548 button
= rb
->button_get(true);
555 button
= rb
->button_get(true);
556 if (button
== (ACTION
| BUTTON_REL
)
558 || button
== (ACTION2
| BUTTON_REL
)
573 static void chopDrawTheWorld(void)
577 while(i
< NUMBER_OF_BLOCKS
)
579 if(mBlocks
[i
].bIsActive
)
581 if(chopBlockOffscreen(&mBlocks
[i
]) == 1)
582 mBlocks
[i
].bIsActive
= 0;
584 chopDrawBlock(&mBlocks
[i
]);
592 while(i
< NUMBER_OF_PARTICLES
)
594 if(mParticles
[i
].bIsActive
)
596 if(chopParticleOffscreen(&mParticles
[i
]) == 1)
597 mParticles
[i
].bIsActive
= 0;
599 chopDrawParticle(&mParticles
[i
]);
605 chopRenderTerrain(&mGround
);
606 chopRenderTerrain(&mRoof
);
610 static void chopDrawParticle(struct CParticle
*mParticle
)
613 int iPosX
= (mParticle
->iWorldX
- iCameraPosX
);
614 int iPosY
= (mParticle
->iWorldY
);
616 rb
->lcd_set_foreground(LCD_RGBPACK(192,192,192));
618 rb
->lcd_set_foreground(LCD_LIGHTGRAY
);
620 rb
->lcd_fillrect(SCALE(iPosX
), SCALE(iPosY
), SCALE(3), SCALE(3));
624 static void chopDrawScene(void)
629 rb
->lcd_set_background(LCD_BLACK
);
631 rb
->lcd_set_background(LCD_WHITE
);
633 rb
->lcd_clear_display();
636 chopDrawPlayer(iPlayerPosX
- iCameraPosX
, iPlayerPosY
);
638 score
= -20 + iPlayerPosX
/3;
641 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
643 rb
->lcd_set_drawmode(DRMODE_FG
);
647 rb
->lcd_set_foreground(LCD_BLACK
);
649 rb
->lcd_set_foreground(LCD_WHITE
);
653 rb
->snprintf(s
, sizeof(s
), "Dist: %d", score
);
655 rb
->snprintf(s
, sizeof(s
), "Distance: %d", score
);
657 rb
->lcd_getstringsize(s
, &w
, NULL
);
658 rb
->lcd_putsxy(2, 2, s
);
659 if (score
< highscore
)
663 rb
->snprintf(s
, sizeof(s
), "Hi: %d", highscore
);
665 rb
->snprintf(s
, sizeof(s
), "Best: %d", highscore
);
667 rb
->lcd_getstringsize(s
, &w2
, NULL
);
668 if (LCD_WIDTH
- 2 - w2
> w
+ 2)
669 rb
->lcd_putsxy(LCD_WIDTH
- 2 - w2
, 2, s
);
671 rb
->lcd_set_drawmode(DRMODE_SOLID
);
676 static int chopMenu(int menunum
)
678 int result
= (menunum
==0)?0:1;
680 bool menu_quit
= false;
682 static const struct opt_items levels
[2] = {
687 MENUITEM_STRINGLIST(menu
,"Chopper Menu",NULL
,"Start New Game","Resume Game",
690 #ifdef HAVE_LCD_COLOR
691 rb
->lcd_set_foreground(LCD_WHITE
);
692 rb
->lcd_set_background(LCD_BLACK
);
694 rb
->lcd_set_foreground(LCD_BLACK
);
695 rb
->lcd_set_background(LCD_WHITE
);
698 rb
->lcd_clear_display();
701 switch(rb
->do_menu(&menu
, &result
, NULL
, false))
703 case 0: /* Start New Game */
708 case 1: /* Resume Game */
712 } else if(menunum
==0){
713 rb
->splash(HZ
, "No game to resume");
717 rb
->set_option("Level", &iLevelMode
, INT
, levels
, 2, NULL
);
723 case MENU_ATTACHED_USB
:
725 res
= PLUGIN_USB_CONNECTED
;
729 rb
->lcd_clear_display();
733 static int chopGameLoop(void)
735 int move_button
, ret
;
737 int end
, i
=0, bdelay
=0, last_button
=BUTTON_NONE
;
739 if (chopUpdateTerrainRecycling(&mGround
) == 1)
740 /* mirror the sky if we've changed the ground */
741 chopCopyTerrain(&mGround
, &mRoof
, 0, - ( (iScreenY
* 3) / 4));
751 end
= *rb
->current_tick
+ (CYCLETIME
* HZ
) / 1000;
753 if(chopUpdateTerrainRecycling(&mGround
) == 1)
754 /* mirror the sky if we've changed the ground */
755 chopCopyTerrain(&mGround
, &mRoof
, 0, - ( (iScreenY
* 3) / 4));
757 iRotorOffset
= iR(-1,1);
759 /* We need to have this here so particles move when we're dead */
761 for (i
=0; i
< NUMBER_OF_PARTICLES
; i
++)
762 if(mParticles
[i
].bIsActive
== 1)
764 mParticles
[i
].iWorldX
+= mParticles
[i
].iSpeedX
;
765 mParticles
[i
].iWorldY
+= mParticles
[i
].iSpeedY
;
768 /* Redraw the main window: */
772 iGravityTimerCountdown
--;
774 if(iGravityTimerCountdown
<= 0)
776 iGravityTimerCountdown
= 3;
777 chopAddParticle(iPlayerPosX
, iPlayerPosY
+5, 0, 0);
780 if(iLevelMode
== LEVEL_MODE_NORMAL
)
781 chopGenerateBlockIfNeeded();
784 move_button
=rb
->button_status();
785 if (rb
->button_get(false) == QUIT
) {
790 last_button
= BUTTON_NONE
;
791 move_button
= BUTTON_NONE
;
794 switch (move_button
) {
799 if (last_button
!= ACTION
801 && last_button
!= ACTION2
810 if (last_button
== ACTION
812 || last_button
== ACTION2
819 if (rb
->default_event_handler(move_button
) == SYS_USB_CONNECTED
)
820 return PLUGIN_USB_CONNECTED
;
823 last_button
= move_button
;
826 iPlayerSpeedY
= bdelay
;
828 } else if (bdelay
> 0) {
829 iPlayerSpeedY
= bdelay
;
833 iCameraPosX
= iPlayerPosX
- 25;
834 iPlayerPosX
+= iPlayerSpeedX
;
835 iPlayerPosY
+= iPlayerSpeedY
;
838 /* increase speed as we go along */
839 if (chopCounter
== 100){
844 if (iPlayerPosY
> iScreenY
-10 || iPlayerPosY
< -5 ||
845 chopPointInTerrain(&mGround
, iPlayerPosX
, iPlayerPosY
+ 10, 0) ||
846 chopPointInTerrain(&mRoof
, iPlayerPosX
,iPlayerPosY
, 1))
855 for (i
=0; i
< NUMBER_OF_BLOCKS
; i
++)
856 if(mBlocks
[i
].bIsActive
== 1)
857 if(chopBlockCollideWithPlayer(&mBlocks
[i
])) {
865 if (end
> *rb
->current_tick
)
866 rb
->sleep(end
-*rb
->current_tick
);
874 static void chopDrawBlock(struct CBlock
*mBlock
)
876 int iPosX
= (mBlock
->iWorldX
- iCameraPosX
);
877 int iPosY
= (mBlock
->iWorldY
);
879 rb
->lcd_set_foreground(LCD_RGBPACK(100,255,100));
881 rb
->lcd_set_foreground(LCD_BLACK
);
883 rb
->lcd_fillrect(SCALE(iPosX
), SCALE(iPosY
), SCALE(mBlock
->iSizeX
),
884 SCALE(mBlock
->iSizeY
));
888 static void chopRenderTerrain(struct CTerrain
*ter
)
896 if(ter
->mNodes
[0].y
< (LCD_HEIGHT
*SIZE
)/2)
899 ay
=(LCD_HEIGHT
*SIZE
);
901 while(i
< ter
->iNodesCount
&& oldx
< iScreenX
)
904 int x
= ter
->mNodes
[i
-1].x
- iCameraPosX
;
905 int y
= ter
->mNodes
[i
-1].y
;
907 int x2
= ter
->mNodes
[i
].x
- iCameraPosX
;
908 int y2
= ter
->mNodes
[i
].y
;
910 rb
->lcd_set_foreground(LCD_RGBPACK(100,255,100));
912 rb
->lcd_set_foreground(LCD_DARKGRAY
);
915 rb
->lcd_drawline(SCALE(x
), SCALE(y
), SCALE(x2
), SCALE(y2
));
917 xlcd_filltriangle(SCALE(x
), SCALE(y
), SCALE(x2
), SCALE(y2
),
918 SCALE(x2
), SCALE(ay
));
919 xlcd_filltriangle(SCALE(x
), SCALE(ay
), SCALE(x2
), SCALE(y2
),
920 SCALE(x2
), SCALE(ay
));
923 xlcd_filltriangle(SCALE(x
), SCALE(ay
), SCALE(x
), SCALE(y
),
924 SCALE(x2
), SCALE(y2
/ 2));
926 xlcd_filltriangle(SCALE(x
), SCALE(ay
), SCALE(x
), SCALE(y
),
927 SCALE(x2
), SCALE((LCD_HEIGHT
*SIZE
) -
928 ((LCD_HEIGHT
*SIZE
) - y2
) / 2));
937 void chopper_load(bool newgame
)
944 iScreenX
= LCD_WIDTH
* SIZE
;
945 iScreenY
= LCD_HEIGHT
* SIZE
;
946 blockh
= iScreenY
/ 5;
947 blockw
= iScreenX
/ 20;
953 iPlayerPosY
= (iScreenY
* 4) / 10;
954 iLastBlockPlacedPosX
= 0;
955 iGravityTimerCountdown
= 2;
961 for (i
=0; i
< NUMBER_OF_PARTICLES
; i
++)
962 mParticles
[i
].bIsActive
= 0;
964 for (i
=0; i
< NUMBER_OF_BLOCKS
; i
++)
965 mBlocks
[i
].bIsActive
= 0;
968 chopClearTerrain(&mGround
);
970 for (i
=0; i
< MAX_TERRAIN_NODES
; i
++)
971 chopAddTerrainNode(&mGround
,i
* 30,g
- iR(0,20));
973 if (chopUpdateTerrainRecycling(&mGround
) == 1)
974 /* mirror the sky if we've changed the ground */
975 chopCopyTerrain(&mGround
, &mRoof
, 0, - ( (iScreenY
* 3) / 4));
977 iLevelMode
= LEVEL_MODE_NORMAL
;
978 if (iLevelMode
== LEVEL_MODE_NORMAL
)
979 /* make it a bit more exciting, cause it's easy terrain... */
983 /* this is the plugin entry point */
984 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
990 rb
->lcd_setfont(FONT_SYSFIXED
);
992 rb
->lcd_set_backdrop(NULL
);
994 #ifdef HAVE_LCD_COLOR
995 rb
->lcd_set_background(LCD_BLACK
);
996 rb
->lcd_set_foreground(LCD_WHITE
);
999 /* Turn off backlight timeout */
1000 backlight_force_on(rb
); /* backlight control in lib/helper.c */
1002 rb
->srand( *rb
->current_tick
);
1005 configfile_init(rb
);
1006 configfile_load(CFG_FILE
, config
, 1, 0);
1009 ret
= chopGameLoop();
1011 configfile_save(CFG_FILE
, config
, 1, 0);
1013 rb
->lcd_setfont(FONT_UI
);
1014 /* Turn on backlight timeout (revert to settings) */
1015 backlight_use_settings(rb
); /* backlight control in lib/helper.c */