1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Kevin Ferrare
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
25 #include "lib/helper.h"
26 #ifdef HAVE_LCD_BITMAP
28 #include "lib/pluginlib_actions.h"
29 #include "lib/fixedpoint.h"
31 #ifndef HAVE_LCD_COLOR
35 #if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
36 /* Archos has not enough plugin RAM for full-width fire :( */
37 #define FIRE_WIDTH 106
40 #define FIRE_WIDTH LCD_WIDTH
46 #ifndef HAVE_LCD_COLOR
48 static unsigned char draw_buffer
[FIRE_WIDTH
];
53 const struct button_mapping
* plugin_contexts
[]= {
55 #if defined(HAVE_REMOTE_LCD)
60 #define FIRE_QUIT PLA_CANCEL
61 #define FIRE_SWITCH_FLAMES_TYPE PLA_LEFT
62 #define FIRE_SWITCH_FLAMES_MOVING PLA_RIGHT
64 #ifdef HAVE_SCROLLWHEEL
65 #define FIRE_INCREASE_MULT PLA_SCROLL_FWD
66 #define FIRE_INCREASE_MULT_REP PLA_SCROLL_FWD_REPEAT
67 #define FIRE_DECREASE_MULT PLA_SCROLL_BACK
68 #define FIRE_DECREASE_MULT_REP PLA_SCROLL_BACK_REPEAT
70 #define FIRE_INCREASE_MULT PLA_UP
71 #define FIRE_INCREASE_MULT_REP PLA_UP_REPEAT
72 #define FIRE_DECREASE_MULT PLA_DOWN
73 #define FIRE_DECREASE_MULT_REP PLA_DOWN_REPEAT
76 #define MIN_FLAME_VALUE 0
77 #define COOL_MAX (440/LCD_HEIGHT+2)
79 #ifndef HAVE_LCD_COLOR
80 static unsigned char palette
[256];
82 void color_palette_init(unsigned char* palette
)
85 for(i
=0;i
<=160;i
++)//palette[i]=(3/2)*i
88 /* 'regular' fire doesn't exceed this value */
89 for(;i
<=255;i
++)//palette[i]=(3/20)*i+216
90 palette
[i
]=(i
*3+20*217)/20;
94 static fb_data palette
[256];
97 * Color palette generation algorithm taken from
98 * the "The Demo Effects Collection" GPL project
99 * Copyright (C) 2002 W.P. van Paassen
101 void color_palette_init(fb_data
* palette
)
104 for (i
= 0; i
< 32; i
++){
105 /* black to blue, 32 values*/
106 palette
[i
]=LCD_RGBPACK(0, 0, 2*i
);
108 /* blue to red, 32 values*/
109 palette
[i
+ 32]=LCD_RGBPACK(8*i
, 0, 64 - 2*i
);
111 /* red to yellow, 32 values*/
112 palette
[i
+ 64]=LCD_RGBPACK(255, 8*i
, 0);
114 /* yellow to white, 162 values */
115 palette
[i
+ 96]=LCD_RGBPACK(255, 255, 0 + 4*i
);
116 palette
[i
+ 128]=LCD_RGBPACK(255, 255, 64 + 4*i
);
117 palette
[i
+ 160]=LCD_RGBPACK(255, 255, 128 + 4*i
);
118 palette
[i
+ 192]=LCD_RGBPACK(255, 255, 192 + i
);
119 palette
[i
+ 224]=LCD_RGBPACK(255, 255, 224 + i
);
121 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
122 rb
->lcd_pal256_update_pal(palette
);
128 static void tab_init_rand(unsigned char *tab
, unsigned int tab_size
,
131 unsigned char *end
= tab
+ tab_size
;
134 *tab
++ = (unsigned char)rb
->rand() % rand_max
;
138 unsigned char fire
[LCD_HEIGHT
+3][FIRE_WIDTH
];
139 unsigned char cooling_map
[LCD_HEIGHT
][FIRE_WIDTH
];
144 /* makes the instance a global variable since it's too big to fit on the target's stack */
145 static struct fire fire
;
147 static inline void fire_convolve(struct fire
* fire
)
149 unsigned int pixel_value
;
150 unsigned int cooling_value
;
151 unsigned char *ptr
, *end
, *cool
;
152 unsigned int mult
=fire
->mult
;
155 /* Convolve the pixels and handle cooling (to add nice shapes effects later) */
156 cool
= &fire
->cooling_map
[0][0];
157 ptr
= &fire
->fire
[0][0];
158 end
= ptr
+ LCD_HEIGHT
*FIRE_WIDTH
;
160 switch (fire
->flames_type
){
163 pixel_value
= ptr
[FIRE_WIDTH
-1] /* fire[y+1][x-1] */
164 + ptr
[2*FIRE_WIDTH
] /* fire[y+2][x] */
165 + ptr
[FIRE_WIDTH
+1] /* fire[y+1][x+1] */
166 + ptr
[3*FIRE_WIDTH
]; /* fire[y+3][x] */
167 pixel_value
= FMULU(pixel_value
, mult
) >> 10;
169 cooling_value
= *cool
++;
170 if (cooling_value
<= pixel_value
)
171 pixel_value
-= cooling_value
;
172 /* else it's too cold, don't frost the pixels !!! */
174 if (pixel_value
> 255)
177 *ptr
++ = pixel_value
;
184 pixel_value
= ptr
[FIRE_WIDTH
-1] /* fire[y+1][x-1] */
185 + ptr
[FIRE_WIDTH
] /* fire[y+1][x] */
186 + ptr
[FIRE_WIDTH
+1] /* fire[y+1][x+1] */
187 + ptr
[2*FIRE_WIDTH
]; /* fire[y+2][x] */
188 pixel_value
= FMULU(pixel_value
, mult
) >> 10;
190 cooling_value
= *cool
++;
191 if (cooling_value
<= pixel_value
)
192 pixel_value
-= cooling_value
;
193 /* else it's too cold, don't frost the pixels !!! */
195 if (pixel_value
> 255)
198 *ptr
++ = pixel_value
;
202 default: /* We should never reach this */
208 static void fire_generate_bottom_seed(struct fire
* fire
)
210 unsigned char *ptr
, *end
;
211 ptr
= &fire
->fire
[LCD_HEIGHT
][0];
212 end
= ptr
+ FIRE_WIDTH
;
214 *ptr
++ = (MIN_FLAME_VALUE
+ rb
->rand() % (256-MIN_FLAME_VALUE
));
218 static inline void fire_step(struct fire
* fire
)
221 /* Randomize the bottom line */
222 fire_generate_bottom_seed(fire
);
223 /* Add here further effects like fire letters, ball ... */
228 static void fire_init(struct fire
* fire
)
233 rb
->memset(&fire
->fire
[0][0], 0, sizeof(fire
->fire
));
234 tab_init_rand(&fire
->cooling_map
[0][0], LCD_HEIGHT
*FIRE_WIDTH
, COOL_MAX
);
235 fire_generate_bottom_seed(fire
);
238 static inline void fire_draw(struct fire
* fire
)
240 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
241 rb
->lcd_blit_pal256((unsigned char*)&fire
->fire
[0][0],0,0,0,0,LCD_WIDTH
,LCD_HEIGHT
);
244 unsigned char *src
= &fire
->fire
[0][0];
246 #ifndef HAVE_LCD_COLOR
247 unsigned char *dest
, *end
;
252 for (y
= 0; y
< LCD_HEIGHT
; y
++){
253 #ifndef HAVE_LCD_COLOR
256 dest
= rb
->lcd_framebuffer
+ LCD_WIDTH
* y
+ FIRE_XPOS
;
258 end
= dest
+ FIRE_WIDTH
;
261 *dest
++ = palette
[*src
++];
263 #ifndef HAVE_LCD_COLOR
264 grey_ub_gray_bitmap(draw_buffer
, 0, y
, FIRE_WIDTH
, 1);
267 #ifdef HAVE_LCD_COLOR
274 void cleanup(void *parameter
)
277 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
278 rb
->cpu_boost(false);
280 #ifndef HAVE_LCD_COLOR
283 /* Turn on backlight timeout (revert to settings) */
284 backlight_use_settings(); /* backlight control in lib/helper.c */
288 #ifndef HAVE_LCD_COLOR
292 size_t gbuf_size
= 0;
294 /* get the remainder of the plugin buffer */
295 gbuf
= (unsigned char *) rb
->plugin_get_buffer(&gbuf_size
);
297 if (!grey_init(gbuf
, gbuf_size
, GREY_ON_COP
,
298 FIRE_WIDTH
, LCD_HEIGHT
, NULL
)){
299 rb
->splash(HZ
, "not enough memory");
302 /* switch on greyscale overlay */
303 grey_set_position(FIRE_XPOS
, 0);
313 #ifndef HAVE_LCD_COLOR
314 if(init_grey()!=PLUGIN_OK
)
315 return(PLUGIN_ERROR
);
317 color_palette_init(palette
);
319 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
329 action
= pluginlib_getaction(0, plugin_contexts
,
330 ARRAYLEN(plugin_contexts
));
337 case FIRE_INCREASE_MULT
:
341 case FIRE_DECREASE_MULT
:
346 case FIRE_SWITCH_FLAMES_TYPE
:
347 fire
.flames_type
= (fire
.flames_type
+ 1) % 2;
350 case FIRE_SWITCH_FLAMES_MOVING
:
351 fire
.moving
= !fire
.moving
;
355 if (rb
->default_event_handler_ex(action
, cleanup
, NULL
)
356 == SYS_USB_CONNECTED
)
357 return PLUGIN_USB_CONNECTED
;
362 /*************************** Plugin entry point ****************************/
364 enum plugin_status
plugin_start(const void* parameter
)
370 rb
->lcd_set_backdrop(NULL
);
372 /* Turn off backlight timeout */
373 backlight_force_on(); /* backlight control in lib/helper.c */
375 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
376 rb
->lcd_set_mode(LCD_MODE_PAL256
);
381 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
382 rb
->lcd_set_mode(LCD_MODE_RGB565
);
388 #endif /* #ifdef HAVE_LCD_BITMAP */