Chameleon

Chameleon Svn Source Tree

Root/branches/andyvand/i386/boot2/gui.c

1/*
2 * gui.c
3 *
4 *
5 * Created by Jasmin Fazlic on 18.12.08.
6 * Copyright 2008/09 Jasmin Fazlic All rights reserved.
7 * Copyright 2008/09 iNDi All rights reserved.
8 *
9 */
10
11#include "gui.h"
12#include "appleboot.h"
13#include "vers.h"
14#include "edid.h"
15
16//#define EMBED_THEME
17
18#ifdef EMBED_THEME
19#include "art.h"
20#define LOADPNG(img)if (loadEmbeddedThemeImage(#img, __## img ##_png, __## img ##_png_len) != 0) { return 1; }
21#else
22#define THEME_NAME_DEFAULT"Default"
23static const char *theme_name = THEME_NAME_DEFAULT;
24#define LOADPNG(img)if (loadThemeImage(#img) != 0) { return 1; }
25#endif
26
27#define MIN(x, y) ((x) < (y) ? (x) : (y))
28#define MAX(x, y) ((x) > (y) ? (x) : (y))
29
30#define VIDEO(x) (bootArgs->Video.v_ ## x)
31
32#define vram VIDEO(baseAddr)
33
34int lasttime=0; // we need this for animating maybe
35
36extern int gDeviceCount;
37
38
39/*
40 * ATTENTION: the enum and the following array images[] MUST match !!!
41 */
42enum {
43iBackground = 0,
44iLogo,
45
46iDeviceGeneric,
47iDeviceHFS,
48iDeviceEXT3,
49iDeviceFAT16,
50iDeviceFAT32,
51iDeviceNTFS,
52iDeviceCDROM,
53iSelection,
54iDeviceScrollPrev,
55iDeviceScrollNext,
56
57iMenuBoot,
58iMenuVerbose,
59iMenuIgnoreCaches,
60iMenuSingleUser,
61iMenuMemoryInfo,
62iMenuVideoInfo,
63iMenuHelp,
64iMenuVerboseDisabled,
65iMenuIgnoreCachesDisabled,
66iMenuSingleUserDisabled,
67iMenuSelection,
68
69iProgressBar,
70iProgressBarBackground,
71
72iTextScrollPrev,
73iTextScrollNext,
74
75iFontConsole,
76iFontSmall,
77};
78
79image_t images[] = {
80{.name = "background",.image = NULL},
81{.name = "logo",.image = NULL},
82
83{.name = "device_generic",.image = NULL},
84{.name = "device_hfsplus",.image = NULL},
85{.name = "device_ext3",.image = NULL},
86{.name = "device_fat16",.image = NULL},
87{.name = "device_fat32",.image = NULL},
88{.name = "device_ntfs",.image = NULL},
89{.name = "device_cdrom",.image = NULL},
90{.name = "device_selection",.image = NULL},
91{.name = "device_scroll_prev",.image = NULL},
92{.name = "device_scroll_next",.image = NULL},
93
94{.name = "menu_boot",.image = NULL},
95{.name = "menu_verbose",.image = NULL},
96{.name = "menu_ignore_caches",.image = NULL},
97{.name = "menu_single_user",.image = NULL},
98{.name = "menu_memory_info",.image = NULL},
99{.name = "menu_video_info",.image = NULL},
100{.name = "menu_help",.image = NULL},
101{.name = "menu_verbose_disabled",.image = NULL},
102{.name = "menu_ignore_caches_disabled",.image = NULL},
103{.name = "menu_single_user_disabled",.image = NULL},
104{.name = "menu_selection",.image = NULL},
105
106{.name = "progress_bar",.image = NULL},
107{.name = "progress_bar_background",.image = NULL},
108
109{.name = "text_scroll_prev",.image = NULL},
110{.name = "text_scroll_next",.image = NULL},
111
112{.name = "font_console",.image = NULL},
113{.name = "font_small",.image = NULL},
114};
115
116int imageCnt = 0;
117
118extern intgDeviceCount;
119extern intselectIndex;
120
121extern MenuItem *menuItems;
122
123char prompt[BOOT_STRING_LEN];
124
125int prompt_pos=0;
126
127char prompt_text[] = "boot: ";
128
129menuitem_t infoMenuItems[] =
130{
131{ .text = "Boot" },
132{ .text = "Boot Verbose" },
133{ .text = "Boot Ignore Caches" },
134{ .text = "Boot Single User" },
135{ .text = "Memory Info" },
136{ .text = "Video Info" },
137{ .text = "Help" }
138};
139
140int initFont(font_t *font, image_t *image);
141void colorFont(font_t *font, uint32_t color);
142void makeRoundedCorners(pixmap_t *p);
143
144static int infoMenuSelection = 0;
145static int infoMenuItemsCount = sizeof(infoMenuItems)/sizeof(infoMenuItems[0]);
146
147static bool infoMenuNativeBoot = false;
148
149static unsigned long screen_params[4] = {0, 0, 0, 0};// here we store the used screen resolution
150
151#ifdef EMBED_THEME
152static int loadEmbeddedThemeImage(const char *image, unsigned char *image_data, unsigned int image_size)
153{
154inti;
155uint16_twidth;
156uint16_theight;
157uint8_t*imagedata;
158
159for (i=0; i < sizeof(images) / sizeof(images[0]); i++) {
160if (strcmp(image, images[i].name) == 0) {
161if (images[i].image == NULL) {
162images[i].image = malloc(sizeof(pixmap_t));
163}
164width = 0;
165height = 0;
166imagedata = NULL;
167if ((loadEmbeddedPngImage(image_data, image_size, &width, &height, &imagedata)) != 0) {
168return 1;
169}
170images[i].image->width = width;
171images[i].image->height = height;
172images[i].image->pixels = (pixel_t *)imagedata;
173flipRB(images[i].image);
174return 0;
175}
176}
177return 1;
178}
179#else
180static int loadThemeImage(const char *image)
181{
182chardirspec[256];
183inti;
184uint16_twidth;
185uint16_theight;
186uint8_t*imagedata;
187
188
189if ((strlen(image) + strlen(theme_name) + 20 ) > sizeof(dirspec)) {
190return 1;
191}
192for (i=0; i < sizeof(images) / sizeof(images[0]); i++) {
193if (strcmp(image, images[i].name) == 0) {
194if (images[i].image == NULL) {
195images[i].image = malloc(sizeof(pixmap_t));
196}
197sprintf(dirspec,"/Extra/Themes/%s/%s.png", theme_name, image);
198width = 0;
199height = 0;
200imagedata = NULL;
201if ((loadPngImage(dirspec, &width, &height, &imagedata)) != 0) {
202printf("ERROR: GUI: could not open '%s/%s.png'!\n", theme_name, image);
203sleep(5);
204return 1;
205}
206images[i].image->width = width;
207images[i].image->height = height;
208images[i].image->pixels = (pixel_t *)imagedata;
209flipRB(images[i].image);
210return 0;
211}
212}
213return 1;
214}
215#endif
216
217static int loadGraphics(void)
218{
219LOADPNG(background);
220LOADPNG(logo);
221
222LOADPNG(device_generic);
223LOADPNG(device_hfsplus);
224LOADPNG(device_ext3);
225LOADPNG(device_fat16);
226LOADPNG(device_fat32);
227LOADPNG(device_ntfs);
228LOADPNG(device_cdrom);
229LOADPNG(device_selection);
230LOADPNG(device_scroll_prev);
231LOADPNG(device_scroll_next);
232
233LOADPNG(menu_boot);
234LOADPNG(menu_verbose);
235LOADPNG(menu_ignore_caches);
236LOADPNG(menu_single_user);
237LOADPNG(menu_memory_info);
238LOADPNG(menu_video_info);
239LOADPNG(menu_help);
240LOADPNG(menu_verbose_disabled);
241LOADPNG(menu_ignore_caches_disabled);
242LOADPNG(menu_single_user_disabled);
243LOADPNG(menu_selection);
244
245LOADPNG(progress_bar);
246LOADPNG(progress_bar_background);
247
248LOADPNG(text_scroll_prev);
249LOADPNG(text_scroll_next);
250
251LOADPNG(font_console);
252LOADPNG(font_small);
253
254initFont( &font_console, &images[iFontConsole]);
255initFont( &font_small, &images[iFontSmall]);
256
257return 0;
258}
259
260pixmap_t *getCroppedPixmapAtPosition( pixmap_t *from, position_t pos, uint16_t width, uint16_t height )
261{
262
263pixmap_t *cropped = malloc( sizeof( pixmap_t ) );
264if( !cropped )
265return 0;
266cropped->pixels = malloc( width * height * 4 );
267if ( !cropped->pixels )
268return 0;
269
270cropped->width = width;
271cropped->height = height;
272
273int destx = 0, desty = 0;
274int srcx = pos.x, srcy = pos.y;
275
276for( ; desty < height; desty++, srcy++)
277{
278for( destx = 0, srcx = pos.x; destx < width; destx++, srcx++ )
279{
280pixel( cropped, destx, desty ).value = pixel( from, srcx, srcy ).value;
281}
282}
283return cropped;
284}
285
286int createBackBuffer( window_t *window )
287{
288gui.backbuffer = malloc(sizeof(pixmap_t));
289if(!gui.backbuffer)
290return 1;
291
292gui.backbuffer->pixels = malloc( window->width * window->height * 4 );
293if(!gui.backbuffer->pixels)
294{
295free(gui.backbuffer);
296gui.backbuffer = 0;
297return 1;
298}
299
300gui.backbuffer->width = gui.screen.width;
301gui.backbuffer->height = gui.screen.height;
302
303return 0;
304}
305
306int createWindowBuffer( window_t *window )
307{
308window->pixmap = malloc(sizeof(pixmap_t));
309if(!window->pixmap)
310return 1;
311
312window->pixmap->pixels = malloc( window->width * window->height * 4 );
313if(!window->pixmap->pixels)
314{
315free(window->pixmap);
316window->pixmap = 0;
317return 1;
318}
319
320window->pixmap->width = window->width;
321window->pixmap->height = window->height;
322
323return 0;
324}
325
326void fillPixmapWithColor(pixmap_t *pm, uint32_t color)
327{
328int x,y;
329
330// fill with given color AARRGGBB
331for( x=0; x < pm->width; x++ )
332for( y=0; y< pm->height; y++)
333pixel(pm,x,y).value = color;
334}
335
336void drawBackground()
337{
338// reset text cursor
339gui.screen.cursor.x = gui.screen.hborder;
340gui.screen.cursor.y = gui.screen.vborder;
341
342fillPixmapWithColor( gui.screen.pixmap, gui.screen.bgcolor);
343
344// draw background.png into background buffer
345blend( images[iBackground].image, gui.screen.pixmap, gui.background.pos );
346
347// draw logo.png into background buffer
348blend( images[iLogo].image, gui.screen.pixmap, gui.logo.pos);
349
350memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
351}
352
353void loadThemeValues(config_file_t *theme, bool overide)
354{
355unsigned int screen_width = gui.screen.width;
356unsigned int screen_height = gui.screen.height;
357unsigned int pixel;
358intalpha;// transparency level 0 (obligue) - 255 (transparent)
359uint32_t color;// color value formatted RRGGBB
360int val, len;
361const char *string;
362
363/*
364 * Parse screen parameters
365 */
366if(getColorForKey("screen_bgcolor", &color, theme ))
367gui.screen.bgcolor = (color & 0x00FFFFFF);
368
369if(getIntForKey("screen_textmargin_h", &val, theme))
370gui.screen.hborder = MIN( gui.screen.width , val );
371
372if(getIntForKey("screen_textmargin_v", &val, theme))
373gui.screen.vborder = MIN( gui.screen.height , val );
374
375/*
376 * Parse background parameters
377 */
378if(getDimensionForKey("background_pos_x", &pixel, theme, screen_width , images[iBackground].image->width ) )
379gui.background.pos.x = pixel;
380
381if(getDimensionForKey("background_pos_y", &pixel, theme, screen_height , images[iBackground].image->height ) )
382gui.background.pos.y = pixel;
383
384/*
385 * Parse logo parameters
386 */
387if(getDimensionForKey("logo_pos_x", &pixel, theme, screen_width , images[iLogo].image->width ) )
388gui.logo.pos.x = pixel;
389
390if(getDimensionForKey("logo_pos_y", &pixel, theme, screen_height , images[iLogo].image->height ) )
391gui.logo.pos.y = pixel;
392
393/*
394 * Parse progress bar parameters
395 */
396if(getDimensionForKey("progressbar_pos_x", &pixel, theme, screen_width , 0 ) )
397gui.progressbar.pos.x = pixel;
398
399if(getDimensionForKey("progressbar_pos_y", &pixel, theme, screen_height , 0 ) )
400gui.progressbar.pos.y = pixel;
401
402/*
403 * Parse countdown text parameters
404 */
405if(getDimensionForKey("countdown_pos_x", &pixel, theme, screen_width , 0 ) )
406gui.countdown.pos.x = pixel;
407
408if(getDimensionForKey("countdown_pos_y", &pixel, theme, screen_height , 0 ) )
409gui.countdown.pos.y = pixel;
410
411/*
412 * Parse devicelist parameters
413 */
414if(getIntForKey("devices_max_visible", &val, theme ))
415gui.maxdevices = MIN( val, gDeviceCount );
416
417if(getIntForKey("devices_iconspacing", &val, theme ))
418gui.devicelist.iconspacing = val;
419
420// check layout for horizontal or vertical
421gui.layout = HorizontalLayout;
422if(getValueForKey( "devices_layout", &string, &len, theme)) {
423if (!strcmp (string, "vertical")) {
424gui.layout = VerticalLayout;
425}
426}
427
428switch (gui.layout) {
429case VerticalLayout:
430gui.devicelist.height = ((images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->height + images[iDeviceScrollNext].image->height) + gui.devicelist.iconspacing);
431gui.devicelist.width = (images[iSelection].image->width + gui.devicelist.iconspacing);
432
433if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , images[iSelection].image->width ) )
434gui.devicelist.pos.x = pixel;
435
436if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , gui.devicelist.height ) )
437gui.devicelist.pos.y = pixel;
438break;
439
440case HorizontalLayout:
441default:
442gui.devicelist.width = ((images[iSelection].image->width + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->width + images[iDeviceScrollNext].image->width) + gui.devicelist.iconspacing);
443gui.devicelist.height = (images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing);
444
445if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , gui.devicelist.width ) )
446gui.devicelist.pos.x = pixel;
447else
448gui.devicelist.pos.x = ( gui.screen.width - gui.devicelist.width ) / 2;
449
450if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , images[iSelection].image->height ) )
451gui.devicelist.pos.y = pixel;
452else
453gui.devicelist.pos.y = ( gui.screen.height - gui.devicelist.height ) / 2;
454break;
455}
456
457if(getColorForKey("devices_bgcolor", &color, theme))
458gui.devicelist.bgcolor = (color & 0x00FFFFFF);
459
460if(getIntForKey("devices_transparency", &alpha, theme))
461gui.devicelist.bgcolor = gui.devicelist.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
462
463/*
464 * Parse infobox parameters
465 */
466if(getIntForKey("infobox_width", &val, theme))
467gui.infobox.width = MIN( screen_width , val );
468
469if(getIntForKey("infobox_height", &val, theme))
470gui.infobox.height = MIN( screen_height , val );
471
472if(getDimensionForKey("infobox_pos_x", &pixel, theme, screen_width , gui.infobox.width ) )
473gui.infobox.pos.x = pixel;
474
475if(getDimensionForKey("infobox_pos_y", &pixel, theme, screen_height , gui.infobox.height ) )
476gui.infobox.pos.y = pixel;
477
478if(getIntForKey("infobox_textmargin_h", &val, theme))
479gui.infobox.hborder = MIN( gui.infobox.width , val );
480
481if(getIntForKey("infobox_textmargin_v", &val, theme))
482gui.infobox.vborder = MIN( gui.infobox.height , val );
483
484if(getColorForKey("infobox_bgcolor", &color, theme))
485gui.infobox.bgcolor = (color & 0x00FFFFFF);
486
487if(getIntForKey("infobox_transparency", &alpha, theme))
488gui.infobox.bgcolor = gui.infobox.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
489
490/*
491 * Parse menu parameters
492 */
493if(getDimensionForKey("menu_width", &pixel, theme, gui.screen.width , 0 ) )
494gui.menu.width = pixel;
495else
496gui.menu.width = images[iMenuSelection].image->width;
497
498if(getDimensionForKey("menu_height", &pixel, theme, gui.screen.height , 0 ) )
499gui.menu.height = pixel;
500else
501gui.menu.height = (infoMenuItemsCount) * images[iMenuSelection].image->height;
502
503if(getDimensionForKey("menu_pos_x", &pixel, theme, screen_width , gui.menu.width ) )
504gui.menu.pos.x = pixel;
505
506if(getDimensionForKey("menu_pos_y", &pixel, theme, screen_height , gui.menu.height ) )
507gui.menu.pos.y = pixel;
508
509if(getIntForKey("menu_textmargin_h", &val, theme))
510gui.menu.hborder = MIN( gui.menu.width , val );
511
512if(getIntForKey("menu_textmargin_v", &val, theme))
513gui.menu.vborder = MIN( gui.menu.height , val );
514
515if(getColorForKey("menu_bgcolor", &color, theme))
516gui.menu.bgcolor = (color & 0x00FFFFFF);
517
518if(getIntForKey("menu_transparency", &alpha, theme))
519gui.menu.bgcolor = gui.menu.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
520
521/*
522 * Parse bootprompt parameters
523 */
524if(getDimensionForKey("bootprompt_width", &pixel, theme, screen_width , 0 ) )
525gui.bootprompt.width = pixel;
526
527if(getIntForKey("bootprompt_height", &val, theme))
528gui.bootprompt.height = MIN( screen_height , val );
529
530if(getDimensionForKey("bootprompt_pos_x", &pixel, theme, screen_width , gui.bootprompt.width ) )
531gui.bootprompt.pos.x = pixel;
532
533if(getDimensionForKey("bootprompt_pos_y", &pixel, theme, screen_height , gui.bootprompt.height ) )
534gui.bootprompt.pos.y = pixel;
535
536if(getIntForKey("bootprompt_textmargin_h", &val, theme))
537gui.bootprompt.hborder = MIN( gui.bootprompt.width , val );
538
539if(getIntForKey("bootprompt_textmargin_v", &val, theme))
540gui.bootprompt.vborder = MIN( gui.bootprompt.height , val );
541
542if(getColorForKey("bootprompt_bgcolor", &color, theme))
543gui.bootprompt.bgcolor = (color & 0x00FFFFFF);
544
545if(getIntForKey("bootprompt_transparency", &alpha, theme))
546gui.bootprompt.bgcolor = gui.bootprompt.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
547
548if(getColorForKey("font_small_color", &color, theme))
549gui.screen.font_small_color = (color & 0x00FFFFFF);
550
551if(getColorForKey("font_console_color", &color, theme))
552gui.screen.font_console_color = (color & 0x00FFFFFF);
553}
554
555int initGUI(void)
556{
557/*intval;*/
558#ifdef EMBED_THEME
559config_file_t*config;
560
561config = &bootInfo->themeConfig;
562if (ParseXMLFile((char *)__theme_plist, &config->dictionary) != 0) {
563return 1;
564}
565#else
566intlen;
567chardirspec[256];
568
569getValueForKey( "Theme", &theme_name, &len, &bootInfo->bootConfig );
570if ((strlen(theme_name) + 27) > sizeof(dirspec)) {
571return 1;
572}
573sprintf(dirspec, "/Extra/Themes/%s/theme.plist", theme_name);
574if (loadConfigFile(dirspec, &bootInfo->themeConfig) != 0) {
575return 1;
576}
577#endif
578
579// determine screen params from edid
580getResolution(&screen_params[0], &screen_params[1], &screen_params[2]);
581
582// Initalizing GUI strucutre.
583bzero(&gui, sizeof(gui_t));
584
585// find best matching vesa mode for our requested width & height
586getGraphicModeParams(screen_params);
587
588// set our screen structure with the mode width & height
589gui.screen.width = screen_params[0];
590gui.screen.height = screen_params[1];
591
592// load graphics otherwise fail and return
593if (loadGraphics() == 0) {
594loadThemeValues(&bootInfo->themeConfig, true);
595colorFont(&font_small, gui.screen.font_small_color);
596colorFont(&font_console, gui.screen.font_console_color);
597
598// create the screen & window buffers
599if (createBackBuffer(&gui.screen) == 0) {
600if (createWindowBuffer(&gui.screen) == 0) {
601if (createWindowBuffer(&gui.devicelist) == 0) {
602if (createWindowBuffer(&gui.bootprompt) == 0) {
603if (createWindowBuffer(&gui.infobox) == 0) {
604if (createWindowBuffer(&gui.menu) == 0) {
605drawBackground();
606// lets copy the screen into the back buffer
607memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
608setVideoMode( GRAPHICS_MODE, 0 );
609gui.initialised = true;
610return 0;
611}
612}
613}
614}
615}
616}
617}
618return 1;
619}
620
621void drawDeviceIcon(BVRef device, pixmap_t *buffer, position_t p)
622{
623int devicetype;
624
625if( diskIsCDROM(device) )
626devicetype = iDeviceCDROM;// Use CDROM icon
627else
628{
629switch (device->part_type)
630{
631case kPartitionTypeHFS:
632
633// TODO: add apple raid icon choices
634
635devicetype = iDeviceHFS;// Use HFS icon
636break;
637
638case kPartitionTypeHPFS:
639devicetype = iDeviceNTFS;// Use HPFS / NTFS icon
640break;
641
642case kPartitionTypeFAT16:
643devicetype = iDeviceFAT16;// Use FAT16 icon
644break;
645
646case kPartitionTypeFAT32:
647devicetype = iDeviceFAT32;// Use FAT32 icon
648break;
649
650case kPartitionTypeEXT3:
651devicetype = iDeviceEXT3;// Use EXT2/3 icon
652break;
653
654default:
655devicetype = iDeviceGeneric;// Use Generic icon
656break;
657}
658}
659
660// draw icon
661blend( images[devicetype].image, buffer, centeredAt( images[devicetype].image, p ));
662
663p.y += (images[iSelection].image->height / 2) + font_console.chars[0]->height;
664
665// draw volume label
666drawStrCenteredAt( device->label, &font_small, buffer, p);
667
668}
669
670void drawDeviceList (int start, int end, int selection)
671{
672int i;
673position_t p, p_prev, p_next;
674
675//uint8_tmaxDevices = MIN( gui.maxdevices, menucount );
676
677fillPixmapWithColor( gui.devicelist.pixmap, gui.devicelist.bgcolor);
678
679makeRoundedCorners( gui.devicelist.pixmap);
680
681switch (gui.layout)
682{
683
684case VerticalLayout:
685p.x = (gui.devicelist.width /2);
686p.y = ( ( images[iSelection].image->height / 2 ) + images[iDeviceScrollPrev].image->height + gui.devicelist.iconspacing );
687
688// place scroll indicators at top & bottom edges
689p_prev = pos ( gui.devicelist.width / 2 , gui.devicelist.iconspacing );
690p_next = pos ( p_prev.x, gui.devicelist.height - gui.devicelist.iconspacing );
691
692break;
693
694default:// use Horizontal layout as the default
695
696case HorizontalLayout:
697p.x = (gui.devicelist.width - ( gui.devicelist.width / gui.maxdevices ) * gui.maxdevices ) / 2 + ( images[iSelection].image->width / 2) + images[iDeviceScrollPrev].image->width + gui.devicelist.iconspacing;
698p.y = ((gui.devicelist.height - font_console.chars[0]->height ) - images[iSelection].image->height) / 2 + ( images[iSelection].image->height / 2 );
699
700// place scroll indicators at left & right edges
701p_prev = pos ( images[iDeviceScrollPrev].image->width / 2 + gui.devicelist.iconspacing / 2, gui.devicelist.height / 2 );
702p_next = pos ( gui.devicelist.width - ( images[iDeviceScrollNext].image->width / 2 + gui.devicelist.iconspacing / 2), gui.devicelist.height / 2 );
703
704break;
705
706}
707
708// draw visible device icons
709for ( i=0; i < gui.maxdevices; i++ )
710{
711BVRef param = menuItems[start+i].param;
712
713if((start+i) == selection)
714{
715 if(param->flags & kBVFlagNativeBoot)
716infoMenuNativeBoot = true;
717 else
718 {
719infoMenuNativeBoot = false;
720if(infoMenuSelection >= INFOMENU_NATIVEBOOT_START && infoMenuSelection <= INFOMENU_NATIVEBOOT_END)
721infoMenuSelection = 0;
722 }
723
724if(gui.menu.draw)
725drawInfoMenuItems();
726
727blend( images[iSelection].image, gui.devicelist.pixmap, centeredAt( images[iSelection].image, p ) );
728
729#if DEBUG
730gui.debug.cursor = pos( 10, 100);
731dprintf( &gui.screen, "label %s\n", param->label );
732dprintf( &gui.screen, "biosdev 0x%x\n", param->biosdev );
733dprintf( &gui.screen, "type 0x%x\n", param->type );
734dprintf( &gui.screen, "flags 0x%x\n", param->flags );
735dprintf( &gui.screen, "part_no %d\n", param->part_no );
736dprintf( &gui.screen, "part_boff 0x%x\n", param->part_boff );
737dprintf( &gui.screen, "part_type 0x%x\n", param->part_type );
738dprintf( &gui.screen, "bps 0x%x\n", param->bps );
739dprintf( &gui.screen, "name %s\n", param->name );
740dprintf( &gui.screen, "type_name %s\n", param->type_name );
741dprintf( &gui.screen, "modtime %d\n", param->modTime );
742#endif
743}
744
745drawDeviceIcon( param, gui.devicelist.pixmap, p );
746
747if (gui.layout == HorizontalLayout)
748{
749p.x += images[iSelection].image->width + gui.devicelist.iconspacing;
750}
751if (gui.layout == VerticalLayout)
752{
753p.y += ( images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing );
754}
755}
756
757// draw prev indicator
758if(start)
759blend( images[iDeviceScrollPrev].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollPrev].image, p_prev ) );
760
761// draw next indicator
762if( end < gDeviceCount - 1 )
763blend( images[iDeviceScrollNext].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollNext].image, p_next ) );
764
765gui.redraw = true;
766
767updateVRAM();
768
769}
770
771void clearGraphicBootPrompt()
772{
773// clear text buffer
774prompt[0] = '\0';
775prompt_pos=0;
776
777
778if(gui.bootprompt.draw == true )
779{
780gui.bootprompt.draw = false;
781gui.redraw = true;
782// this causes extra frames to be drawn
783//updateVRAM();
784}
785
786return;
787}
788
789void updateGraphicBootPrompt(int key)
790{
791if ( key == kBackspaceKey )
792prompt[--prompt_pos] = '\0';
793else
794{
795prompt[prompt_pos] = key;
796prompt_pos++;
797prompt[prompt_pos] = '\0';
798}
799
800fillPixmapWithColor( gui.bootprompt.pixmap, gui.bootprompt.bgcolor);
801
802makeRoundedCorners( gui.bootprompt.pixmap);
803
804position_t p_text = pos( gui.bootprompt.hborder , ( ( gui.bootprompt.height - font_console.chars[0]->height) ) / 2 );
805
806// print the boot prompt text
807drawStr(prompt_text, &font_console, gui.bootprompt.pixmap, p_text);
808
809// get the position of the end of the boot prompt text to display user input
810position_t p_prompt = pos( p_text.x + ( ( strlen(prompt_text) ) * font_console.chars[0]->width ), p_text.y );
811
812// calculate the position of the cursor
813intoffset = ( prompt_pos - ( ( gui.bootprompt.width / font_console.chars[0]->width ) - strlen(prompt_text) - 2 ) );
814
815if ( offset < 0)
816offset = 0;
817
818drawStr( prompt+offset, &font_console, gui.bootprompt.pixmap, p_prompt);
819
820gui.menu.draw = false;
821gui.bootprompt.draw = true;
822gui.redraw = true;
823
824updateVRAM();
825
826return;
827}
828
829inline
830void vramwrite (void *data, int width, int height)
831{
832if (VIDEO (depth) == 32 && VIDEO (rowBytes) == gui.backbuffer->width * 4)
833memcpy((uint8_t *)vram, gui.backbuffer->pixels, VIDEO (rowBytes)*VIDEO (height));
834else
835{
836uint32_t r, g, b;
837int i, j;
838for (i = 0; i < VIDEO (height); i++)
839for (j = 0; j < VIDEO (width); j++)
840{
841b = ((uint8_t *) data)[4*i*width + 4*j];
842g = ((uint8_t *) data)[4*i*width + 4*j + 1];
843r = ((uint8_t *) data)[4*i*width + 4*j + 2];
844switch (VIDEO (depth))
845{
846case 32:
847*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*4) = (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);
848break;
849case 24:
850*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3) = ((*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3))&0xff000000)
851| (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);
852break;
853case 16:
854// Somehow 16-bit is always 15-bits really
855//*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xfc)<<3) | ((r&0xf8)<<8);
856//break;
857case 15:
858*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xf8)<<2) | ((r&0xf8)<<7);
859break;
860}
861}
862}
863}
864
865void updateVRAM()
866{
867if (gui.redraw)
868{
869if (gui.devicelist.draw)
870blend( gui.devicelist.pixmap, gui.backbuffer, gui.devicelist.pos );
871
872if (gui.bootprompt.draw)
873blend( gui.bootprompt.pixmap, gui.backbuffer, gui.bootprompt.pos );
874
875if (gui.menu.draw)
876blend( gui.menu.pixmap, gui.backbuffer, gui.menu.pos );
877
878if (gui.infobox.draw)
879blend( gui.infobox.pixmap, gui.backbuffer, gui.infobox.pos );
880}
881
882vramwrite ( gui.backbuffer->pixels, gui.backbuffer->width, gui.backbuffer->height );
883
884if (gui.redraw)
885{
886memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
887gui.redraw = false;
888}
889}
890
891struct putc_info {
892 char * str;
893 char * last_str;
894};
895
896static void
897sputc(int c, struct putc_info * pi)
898{
899 if (pi->last_str)
900 if (pi->str == pi->last_str) {
901 *(pi->str) = '\0';
902 return;
903 }
904 *(pi->str)++ = c;
905}
906
907int gprintf( window_t * window, const char * fmt, ...)
908{
909char *formattedtext;
910
911va_list ap;
912
913struct putc_info pi;
914
915if ((formattedtext = malloc(1024)) != NULL) {
916// format the text
917va_start(ap, fmt);
918pi.str = formattedtext;
919pi.last_str = 0;
920prf(fmt, ap, sputc, &pi);
921*pi.str = '\0';
922va_end(ap);
923
924position_torigin, cursor, bounds;
925
926int i;
927int character;
928
929origin.x = MAX( window->cursor.x, window->hborder );
930origin.y = MAX( window->cursor.y, window->vborder );
931
932bounds.x = ( window->width - window->hborder );
933bounds.y = ( window->height - window->vborder );
934
935cursor = origin;
936
937font_t *font = &font_console;
938
939for( i=0; i< strlen(formattedtext); i++ )
940{
941character = formattedtext[i];
942
943character -= 32;
944
945// newline ?
946if( formattedtext[i] == '\n' )
947{
948cursor.x = window->hborder;
949cursor.y += font->height;
950
951if ( cursor.y > bounds.y )
952cursor.y = origin.y;
953
954continue;
955}
956
957// tab ?
958if( formattedtext[i] == '\t' )
959cursor.x += ( font->chars[0]->width * 5 );
960
961// draw the character
962if( font->chars[character])
963blend(font->chars[character], window->pixmap, cursor);
964
965cursor.x += font->chars[character]->width;
966
967// check x pos and do newline
968if ( cursor.x > bounds.x )
969{
970cursor.x = origin.x;
971cursor.y += font->height;
972}
973
974// check y pos and reset to origin.y
975if ( cursor.y > bounds.y )
976cursor.y = origin.y;
977}
978
979// update cursor postition
980window->cursor = cursor;
981
982free(formattedtext);
983
984return 0;
985
986}
987return 1;
988}
989
990int dprintf( window_t * window, const char * fmt, ...)
991{
992char *formattedtext;
993
994va_list ap;
995
996//window = &gui.debug;
997
998struct putc_info pi;
999
1000if ((formattedtext = malloc(1024)) != NULL) {
1001// format the text
1002va_start(ap, fmt);
1003pi.str = formattedtext;
1004pi.last_str = 0;
1005prf(fmt, ap, sputc, &pi);
1006*pi.str = '\0';
1007va_end(ap);
1008
1009position_torigin, cursor, bounds;
1010
1011int i;
1012int character;
1013
1014origin.x = MAX( gui.debug.cursor.x, window->hborder );
1015origin.y = MAX( gui.debug.cursor.y, window->vborder );
1016
1017bounds.x = ( window->width - window->hborder );
1018bounds.y = ( window->height - window->vborder );
1019
1020cursor = origin;
1021
1022font_t *font = &font_console;
1023
1024for( i=0; i< strlen(formattedtext); i++ )
1025{
1026character = formattedtext[i];
1027
1028character -= 32;
1029
1030// newline ?
1031if( formattedtext[i] == '\n' )
1032{
1033cursor.x = window->hborder;
1034cursor.y += font->height;
1035
1036if ( cursor.y > bounds.y )
1037cursor.y = origin.y;
1038
1039continue;
1040}
1041
1042// tab ?
1043if( formattedtext[i] == '\t' )
1044cursor.x += ( font->chars[0]->width * 5 );
1045
1046// draw the character
1047if( font->chars[character])
1048blend(font->chars[character], gui.backbuffer, cursor);
1049
1050cursor.x += font->chars[character]->width;
1051
1052// check x pos and do newline
1053if ( cursor.x > bounds.x )
1054{
1055cursor.x = origin.x;
1056cursor.y += font->height;
1057}
1058
1059// check y pos and reset to origin.y
1060if ( cursor.y > bounds.y )
1061cursor.y = origin.y;
1062}
1063
1064// update cursor postition
1065gui.debug.cursor = cursor;
1066
1067free(formattedtext);
1068
1069return 0;
1070
1071}
1072return 1;
1073}
1074
1075int vprf(const char * fmt, va_list ap)
1076{
1077int i;
1078int character;
1079
1080char *formattedtext;
1081window_t *window = &gui.screen;
1082struct putc_info pi;
1083
1084position_torigin, cursor, bounds;
1085font_t *font = &font_console;
1086
1087if ((formattedtext = malloc(1024)) != NULL) {
1088// format the text
1089pi.str = formattedtext;
1090pi.last_str = 0;
1091prf(fmt, ap, sputc, &pi);
1092*pi.str = '\0';
1093
1094origin.x = MAX( window->cursor.x, window->hborder );
1095origin.y = MAX( window->cursor.y, window->vborder );
1096bounds.x = ( window->width - ( window->hborder * 2 ) );
1097bounds.y = ( window->height - ( window->vborder * 2 ) );
1098cursor = origin;
1099
1100for( i=0; i< strlen(formattedtext); i++ )
1101{
1102character = formattedtext[i];
1103character -= 32;
1104
1105// newline ?
1106if( formattedtext[i] == '\n' )
1107{
1108cursor.x = window->hborder;
1109cursor.y += font->height;
1110if ( cursor.y > bounds.y )
1111{
1112gui.redraw = true;
1113updateVRAM();
1114cursor.y = window->vborder;
1115}
1116window->cursor.y = cursor.y;
1117continue;
1118}
1119
1120// tab ?
1121if( formattedtext[i] == '\t' )
1122{
1123cursor.x = ( cursor.x / ( font->chars[0]->width * 8 ) + 1 ) * ( font->chars[0]->width * 8 );
1124continue;
1125}
1126cursor.x += font->chars[character]->width;
1127
1128// check x pos and do newline
1129if ( cursor.x > bounds.x )
1130{
1131cursor.x = origin.x;
1132cursor.y += font->height;
1133}
1134
1135// check y pos and reset to origin.y
1136if ( cursor.y > ( bounds.y + font->chars[0]->height) )
1137{
1138gui.redraw = true;
1139updateVRAM();
1140cursor.y = window->vborder;
1141}
1142// draw the character
1143if( font->chars[character])
1144blend(font->chars[character], gui.backbuffer, cursor);
1145}
1146// save cursor postition
1147window->cursor.x = cursor.x;
1148updateVRAM();
1149free(formattedtext);
1150return 0;
1151}
1152return 1;
1153}
1154
1155void drawStr(char *ch, font_t *font, pixmap_t *blendInto, position_t p)
1156{
1157int i=0;
1158int y=0; // we need this to support multilines '\n'
1159int x=0;
1160
1161for(i=0;i<strlen(ch);i++)
1162{
1163int cha=(int)ch[i];
1164
1165cha-=32;
1166
1167// newline ?
1168if( ch[i] == '\n' )
1169{
1170x = 0;
1171y += font->height;
1172continue;
1173}
1174
1175// tab ?
1176if( ch[i] == '\t' )
1177x+=(font->chars[0]->width*5);
1178
1179if(font->chars[cha])
1180blend(font->chars[cha], blendInto, pos(p.x+x, p.y+y));
1181
1182x += font->chars[cha]->width;
1183}
1184}
1185
1186void drawStrCenteredAt(char *text, font_t *font, pixmap_t *blendInto, position_t p)
1187{
1188int i = 0;
1189int width = 0;
1190
1191// calculate the width in pixels
1192for(i=0;i<strlen(text);i++)
1193width += font->chars[text[i]-32]->width;
1194
1195p.x = ( p.x - ( width / 2 ) );
1196p.y = ( p.y - ( font->height / 2 ) );
1197
1198if ( p.x == -6 )
1199{
1200p.x = 0;
1201}
1202
1203for(i=0;i<strlen(text);i++)
1204{
1205int cha=(int)text[i];
1206
1207cha-=32;
1208
1209if(font->chars[cha])
1210{
1211blend(font->chars[cha], blendInto, p);
1212p.x += font->chars[cha]->width;
1213}
1214}
1215
1216}
1217
1218int initFont(font_t *font, image_t *data)
1219{
1220unsigned int x = 0, y = 0, x2 = 0, x3 = 0;
1221
1222int start = 0, end = 0, count = 0, space = 0;
1223
1224bool monospaced = false;
1225
1226font->height = data->image->height;
1227
1228for( x = 0; x < data->image->width; x++)
1229{
1230start = end;
1231
1232// if the pixel is red we've reached the end of the char
1233if( pixel( data->image, x, 0 ).value == 0xFFFF0000)
1234{
1235end = x + 1;
1236
1237if( (font->chars[count] = malloc(sizeof(pixmap_t)) ) )
1238{
1239font->chars[count]->width = ( end - start) - 1;
1240font->chars[count]->height = font->height;
1241
1242if ( ( font->chars[count]->pixels = malloc( font->chars[count]->width * data->image->height * 4) ) )
1243{
1244space += ( font->chars[count]->width * data->image->height * 4 );
1245// we skip the first line because there are just the red pixels for the char width
1246for( y = 1; y< (font->height); y++)
1247{
1248for( x2 = start, x3 = 0; x2 < end; x2++, x3++)
1249{
1250pixel( font->chars[count], x3, y ) = pixel( data->image, x2, y );
1251}
1252}
1253
1254// check if font is monospaced
1255if( ( count > 0 ) && ( font->width != font->chars[count]->width ) )
1256monospaced = true;
1257
1258font->width = font->chars[count]->width;
1259
1260count++;
1261}
1262}
1263}
1264}
1265
1266if(monospaced)
1267font->width = 0;
1268
1269return 0;
1270}
1271
1272void colorFont(font_t *font, uint32_t color)
1273{
1274if( !color )
1275return;
1276
1277int x, y, width, height;
1278int count = 0;
1279pixel_t *buff;
1280
1281while( font->chars[count++] )
1282{
1283width = font->chars[count-1]->width;
1284height = font->chars[count-1]->height;
1285for( y = 0; y < height; y++ )
1286{
1287for( x = 0; x < width; x++ )
1288{
1289buff = &(pixel( font->chars[count-1], x, y ));
1290if( buff->ch.a )
1291{
1292buff->ch.r = (color & 0xFFFF0000) >> 16;
1293buff->ch.g = (color & 0xFF00FF00) >> 8;
1294buff->ch.b = (color & 0xFF0000FF);
1295}
1296}
1297}
1298}
1299}
1300
1301void makeRoundedCorners(pixmap_t *p)
1302{
1303int x,y;
1304int width=p->width-1;
1305int height=p->height-1;
1306
1307// 10px rounded corner alpha values
1308uint8_t roundedCorner[10][10] =
1309{
1310{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0xC0, 0xFF},
1311{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF},
1312{ 0x00, 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1313{ 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1314{ 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1315{ 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1316{ 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1317{ 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1318{ 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1319{ 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
1320};
1321
1322uint8_t alpha=0;
1323
1324for( y=0; y<10; y++)
1325{
1326for( x=0; x<10; x++)
1327{
1328// skip if the pixel should be visible
1329if(roundedCorner[y][x] != 0xFF)
1330{
1331alpha = ( roundedCorner[y][x] ? (uint8_t) (roundedCorner[y][x] * pixel(p, x, y).ch.a) / 255 : 0 );
1332// Upper left corner
1333pixel(p, x, y).ch.a = alpha;
1334
1335// upper right corner
1336pixel(p, width-x,y).ch.a = alpha;
1337
1338// lower left corner
1339pixel(p, x, height-y).ch.a = alpha;
1340
1341// lower right corner
1342pixel(p, width-x, height-y).ch.a = alpha;
1343}
1344}
1345}
1346}
1347
1348void showInfoBox(char *title, char *text)
1349{
1350int i, key, lines, visiblelines;
1351
1352int currentline=0;
1353int cnt=0;
1354int offset=0;
1355
1356if( !title || !text )
1357return;
1358
1359position_t pos_title = pos ( gui.infobox.vborder, gui.infobox.vborder );
1360
1361// calculate number of lines in the title
1362for ( i = 0, lines = 1; i<strlen(title); i++ )
1363if( title[i] == '\n')
1364lines++;
1365
1366// y position of text is lines in title * height of font
1367position_t pos_text = pos( pos_title.x , pos_title.y + ( font_console.height * lines ));
1368
1369// calculate number of lines in the text
1370for ( i=0, lines = 1; i<strlen(text); i++ )
1371if( text[i] == '\n')
1372lines++;
1373
1374// if text ends with \n strip off
1375if( text[i] == '\n' || text[i] == '\0')
1376lines--;
1377
1378visiblelines = ( ( gui.infobox.height - ( gui.infobox.vborder * 2 ) ) / font_console.height ) - 1;
1379
1380// lets display the text and allow scroll thru using up down / arrows
1381while(1)
1382{
1383// move to current line in text
1384for( offset = 0, i = 0; offset < strlen(text); offset++ )
1385{
1386if( currentline == i)
1387break;
1388if( text[offset] =='\n')
1389i++;
1390}
1391
1392// find last visible line in text and place \0
1393for( i = offset, cnt = 0; i < strlen(text); i++)
1394{
1395if(text[i]=='\n')
1396cnt++;
1397if ( cnt == visiblelines )
1398{
1399text[i]='\0';
1400break;
1401}
1402}
1403
1404fillPixmapWithColor( gui.infobox.pixmap, gui.infobox.bgcolor);
1405
1406makeRoundedCorners( gui.infobox.pixmap);
1407
1408// print the title if present
1409if( title )
1410drawStr(title, &font_console, gui.infobox.pixmap, pos_title);
1411
1412// print the text
1413drawStr( text + offset, &font_console, gui.infobox.pixmap, pos_text);
1414
1415// restore \n in text
1416if ( cnt == visiblelines )
1417text[i] = '\n';
1418
1419position_t pos_indicator = pos( gui.infobox.width - ( images[iTextScrollPrev].image->width - ( gui.infobox.vborder / 2) ), pos_text.y );
1420
1421// draw prev indicator
1422if(offset)
1423{
1424blend( images[iTextScrollPrev].image, gui.infobox.pixmap, centeredAt( images[iTextScrollPrev].image, pos_indicator ));
1425}
1426
1427// draw next indicator
1428if( lines > ( currentline + visiblelines ) )
1429{
1430pos_indicator.y = ( gui.infobox.height - ( ( images[iTextScrollNext].image->width + gui.infobox.vborder ) / 2 ) );
1431blend( images[iTextScrollNext].image, gui.infobox.pixmap, centeredAt( images[iTextScrollNext].image, pos_indicator ) );
1432}
1433
1434gui.bootprompt.draw = false;
1435gui.infobox.draw = true;
1436gui.redraw = true;
1437
1438updateVRAM();
1439
1440key = getc();
1441
1442if( key == kUpArrowkey )
1443if( currentline > 0 )
1444currentline--;
1445
1446if( key == kDownArrowkey )
1447if( lines > ( currentline + visiblelines ) )
1448currentline++;
1449
1450if( key == kEscapeKey || key == 'q' || key == 'Q')
1451{
1452gui.infobox.draw = false;
1453gui.redraw = true;
1454updateVRAM();
1455break;
1456}
1457}
1458}
1459
1460void animateProgressBar()
1461{
1462int y;
1463
1464if( time18() > lasttime)
1465{
1466lasttime = time18();
1467
1468pixmap_t *buffBar = images[iProgressBar].image;
1469
1470uint32_t buff = buffBar->pixels[0].value;
1471
1472memcpy( buffBar->pixels, buffBar->pixels + 1, ( (buffBar->width*buffBar->height) - 1 ) * 4 );
1473
1474for( y = buffBar->height - 1; y > 0; y--)
1475pixel(buffBar, buffBar->width - 1, y) = pixel(buffBar, buffBar->width - 1, y - 1);
1476
1477pixel(buffBar, buffBar->width-1, 0).value = buff;
1478}
1479}
1480
1481void drawProgressBar(pixmap_t *blendInto, uint16_t width, position_t p, uint8_t progress)
1482{
1483if(progress>100)
1484return;
1485
1486p.x = ( p.x - ( width / 2 ) );
1487
1488int todraw = (width * progress) / 100;
1489
1490pixmap_t *buff = images[iProgressBar].image;
1491pixmap_t *buffBG = images[iProgressBarBackground].image;
1492if(!buff || !buffBG)
1493return;
1494
1495pixmap_t progressbar;
1496progressbar.pixels=malloc(width * 4 * buff->height);
1497if(!progressbar.pixels)
1498return;
1499
1500progressbar.width = width;
1501progressbar.height = buff->height;
1502
1503int x=0,x2=0,y=0;
1504
1505for(y=0; y<buff->height; y++)
1506{
1507for(x=0; x<todraw; x++, x2++)
1508{
1509if(x2 == (buff->width-1)) x2=0;
1510pixel(&progressbar, x,y).value = pixel(buff, x2,y).value;
1511}
1512x2=0;
1513}
1514
1515for(y=0; y<buff->height; y++)
1516{
1517for(x=todraw, x2 = 0; x < width - 1; x++, x2++)
1518{
1519if(x2 == (buffBG->width -2 )) x2 = 0;
1520pixel(&progressbar, x,y).value = pixel(buffBG, x2,y).value;
1521}
1522if(progress < 100)
1523pixel(&progressbar, width - 1, y).value = pixel(buffBG, buffBG->width - 1, y).value;
1524if(progress == 0)
1525pixel(&progressbar, 0, y).value = pixel(buffBG, buffBG->width - 1, y).value;
1526x2=0;
1527}
1528
1529blend(&progressbar, blendInto, p);
1530animateProgressBar();
1531free(progressbar.pixels);
1532}
1533
1534void drawInfoMenuItems()
1535{
1536int i,n;
1537
1538position_t position;
1539
1540pixmap_t *selection = images[iMenuSelection].image;
1541
1542pixmap_t *pbuff;
1543
1544fillPixmapWithColor(gui.menu.pixmap, gui.menu.bgcolor);
1545
1546makeRoundedCorners(gui.menu.pixmap);
1547
1548uint8_t offset = infoMenuNativeBoot ? 0 : infoMenuItemsCount - 1;
1549
1550position = pos(0,0);
1551
1552for ( i = 0, n = iMenuBoot; i < infoMenuItemsCount; i++, n++)
1553{
1554if (i == infoMenuSelection)
1555blend(selection, gui.menu.pixmap, position);
1556
1557pbuff = images[n].image;
1558if (offset && i >= INFOMENU_NATIVEBOOT_START && i <= INFOMENU_NATIVEBOOT_END)
1559blend( images[n + (iMenuHelp - iMenuBoot)].image , gui.menu.pixmap,
1560pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
1561else
1562blend( pbuff, gui.menu.pixmap,
1563pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
1564
1565drawStr(infoMenuItems[i].text, &font_console, gui.menu.pixmap,
1566pos(position.x + (pbuff->width + gui.menu.hborder),
1567position.y + ((selection->height - font_console.height) / 2)));
1568position.y += images[iMenuSelection].image->height;
1569
1570}
1571
1572gui.redraw = true;
1573}
1574
1575int drawInfoMenu()
1576{
1577drawInfoMenuItems();
1578
1579gui.menu.draw = true;
1580
1581updateVRAM();
1582
1583return 1;
1584}
1585
1586int updateInfoMenu(int key)
1587{
1588switch (key)
1589{
1590
1591case kUpArrowkey:// up arrow
1592if (infoMenuSelection > 0)
1593{
1594if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_END + 1)
1595infoMenuSelection -= 4;
1596
1597else
1598infoMenuSelection--;
1599drawInfoMenuItems();
1600updateVRAM();
1601
1602} else {
1603
1604gui.menu.draw = false;
1605gui.redraw = true;
1606
1607updateVRAM();
1608
1609return CLOSE_INFO_MENU;
1610}
1611break;
1612
1613case kDownArrowkey:// down arrow
1614if (infoMenuSelection < infoMenuItemsCount - 1)
1615{
1616if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_START - 1)
1617infoMenuSelection += 4;
1618else
1619infoMenuSelection++;
1620drawInfoMenuItems();
1621updateVRAM();
1622}
1623break;
1624
1625case kReturnKey:
1626key = 0;
1627if( infoMenuSelection == MENU_SHOW_MEMORY_INFO )
1628showInfoBox( "Memory Info. Press q to quit.\n", getMemoryInfoString());
1629
1630else if( infoMenuSelection == MENU_SHOW_VIDEO_INFO )
1631showInfoBox( getVBEInfoString(), getVBEModeInfoString() );
1632
1633else if( infoMenuSelection == MENU_SHOW_HELP )
1634showHelp();
1635
1636else
1637{
1638int buff = infoMenuSelection;
1639infoMenuSelection = 0;
1640return buff;
1641}
1642break;
1643}
1644return DO_NOT_BOOT;
1645}
1646
1647uint16_t bootImageWidth = 0;
1648uint16_t bootImageHeight = 0;
1649uint8_t *bootImageData = NULL;
1650static bool usePngImage = true;
1651
1652//==========================================================================
1653// loadBootGraphics
1654static void loadBootGraphics(void)
1655{
1656if (bootImageData != NULL) {
1657return;
1658}
1659
1660#ifdef EMBED_THEME
1661if ((loadEmbeddedPngImage(__boot_png, __boot_png_len, &bootImageWidth, &bootImageHeight, &bootImageData)) != 0) {
1662usePngImage = false;
1663}
1664#else
1665char dirspec[256];
1666
1667if ((strlen(theme_name) + 24) > sizeof(dirspec)) {
1668usePngImage = false;
1669return;
1670}
1671sprintf(dirspec, "/Extra/Themes/%s/boot.png", theme_name);
1672if (loadPngImage(dirspec, &bootImageWidth, &bootImageHeight, &bootImageData) != 0) {
1673usePngImage = false;
1674}
1675#endif
1676}
1677
1678//==========================================================================
1679// drawBootGraphics
1680void drawBootGraphics(void)
1681{
1682/*int pos;*/
1683int length;
1684const char *dummyVal;
1685bool legacy_logo;
1686uint16_t x, y;
1687
1688/** Read default resolution from the graphics card, instead of the theme **/
1689getResolution(&screen_params[0], &screen_params[1], &screen_params[2]);
1690
1691if (getBoolForKey("Legacy Logo", &legacy_logo, &bootInfo->bootConfig) && legacy_logo) {
1692usePngImage = false;
1693} else if (bootImageData == NULL) {
1694loadBootGraphics();
1695}
1696
1697/*// parse screen size parameters
1698if (getIntForKey("boot_width", &pos, &bootInfo->themeConfig)) {
1699screen_params[0] = pos;
1700} else {
1701screen_params[0] = DEFAULT_SCREEN_WIDTH;
1702}
1703if (getIntForKey("boot_height", &pos, &bootInfo->themeConfig)) {
1704screen_params[1] = pos;
1705} else {
1706screen_params[1] = DEFAULT_SCREEN_HEIGHT;
1707}
1708screen_params[2] = 32;*/
1709
1710gui.screen.width = screen_params[0];
1711gui.screen.height = screen_params[1];
1712
1713// find best matching vesa mode for our requested width & height
1714getGraphicModeParams(screen_params);
1715
1716setVideoMode(GRAPHICS_MODE, 0);
1717
1718if (getValueForKey("-checkers", &dummyVal, &length, &bootInfo->bootConfig)) {
1719drawCheckerBoard();
1720} else {
1721// Fill the background to 75% grey (same as BootX).
1722drawColorRectangle(0, 0, screen_params[0], screen_params[1], 0x01);
1723}
1724if ((bootImageData) && (usePngImage)) {
1725x = (screen_params[0] - MIN(bootImageWidth, screen_params[0])) / 2;
1726y = (screen_params[1] - MIN(bootImageHeight, screen_params[1])) / 2;
1727
1728// Draw the image in the center of the display.
1729blendImage(x, y, bootImageWidth, bootImageHeight, bootImageData);
1730} else {
1731uint8_t *appleBootPict;
1732bootImageData = NULL;
1733bootImageWidth = kAppleBootWidth;
1734bootImageHeight = kAppleBootHeight;
1735
1736// Prepare the data for the default Apple boot image.
1737appleBootPict = (uint8_t *) decodeRLE(gAppleBootPictRLE, kAppleBootRLEBlocks, bootImageWidth * bootImageHeight);
1738if (appleBootPict) {
1739convertImage(bootImageWidth, bootImageHeight, appleBootPict, &bootImageData);
1740if (bootImageData) {
1741x = (screen_params[0] - MIN(kAppleBootWidth, screen_params[0])) / 2;
1742y = (screen_params[1] - MIN(kAppleBootHeight, screen_params[1])) / 2;
1743drawDataRectangle(x, y, kAppleBootWidth, kAppleBootHeight, bootImageData);
1744free(bootImageData);
1745}
1746free(appleBootPict);
1747}
1748}
1749}
1750

Archive Download this file

Revision: 141