Magellan Linux

Contents of /trunk/busybox/patches/busybox-1.15.3-fbsplash-tykef-1.0.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1044 - (show annotations) (download)
Sat May 8 10:56:35 2010 UTC (13 years, 11 months ago) by niro
File size: 55144 byte(s)
-adds some advanced features to fbslash

1 *** busybox-1.15.0/include/usage.h.orig 2009-08-22 14:52:14.000000000 +0200
2 --- busybox-1.15.0/include/usage.h 2009-09-01 08:42:18.000000000 +0200
3 ***************
4 *** 156,162 ****
5 "\n -n Start new tone" \
6
7 #define fbsplash_trivial_usage \
8 ! "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD]"
9 #define fbsplash_full_usage "\n\n" \
10 "Options:\n" \
11 "\n -s Image" \
12 --- 156,163 ----
13 "\n -n Start new tone" \
14
15 #define fbsplash_trivial_usage \
16 ! "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD] " \
17 ! IF_FEATURE_FBSPLASH_FONTLOAD( "[-m FONTMAPFILE]" )
18 #define fbsplash_full_usage "\n\n" \
19 "Options:\n" \
20 "\n -s Image" \
21 ***************
22 *** 165,172 ****
23 --- 166,178 ----
24 "\n -i Config file (var=value):" \
25 "\n BAR_LEFT,BAR_TOP,BAR_WIDTH,BAR_HEIGHT" \
26 "\n BAR_R,BAR_G,BAR_B" \
27 + "\n TEXT_LEFT,TEXT_TOP,TEXT_R,TEXT_G,TEXT_B,TEXT_SIZE" \
28 "\n -f Control pipe (else exit after drawing image)" \
29 "\n commands: 'NN' (% for progress bar) or 'exit'" \
30 + IF_FEATURE_FBSPLASH_FONTLOAD( \
31 + "\n -m Font map file" \
32 + "\n commands: 'NN' (% for progress bar), 'write:string to print' or 'exit'" \
33 + )
34
35 #define brctl_trivial_usage \
36 "COMMAND [BRIDGE [INTERFACE]]"
37 *** busybox-1.15.0/miscutils/Config.in.orig 2009-08-22 17:59:16.000000000 +0200
38 --- busybox-1.15.0/miscutils/Config.in 2009-09-01 08:44:41.000000000 +0200
39 ***************
40 *** 256,262 ****
41 default n
42 help
43 Shows splash image and progress bar on framebuffer device.
44 ! Can be used during boot phase of an embedded device. ~2kb.
45 Usage:
46 - use kernel option 'vga=xxx' or otherwise enable fb device.
47 - put somewhere fbsplash.cfg file and an image in .ppm format.
48 --- 256,263 ----
49 default n
50 help
51 Shows splash image and progress bar on framebuffer device.
52 ! Can be used during boot phase of an embedded device.
53 ! Code size is 2..7kb depends on enabled features.
54 Usage:
55 - use kernel option 'vga=xxx' or otherwise enable fb device.
56 - put somewhere fbsplash.cfg file and an image in .ppm format.
57 ***************
58 *** 272,277 ****
59 --- 273,316 ----
60 "NN" (ASCII decimal number) - percentage to show on progress bar
61 "exit" - well you guessed it
62
63 + config FEATURE_FBSPLASH_8BPP
64 + bool "support 8bit depth with color mapping"
65 + depends on FBSPLASH
66 + help
67 + support for low color framebuffer that's need color mapping ~350 b
68 +
69 + config FEATURE_FBSPLASH_SPRITES
70 + bool "Render icons and animations"
71 + default n
72 + depends on FBSPLASH
73 + help
74 + This option adds the ability to display icons on the
75 + image displayed by the fbsplash applet. ~1.5kb.
76 + - command for fifo:
77 + "load:x:y:filename" - load images from file
78 + each sprite is one square area when image is wider than higher
79 + before load new sprite set, old area is cleared.
80 + "sprite:n" - show one sprite - sprite 0 is background.
81 + "anime:n:m:t" - anime from sprite n up/down to sprite m
82 + time between sprites is in t * 100 msec.
83 +
84 + config FEATURE_FBSPLASH_TEXT
85 + bool "text rendering"
86 + default n
87 + depends on FBSPLASH
88 + help
89 + This option adds the ability to print text messages on the
90 + image displayed by the fbsplash applet. ~2kb.
91 + - command for fifo:
92 + "write:string to print" - print the string after the word "write:"
93 +
94 + config FEATURE_FBSPLASH_FONTLOAD
95 + bool "font loading"
96 + depends on FEATURE_FBSPLASH_TEXT
97 + help
98 + The font is loaded from a standard console font file.
99 + Supported are psf v1.x and psf v2.0 files including mapping ~1kb.
100 +
101 config FLASH_LOCK
102 bool "flash_lock"
103 default n
104 *** busybox-1.15.0/miscutils/fbsplash.c.orig 2009-08-21 00:26:14.000000000 +0200
105 --- busybox-1.15.0/miscutils/fbsplash.c 2009-09-01 08:42:18.000000000 +0200
106 ***************
107 *** 1,6 ****
108 --- 1,7 ----
109 /* vi: set sw=4 ts=4: */
110 /*
111 * Copyright (C) 2008 Michele Sanges <michele.sanges@gmail.com>
112 + * Copyright (C) 2009 Jiri Gabriel <george.gabriel@seznam.cz>
113 *
114 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
115 *
116 ***************
117 *** 10,51 ****
118 * - run applet: $ setsid fbsplash [params] &
119 * -c: hide cursor
120 * -d /dev/fbN: framebuffer device (if not /dev/fb0)
121 ! * -s path_to_image_file (can be "-" for stdin)
122 * -i path_to_cfg_file
123 * -f path_to_fifo (can be "-" for stdin)
124 * - if you want to run it only in presence of a kernel parameter
125 * (for example fbsplash=on), use:
126 * grep -q "fbsplash=on" </proc/cmdline && setsid fbsplash [params]
127 * - commands for fifo:
128 * "NN" (ASCII decimal number) - percentage to show on progress bar.
129 ! * "exit" (or just close fifo) - well you guessed it.
130 */
131
132 #include "libbb.h"
133 #include <linux/fb.h>
134
135 /* If you want logging messages on /tmp/fbsplash.log... */
136 #define DEBUG 0
137
138 ! #define BYTES_PER_PIXEL 2
139
140 ! typedef unsigned short DATA;
141
142 struct globals {
143 #if DEBUG
144 bool bdebug_messages; // enable/disable logging
145 FILE *logfile_fd; // log file
146 #endif
147 ! unsigned char *addr; // pointer to framebuffer memory
148 ! unsigned ns[7]; // n-parameters
149 const char *image_filename;
150 struct fb_var_screeninfo scr_var;
151 struct fb_fix_screeninfo scr_fix;
152 };
153 #define G (*ptr_to_globals)
154 #define INIT_G() do { \
155 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
156 } while (0)
157
158 #define nbar_width ns[0] // progress bar width
159 #define nbar_height ns[1] // progress bar height
160 --- 11,198 ----
161 * - run applet: $ setsid fbsplash [params] &
162 * -c: hide cursor
163 * -d /dev/fbN: framebuffer device (if not /dev/fb0)
164 ! * -s path_to_image_file - ppm or ppm.gz or ppm.bz2
165 * -i path_to_cfg_file
166 * -f path_to_fifo (can be "-" for stdin)
167 + * -m font map file - standard psf file (v1 and v2) can be with unumap
168 * - if you want to run it only in presence of a kernel parameter
169 * (for example fbsplash=on), use:
170 * grep -q "fbsplash=on" </proc/cmdline && setsid fbsplash [params]
171 * - commands for fifo:
172 * "NN" (ASCII decimal number) - percentage to show on progress bar.
173 ! * if number is smaller than zero progress bar is filled from left.
174 ! * "write:string to print" - print the string after the word "write:"
175 ! * "exit" - well you guessed it.
176 ! */
177 !
178 ! /*
179 ! * enhancements:
180 ! * - framebuffer can be in depth 8,15,16,24,32 PSEUDOCOLR,TRUECOLOR
181 ! * not only 16
182 ! * - image file cannot be stdin
183 ! * - bugfix: if virtual size is bigger than visual resolution
184 ! * - progress bar can be dscending for shutdown (-1..-100)
185 ! * - progress bar is from background picture + color in cfg - only colorize.
186 ! * - bouncing bar - command "bounce" and at start.
187 ! * - smaller image is shown centered on screen cfg positions recalc on demand.
188 ! * - without text rendering and sprites grow size is only 800b.
189 ! * text rendering:
190 ! * - font is standard psf console font
191 ! * - if font not specified or not compiled in fontload function
192 ! * font is used from kernel using KDFONTOP / GIO_FONTX / GIO_FONT
193 ! * - colorize text render by \033[30m .. \033[37m,\033[1;30 .. \033[1;37m
194 ! * sprites:
195 ! * - animated sprites load by fifo command "load:x:y:filename".
196 ! * File is ppm format may be gzipped/bzipped or raw.
197 ! * Frame/Icon is always square. Width of each Frame is image height.
198 ! * Frame number 0 is always created for save background.
199 ! * Transparent color is in ppm file is stored as #FF00FF - purple.
200 ! * Show frame by pipe command "sprite:n" where n is frame number.
201 ! * Run animated sequence by "anime:n:m:t" where
202 ! * n is first frame m is last frame, t is time between displaying
203 ! * frames in 0.1sec. n can be bigger than m for reverse order in anime.
204 */
205
206 #include "libbb.h"
207 + #if BB_BIG_ENDIAN
208 + #warning "fbsplash work only on little endian architecures. Sorry"
209 + int fbsplash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
210 + int fbsplash_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) {
211 + bb_error_msg_and_die("fbsplash not work on big endian architectures.");
212 + return 1;
213 + }
214 +
215 + #else
216 #include <linux/fb.h>
217 + #if ENABLE_FEATURE_FBSPLASH_TEXT
218 + #include <linux/kd.h>
219 +
220 + /* if you have fonts with sequences can turn this to 1 i not find any font with this feature
221 + ~510 bytes of code */
222 + #define ENABLE_FEATURE_FBSPLASH_PSFSEQS 0
223 +
224 + /* if you not use text colors and need optimize size - disable text colors
225 + ~250 bytes of code */
226 + #define ENABLE_FEATURE_FBSPLASH_TEXT_COLORS 1
227 +
228 + #if !defined(GIO_UNIMAP)
229 + struct unipair {
230 + unsigned short unicode;
231 + unsigned short fontpos;
232 + } __atribute__ ((packed));
233 +
234 + struct unimapdesc {
235 + unsigned short entry_ct;
236 + struct unipair *entries;
237 + } __atribute__ ((packed));
238 + #endif
239 +
240 + #if ENABLE_FEATURE_FBSPLASH_FONTLOAD
241 +
242 + enum { // uint16
243 + PSF1_MAGIC = 0x0436,
244 + PSF1_SEPARATOR = 0xFFFF,
245 + PSF1_STARTSEQ = 0xFFFE
246 + };
247 +
248 + enum { // uint32
249 + PSF2_MAGIC = 0x864ab572,
250 + PSF2_HAS_UNICODE_TABLE = 0x01, /* bits used in flags */
251 + PSF2_MAXVERSION = 0 /* max version recognized so far */
252 + };
253 +
254 + enum { // uint8
255 + PSF1_MODE512 = 0x01,
256 + PSF1_MODEHASTAB = 0x02,
257 + PSF1_MODEHASSEQ = 0x04,
258 + PSF1_MAXMODE = 0x05,
259 + PSF2_STARTSEQ = 0xFE,
260 + PSF2_SEPARATOR = 0xFF
261 + };
262 +
263 + struct psf1_header {
264 + uint16_t magic; /* Magic number */
265 + uint8_t mode; /* PSF font mode */
266 + uint8_t charsize; /* Character size */
267 + } __attribute__ ((packed));
268 +
269 + struct psf2_header {
270 + uint32_t magic;
271 + uint32_t version;
272 + uint32_t headersize; /* offset of bitmaps in file */
273 + uint32_t flags;
274 + uint32_t length; /* number of glyphs */
275 + uint32_t charsize; /* number of bytes for each character */
276 + uint32_t height, width; /* max dimensions of glyphs */
277 + /* charsize = height * ((width + 7) / 8) */
278 + } __attribute__ ((packed));
279 +
280 + #endif // FONTLOAD
281 + struct fbfont {
282 + uint8_t *mem1;
283 + uint8_t *glyphs;
284 + struct unimapdesc ud;
285 + int height;
286 + int width;
287 + int glyphcount;
288 + int charsize;
289 + int rowbytes;
290 + };
291 +
292 + #endif
293
294 /* If you want logging messages on /tmp/fbsplash.log... */
295 #define DEBUG 0
296
297 ! typedef uint32_t RGB;
298
299 ! struct sprite {
300 ! int w,h,bw; // width height in pixels, width in bytes
301 ! uint8_t pixbuf[0];
302 ! };
303 !
304 ! struct ppmfile {
305 ! int fd;
306 ! int sizx,sizy;
307 ! int bufhead,buftail;
308 ! uint8_t buf[0]; // buf for entire pixels row
309 ! };
310
311 struct globals {
312 #if DEBUG
313 bool bdebug_messages; // enable/disable logging
314 FILE *logfile_fd; // log file
315 #endif
316 ! unsigned char *addr; // pointer to visible framebuffer memory
317 ! unsigned char *mapaddr; // pointer to framebuffer memory
318 ! #if ENABLE_FEATURE_FBSPLASH_TEXT
319 ! #define FBCFGVALS 13
320 ! #else
321 ! #define FBCFGVALS 7
322 ! #endif
323 ! unsigned ns[FBCFGVALS]; // n-parameters
324 const char *image_filename;
325 struct fb_var_screeninfo scr_var;
326 struct fb_fix_screeninfo scr_fix;
327 + int bytes_per_pixel,x0,y0; // offset for centering
328 + struct sprite *spb1,*spb2;
329 + #if ENABLE_FEATURE_FBSPLASH_TEXT
330 + struct fbfont *font;
331 + struct sprite *spt;
332 + uint8_t *unknown_glyph;
333 + #if ENABLE_FEATURE_FBSPLASH_PSFSEQS
334 + uint8_t combglyph[4*32]; /* max width=32 max height=32 */
335 + #endif
336 + #endif
337 };
338 +
339 #define G (*ptr_to_globals)
340 #define INIT_G() do { \
341 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
342 } while (0)
343 + #if ENABLE_FEATURE_FBSPLASH_TEXT
344 + #define GF (*(ptr_to_globals->font))
345 + #endif
346
347 #define nbar_width ns[0] // progress bar width
348 #define nbar_height ns[1] // progress bar height
349 ***************
350 *** 54,59 ****
351 --- 201,275 ----
352 #define nbar_colr ns[4] // progress bar color red component
353 #define nbar_colg ns[5] // progress bar color green component
354 #define nbar_colb ns[6] // progress bar color blue component
355 + #define text_posx ns[7] // text horizontal position
356 + #define text_posy ns[8] // text vertical position
357 + #define text_colr ns[9] // text color red component
358 + #define text_colg ns[10] // text color green component
359 + #define text_colb ns[11] // text color blue component
360 + #define text_size ns[12] // text size (1 to 4)
361 +
362 + /**
363 + * A function to compute pixel value
364 + */
365 + static RGB FAST_FUNC makecol(uint16_t r, uint16_t g, uint16_t b) {
366 + if (r > 255) r = 255;
367 + if (g > 255) g = 255;
368 + if (b > 255) b = 255;
369 + #if ENABLE_FEATURE_FBSPLASH_8BPP
370 + if (G.bytes_per_pixel == 1) {
371 + // mymap is 6*8*5 = 240 values on offset 16
372 + // (r/42.6666) + (g/32) + (b/51.2)
373 + return 16 + (((r << 8) + r) / 13107) * 40 +
374 + (((g << 8) + g) / 9362) * 5 +
375 + (((b << 8) + b) / 16383);
376 + }
377 + #endif
378 + return ((r >> (8 - G.scr_var.red.length )) << G.scr_var.red.offset) |
379 + ((g >> (8 - G.scr_var.green.length)) << G.scr_var.green.offset) |
380 + ((b >> (8 - G.scr_var.blue.length )) << G.scr_var.blue.offset);
381 + }
382 +
383 + /*
384 + * A function to put the pixel row
385 + */
386 + static void fb_putpixrow(int x, int y, int w, uint8_t *rgb) {
387 + uint8_t *a;
388 + int realw;
389 + if (x < 0 || y < 0 || x > G.scr_var.xres || y > G.scr_var.yres) return;
390 + a = G.addr + G.scr_fix.line_length * y + G.bytes_per_pixel * x;
391 + realw = ((x + w) < G.scr_var.xres ? w : G.scr_var.xres - x) * G.bytes_per_pixel;
392 + memcpy(a,rgb,realw);
393 + return;
394 + }
395 +
396 + /*
397 + * A function to put the sprite to position or fill sprite from videoram
398 + */
399 + static void fb_sprite(int x, int y, int x0, int width, struct sprite *s, int direction) {
400 + uint8_t *a,*p;
401 + int realw,iy;
402 +
403 + if (x < 0 || y < 0 || x > G.scr_var.xres || y > G.scr_var.yres ||
404 + x0 >= s->w || x0 < 0 || width > (s->w - x0)) {
405 + return;
406 + }
407 + realw = ((x + width) < G.scr_var.xres ? width : (G.scr_var.xres - x)) * G.bytes_per_pixel;
408 + a = G.addr + G.scr_fix.line_length * y + G.bytes_per_pixel * x;
409 + p = &(s->pixbuf[x0 * G.bytes_per_pixel]);
410 + for (iy = 0; iy < s->h; iy++) {
411 + if ((iy + y) > G.scr_var.yres) break;
412 + if (direction == 1) {
413 + memcpy(p,a,realw);
414 + } else {
415 + memcpy(a,p,realw);
416 + }
417 + a += G.scr_fix.line_length;
418 + p += s->bw;
419 + }
420 + return;
421 + }
422 + #define fb_putsprite(x,y,s) fb_sprite(x,y,0,s->w,s,0)
423 + #define fb_getsprite(x,y,s) fb_sprite(x,y,0,s->w,s,1)
424
425 #if DEBUG
426 #define DEBUG_MESSAGE(strMessage, args...) \
427 ***************
428 *** 78,231 ****
429 xioctl(fbfd, FBIOGET_VSCREENINFO, &G.scr_var);
430 xioctl(fbfd, FBIOGET_FSCREENINFO, &G.scr_fix);
431
432 ! if (G.scr_var.bits_per_pixel != 16)
433 ! bb_error_msg_and_die("only 16 bpp is supported");
434
435 // map the device in memory
436 ! G.addr = mmap(NULL,
437 ! G.scr_var.xres * G.scr_var.yres
438 ! * BYTES_PER_PIXEL /*(G.scr_var.bits_per_pixel / 8)*/ ,
439 PROT_WRITE, MAP_SHARED, fbfd, 0);
440 ! if (G.addr == MAP_FAILED)
441 bb_perror_msg_and_die("mmap");
442 close(fbfd);
443 }
444
445
446 /**
447 - * Draw hollow rectangle on framebuffer
448 - */
449 - static void fb_drawrectangle(void)
450 - {
451 - int cnt;
452 - DATA thispix;
453 - DATA *ptr1, *ptr2;
454 - unsigned char nred = G.nbar_colr/2;
455 - unsigned char ngreen = G.nbar_colg/2;
456 - unsigned char nblue = G.nbar_colb/2;
457 -
458 - nred >>= 3; // 5-bit red
459 - ngreen >>= 2; // 6-bit green
460 - nblue >>= 3; // 5-bit blue
461 - thispix = nblue + (ngreen << 5) + (nred << (5+6));
462 -
463 - // horizontal lines
464 - ptr1 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL);
465 - ptr2 = (DATA*)(G.addr + ((G.nbar_posy + G.nbar_height - 1) * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL);
466 - cnt = G.nbar_width - 1;
467 - do {
468 - *ptr1++ = thispix;
469 - *ptr2++ = thispix;
470 - } while (--cnt >= 0);
471 -
472 - // vertical lines
473 - ptr1 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL);
474 - ptr2 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx + G.nbar_width - 1) * BYTES_PER_PIXEL);
475 - cnt = G.nbar_height - 1 /* HUH?! G.nbar_posy + G.nbar_height - 1 - G.nbar_posy*/;
476 - do {
477 - *ptr1 = thispix; ptr1 += G.scr_var.xres;
478 - *ptr2 = thispix; ptr2 += G.scr_var.xres;
479 - } while (--cnt >= 0);
480 - }
481 -
482 -
483 - /**
484 - * Draw filled rectangle on framebuffer
485 - * \param nx1pos,ny1pos upper left position
486 - * \param nx2pos,ny2pos down right position
487 - * \param nred,ngreen,nblue rgb color
488 - */
489 - static void fb_drawfullrectangle(int nx1pos, int ny1pos, int nx2pos, int ny2pos,
490 - unsigned char nred, unsigned char ngreen, unsigned char nblue)
491 - {
492 - int cnt1, cnt2, nypos;
493 - DATA thispix;
494 - DATA *ptr;
495 -
496 - nred >>= 3; // 5-bit red
497 - ngreen >>= 2; // 6-bit green
498 - nblue >>= 3; // 5-bit blue
499 - thispix = nblue + (ngreen << 5) + (nred << (5+6));
500 -
501 - cnt1 = ny2pos - ny1pos;
502 - nypos = ny1pos;
503 - do {
504 - ptr = (DATA*)(G.addr + (nypos * G.scr_var.xres + nx1pos) * BYTES_PER_PIXEL);
505 - cnt2 = nx2pos - nx1pos;
506 - do {
507 - *ptr++ = thispix;
508 - } while (--cnt2 >= 0);
509 -
510 - nypos++;
511 - } while (--cnt1 >= 0);
512 - }
513 -
514 -
515 - /**
516 * Draw a progress bar on framebuffer
517 ! * \param percent percentage of loading
518 */
519 ! static void fb_drawprogressbar(unsigned percent)
520 {
521 ! int i, left_x, top_y, width, height;
522
523 ! // outer box
524 ! left_x = G.nbar_posx;
525 ! top_y = G.nbar_posy;
526 ! width = G.nbar_width - 1;
527 ! height = G.nbar_height - 1;
528 ! if ((height | width) < 0)
529 return;
530 ! // NB: "width" of 1 actually makes rect with width of 2!
531 ! fb_drawrectangle();
532 !
533 ! // inner "empty" rectangle
534 ! left_x++;
535 ! top_y++;
536 ! width -= 2;
537 ! height -= 2;
538 ! if ((height | width) < 0)
539 return;
540 ! fb_drawfullrectangle(
541 ! left_x, top_y,
542 ! left_x + width, top_y + height,
543 ! G.nbar_colr, G.nbar_colg, G.nbar_colb);
544 !
545 ! if (percent > 0) {
546 ! // actual progress bar
547 ! width = width * percent / 100;
548 ! i = height;
549 ! if (height == 0)
550 ! height++; // divide by 0 is bad
551 ! while (i >= 0) {
552 ! // draw one-line thick "rectangle"
553 ! // top line will have gray lvl 200, bottom one 100
554 ! unsigned gray_level = 100 + i*100/height;
555 ! fb_drawfullrectangle(
556 ! left_x, top_y, left_x + width, top_y,
557 ! gray_level, gray_level, gray_level);
558 ! top_y++;
559 ! i--;
560 ! }
561 ! }
562 }
563
564
565 /**
566 ! * Draw image from PPM file
567 */
568 ! static void fb_drawimage(void)
569 ! {
570 ! char *head, *ptr;
571 ! FILE *theme_file;
572 ! unsigned char *pixline;
573 ! unsigned i, j, width, height, line_size;
574 !
575 ! theme_file = xfopen_stdin(G.image_filename);
576 ! head = xmalloc(256);
577 !
578 /* parse ppm header
579 ! * - A ppm image’s magic number is the two characters "P6".
580 * - Whitespace (blanks, TABs, CRs, LFs).
581 * - A width, formatted as ASCII characters in decimal.
582 * - Whitespace.
583 --- 294,411 ----
584 xioctl(fbfd, FBIOGET_VSCREENINFO, &G.scr_var);
585 xioctl(fbfd, FBIOGET_FSCREENINFO, &G.scr_fix);
586
587 ! #if ENABLE_FEATURE_FBSPLASH_8BPP
588 ! if ((G.scr_var.bits_per_pixel < 8) ||
589 ! (G.scr_fix.type != FB_TYPE_PACKED_PIXELS)) {
590 ! bb_error_msg_and_die("only 8,15,16,24 and 32 bpp is supported");
591 ! }
592 ! #else
593 ! if ((G.scr_var.bits_per_pixel < 15) ||
594 ! (G.scr_fix.type != FB_TYPE_PACKED_PIXELS)) {
595 ! bb_error_msg_and_die("only 15,16,24 and 32 bpp is supported");
596 ! }
597 ! #endif
598 ! switch (G.scr_fix.visual) {
599 ! #if ENABLE_FEATURE_FBSPLASH_8BPP
600 ! case FB_VISUAL_PSEUDOCOLOR: do {
601 ! uint8_t *cmem;
602 ! struct fb_cmap *cmap;
603 ! int r,g,b,i;
604 ! cmem = xzalloc(sizeof(struct fb_cmap) + sizeof(uint16_t) * 3 * 256);
605 ! cmap = (struct fb_cmap *)cmem;
606 ! cmap->len = 256;
607 ! cmap->red = (uint16_t *)&(cmem[sizeof(struct fb_cmap)]);
608 ! cmap->green = &(cmap->red[256]);
609 ! cmap->blue = &(cmap->green[256]);
610 ! xioctl(fbfd, FBIOGETCMAP, cmem); // read original palette
611 ! // fill cmap with my 6x8x5 pallette
612 ! for (r = 0,i = 16; r < 6; r++) {
613 ! for (g = 0; g < 8; g++) {
614 ! for (b = 0; b < 5; b++, i++) {
615 ! cmap->red[i] = r * 13107;
616 ! cmap->green[i] = g * 9362;
617 ! cmap->blue[i] = b * 16383;
618 ! }
619 ! }
620 ! }
621 ! xioctl(fbfd, FBIOPUTCMAP, cmem);
622 ! free(cmem);
623 ! } while(0);
624 ! #endif
625 ! case FB_VISUAL_TRUECOLOR:
626 ! break;
627 ! default:
628 ! bb_error_msg_and_die("only TrueColor modes is supported");
629 ! }
630
631 + G.bytes_per_pixel = (G.scr_var.bits_per_pixel + 7) / 8;
632 // map the device in memory
633 ! G.mapaddr = mmap(NULL,
634 ! G.scr_var.yres_virtual * G.scr_fix.line_length ,
635 PROT_WRITE, MAP_SHARED, fbfd, 0);
636 ! if (G.mapaddr == MAP_FAILED)
637 bb_perror_msg_and_die("mmap");
638 + G.addr = G.mapaddr + G.scr_var.yoffset * G.scr_fix.line_length;
639 close(fbfd);
640 }
641
642
643 /**
644 * Draw a progress bar on framebuffer
645 ! * \param frompct percentage on which bar starting
646 ! * \param topct percentage where bar end
647 */
648 ! static void fb_drawnbar(int frompct, int topct)
649 {
650 ! int w0,w1,w2;
651
652 ! if (G.spb1 == NULL || G.spb2 == NULL)
653 return;
654 ! if (frompct < 0 || frompct > 100 ||
655 ! topct < 0 || topct > 100 ||
656 ! frompct > topct) {
657 return;
658 ! }
659 ! w0 = G.spb1->w * frompct / 100;
660 ! w0 = (w0 > G.spb1->w ? G.spb1->w : w0);
661 ! w2 = G.spb1->w * (100 - topct) / 100;
662 ! w2 = ((w0 + w2) > G.spb1->w ? G.spb1->w - w0 : w2);
663 ! w1 = G.spb1->w - w0 - w2;
664 ! if (w0 > 0)
665 ! fb_sprite(G.nbar_posx, G.nbar_posy, 0, w0, G.spb1, 0); // left "empty" area
666 ! if (w1 > 0)
667 ! fb_sprite(G.nbar_posx + w0, G.nbar_posy, w0, w1, G.spb2, 0); // filled area
668 ! if (w2 > 0)
669 ! fb_sprite(G.nbar_posx + w0 + w1, G.nbar_posy, w0 + w1, w2, G.spb1, 0); // right "empty" area
670 }
671
672 + static struct sprite *fb_newsprite(int pw, int ph, int scrx, int scry) {
673 + struct sprite *s;
674 + s=xmalloc(sizeof(struct sprite) +
675 + ph * pw * G.bytes_per_pixel);
676 + s->w = pw;
677 + s->h = ph;
678 + s->bw = pw * G.bytes_per_pixel;
679 + if (scrx >= 0) fb_getsprite(scrx, scry, s); // read
680 + return s;
681 + }
682
683 /**
684 ! * Open PPM file - must be binary, color maxval 255
685 */
686 ! static struct ppmfile *ppm_open(const char *filename) {
687 ! int i,k,l,val;
688 ! struct ppmfile *p;
689 ! uint8_t *s;
690 ! char *e;
691 !
692 ! i = open_zipped(filename);
693 ! if (i == -1) return NULL;
694 ! p = (struct ppmfile *) xmalloc(sizeof(struct ppmfile) + 600);
695 ! // initial buf 600 bytes header cannot be larger
696 ! p->fd = i;
697 /* parse ppm header
698 ! * - A ppm images magic number is the two characters "P6".
699 * - Whitespace (blanks, TABs, CRs, LFs).
700 * - A width, formatted as ASCII characters in decimal.
701 * - Whitespace.
702 ***************
703 *** 237,292 ****
704 * - A raster of Width * Height pixels in triplets of rgb
705 * in pure binary by 1 (or not implemented 2) bytes.
706 */
707 ! while (1) {
708 ! if (fgets(head, 256, theme_file) == NULL
709 ! /* do not overrun the buffer */
710 ! || strlen(bb_common_bufsiz1) >= sizeof(bb_common_bufsiz1) - 256)
711 ! bb_error_msg_and_die("bad PPM file '%s'", G.image_filename);
712 !
713 ! ptr = memchr(skip_whitespace(head), '#', 256);
714 ! if (ptr != NULL)
715 ! *ptr = 0; /* ignore comments */
716 ! strcat(bb_common_bufsiz1, head);
717 ! // width, height, max_color_val
718 ! if (sscanf(bb_common_bufsiz1, "P6 %u %u %u", &width, &height, &i) == 3
719 ! && i <= 255)
720 ! break;
721 ! /* If we do not find a signature throughout the whole file then
722 ! we will diagnose this via EOF on read in the head of the loop. */
723 }
724
725 ! if (ENABLE_FEATURE_CLEAN_UP)
726 ! free(head);
727 ! if (width != G.scr_var.xres || height != G.scr_var.yres)
728 bb_error_msg_and_die("PPM %dx%d does not match screen %dx%d",
729 ! width, height, G.scr_var.xres, G.scr_var.yres);
730 ! line_size = width*3;
731 if (width > G.scr_var.xres)
732 width = G.scr_var.xres;
733 if (height > G.scr_var.yres)
734 height = G.scr_var.yres;
735
736 ! pixline = xmalloc(line_size);
737 ! for (j = 0; j < height; j++) {
738 ! unsigned char *pixel = pixline;
739 ! DATA *src = (DATA *)(G.addr + j * G.scr_fix.line_length);
740
741 ! if (fread(pixline, 1, line_size, theme_file) != line_size)
742 ! bb_error_msg_and_die("bad PPM file '%s'", G.image_filename);
743 for (i = 0; i < width; i++) {
744 ! unsigned thispix;
745 ! thispix = (((unsigned)pixel[0] << 8) & 0xf800)
746 ! | (((unsigned)pixel[1] << 3) & 0x07e0)
747 ! | (((unsigned)pixel[2] >> 3));
748 ! *src++ = thispix;
749 pixel += 3;
750 }
751 }
752 ! if (ENABLE_FEATURE_CLEAN_UP)
753 ! free(pixline);
754 ! fclose(theme_file);
755 }
756
757
758 /**
759 * Parse configuration file
760 --- 417,1159 ----
761 * - A raster of Width * Height pixels in triplets of rgb
762 * in pure binary by 1 (or not implemented 2) bytes.
763 */
764 ! l=read(p->fd,&(p->buf[0]),600);
765 ! if ((l < 0) || (p->buf[0] != 'P') || (p->buf[1] != '6')) {
766 ! goto ppmopen_end;
767 ! }
768 ! for (s = &(p->buf[2]), i = 0, k = 0; s < &(p->buf[l]) && (k < 3); ) {
769 ! switch (i) {
770 ! case 0:
771 ! if (*s <= ' ') {
772 ! s++; // skip whitespaces
773 ! } else {
774 ! i++; // next state
775 ! }
776 ! break;
777 ! case 1: // num or rmks
778 ! if (*s == '#') {
779 ! i = 2;
780 ! } else {
781 ! val=bb_strtoi((char *)s,&e,10);
782 ! if (s == (uint8_t *)e) goto ppmopen_end; // no number - error
783 ! s=(uint8_t *)e;
784 ! i=0; // skip whitespaces
785 ! switch (++k) {
786 ! case 1: p->sizx = val; break;
787 ! case 2: p->sizy = val; break;
788 ! case 3:
789 ! if (val > 255)
790 ! goto ppmopen_end; // only 1 byte per color
791 ! s++;
792 ! p->bufhead = s - &(p->buf[0]);
793 ! p->buftail = l;
794 ! break;
795 ! }
796 ! }
797 ! break;
798 ! case 2: // skip to eol
799 ! if (*s == 10) i=0;
800 ! s++;
801 ! break;
802 ! }
803 ! }
804 ! if (p->sizx < 1 || p->sizy < 1) goto ppmopen_end;
805 ! if (p->sizx > 200) {
806 ! // buf is only 600 bytes = 200 pix prealocated - need more.
807 ! p = xrealloc(p,sizeof(struct ppmfile) + 3 * p->sizx);
808 }
809 + return p;
810
811 ! ppmopen_end:
812 ! close(p->fd);
813 ! free(p);
814 ! return NULL;
815 ! }
816 !
817 ! /**
818 ! * Read pixelline from ppm to internal buffer and return pointer
819 ! */
820 ! static uint8_t *ppm_readline(struct ppmfile *p) {
821 ! int i;
822 ! if (p==NULL) return NULL;
823 ! if (p->bufhead < p->buftail) {
824 ! // pack buffer
825 ! for (i = 0; p->bufhead < p->buftail; i++) {
826 ! p->buf[i]=p->buf[p->bufhead++];
827 ! }
828 ! p->buftail = i;
829 ! } else {
830 ! p->buftail = 0;
831 ! }
832 ! while (p->buftail < (p->sizx * 3)) {
833 ! i=read(p->fd, &(p->buf[p->buftail]), (p->sizx * 3) - p->buftail);
834 ! if (i < 0) return NULL;
835 ! p->buftail += i;
836 ! }
837 ! p->bufhead = p->sizx * 3;
838 ! return &(p->buf[0]);
839 ! }
840 !
841 ! /**
842 ! * Close ppmfile
843 ! */
844 !
845 ! static void ppm_close(struct ppmfile *p) {
846 ! if (p == NULL) return;
847 ! close(p->fd);
848 ! free(p);
849 ! }
850 !
851 ! /**
852 ! * Draws a PPM image.
853 ! */
854 ! static void fb_drawimage(void)
855 ! {
856 ! struct ppmfile *ppm;
857 ! unsigned char *pixel;
858 ! unsigned char *rgbline,*rgbpix,*sprpix;
859 ! RGB thispix;
860 ! unsigned i, j, width, height;
861 !
862 ! ppm = ppm_open(G.image_filename);
863 ! if (ppm == NULL)
864 ! bb_error_msg_and_die("PPM file %s cannot be opened",G.image_filename);
865 ! width = ppm->sizx;
866 ! height = ppm->sizy;
867 ! if (width > G.scr_var.xres || height > G.scr_var.yres)
868 bb_error_msg_and_die("PPM %dx%d does not match screen %dx%d",
869 ! width, height, G.scr_var.xres, G.scr_var.yres);
870 if (width > G.scr_var.xres)
871 width = G.scr_var.xres;
872 if (height > G.scr_var.yres)
873 height = G.scr_var.yres;
874
875 ! G.x0 = (width == G.scr_var.xres ? 0 : (G.scr_var.xres - width) / 2);
876 ! G.y0 = (height == G.scr_var.yres ? 0 : (G.scr_var.yres - height) / 2);
877 ! rgbline = xmalloc((width * G.bytes_per_pixel) + sizeof(RGB));
878
879 ! for (j = 0; j < height; j++) {
880 ! pixel = ppm_readline(ppm);
881 ! rgbpix = rgbline;
882 ! if (pixel == NULL)
883 ! bb_error_msg_and_die("bad PPM file '%s' line %d", G.image_filename,j);
884 ! if (G.spb2 != NULL && j >= G.nbar_posy && j < (G.nbar_posy + G.spb2->h)) {
885 ! sprpix = &(G.spb2->pixbuf[(j - G.nbar_posy) * G.spb2->bw]);
886 ! } else {
887 ! sprpix = NULL;
888 ! }
889 for (i = 0; i < width; i++) {
890 ! thispix = makecol(pixel[0],pixel[1],pixel[2]);
891 ! *((RGB*)rgbpix) = thispix;
892 ! if ((sprpix != NULL) && (i >= G.nbar_posx)) {
893 ! if (G.nbar_colr >= 256) { // Multiple not add
894 ! thispix = makecol((G.nbar_colr & 255) * pixel[0], (G.nbar_colg & 255) * pixel[1], (G.nbar_colb & 255) * pixel[2]);
895 ! } else {
896 ! thispix = makecol(G.nbar_colr + pixel[0], G.nbar_colg + pixel[1], G.nbar_colb + pixel[2]);
897 ! }
898 ! memcpy(sprpix,&thispix,G.bytes_per_pixel);
899 ! if (i >= (G.nbar_posx + G.spb2->w - 1)) {
900 ! sprpix = NULL;
901 ! } else {
902 ! sprpix += G.bytes_per_pixel;
903 ! }
904 ! }
905 pixel += 3;
906 + rgbpix += G.bytes_per_pixel;
907 + }
908 + fb_putpixrow(G.x0,j + G.y0,width,rgbline);
909 + }
910 + free(rgbline);
911 + ppm_close(ppm);
912 + // recalc cfg if centered image
913 + G.nbar_posx += G.x0;
914 + G.nbar_posy += G.y0;
915 + #if ENABLE_FEATURE_FBSPLASH_TEXT
916 + G.text_posx += G.x0;
917 + G.text_posy += G.y0;
918 + #endif
919 + }
920 +
921 + #if ENABLE_FEATURE_FBSPLASH_SPRITES
922 + /**
923 + * Read rectangle sprites from ppm file
924 + * \return pointer to array of sprites
925 + * \return number of sprites loaded
926 + */
927 + static struct sprite *fb_loadsprites(char *filename, int sx, int sy) {
928 + struct ppmfile *ppm;
929 + uint8_t *pixel, *rgbpix;
930 + struct sprite *s=NULL;
931 + int y,i;
932 + RGB thispix;
933 +
934 + if ((ppm = ppm_open(filename)) == NULL) goto readsprites_out;
935 + s = fb_newsprite(ppm->sizx + ppm->sizy, ppm->sizy, -1, -1);
936 + fb_sprite(sx + G.x0, sy + G.y0, 0, s->h, s, 1); // load square 0 - background
937 + rgbpix = &(s->pixbuf[0]);
938 + for (y = 0; y < ppm->sizy; y++) {
939 + // skip square 0
940 + rgbpix += s->h * G.bytes_per_pixel;
941 + // read from file
942 + pixel = ppm_readline(ppm);
943 + for (i = 0; (pixel != NULL) && (i < ppm->sizx); i++) {
944 + if (pixel[0]==0xFF && pixel[1]==0 && pixel[2]==0xFF) {
945 + // transparent color => get pixel from square 0
946 + memcpy(&thispix,
947 + &(s->pixbuf[y * s->bw + (i % s->h) * G.bytes_per_pixel]),
948 + G.bytes_per_pixel);
949 + } else {
950 + thispix = makecol(pixel[0],pixel[1],pixel[2]);
951 + }
952 + memcpy(rgbpix,&thispix,G.bytes_per_pixel);
953 + pixel += 3;
954 + rgbpix += G.bytes_per_pixel;
955 + }
956 + }
957 + ppm_close(ppm);
958 + return s;
959 + readsprites_out:
960 + if (s != NULL) free(s);
961 + return NULL;
962 + }
963 +
964 + #define fb_putanim(x,y,n,s) fb_sprite(x + G.x0,y + G.y0,s->h * n,s->h,s,0)
965 + #endif
966 +
967 + #if ENABLE_FEATURE_FBSPLASH_TEXT
968 +
969 + /*
970 + * A function to put the pixel
971 + */
972 + static void fb_putpixel(int x, int y, RGB rgb) {
973 + uint8_t *a;
974 + if (x < 0 || y < 0 || x > G.scr_var.xres || y > G.scr_var.yres) return;
975 + a=G.addr + G.scr_fix.line_length * y + G.bytes_per_pixel * x;
976 + memcpy(a,&rgb,G.bytes_per_pixel);
977 + /*
978 + switch (G.scr_var.bits_per_pixel) {
979 + case 8:
980 + *a = rgb & 0xFF;
981 + break;
982 + case 15:
983 + case 16:
984 + *((uint16_t *)a) = rgb & 0xFFFF;
985 + break;
986 + case 24:
987 + a[0] = rgb & 0xFF;
988 + a[1] = (rgb >> 8) & 0xFF;
989 + a[2] = (rgb >> 16) & 0xFF;
990 + break;
991 + case 32:
992 + *((uint32_t *)a) = rgb;
993 + break;
994 + }
995 + */
996 + return;
997 + }
998 +
999 + /**
1000 + * UTF-8 - get one charcter and advance to next
1001 + * ??? this function may be in libbb ???
1002 + * \return UCS4 value
1003 + */
1004 + static uint32_t ucs4value(uint8_t **s) {
1005 + uint8_t *c;
1006 + uint32_t ucs,w;
1007 + int count;
1008 +
1009 + if (s==NULL || *s==NULL || **s==0) return 0;
1010 + c = *s;
1011 + ucs = *c++;
1012 + if (ucs >= 0xC0) { /* 0x80..0xBF is error in utf8 but i use as-is */
1013 + for (w = ucs & 0x7F, count = 0;(w & 0x40) == 0x40; count++) {
1014 + w <<= 1;
1015 + }
1016 + ucs=ucs & (0x7E >> count);
1017 + for(; count > 0; count--) {
1018 + if ((*c & 0xC0) != 0x80) { /* error in utf8 */
1019 + ucs=0;
1020 + break;
1021 + }
1022 + ucs = (ucs << 6) + (*c++ & 0x3F);
1023 + }
1024 + }
1025 + *s=c;
1026 + return ucs;
1027 + }
1028 +
1029 + /**
1030 + * Find in GF.ud.entries desired UTF-8 char and advance to next char
1031 + * can combine glyphs in own memory
1032 + * \param s pointer to utf8 char pointer
1033 + * \return pinter to glyph
1034 + */
1035 + static uint8_t *getglyph(uint8_t **s) {
1036 + uint32_t ucs;
1037 + uint8_t *c,*g;
1038 + int utflen,i;
1039 +
1040 + if (s == NULL || *s == NULL || **s == 0)
1041 + return G.unknown_glyph; /* end of string - no advance */
1042 + c = *s;
1043 + ucs = ucs4value(&c);
1044 + utflen = c - *s;
1045 + g = G.unknown_glyph;
1046 + if (GF.ud.entries == NULL) {
1047 + if (ucs < GF.glyphcount) {
1048 + g = GF.glyphs + GF.charsize * ucs;
1049 + }
1050 + } else if (ucs <= 0xFFFF) { // only ucs2
1051 + #if ENABLE_FEATURE_FBSPLASH_PSFSEQS
1052 + int j,compose;
1053 + memset(G.combglyph,0,sizeof(G.combglyph));
1054 + for (i = 0, compose=0; i < GF.ud.entry_ct; i++) {
1055 + if (GF.ud.entries[i].unicode == ucs) {
1056 + g=GF.glyphs +
1057 + GF.ud.entries[i].fontpos * GF.charsize;
1058 + for (j = 0; j < GF.charsize; j++) {
1059 + G.combglyph[j] |= g[j];
1060 + }
1061 + compose++;
1062 + }
1063 + }
1064 + if (compose > 1) { // found more than one
1065 + g = &(G.combglyph[0]);
1066 + }
1067 + #else
1068 + // no sequences - first found win
1069 + for (i = 0; i < GF.ud.entry_ct ; i++) {
1070 + if (GF.ud.entries[i].unicode == ucs) {
1071 + g = GF.glyphs + GF.ud.entries[i].fontpos * GF.charsize;
1072 + break;
1073 + }
1074 + }
1075 + #endif
1076 + }
1077 + *s=c;
1078 + return g;
1079 + }
1080 +
1081 + /**
1082 + * Draws a single character on framebuffer.
1083 + * \param nXPos horizontal position from which draw the character.
1084 + * \param nYPos vertical position from which draw the character.
1085 + * \param nCharSize character scale factor [1..4].
1086 + * \param pointer to *nChar character to draw - auto advance by utf8.
1087 + * \param RGB color
1088 + */
1089 + static void fb_drawchar(int nXPos, int nYPos, int nCharSize,
1090 + uint8_t **nChar, RGB thispix)
1091 + {
1092 + int x,y,px;
1093 + uint8_t *glyph;
1094 +
1095 + if (G.font==NULL || GF.height==0 || GF.glyphs==NULL) return;
1096 + if (G.unknown_glyph == NULL) {
1097 + uint8_t *unknown;
1098 + const uint8_t unconst[]="?";
1099 + unknown=(uint8_t *)unconst;
1100 + G.unknown_glyph = getglyph(&unknown);
1101 + }
1102 +
1103 + glyph=getglyph(nChar);
1104 + if (glyph==NULL) return;
1105 + glyph-=GF.rowbytes;
1106 + for (y = 0; y < (GF.height * nCharSize); y++) {
1107 + if ((y % nCharSize) == 0) glyph+=GF.rowbytes;
1108 + for (x = 0,px = -1; x < (GF.width * nCharSize); x++) {
1109 + if ((x % nCharSize) == 0) px++;
1110 + if ((glyph[px / 8] & (0x80 >> (px % 8))) != 0) {
1111 + fb_putpixel(nXPos + x, nYPos + y,thispix);
1112 + }
1113 + }
1114 + }
1115 + }
1116 +
1117 +
1118 + /**
1119 + * Draws a string on framebuffer.
1120 + * \param *strString pointer to the string.
1121 + */
1122 + static void fb_drawstring(char *strString)
1123 + {
1124 + RGB thispix;
1125 + int nCharSize;
1126 + int x;
1127 + uint8_t *c;
1128 +
1129 + // size check
1130 + nCharSize = G.text_size;
1131 + if (nCharSize < 1)
1132 + nCharSize = 1;
1133 + else if (nCharSize > 4)
1134 + nCharSize = 4;
1135 +
1136 + if (G.font==NULL || GF.height==0 || GF.glyphs==NULL) return;
1137 +
1138 + // redraws the portion of image interested to the old write operation
1139 + fb_putsprite(G.text_posx, G.text_posy, G.spt);
1140 +
1141 + // new write operation
1142 + thispix=makecol(G.text_colr,G.text_colg,G.text_colb);
1143 + for (x = G.text_posx, c = (uint8_t *)strString; *c != 0;) {
1144 + #if ENABLE_FEATURE_FBSPLASH_TEXT_COLORS
1145 + if (*c==0x1b && c[1]=='[') {
1146 + long newcol=0,first;
1147 + char *e;
1148 + e=(char *)&(c[1]);
1149 + do {
1150 + first=newcol;
1151 + ++e;
1152 + newcol = strtol(e,&e,10);
1153 + } while (*e == ';');
1154 + if (*e == 'm' && ((newcol == 0) || (newcol >= 30 && newcol <= 37))) {
1155 + if (newcol >= 30 && newcol <= 37) {
1156 + if (newcol == 0 && first == 1) {
1157 + thispix=makecol(0x33,0x33,0x33);
1158 + } else {
1159 + newcol -= 30;
1160 + first = (first == 1 ? 0xFF : 0xCC);
1161 + thispix=makecol((newcol & 1) ? first : 0,
1162 + (newcol & 2) ? first : 0,
1163 + (newcol & 4) ? first : 0);
1164 + }
1165 + } else {
1166 + thispix=makecol(G.text_colr,G.text_colg,G.text_colb);
1167 + }
1168 + c=(uint8_t *)(++e);
1169 + continue;
1170 + }
1171 + }
1172 + #endif
1173 + fb_drawchar(x, G.text_posy, nCharSize, &c, thispix);
1174 + x += GF.width * nCharSize;
1175 + if (x >= G.scr_var.xres) break; // too long string
1176 + }
1177 + }
1178 +
1179 + /**
1180 + * Free readed font structure with all allocated memory
1181 + */
1182 + static void fb_freefont(void) {
1183 + if (G.font != NULL) {
1184 + if (GF.mem1 != NULL) free(GF.mem1);
1185 + if (GF.ud.entries != NULL) free(GF.ud.entries);
1186 + free(G.font);
1187 + G.font=NULL;
1188 + }
1189 + }
1190 +
1191 + /**
1192 + * Read font and mapping from console using ioctl GIO_FONT and GIO_UNIMAP
1193 + */
1194 + static void fb_readvgafont(void) {
1195 + int fd,i;
1196 + #if (defined(KDFONTOP) && defined(KD_FONT_OP_GET)) || defined(GIO_FONTX)
1197 + #if defined(KDFONTOP) && defined(KD_FONT_OP_GET)
1198 + struct console_font_op fo;
1199 + fd = open(CURRENT_TTY,O_NONBLOCK);
1200 + // if (fd == -1) fd = open("/dev/tty0",O_NOCTTY);
1201 + // if (fd == -1) fd = open("/dev/tty1",O_NOCTTY);
1202 + if (fd == -1) return;
1203 +
1204 + fo.data = NULL;
1205 + fo.charcount = 0;
1206 + fo.height = 32; fo.width = 32; // max usable font size
1207 + fo.flags = 0;
1208 + fo.op = KD_FONT_OP_GET;
1209 + if (ioctl(fd, KDFONTOP, &fo) == 0) {
1210 + i = (fo.width + 7) / 8;
1211 + fo.data = xmalloc(fo.charcount * 32 * i);
1212 + if (ioctl(fd, KDFONTOP, &fo) == -1) {
1213 + free(fo.data);
1214 + goto fb_vgafontout;
1215 + }
1216 + }
1217 + if (G.font != NULL) fb_freefont();
1218 + G.font = (struct fbfont *) xzalloc(sizeof(struct fbfont));
1219 + GF.height = fo.height;
1220 + GF.glyphcount = fo.charcount;
1221 + GF.width = fo.width;
1222 + GF.rowbytes = (fo.width + 7) / 8;
1223 + GF.charsize = GF.height * GF.rowbytes;
1224 + GF.mem1 = (uint8_t *) xmalloc(GF.height * GF.glyphcount * GF.rowbytes);
1225 + GF.glyphs = GF.mem1;
1226 + for (i = 0; i < GF.glyphcount; i++) {
1227 + memcpy(&(GF.glyphs[i * GF.height * GF.rowbytes]),
1228 + &(fo.data[i * 32 * GF.rowbytes]),
1229 + GF.height * GF.rowbytes);
1230 + }
1231 + if (fo.data) free(fo.data);
1232 + #else // KDFONTOP / GIO_FONTX
1233 + struct consolefontdesc cfd;
1234 + int j;
1235 + fd = open(CURRENT_TTY,O_NONBLOCK);
1236 + // if (fd == -1) fd = open("/dev/tty0",O_NOCTTY);
1237 + // if (fd == -1) fd = open("/dev/tty1",O_NOCTTY);
1238 + if (fd == -1) return;
1239 +
1240 + cfd.chardata = NULL;
1241 + cfd.charcount = 0;
1242 + cfd.charheight = 0;
1243 + if (ioctl(fd, GIO_FONTX, &cfd) == 0) {
1244 + cfd.chardata = xmalloc(cfd.charcount * 32);
1245 + if (ioctl(fd, GIO_FONTX, &cfd) == -1) {
1246 + free(cfd.chardata);
1247 + goto fb_vgafontout;
1248 + }
1249 + } else {
1250 + cfd.charcount=256;
1251 + cfd.chardata = xmalloc(256 * 32);
1252 + if (ioctl(fd, GIO_FONT, cfd.chardata) != 0) {
1253 + free(cfd.chardata);
1254 + goto fb_vgafontout;
1255 + }
1256 + // compute real height
1257 + cfd.charheight=0;
1258 + for (j = 31; (j > 0) && (cfd.charheight == 0); j--) {
1259 + for (i = 0; (i < 256) && (cfd.charheight == 0); i++) {
1260 + if (cfd.chardata[i*32+j] != 0)
1261 + cfd.charheight=j;
1262 + }
1263 + }
1264 + }
1265 + if (cfd.charheight != 0) {
1266 + if (G.font != NULL) fb_freefont();
1267 + G.font = (struct fbfont *) xzalloc(sizeof(struct fbfont));
1268 + GF.charsize = cfd.charheight;
1269 + GF.height = GF.charsize;
1270 + GF.glyphcount = cfd.charcount;
1271 + GF.width = 8;
1272 + GF.rowbytes = 1;
1273 + GF.mem1 = (uint8_t *) xmalloc(GF.height * GF.glyphcount);
1274 + GF.glyphs = GF.mem1;
1275 + // pack font
1276 + for (i = 0; i < GF.glyphcount; i++) {
1277 + memcpy(&(GF.glyphs[i * GF.height]),
1278 + &(cfd.chardata[i * 32]),
1279 + GF.height);
1280 }
1281 }
1282 ! free(cfd.chardata);
1283 ! #endif // FONTOP / FONTX
1284 ! #if defined(GIO_UNIMAP)
1285 ! GF.ud.entry_ct = 0;
1286 ! ioctl(fd, GIO_UNIMAP, &(GF.ud));
1287 ! if (errno != ENOMEM) {
1288 ! goto fb_vgafontout;
1289 ! }
1290 ! if (GF.ud.entry_ct > 0) {
1291 ! GF.ud.entries = xmalloc(GF.ud.entry_ct * sizeof(struct unipair));
1292 ! if (ioctl(fd, GIO_UNIMAP, &(GF.ud)) == -1) {
1293 ! // error no unimap
1294 ! free(GF.ud.entries);
1295 ! GF.ud.entry_ct = 0;
1296 ! }
1297 ! }
1298 ! #endif // GIO_UNIMAP
1299 ! fb_vgafontout:
1300 ! close(fd);
1301 ! #endif // GIO_FONTX or KDFONTOP available
1302 ! return;
1303 ! }
1304 !
1305 ! #if ENABLE_FEATURE_FBSPLASH_FONTLOAD
1306 !
1307 ! static uint16_t nextuni(int ver, uint8_t *map, int *pos) {
1308 ! uint16_t rv;
1309 ! int i;
1310 ! i=*pos;
1311 ! if (ver==1) {
1312 ! rv = map[i + 1];
1313 ! rv = (rv << 8) + map[i];
1314 ! i += 2;
1315 ! } else { // ver 2
1316 ! if (map[i] == 0xFF) rv = 0xFFFF;
1317 ! else if (map[i] == 0xFE) rv = 0xFFFE;
1318 ! else if (map[i] < 0xC0) rv = map[i];
1319 ! else if (map[i] < 0xE0) {
1320 ! rv = map[i] & 0x1F;
1321 ! if ((map[i + 1] & 0xC0) == 0x80)
1322 ! rv = (rv << 6) + (map[++i] & 0x3F);
1323 ! } else if (map[i] < 0xF0) {
1324 ! rv = map[i] & 0x0F;
1325 ! if ((map[i + 1] & 0xC0) == 0x80)
1326 ! rv = (rv << 6) + (map[++i] & 0x3F);
1327 ! if ((map[i + 1] & 0xC0) == 0x80)
1328 ! rv = (rv << 6) + (map[++i] & 0x3F);
1329 ! } else rv = map[i];
1330 ! i++;
1331 ! }
1332 ! *pos=i;
1333 ! return rv;
1334 }
1335
1336 + /**
1337 + * Convert unimap from psf v1 and psf v2 to unimapdesc
1338 + */
1339 + static void convertmap(int ver, uint8_t *map, int mapsize, struct unimapdesc *ud) {
1340 + int i,j,k,glyph,glycodes;
1341 + #if ENABLE_FEATURE_FBSPLASH_PSFSEQS
1342 + int l, seqlen=0, *seq=NULL;
1343 + #endif
1344 + uint16_t e;
1345 + ud->entry_ct=0;
1346 + for (i = 0, glycodes=0; i < mapsize; ) {
1347 + e = nextuni(ver, map, &i);
1348 + if (e == PSF1_STARTSEQ) {
1349 + #if ENABLE_FEATURE_FBSPLASH_PSFSEQS
1350 + seqlen++;
1351 + #endif
1352 + e = nextuni(ver, map, &i);
1353 + while ((e != PSF1_SEPARATOR) && (i < mapsize)) {
1354 + #if ENABLE_FEATURE_FBSPLASH_PSFSEQS
1355 + ud->entry_ct += glycodes;
1356 + #endif
1357 + e = nextuni(ver, map, &i);
1358 + }
1359 + glycodes=0;
1360 + } else if (e == PSF1_SEPARATOR) {
1361 + ud->entry_ct += glycodes;
1362 + glycodes=0;
1363 + } else {
1364 + glycodes++;
1365 + }
1366 + }
1367 + ud->entries = (struct unipair *)
1368 + xmalloc(sizeof(struct unimapdesc) * ud->entry_ct);
1369 + #if ENABLE_FEATURE_FBSPLASH_PSFSEQS
1370 + if (seqlen > 0) {
1371 + seq = xzalloc(sizeof(int) * (seqlen + 1));
1372 + }
1373 + #endif
1374 + for (i = 0, glyph = 0, j = 0, k = 0; i < mapsize; ) {
1375 + e = nextuni(ver, map, &i);
1376 + if (e == PSF1_STARTSEQ) {
1377 + e = nextuni(ver, map, &i);
1378 + k++; // this is seqence - position saved
1379 + // remove sequence - this is not glyph
1380 + while (ud->entries[j-1].fontpos == glyph && j > 0) {
1381 + j--;
1382 + }
1383 + // skip chars in seq
1384 + while ((e != PSF1_SEPARATOR) && (i < mapsize)) {
1385 + e = nextuni(ver, map, &i);
1386 + }
1387 + #if ENABLE_FEATURE_FBSPLASH_PSFSEQS
1388 + if (k < seqlen) seq[k] = i;
1389 + #endif
1390 + } else if (e == PSF1_SEPARATOR) {
1391 + glyph++;
1392 + #if ENABLE_FEATURE_FBSPLASH_PSFSEQS
1393 + // next may be sequence
1394 + if (k < seqlen) seq[k] = i;
1395 + #endif
1396 + } else if (j < ud->entry_ct) {
1397 + ud->entries[j].unicode=e;
1398 + ud->entries[j++].fontpos=glyph;
1399 + }
1400 + }
1401 + #if ENABLE_FEATURE_FBSPLASH_PSFSEQS
1402 + i = 0;
1403 + while (i < seqlen) {
1404 + k = seq[i];
1405 + do {
1406 + e = nextuni(ver, map, &k);
1407 + } while (e != PSF1_STARTSEQ && e != PSF1_SEPARATOR && k < mapsize);
1408 + if (e == PSF1_STARTSEQ) {
1409 + e = nextuni(ver, map, &k);
1410 + while ((e != PSF1_SEPARATOR) && (k < mapsize)) {
1411 + // find glyph in table
1412 + glyph = 0;
1413 + while ((glyph < j) && (ud->entries[glyph].unicode != e)) {
1414 + glyph++;
1415 + }
1416 + // write glyph to table for all chars
1417 + if (glyph < j) { // found
1418 + l = seq[i]; // code pointer
1419 + e = nextuni(ver, map, &l);
1420 + while(e != PSF1_STARTSEQ && l < mapsize) {
1421 + ud->entries[j].unicode=e;
1422 + ud->entries[j++].fontpos=ud->entries[glyph].fontpos;
1423 + e = nextuni(ver, map, &l);
1424 + }
1425 + }
1426 + e = nextuni(ver, map, &k);
1427 + }
1428 + }
1429 + i++;
1430 + }
1431 + if (seqlen > 0) {
1432 + // remove unfound glyphs if any
1433 + ud->entry_ct = j;
1434 + free(seq);
1435 + }
1436 + #endif
1437 + }
1438 +
1439 + /**
1440 + * Read PSF v1 and PSF v2 fonts to own font structure
1441 + */
1442 + static void fb_readpsf(const char *filename) {
1443 + unsigned int len;
1444 + int maplen;
1445 + uint8_t *buf;
1446 + struct psf1_header *psf1;
1447 + struct psf2_header *psf2;
1448 +
1449 + if (G.font != NULL) fb_freefont();
1450 + len = 48*1024; // can't be larger
1451 + buf = xmalloc_open_zipped_read_close(filename, &len);
1452 + if (buf == NULL) {
1453 + bb_simple_perror_msg_and_die(filename);
1454 + }
1455 + if (len < 1024) {
1456 + goto badfmt;
1457 + }
1458 + G.font = (struct fbfont *) xzalloc(sizeof(struct fbfont));
1459 + GF.mem1 = buf;
1460 + psf1 = (struct psf1_header *)buf;
1461 + psf2 = (struct psf2_header *)buf;
1462 + if ((psf1->magic == PSF1_MAGIC) && (psf1->mode <= PSF1_MAXMODE)) {
1463 + GF.glyphs = &(buf[sizeof(struct psf1_header)]);
1464 + GF.charsize = psf1->charsize;
1465 + GF.height = GF.charsize;
1466 + GF.glyphcount = ((psf1->mode & PSF1_MODE512) ? 512 : 256);
1467 + GF.width = 8;
1468 + maplen = len - sizeof(struct psf1_header) -
1469 + (GF.charsize * GF.glyphcount);
1470 + if ((maplen > 0) && ((psf1->mode & PSF1_MODEHASTAB) != 0)) {
1471 + convertmap(1,&(buf[len - maplen]),maplen,&(GF.ud));
1472 + } else {
1473 + if (maplen < 0) goto badfmt;
1474 + }
1475 + } else if ((psf2->magic == PSF2_MAGIC) &&
1476 + (psf2->version <= PSF2_MAXVERSION)) {
1477 + GF.glyphs=&(buf[psf2->headersize]);
1478 + GF.height = psf2->height;
1479 + GF.width = psf2->width;
1480 + GF.glyphcount = psf2->length;
1481 + GF.charsize = psf2->charsize;
1482 + maplen = len - psf2->headersize -
1483 + (GF.charsize * GF.glyphcount);
1484 + if ((maplen > 0) && ((psf2->flags & PSF2_HAS_UNICODE_TABLE) != 0)) {
1485 + convertmap(2,&(buf[len - maplen]),maplen,&(GF.ud));
1486 + } else {
1487 + if (maplen < 0) goto badfmt;
1488 + }
1489 + } else {
1490 + goto badfmt;
1491 + }
1492 + GF.rowbytes = GF.charsize / GF.height;
1493 +
1494 + return;
1495 + badfmt:
1496 + if (G.font) fb_freefont();
1497 + bb_error_msg_and_die("Cannot read file %s - unrecognized format\n",filename);
1498 + }
1499 + #endif // FONTLOAD
1500 + #endif // TEXT
1501
1502 /**
1503 * Parse configuration file
1504 ***************
1505 *** 298,303 ****
1506 --- 1165,1173 ----
1507 "BAR_WIDTH\0" "BAR_HEIGHT\0"
1508 "BAR_LEFT\0" "BAR_TOP\0"
1509 "BAR_R\0" "BAR_G\0" "BAR_B\0"
1510 + #if ENABLE_FEATURE_FBSPLASH_TEXT
1511 + "TEXT_LEFT\0" "TEXT_TOP\0" "TEXT_R\0" "TEXT_G\0" "TEXT_B\0" "TEXT_SIZE\0"
1512 + #endif
1513 #if DEBUG
1514 "DEBUG\0"
1515 #endif
1516 ***************
1517 *** 305,319 ****
1518 char *token[2];
1519 parser_t *parser = config_open2(cfg_filename, xfopen_stdin);
1520 while (config_read(parser, token, 2, 2, "#=",
1521 ! (PARSE_NORMAL | PARSE_MIN_DIE) & ~(PARSE_TRIM | PARSE_COLLAPSE))) {
1522 unsigned val = xatoi_u(token[1]);
1523 int i = index_in_strings(param_names, token[0]);
1524 if (i < 0)
1525 bb_error_msg_and_die("syntax error: %s", token[0]);
1526 ! if (i >= 0 && i < 7)
1527 G.ns[i] = val;
1528 #if DEBUG
1529 ! if (i == 7) {
1530 G.bdebug_messages = val;
1531 if (G.bdebug_messages)
1532 G.logfile_fd = xfopen_for_write("/tmp/fbsplash.log");
1533 --- 1175,1189 ----
1534 char *token[2];
1535 parser_t *parser = config_open2(cfg_filename, xfopen_stdin);
1536 while (config_read(parser, token, 2, 2, "#=",
1537 ! (PARSE_NORMAL | PARSE_MIN_DIE) & ~(PARSE_TRIM | PARSE_COLLAPSE))) {
1538 unsigned val = xatoi_u(token[1]);
1539 int i = index_in_strings(param_names, token[0]);
1540 if (i < 0)
1541 bb_error_msg_and_die("syntax error: %s", token[0]);
1542 ! if (i >= 0 && i < FBCFGVALS)
1543 G.ns[i] = val;
1544 #if DEBUG
1545 ! if (i == FBCFGVALS) {
1546 G.bdebug_messages = val;
1547 if (G.bdebug_messages)
1548 G.logfile_fd = xfopen_for_write("/tmp/fbsplash.log");
1549 ***************
1550 *** 327,337 ****
1551 int fbsplash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1552 int fbsplash_main(int argc UNUSED_PARAM, char **argv)
1553 {
1554 const char *fb_device, *cfg_filename, *fifo_filename;
1555 ! FILE *fp = fp; // for compiler
1556 ! char *num_buf;
1557 ! unsigned num;
1558 bool bCursorOff;
1559
1560 INIT_G();
1561
1562 --- 1197,1220 ----
1563 int fbsplash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1564 int fbsplash_main(int argc UNUSED_PARAM, char **argv)
1565 {
1566 + #if ENABLE_FEATURE_FBSPLASH_FONTLOAD
1567 + const char *fontmap_filename = NULL;
1568 + #endif
1569 const char *fb_device, *cfg_filename, *fifo_filename;
1570 ! char num_buf[512];
1571 ! int num;
1572 bool bCursorOff;
1573 + struct timeval tim;
1574 + fd_set rdfds;
1575 + FILE *fp=fp;
1576 + int bounce_x=0;
1577 + #if ENABLE_FEATURE_FBSPLASH_SPRITES
1578 + int anim_x,anim_y, /* position of sprite or animation */
1579 + anim_n,anim_m, /* min sprite, max sprite for animation */
1580 + anim_p=0, /* actual sprite */
1581 + anim_t=0,anim_now=0; /* time between steps */
1582 + struct sprite *spa=NULL;
1583 + #endif
1584
1585 INIT_G();
1586
1587 ***************
1588 *** 339,347 ****
1589 fb_device = "/dev/fb0";
1590 cfg_filename = NULL;
1591 fifo_filename = NULL;
1592 bCursorOff = 1 & getopt32(argv, "cs:d:i:f:",
1593 &G.image_filename, &fb_device, &cfg_filename, &fifo_filename);
1594 !
1595 // parse configuration file
1596 if (cfg_filename)
1597 init(cfg_filename);
1598 --- 1222,1240 ----
1599 fb_device = "/dev/fb0";
1600 cfg_filename = NULL;
1601 fifo_filename = NULL;
1602 +
1603 + #if ENABLE_FEATURE_FBSPLASH_FONTLOAD
1604 + bCursorOff = 1 & getopt32(argv, "cs:d:i:f:m:",
1605 + &G.image_filename, &fb_device, &cfg_filename, &fifo_filename, &fontmap_filename);
1606 +
1607 + if (fontmap_filename) fb_readpsf(fontmap_filename);
1608 + #else
1609 bCursorOff = 1 & getopt32(argv, "cs:d:i:f:",
1610 &G.image_filename, &fb_device, &cfg_filename, &fifo_filename);
1611 ! #endif
1612 ! #if ENABLE_FEATURE_FBSPLASH_TEXT
1613 ! if (G.font==NULL) fb_readvgafont();
1614 ! #endif
1615 // parse configuration file
1616 if (cfg_filename)
1617 init(cfg_filename);
1618 ***************
1619 *** 357,369 ****
1620 full_write(STDOUT_FILENO, "\x1b" "[?25l", 6);
1621 }
1622
1623 fb_drawimage();
1624
1625 if (!fifo_filename)
1626 return EXIT_SUCCESS;
1627
1628 fp = xfopen_stdin(fifo_filename);
1629 ! if (fp != stdin) {
1630 // For named pipes, we want to support this:
1631 // mkfifo cmd_pipe
1632 // fbsplash -f cmd_pipe .... &
1633 --- 1250,1274 ----
1634 full_write(STDOUT_FILENO, "\x1b" "[?25l", 6);
1635 }
1636
1637 + if (fifo_filename != NULL) {
1638 + G.spb2 = fb_newsprite(G.nbar_width, G.nbar_height, -1, -1);
1639 + }
1640 +
1641 fb_drawimage();
1642
1643 + G.spb1 = fb_newsprite(G.nbar_width, G.nbar_height, G.nbar_posx, G.nbar_posy);
1644 + #if ENABLE_FEATURE_FBSPLASH_TEXT
1645 + if (G.font != NULL)
1646 + G.spt = fb_newsprite(G.scr_var.xres - G.text_posx,
1647 + GF.height * G.text_size,
1648 + G.text_posx, G.text_posy);
1649 + #endif
1650 +
1651 if (!fifo_filename)
1652 return EXIT_SUCCESS;
1653
1654 fp = xfopen_stdin(fifo_filename);
1655 ! if (fp != stdin) {
1656 // For named pipes, we want to support this:
1657 // mkfifo cmd_pipe
1658 // fbsplash -f cmd_pipe .... &
1659 ***************
1660 *** 375,407 ****
1661 // when last writer closes input end.
1662 // The simplest way is to open fifo for writing too
1663 // and become an additional writer :)
1664 ! open(fifo_filename, O_WRONLY); // errors are ignored
1665 ! }
1666
1667 - fb_drawprogressbar(0);
1668 // Block on read, waiting for some input.
1669 // Use of <stdio.h> style I/O allows to correctly
1670 // handle a case when we have many buffered lines
1671 // already in the pipe
1672 ! while ((num_buf = xmalloc_fgetline(fp)) != NULL) {
1673 ! if (strncmp(num_buf, "exit", 4) == 0) {
1674 ! DEBUG_MESSAGE("exit");
1675 ! break;
1676 ! }
1677 ! num = atoi(num_buf);
1678 ! if (isdigit(num_buf[0]) && (num <= 100)) {
1679 #if DEBUG
1680 ! char strVal[10];
1681 ! sprintf(strVal, "%d", num);
1682 ! DEBUG_MESSAGE(strVal);
1683 #endif
1684 - fb_drawprogressbar(num);
1685 }
1686 - free(num_buf);
1687 }
1688 !
1689 if (bCursorOff) // restore cursor
1690 full_write(STDOUT_FILENO, "\x1b" "[?25h", 6);
1691
1692 return EXIT_SUCCESS;
1693 }
1694 --- 1280,1416 ----
1695 // when last writer closes input end.
1696 // The simplest way is to open fifo for writing too
1697 // and become an additional writer :)
1698 ! open(fifo_filename, O_WRONLY | O_NDELAY); // errors are ignored
1699 ! }
1700
1701 // Block on read, waiting for some input.
1702 // Use of <stdio.h> style I/O allows to correctly
1703 // handle a case when we have many buffered lines
1704 // already in the pipe
1705 ! // select and fgets work just in time only in nobuf mode
1706 ! setvbuf(fp, NULL, _IONBF, 0);
1707 ! tim.tv_sec = 0;
1708 ! tim.tv_usec = 100000;
1709 ! while (1) {
1710 ! FD_ZERO(&rdfds);
1711 ! FD_SET(fileno(fp),&rdfds);
1712 ! if ((num=select(fileno(fp) + 1,&rdfds,NULL,NULL,&tim))==-1)
1713 ! break; // select error
1714 ! if (num != 0 && fgets(num_buf,sizeof(num_buf) - 1,fp) != NULL) {
1715 ! num_buf[sizeof(num_buf) - 1]=0;
1716 ! num=strlen(num_buf) - 1;
1717 ! if (num >= 0 && num_buf[num]==10) num_buf[num]=0;
1718 ! if (strncmp(num_buf, "exit", 4) == 0) {
1719 ! DEBUG_MESSAGE("exit");
1720 ! break;
1721 ! } else if (strncmp(num_buf, "bounce", 6) == 0) {
1722 ! bounce_x = 0;
1723 ! #if ENABLE_FEATURE_FBSPLASH_TEXT
1724 ! } else if (strncmp(num_buf, "write:", 6) == 0) {
1725 ! if (G.font!=NULL) fb_drawstring(num_buf + 6);
1726 ! DEBUG_MESSAGE(num_buf);
1727 ! #endif
1728 ! #if ENABLE_FEATURE_FBSPLASH_SPRITES
1729 ! } else if (strncmp(num_buf, "load:", 5) == 0) {
1730 ! if (spa) {
1731 ! fb_putanim(anim_x,anim_y,0,spa); // hide old
1732 ! free(spa);
1733 ! spa=NULL;
1734 ! }
1735 ! if (sscanf(&(num_buf[5]),"%d:%d:",
1736 ! &anim_x,&anim_y) == 2) {
1737 ! // skip x:y
1738 ! for (num=5;num_buf[num] != ':';) num++;
1739 ! for (num++;num_buf[num] != ':';) num++;
1740 ! spa=fb_loadsprites(&(num_buf[num + 1]),anim_x,anim_y);
1741 ! anim_t = anim_now = 0; // stop animation
1742 ! }
1743 ! } else if (strncmp(num_buf, "sprite:", 7) == 0) {
1744 ! if (spa != NULL) {
1745 ! // "sprite:n"
1746 ! anim_t = anim_now = 0; // stop animation
1747 ! anim_p = atoi(&(num_buf[7]));
1748 ! if (anim_p >= 0) {
1749 ! fb_putanim(anim_x,anim_y,anim_p,spa);
1750 ! }
1751 ! }
1752 ! } else if (strncmp(num_buf, "anime:", 6) == 0) {
1753 ! if (spa != NULL) {
1754 ! // "anime:n:m:t"
1755 ! if ((sscanf(&(num_buf[6]),"%d:%d:%d",
1756 ! &anim_n,&anim_m,&anim_t) == 3) &&
1757 ! (anim_n >= 0) && (anim_m >= 0)) {
1758 ! anim_p = anim_n; // first frame
1759 ! fb_putanim(anim_x,anim_y,anim_p,spa);
1760 ! anim_now = anim_t; // next sprite after time t
1761 ! } else {
1762 ! anim_now = anim_t = 0; // stop animation
1763 ! }
1764 ! }
1765 ! #endif
1766 ! } else {
1767 ! num = atoi(num_buf);
1768 ! if ((isdigit(num_buf[0]) || (num_buf[0]=='-')) &&
1769 ! (num >= -100 && num <= 100)) {
1770 #if DEBUG
1771 ! char strVal[10];
1772 ! sprintf(strVal, "%d", num);
1773 ! DEBUG_MESSAGE(strVal);
1774 ! #endif
1775 ! if (num < 0) {
1776 ! fb_drawnbar(-1 * num,100);
1777 ! } else {
1778 ! fb_drawnbar(0,num);
1779 ! }
1780 ! bounce_x = -1; // stop bounce
1781 ! }
1782 ! }
1783 ! } else {
1784 ! if (fp == stdin && feof(fp)) break; // stdin closed END
1785 ! }
1786 ! if (tim.tv_usec == 0) { // timeout - anime
1787 ! tim.tv_usec = 100000;
1788 ! if (bounce_x >= 0) {
1789 ! bounce_x += 5;
1790 ! if (bounce_x > 160) bounce_x = 0;
1791 ! if (bounce_x > 80)
1792 ! fb_drawnbar(160 - bounce_x,180 - bounce_x);
1793 ! else
1794 ! fb_drawnbar(bounce_x, bounce_x + 20);
1795 ! }
1796 ! #if ENABLE_FEATURE_FBSPLASH_SPRITES
1797 ! if (spa != NULL && anim_t != 0) {
1798 ! --anim_now;
1799 ! if (anim_now <= 0) {
1800 ! anim_now = anim_t; // wait
1801 ! if (anim_n < anim_m) {
1802 ! anim_p++;
1803 ! if (anim_p > anim_m) anim_p = anim_n;
1804 ! } else {
1805 ! anim_p--;
1806 ! if (anim_p < anim_m) anim_p = anim_n;
1807 ! }
1808 ! fb_putanim(anim_x,anim_y,anim_p,spa);
1809 ! }
1810 ! }
1811 #endif
1812 }
1813 }
1814 ! if (G.spb1 != NULL) free(G.spb1);
1815 ! G.spb1 = NULL;
1816 ! if (G.spb2 != NULL) free(G.spb2);
1817 ! G.spb2 = NULL;
1818 ! #if ENABLE_FEATURE_FBSPLASH_TEXT
1819 ! if (G.font != NULL) fb_freefont();
1820 ! if (G.spt != NULL) free(G.spt);
1821 ! G.spt = NULL;
1822 ! #endif
1823 ! #if ENABLE_FEATURE_FBSPLASH_SPRITES
1824 ! if (spa != NULL) free(spa);
1825 ! #endif
1826 if (bCursorOff) // restore cursor
1827 full_write(STDOUT_FILENO, "\x1b" "[?25h", 6);
1828
1829 return EXIT_SUCCESS;
1830 }
1831 + #endif
1832 *** busybox-1.15.0/miscutils/fbsplash.cfg.orig 2009-08-21 00:26:14.000000000 +0200
1833 --- busybox-1.15.0/miscutils/fbsplash.cfg 2009-09-01 08:42:18.000000000 +0200
1834 ***************
1835 *** 7,9 ****
1836 --- 7,19 ----
1837 BAR_R=80
1838 BAR_G=80
1839 BAR_B=130
1840 + # the below settings are active only if you enable the option FBSPLASH_TEXT_RENDERING
1841 + # text position
1842 + #TEXT_LEFT=100
1843 + #TEXT_TOP=350
1844 + ## text color
1845 + #TEXT_R=80
1846 + #TEXT_G=80
1847 + #TEXT_B=130
1848 + ## text size (1 to 4)
1849 + #TEXT_SIZE=2