Fix empty commit: Add grayscale support for ARM in vertical packing format.
[Rockbox.git] / apps / plugins / fire.c
blobfb08e5a5f13e1ef43d66cff00c7240d2c21f9884
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Kevin Ferrare
12 * Fire demo plugin
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "plugin.h"
23 #include "helper.h"
25 #ifdef HAVE_LCD_BITMAP /* and also not for the Player */
26 #ifndef HAVE_LCD_COLOR
27 #include "gray.h"
28 #endif
30 PLUGIN_HEADER
32 /******************************* Globals ***********************************/
34 static struct plugin_api* rb; /* global api struct pointer */
36 static unsigned char fire[LCD_HEIGHT+3][LCD_WIDTH];
37 static unsigned char cooling_map[LCD_HEIGHT][LCD_WIDTH];
39 #ifndef HAVE_LCD_COLOR
40 static unsigned char *gbuf;
41 static size_t gbuf_size = 0;
42 static unsigned char draw_buffer[8*LCD_WIDTH];
43 #endif
45 /* Key assignement */
47 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
48 #define FIRE_QUIT BUTTON_OFF
49 #define FIRE_SWITCH_FLAMES_TYPE BUTTON_MODE
50 #define FIRE_SWITCH_FLAMES_MOVING BUTTON_REC
51 #define FIRE_INCREASE_MULT BUTTON_UP
52 #define FIRE_DECREASE_MULT BUTTON_DOWN
54 #define FIRE_RC_QUIT BUTTON_RC_STOP
56 #elif CONFIG_KEYPAD == RECORDER_PAD
57 #define FIRE_QUIT BUTTON_OFF
58 #define FIRE_SWITCH_FLAMES_TYPE BUTTON_ON
59 #define FIRE_SWITCH_FLAMES_MOVING BUTTON_PLAY
60 #define FIRE_INCREASE_MULT BUTTON_UP
61 #define FIRE_DECREASE_MULT BUTTON_DOWN
63 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
64 #define FIRE_QUIT BUTTON_OFF
65 #define FIRE_SWITCH_FLAMES_TYPE BUTTON_ON
66 #define FIRE_SWITCH_FLAMES_MOVING BUTTON_SELECT
67 #define FIRE_INCREASE_MULT BUTTON_UP
68 #define FIRE_DECREASE_MULT BUTTON_DOWN
70 #elif CONFIG_KEYPAD == ONDIO_PAD
71 #define FIRE_QUIT BUTTON_OFF
72 #define FIRE_SWITCH_FLAMES_TYPE BUTTON_MENU
73 #define FIRE_SWITCH_FLAMES_MOVING BUTTON_RIGHT
74 #define FIRE_INCREASE_MULT BUTTON_UP
75 #define FIRE_DECREASE_MULT BUTTON_DOWN
77 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
78 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
79 #define FIRE_QUIT BUTTON_MENU
80 #define FIRE_SWITCH_FLAMES_TYPE BUTTON_SELECT
81 #define FIRE_SWITCH_FLAMES_MOVING BUTTON_RIGHT
82 #define FIRE_INCREASE_MULT BUTTON_SCROLL_FWD
83 #define FIRE_DECREASE_MULT BUTTON_SCROLL_BACK
85 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
86 #define FIRE_QUIT BUTTON_POWER
87 #define FIRE_SWITCH_FLAMES_TYPE BUTTON_LEFT
88 #define FIRE_SWITCH_FLAMES_MOVING BUTTON_RIGHT
89 #define FIRE_INCREASE_MULT BUTTON_UP
90 #define FIRE_DECREASE_MULT BUTTON_DOWN
92 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
93 #define FIRE_QUIT BUTTON_POWER
94 #define FIRE_SWITCH_FLAMES_TYPE BUTTON_LEFT
95 #define FIRE_SWITCH_FLAMES_MOVING BUTTON_RIGHT
96 #define FIRE_INCREASE_MULT BUTTON_UP
97 #define FIRE_DECREASE_MULT BUTTON_DOWN
99 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
100 (CONFIG_KEYPAD == SANSA_C200_PAD)
101 #define FIRE_QUIT BUTTON_POWER
102 #define FIRE_SWITCH_FLAMES_TYPE BUTTON_LEFT
103 #define FIRE_SWITCH_FLAMES_MOVING BUTTON_RIGHT
104 #define FIRE_INCREASE_MULT BUTTON_UP
105 #define FIRE_DECREASE_MULT BUTTON_DOWN
107 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
108 #define FIRE_QUIT BUTTON_POWER
109 #define FIRE_SWITCH_FLAMES_TYPE BUTTON_LEFT
110 #define FIRE_SWITCH_FLAMES_MOVING BUTTON_RIGHT
111 #define FIRE_INCREASE_MULT BUTTON_SCROLL_UP
112 #define FIRE_DECREASE_MULT BUTTON_SCROLL_DOWN
114 #elif (CONFIG_KEYPAD == IRIVER_IFP7XX_PAD)
115 #define FIRE_QUIT BUTTON_PLAY
116 #define FIRE_SWITCH_FLAMES_TYPE BUTTON_MODE
117 #define FIRE_SWITCH_FLAMES_MOVING BUTTON_EQ
118 #define FIRE_INCREASE_MULT BUTTON_UP
119 #define FIRE_DECREASE_MULT BUTTON_DOWN
121 #endif
123 #define MIN_FLAME_VALUE 0
124 #define COOL_MAX (440/LCD_HEIGHT+2)
126 /* fast unsigned multiplication (16x16bit->32bit or 32x32bit->32bit,
127 * whichever is faster for the architecture) */
128 #ifdef CPU_ARM
129 #define FMULU(a, b) ((uint32_t) (((uint32_t) (a)) * ((uint32_t) (b))))
130 #else /* SH1, coldfire */
131 #define FMULU(a, b) ((uint32_t) (((uint16_t) (a)) * ((uint16_t) (b))))
132 #endif
134 #ifndef HAVE_LCD_COLOR
135 static const unsigned char palette[256] = {
136 0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22,
137 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45, 46,
138 48, 49, 51, 52, 54, 55, 57, 59, 60, 61, 63, 64, 66, 67, 69, 70,
139 72, 73, 75, 76, 78, 79, 81, 82, 84, 85, 87, 88, 90, 91, 93, 94,
140 96, 97, 99, 100, 102, 103, 105, 106, 108, 109, 111, 112, 114, 115, 117, 118,
141 120, 121, 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 142,
142 144, 145, 147, 148, 150, 151, 153, 154, 156, 157, 159, 160, 162, 163, 165, 166,
143 168, 169, 171, 172, 174, 175, 177, 178, 180, 181, 183, 184, 186, 187, 189, 190,
144 192, 193, 195, 196, 198, 199, 201, 202, 204, 205, 207, 208, 210, 211, 213, 214,
145 216, 217, 219, 220, 222, 223, 225, 226, 228, 229, 231, 232, 234, 235, 237, 238,
146 /* 'regular' fire doesn't exceed this value */
147 240, 240, 240, 240, 240, 240, 241, 241, 241, 241, 241, 241, 242, 242, 242, 242,
148 242, 242, 243, 243, 243, 243, 243, 243, 244, 244, 244, 244, 244, 244, 245, 245,
149 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 247, 247, 247, 247, 247, 247,
150 248, 248, 248, 248, 248, 248, 249, 249, 249, 249, 249, 249, 250, 250, 250, 250,
151 250, 250, 251, 251, 251, 251, 251, 251, 252, 252, 252, 252, 252, 252, 253, 253,
152 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255
154 #else
155 #define L(r,g,b) LCD_RGBPACK(r,g,b)
157 static const fb_data colorpalette[256] = {
158 L( 0, 0, 0), L( 5, 0, 0), L( 10, 0, 0), L( 15, 0, 0), L( 20, 0, 0),
159 L( 25, 0, 0), L( 30, 0, 0), L( 35, 0, 0), L( 40, 0, 0), L( 45, 0, 0),
160 L( 50, 0, 0), L( 55, 0, 0), L( 60, 0, 0), L( 65, 0, 0), L( 70, 0, 0),
161 L( 75, 0, 0), L( 80, 0, 0), L( 85, 0, 0), L( 90, 0, 0), L( 95, 0, 0),
162 L(100, 0, 0), L(105, 0, 0), L(110, 0, 0), L(115, 0, 0), L(120, 0, 0),
163 L(125, 0, 0), L(130, 0, 0), L(135, 0, 0), L(140, 0, 0), L(145, 0, 0),
164 L(150, 0, 0), L(155, 0, 0), L(160, 0, 0), L(165, 0, 0), L(170, 0, 0),
165 L(175, 0, 0), L(180, 0, 0), L(185, 0, 0), L(186, 2, 0), L(187, 5, 1),
166 L(188, 6, 2), L(189, 8, 3), L(190, 10, 4), L(191, 12, 4), L(192, 14, 5),
167 L(193, 15, 6), L(194, 17, 7), L(195, 19, 8), L(196, 21, 8), L(197, 22, 9),
168 L(198, 24, 10), L(198, 26, 10), L(199, 28, 10), L(200, 29, 11), L(201, 32, 11),
169 L(202, 34, 12), L(203, 36, 13), L(204, 39, 13), L(205, 40, 14), L(206, 42, 14),
170 L(207, 43, 15), L(208, 46, 16), L(208, 48, 17), L(209, 50, 18), L(210, 51, 18),
171 L(212, 53, 19), L(213, 55, 20), L(214, 57, 21), L(215, 59, 22), L(216, 61, 22),
172 L(217, 63, 23), L(217, 65, 24), L(218, 67, 24), L(219, 69, 25), L(220, 70, 25),
173 L(222, 72, 26), L(223, 74, 27), L(224, 76, 28), L(225, 78, 28), L(225, 80, 29),
174 L(226, 82, 29), L(227, 84, 30), L(228, 86, 31), L(228, 88, 32), L(229, 90, 32),
175 L(230, 92, 32), L(231, 94, 33), L(232, 96, 34), L(233, 98, 35), L(234, 99, 36),
176 L(235,101, 37), L(236,103, 37), L(237,105, 38), L(238,107, 39), L(240,109, 39),
177 L(240,111, 40), L(241,113, 40), L(242,114, 41), L(242,116, 42), L(243,119, 43),
178 L(245,120, 43), L(246,122, 44), L(247,124, 44), L(248,126, 46), L(248,128, 47),
179 L(249,130, 47), L(251,131, 47), L(252,133, 48), L(253,135, 49), L(253,138, 49),
180 L(253,140, 50), L(254,143, 49), L(254,145, 48), L(253,148, 47), L(253,151, 46),
181 L(253,154, 45), L(253,156, 44), L(253,158, 44), L(252,162, 42), L(252,165, 41),
182 L(252,167, 41), L(252,170, 40), L(251,173, 40), L(252,175, 38), L(252,178, 37),
183 L(251,181, 37), L(251,183, 36), L(251,186, 35), L(250,189, 34), L(250,192, 33),
184 L(250,194, 33), L(249,198, 31), L(249,200, 31), L(249,203, 30), L(249,206, 29),
185 L(249,209, 28), L(249,211, 27), L(249,214, 26), L(248,216, 25), L(248,219, 25),
186 L(248,222, 24), L(248,224, 23), L(248,227, 22), L(248,230, 21), L(248,232, 21),
187 L(247,236, 19), L(247,238, 23), L(247,239, 31), L(247,239, 45), L(247,240, 55),
188 L(248,240, 68), L(247,241, 78), L(248,241, 90), L(247,242,102), L(248,242,114),
189 L(247,243,125), L(248,243,138), L(248,243,153), L(248,244,162), L(248,245,174),
190 /* 'regular' fire doesn't exceed this value */
191 L(247,245,182), L(247,245,182), L(247,245,183), L(247,245,183), L(247,245,184),
192 L(247,245,184), L(247,245,185), L(247,245,185), L(247,245,186), L(247,245,186),
193 L(247,245,187), L(247,245,187), L(247,245,188), L(247,245,188), L(247,245,189),
194 L(247,245,189), L(248,245,190), L(248,245,190), L(248,245,191), L(248,245,191),
195 L(248,245,192), L(248,245,192), L(248,245,193), L(248,245,193), L(248,245,194),
196 L(248,245,194), L(248,245,195), L(248,245,195), L(248,245,196), L(248,245,196),
197 L(248,245,197), L(248,245,197), L(248,245,198), L(248,245,198), L(248,245,199),
198 L(248,245,199), L(248,245,200), L(248,245,200), L(248,245,201), L(248,245,201),
199 L(248,245,202), L(248,245,202), L(248,245,203), L(248,245,203), L(248,245,204),
200 L(248,245,204), L(248,245,205), L(248,245,205), L(248,246,206), L(248,246,206),
201 L(248,246,207), L(248,246,207), L(248,246,208), L(248,246,208), L(248,246,209),
202 L(248,246,209), L(248,246,210), L(248,246,210), L(248,246,211), L(248,246,211),
203 L(248,246,212), L(248,246,212), L(248,246,213), L(248,246,213), L(248,246,214),
204 L(248,246,214), L(248,246,215), L(248,246,215), L(248,246,216), L(248,246,216),
205 L(248,246,217), L(248,246,217), L(248,246,218), L(248,246,218), L(248,246,219),
206 L(248,246,219), L(248,246,220), L(248,246,220), L(248,246,221), L(248,246,221),
207 L(248,246,222), L(248,246,222), L(248,246,223), L(248,246,223), L(248,246,224),
208 L(248,246,224), L(248,246,225), L(248,246,225), L(248,246,226), L(248,246,226),
209 L(248,246,227), L(248,246,227), L(248,246,228), L(248,246,228), L(248,246,229),
210 L(248,246,229)
212 #endif
214 static inline void tab_init_rand(unsigned char *tab, unsigned int tab_size,
215 int rand_max)
217 unsigned char *end = tab + tab_size;
219 while(tab < end)
220 *tab++ = (unsigned char)rb->rand() % rand_max;
223 static inline void fire_generate(int mult, int flames_type, bool moving)
225 unsigned int pixel_value = 0; /* stop the compiler complaining */
226 unsigned int cooling_value;
227 unsigned char *ptr, *end, *cool;
229 /* Randomize the bottom line */
230 if(moving)
231 {/* moving must be true the first time the function is called */
232 ptr = &fire[LCD_HEIGHT][0];
233 end = ptr + LCD_WIDTH;
237 *ptr++ = (MIN_FLAME_VALUE + rb->rand() % (256-MIN_FLAME_VALUE));
239 while (ptr < end);
241 rb->yield();
243 /* Convolve the pixels and handle cooling (to add nice shapes effects later) */
244 cool = &cooling_map[0][0];
245 ptr = &fire[0][0];
246 end = ptr + LCD_HEIGHT*LCD_WIDTH;
248 switch (flames_type)
250 case 0:
253 pixel_value = ptr[LCD_WIDTH-1] /* fire[y+1][x-1] */
254 + ptr[2*LCD_WIDTH] /* fire[y+2][x] */
255 + ptr[LCD_WIDTH+1] /* fire[y+1][x+1] */
256 + ptr[3*LCD_WIDTH]; /* fire[y+3][x] */
257 pixel_value = FMULU(pixel_value, mult) >> 10;
259 cooling_value = *cool++;
260 if (cooling_value <= pixel_value)
261 pixel_value -= cooling_value;
262 /* else it's too cold, don't frost the pixels !!! */
264 if (pixel_value > 255)
265 pixel_value = 255;
267 *ptr++ = pixel_value;
269 while (ptr < end);
270 break;
272 case 1:
273 mult -= 2;
276 pixel_value = ptr[LCD_WIDTH-1] /* fire[y+1][x-1] */
277 + ptr[LCD_WIDTH] /* fire[y+1][x] */
278 + ptr[LCD_WIDTH+1] /* fire[y+1][x+1] */
279 + ptr[2*LCD_WIDTH]; /* fire[y+2][x] */
280 pixel_value = FMULU(pixel_value, mult) >> 10;
282 cooling_value = *cool++;
283 if (cooling_value <= pixel_value)
284 pixel_value -= cooling_value;
285 /* else it's too cold, don't frost the pixels !!! */
287 if (pixel_value > 255)
288 pixel_value = 255;
290 *ptr++ = pixel_value;
292 while (ptr < end);
293 break;
295 default: /* We should never reach this */
296 break;
298 rb->yield();
301 static inline void fire_draw(void)
303 #ifndef HAVE_LCD_COLOR
304 int block;
305 unsigned char *dest, *end;
306 unsigned char *src = &fire[0][0];
308 for (block = 0; block < LCD_HEIGHT; block += 8)
310 dest = draw_buffer;
311 end = dest + 8*LCD_WIDTH;
314 *dest++ = palette[*src++];
315 while(dest < end);
317 gray_ub_gray_bitmap(draw_buffer, 0, block, LCD_WIDTH, 8);
319 #else
320 fb_data* dest = rb->lcd_framebuffer;
321 fb_data* end = rb->lcd_framebuffer+(LCD_WIDTH*LCD_HEIGHT);
322 unsigned char* src = &fire[0][0];
325 *dest++ = colorpalette[*src++];
326 while (dest < end);
328 rb->lcd_update();
329 #endif
332 void cleanup(void *parameter)
334 (void)parameter;
336 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
337 rb->cpu_boost(false);
338 #endif
339 #ifndef HAVE_LCD_COLOR
340 gray_release();
341 #endif
342 /* Turn on backlight timeout (revert to settings) */
343 backlight_use_settings(rb); /* backlight control in lib/helper.c */
347 * Main function that also contain the main plasma
348 * algorithm.
351 int main(void)
353 int button;
354 int mult = 261;
355 int flames_type=0;
356 bool moving=true;
357 #ifndef HAVE_LCD_COLOR
358 int shades;
360 /* get the remainder of the plugin buffer */
361 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size);
362 shades = gray_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT,
363 32, 1<<8, NULL) + 1;
364 if(shades <= 1)
366 rb->splash(HZ, "not enough memory");
367 return PLUGIN_ERROR;
369 /* switch on grayscale overlay */
370 gray_show(true);
371 #endif
373 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
374 rb->cpu_boost(true);
375 #endif
376 rb->memset(&fire[0][0], 0, sizeof(fire));
377 tab_init_rand(&cooling_map[0][0], LCD_HEIGHT*LCD_WIDTH, COOL_MAX);
378 while (true)
380 fire_generate(mult, flames_type, moving);
381 fire_draw();
382 rb->yield();
384 button = rb->button_get(false);
386 switch(button)
388 #ifdef FIRE_RC_QUIT
389 case FIRE_RC_QUIT :
390 #endif
391 case (FIRE_QUIT):
392 cleanup(NULL);
393 return PLUGIN_OK;
394 break;
396 case (FIRE_INCREASE_MULT):
397 ++mult;
398 break;
400 case (FIRE_DECREASE_MULT):
401 if (mult > 0)
402 --mult;
403 break;
405 case (FIRE_SWITCH_FLAMES_TYPE):
406 flames_type = (flames_type + 1) % 2;
407 break;
409 case (FIRE_SWITCH_FLAMES_MOVING):
410 moving = !moving;
411 break;
413 default:
414 if (rb->default_event_handler_ex(button, cleanup, NULL)
415 == SYS_USB_CONNECTED)
416 return PLUGIN_USB_CONNECTED;
417 break;
422 /*************************** Plugin entry point ****************************/
424 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
426 int ret;
428 rb = api; // copy to global api pointer
429 (void)parameter;
430 #if LCD_DEPTH > 1
431 rb->lcd_set_backdrop(NULL);
432 #endif
433 /* Turn off backlight timeout */
434 backlight_force_on(rb); /* backlight control in lib/helper.c */
436 ret = main();
438 return ret;
441 #endif /* #ifdef HAVE_LCD_BITMAP */