Chameleon

Chameleon Svn Source Tree

Root/trunk/i386/boot2/gui.c

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

Archive Download this file

Revision: 127