Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 137