Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 215