Chameleon

Chameleon Svn Source Tree

Root/branches/meklortOld/i386/modules/GUI/gui.c

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

Archive Download this file

Revision: 1146