Chameleon

Chameleon Svn Source Tree

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

Source at commit 251 created 13 years 9 months ago.
By meklort, Make md0 image user selectable. Falls back to Postboot.img
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//intval;
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/*
582// parse display size parameters
583if (getIntForKey("screen_width", &val, &bootInfo->themeConfig)) {
584screen_params[0] = val;
585}
586if (getIntForKey("screen_height", &val, &bootInfo->themeConfig)) {
587screen_params[1] = val;
588}
589screen_params[2] = 32;
590*/
591getResolution(&screen_params[0], &screen_params[1], &screen_params[2]);
592
593
594// Initalizing GUI strucutre.
595bzero(&gui, sizeof(gui_t));
596
597// find best matching vesa mode for our requested width & height
598getGraphicModeParams(screen_params);
599
600// set our screen structure with the mode width & height
601gui.screen.width = screen_params[0];
602gui.screen.height = screen_params[1];
603
604// load graphics otherwise fail and return
605if (loadGraphics() == 0) {
606loadThemeValues(&bootInfo->themeConfig, true);
607colorFont(&font_small, gui.screen.font_small_color);
608colorFont(&font_console, gui.screen.font_console_color);
609
610// create the screen & window buffers
611if (createBackBuffer(&gui.screen) == 0) {
612if (createWindowBuffer(&gui.screen) == 0) {
613if (createWindowBuffer(&gui.devicelist) == 0) {
614if (createWindowBuffer(&gui.bootprompt) == 0) {
615if (createWindowBuffer(&gui.infobox) == 0) {
616if (createWindowBuffer(&gui.menu) == 0) {
617drawBackground();
618// lets copy the screen into the back buffer
619memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
620setVideoMode( GRAPHICS_MODE, 0 );
621gui.initialised = true;
622return 0;
623}
624}
625}
626}
627}
628}
629}
630return 1;
631}
632
633void drawDeviceIcon(BVRef device, pixmap_t *buffer, position_t p)
634{
635int devicetype;
636
637if( diskIsCDROM(device) )
638devicetype = iDeviceCDROM;// Use CDROM icon
639else
640{
641switch (device->part_type)
642{
643case kPartitionTypeHFS:
644
645// TODO: add apple raid icon choices
646
647devicetype = iDeviceHFS;// Use HFS icon
648break;
649
650case kPartitionTypeHPFS:
651devicetype = iDeviceNTFS;// Use HPFS / NTFS icon
652break;
653
654case kPartitionTypeFAT16:
655devicetype = iDeviceFAT16;// Use FAT16 icon
656break;
657
658case kPartitionTypeFAT32:
659devicetype = iDeviceFAT32;// Use FAT32 icon
660break;
661
662case kPartitionTypeEXT3:
663devicetype = iDeviceEXT3;// Use EXT2/3 icon
664break;
665
666default:
667devicetype = iDeviceGeneric;// Use Generic icon
668break;
669}
670}
671
672// draw icon
673blend( images[devicetype].image, buffer, centeredAt( images[devicetype].image, p ));
674
675p.y += (images[iSelection].image->height / 2) + font_console.chars[0]->height;
676
677// draw volume label
678drawStrCenteredAt( device->label, &font_small, buffer, p);
679
680}
681
682void drawDeviceList (int start, int end, int selection)
683{
684int i;
685position_t p, p_prev, p_next;
686
687//uint8_tmaxDevices = MIN( gui.maxdevices, menucount );
688
689fillPixmapWithColor( gui.devicelist.pixmap, gui.devicelist.bgcolor);
690
691makeRoundedCorners( gui.devicelist.pixmap);
692
693switch (gui.layout)
694{
695
696case VerticalLayout:
697p.x = (gui.devicelist.width /2);
698p.y = ( ( images[iSelection].image->height / 2 ) + images[iDeviceScrollPrev].image->height + gui.devicelist.iconspacing );
699
700// place scroll indicators at top & bottom edges
701p_prev = pos ( gui.devicelist.width / 2 , gui.devicelist.iconspacing );
702p_next = pos ( p_prev.x, gui.devicelist.height - gui.devicelist.iconspacing );
703
704break;
705
706default:// use Horizontal layout as the default
707
708case HorizontalLayout:
709p.x = (gui.devicelist.width - ( gui.devicelist.width / gui.maxdevices ) * gui.maxdevices ) / 2 + ( images[iSelection].image->width / 2) + images[iDeviceScrollPrev].image->width + gui.devicelist.iconspacing;
710p.y = ((gui.devicelist.height - font_console.chars[0]->height ) - images[iSelection].image->height) / 2 + ( images[iSelection].image->height / 2 );
711
712// place scroll indicators at left & right edges
713p_prev = pos ( images[iDeviceScrollPrev].image->width / 2 + gui.devicelist.iconspacing / 2, gui.devicelist.height / 2 );
714p_next = pos ( gui.devicelist.width - ( images[iDeviceScrollNext].image->width / 2 + gui.devicelist.iconspacing / 2), gui.devicelist.height / 2 );
715
716break;
717
718}
719
720// draw visible device icons
721for ( i=0; i < gui.maxdevices; i++ )
722{
723BVRef param = menuItems[start+i].param;
724
725if((start+i) == selection)
726{
727 if(param->flags & kBVFlagNativeBoot)
728infoMenuNativeBoot = true;
729 else
730 {
731infoMenuNativeBoot = false;
732if(infoMenuSelection >= INFOMENU_NATIVEBOOT_START && infoMenuSelection <= INFOMENU_NATIVEBOOT_END)
733infoMenuSelection = 0;
734 }
735
736if(gui.menu.draw)
737drawInfoMenuItems();
738
739blend( images[iSelection].image, gui.devicelist.pixmap, centeredAt( images[iSelection].image, p ) );
740
741#if DEBUG
742gui.debug.cursor = pos( 10, 100);
743dprintf( &gui.screen, "label %s\n", param->label );
744dprintf( &gui.screen, "biosdev 0x%x\n", param->biosdev );
745 dprintf(&gui.screen, "width %d\n", gui.screen.width);
746 dprintf(&gui.screen, "height %d\n", gui.screen.height);
747dprintf( &gui.screen, "type 0x%x\n", param->type );
748dprintf( &gui.screen, "flags 0x%x\n", param->flags );
749dprintf( &gui.screen, "part_no %d\n", param->part_no );
750dprintf( &gui.screen, "part_boff 0x%x\n", param->part_boff );
751dprintf( &gui.screen, "part_type 0x%x\n", param->part_type );
752dprintf( &gui.screen, "bps 0x%x\n", param->bps );
753dprintf( &gui.screen, "name %s\n", param->name );
754dprintf( &gui.screen, "type_name %s\n", param->type_name );
755dprintf( &gui.screen, "modtime %d\n", param->modTime );
756#endif
757}
758
759drawDeviceIcon( param, gui.devicelist.pixmap, p );
760
761if (gui.layout == HorizontalLayout)
762{
763p.x += images[iSelection].image->width + gui.devicelist.iconspacing;
764}
765if (gui.layout == VerticalLayout)
766{
767p.y += ( images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing );
768}
769}
770
771// draw prev indicator
772if(start)
773blend( images[iDeviceScrollPrev].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollPrev].image, p_prev ) );
774
775// draw next indicator
776if( end < gDeviceCount - 1 )
777blend( images[iDeviceScrollNext].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollNext].image, p_next ) );
778
779gui.redraw = true;
780
781updateVRAM();
782
783}
784
785void clearGraphicBootPrompt()
786{
787// clear text buffer
788prompt[0] = '\0';
789prompt_pos=0;
790
791
792if(gui.bootprompt.draw == true )
793{
794gui.bootprompt.draw = false;
795gui.redraw = true;
796// this causes extra frames to be drawn
797//updateVRAM();
798}
799
800return;
801}
802
803void updateGraphicBootPrompt(int key)
804{
805if ( key == kBackspaceKey )
806prompt[--prompt_pos] = '\0';
807else
808{
809prompt[prompt_pos] = key;
810prompt_pos++;
811prompt[prompt_pos] = '\0';
812}
813
814fillPixmapWithColor( gui.bootprompt.pixmap, gui.bootprompt.bgcolor);
815
816makeRoundedCorners( gui.bootprompt.pixmap);
817
818position_t p_text = pos( gui.bootprompt.hborder , ( ( gui.bootprompt.height - font_console.chars[0]->height) ) / 2 );
819
820// print the boot prompt text
821drawStr(prompt_text, &font_console, gui.bootprompt.pixmap, p_text);
822
823// get the position of the end of the boot prompt text to display user input
824position_t p_prompt = pos( p_text.x + ( ( strlen(prompt_text) ) * font_console.chars[0]->width ), p_text.y );
825
826// calculate the position of the cursor
827intoffset = ( prompt_pos - ( ( gui.bootprompt.width / font_console.chars[0]->width ) - strlen(prompt_text) - 2 ) );
828
829if ( offset < 0)
830offset = 0;
831
832drawStr( prompt+offset, &font_console, gui.bootprompt.pixmap, p_prompt);
833
834gui.menu.draw = false;
835gui.bootprompt.draw = true;
836gui.redraw = true;
837
838updateVRAM();
839
840return;
841}
842
843inline
844void vramwrite (void *data, int width, int height)
845{
846if (VIDEO (depth) == 32 && VIDEO (rowBytes) == gui.backbuffer->width * 4)
847memcpy((uint8_t *)vram, gui.backbuffer->pixels, VIDEO (rowBytes)*VIDEO (height));
848else
849{
850uint32_t r, g, b;
851int i, j;
852for (i = 0; i < VIDEO (height); i++)
853for (j = 0; j < VIDEO (width); j++)
854{
855b = ((uint8_t *) data)[4*i*width + 4*j];
856g = ((uint8_t *) data)[4*i*width + 4*j + 1];
857r = ((uint8_t *) data)[4*i*width + 4*j + 2];
858switch (VIDEO (depth))
859{
860case 32:
861*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*4) = (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);
862break;
863case 24:
864*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3) = ((*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3))&0xff000000)
865| (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);
866break;
867case 16:
868// Somehow 16-bit is always 15-bits really
869//*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xfc)<<3) | ((r&0xf8)<<8);
870//break;
871case 15:
872*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xf8)<<2) | ((r&0xf8)<<7);
873break;
874}
875}
876}
877}
878
879void updateVRAM()
880{
881if (gui.redraw)
882{
883if (gui.devicelist.draw)
884blend( gui.devicelist.pixmap, gui.backbuffer, gui.devicelist.pos );
885
886if (gui.bootprompt.draw)
887blend( gui.bootprompt.pixmap, gui.backbuffer, gui.bootprompt.pos );
888
889if (gui.menu.draw)
890blend( gui.menu.pixmap, gui.backbuffer, gui.menu.pos );
891
892if (gui.infobox.draw)
893blend( gui.infobox.pixmap, gui.backbuffer, gui.infobox.pos );
894}
895
896vramwrite ( gui.backbuffer->pixels, gui.backbuffer->width, gui.backbuffer->height );
897
898if (gui.redraw)
899{
900memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
901gui.redraw = false;
902}
903}
904
905struct putc_info {
906 char * str;
907 char * last_str;
908};
909
910static void
911sputc(int c, struct putc_info * pi)
912{
913 if (pi->last_str)
914 if (pi->str == pi->last_str) {
915 *(pi->str) = '\0';
916 return;
917 }
918 *(pi->str)++ = c;
919}
920
921int gprintf( window_t * window, const char * fmt, ...)
922{
923char *formattedtext;
924
925va_list ap;
926
927struct putc_info pi;
928
929if ((formattedtext = malloc(1024)) != NULL) {
930// format the text
931va_start(ap, fmt);
932pi.str = formattedtext;
933pi.last_str = 0;
934prf(fmt, ap, sputc, &pi);
935*pi.str = '\0';
936va_end(ap);
937
938position_torigin, cursor, bounds;
939
940int i;
941int character;
942
943origin.x = MAX( window->cursor.x, window->hborder );
944origin.y = MAX( window->cursor.y, window->vborder );
945
946bounds.x = ( window->width - window->hborder );
947bounds.y = ( window->height - window->vborder );
948
949cursor = origin;
950
951font_t *font = &font_console;
952
953for( i=0; i< strlen(formattedtext); i++ )
954{
955character = formattedtext[i];
956
957character -= 32;
958
959// newline ?
960if( formattedtext[i] == '\n' )
961{
962cursor.x = window->hborder;
963cursor.y += font->height;
964
965if ( cursor.y > bounds.y )
966cursor.y = origin.y;
967
968continue;
969}
970
971// tab ?
972if( formattedtext[i] == '\t' )
973cursor.x += ( font->chars[0]->width * 5 );
974
975// draw the character
976if( font->chars[character])
977blend(font->chars[character], window->pixmap, cursor);
978
979cursor.x += font->chars[character]->width;
980
981// check x pos and do newline
982if ( cursor.x > bounds.x )
983{
984cursor.x = origin.x;
985cursor.y += font->height;
986}
987
988// check y pos and reset to origin.y
989if ( cursor.y > bounds.y )
990cursor.y = origin.y;
991}
992
993// update cursor postition
994window->cursor = cursor;
995
996free(formattedtext);
997
998return 0;
999
1000}
1001return 1;
1002}
1003
1004int dprintf( window_t * window, const char * fmt, ...)
1005{
1006char *formattedtext;
1007
1008va_list ap;
1009
1010//window = &gui.debug;
1011
1012struct putc_info pi;
1013
1014if ((formattedtext = malloc(1024)) != NULL) {
1015// format the text
1016va_start(ap, fmt);
1017pi.str = formattedtext;
1018pi.last_str = 0;
1019prf(fmt, ap, sputc, &pi);
1020*pi.str = '\0';
1021va_end(ap);
1022
1023position_torigin, cursor, bounds;
1024
1025int i;
1026int character;
1027
1028origin.x = MAX( gui.debug.cursor.x, window->hborder );
1029origin.y = MAX( gui.debug.cursor.y, window->vborder );
1030
1031bounds.x = ( window->width - window->hborder );
1032bounds.y = ( window->height - window->vborder );
1033
1034cursor = origin;
1035
1036font_t *font = &font_console;
1037
1038for( i=0; i< strlen(formattedtext); i++ )
1039{
1040character = formattedtext[i];
1041
1042character -= 32;
1043
1044// newline ?
1045if( formattedtext[i] == '\n' )
1046{
1047cursor.x = window->hborder;
1048cursor.y += font->height;
1049
1050if ( cursor.y > bounds.y )
1051cursor.y = origin.y;
1052
1053continue;
1054}
1055
1056// tab ?
1057if( formattedtext[i] == '\t' )
1058cursor.x += ( font->chars[0]->width * 5 );
1059
1060// draw the character
1061if( font->chars[character])
1062blend(font->chars[character], gui.backbuffer, cursor);
1063
1064cursor.x += font->chars[character]->width;
1065
1066// check x pos and do newline
1067if ( cursor.x > bounds.x )
1068{
1069cursor.x = origin.x;
1070cursor.y += font->height;
1071}
1072
1073// check y pos and reset to origin.y
1074if ( cursor.y > bounds.y )
1075cursor.y = origin.y;
1076}
1077
1078// update cursor postition
1079gui.debug.cursor = cursor;
1080
1081free(formattedtext);
1082
1083return 0;
1084
1085}
1086return 1;
1087}
1088
1089int vprf(const char * fmt, va_list ap)
1090{
1091int i;
1092int character;
1093
1094char *formattedtext;
1095window_t *window = &gui.screen;
1096struct putc_info pi;
1097
1098position_torigin, cursor, bounds;
1099font_t *font = &font_console;
1100
1101if ((formattedtext = malloc(1024)) != NULL) {
1102// format the text
1103pi.str = formattedtext;
1104pi.last_str = 0;
1105prf(fmt, ap, sputc, &pi);
1106*pi.str = '\0';
1107
1108origin.x = MAX( window->cursor.x, window->hborder );
1109origin.y = MAX( window->cursor.y, window->vborder );
1110bounds.x = ( window->width - ( window->hborder * 2 ) );
1111bounds.y = ( window->height - ( window->vborder * 2 ) );
1112cursor = origin;
1113
1114for( i=0; i< strlen(formattedtext); i++ )
1115{
1116character = formattedtext[i];
1117character -= 32;
1118
1119// newline ?
1120if( formattedtext[i] == '\n' )
1121{
1122cursor.x = window->hborder;
1123cursor.y += font->height;
1124if ( cursor.y > bounds.y )
1125{
1126gui.redraw = true;
1127updateVRAM();
1128cursor.y = window->vborder;
1129}
1130window->cursor.y = cursor.y;
1131continue;
1132}
1133
1134// tab ?
1135if( formattedtext[i] == '\t' )
1136{
1137cursor.x = ( cursor.x / ( font->chars[0]->width * 8 ) + 1 ) * ( font->chars[0]->width * 8 );
1138continue;
1139}
1140cursor.x += font->chars[character]->width;
1141
1142// check x pos and do newline
1143if ( cursor.x > bounds.x )
1144{
1145cursor.x = origin.x;
1146cursor.y += font->height;
1147}
1148
1149// check y pos and reset to origin.y
1150if ( cursor.y > ( bounds.y + font->chars[0]->height) )
1151{
1152gui.redraw = true;
1153updateVRAM();
1154cursor.y = window->vborder;
1155}
1156// draw the character
1157if( font->chars[character])
1158blend(font->chars[character], gui.backbuffer, cursor);
1159}
1160// save cursor postition
1161window->cursor.x = cursor.x;
1162updateVRAM();
1163free(formattedtext);
1164return 0;
1165}
1166return 1;
1167}
1168
1169void drawStr(char *ch, font_t *font, pixmap_t *blendInto, position_t p)
1170{
1171int i=0;
1172int y=0; // we need this to support multilines '\n'
1173int x=0;
1174
1175for(i=0;i<strlen(ch);i++)
1176{
1177int cha=(int)ch[i];
1178
1179cha-=32;
1180
1181// newline ?
1182if( ch[i] == '\n' )
1183{
1184x = 0;
1185y += font->height;
1186continue;
1187}
1188
1189// tab ?
1190if( ch[i] == '\t' )
1191x+=(font->chars[0]->width*5);
1192
1193if(font->chars[cha])
1194blend(font->chars[cha], blendInto, pos(p.x+x, p.y+y));
1195
1196x += font->chars[cha]->width;
1197}
1198}
1199
1200void drawStrCenteredAt(char *text, font_t *font, pixmap_t *blendInto, position_t p)
1201{
1202int i = 0;
1203int width = 0;
1204
1205// calculate the width in pixels
1206for(i=0;i<strlen(text);i++)
1207width += font->chars[text[i]-32]->width;
1208
1209p.x = ( p.x - ( width / 2 ) );
1210p.y = ( p.y - ( font->height / 2 ) );
1211
1212if ( p.x == -6 )
1213{
1214p.x = 0;
1215}
1216
1217for(i=0;i<strlen(text);i++)
1218{
1219int cha=(int)text[i];
1220
1221cha-=32;
1222
1223if(font->chars[cha])
1224{
1225blend(font->chars[cha], blendInto, p);
1226p.x += font->chars[cha]->width;
1227}
1228}
1229
1230}
1231
1232int initFont(font_t *font, image_t *data)
1233{
1234unsigned int x = 0, y = 0, x2 = 0, x3 = 0;
1235
1236int start = 0, end = 0, count = 0, space = 0;
1237
1238bool monospaced = false;
1239
1240font->height = data->image->height;
1241
1242for( x = 0; x < data->image->width; x++)
1243{
1244start = end;
1245
1246// if the pixel is red we've reached the end of the char
1247if( pixel( data->image, x, 0 ).value == 0xFFFF0000)
1248{
1249end = x + 1;
1250
1251if( (font->chars[count] = malloc(sizeof(pixmap_t)) ) )
1252{
1253font->chars[count]->width = ( end - start) - 1;
1254font->chars[count]->height = font->height;
1255
1256if ( ( font->chars[count]->pixels = malloc( font->chars[count]->width * data->image->height * 4) ) )
1257{
1258space += ( font->chars[count]->width * data->image->height * 4 );
1259// we skip the first line because there are just the red pixels for the char width
1260for( y = 1; y< (font->height); y++)
1261{
1262for( x2 = start, x3 = 0; x2 < end; x2++, x3++)
1263{
1264pixel( font->chars[count], x3, y ) = pixel( data->image, x2, y );
1265}
1266}
1267
1268// check if font is monospaced
1269if( ( count > 0 ) && ( font->width != font->chars[count]->width ) )
1270monospaced = true;
1271
1272font->width = font->chars[count]->width;
1273
1274count++;
1275}
1276}
1277}
1278}
1279
1280if(monospaced)
1281font->width = 0;
1282
1283return 0;
1284}
1285
1286void colorFont(font_t *font, uint32_t color)
1287{
1288if( !color )
1289return;
1290
1291int x, y, width, height;
1292int count = 0;
1293pixel_t *buff;
1294
1295while( font->chars[count++] )
1296{
1297width = font->chars[count-1]->width;
1298height = font->chars[count-1]->height;
1299for( y = 0; y < height; y++ )
1300{
1301for( x = 0; x < width; x++ )
1302{
1303buff = &(pixel( font->chars[count-1], x, y ));
1304if( buff->ch.a )
1305{
1306buff->ch.r = (color & 0xFFFF0000) >> 16;
1307buff->ch.g = (color & 0xFF00FF00) >> 8;
1308buff->ch.b = (color & 0xFF0000FF);
1309}
1310}
1311}
1312}
1313}
1314
1315void makeRoundedCorners(pixmap_t *p)
1316{
1317int x,y;
1318int width=p->width-1;
1319int height=p->height-1;
1320
1321// 10px rounded corner alpha values
1322uint8_t roundedCorner[10][10] =
1323{
1324{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0xC0, 0xFF},
1325{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF},
1326{ 0x00, 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1327{ 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1328{ 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1329{ 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1330{ 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1331{ 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1332{ 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1333{ 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
1334};
1335
1336uint8_t alpha=0;
1337
1338for( y=0; y<10; y++)
1339{
1340for( x=0; x<10; x++)
1341{
1342// skip if the pixel should be visible
1343if(roundedCorner[y][x] != 0xFF)
1344{
1345alpha = ( roundedCorner[y][x] ? (uint8_t) (roundedCorner[y][x] * pixel(p, x, y).ch.a) / 255 : 0 );
1346// Upper left corner
1347pixel(p, x, y).ch.a = alpha;
1348
1349// upper right corner
1350pixel(p, width-x,y).ch.a = alpha;
1351
1352// lower left corner
1353pixel(p, x, height-y).ch.a = alpha;
1354
1355// lower right corner
1356pixel(p, width-x, height-y).ch.a = alpha;
1357}
1358}
1359}
1360}
1361
1362void showInfoBox(char *title, char *text)
1363{
1364int i, key, lines, visiblelines;
1365
1366int currentline=0;
1367int cnt=0;
1368int offset=0;
1369
1370if( !title || !text )
1371return;
1372
1373position_t pos_title = pos ( gui.infobox.vborder, gui.infobox.vborder );
1374
1375// calculate number of lines in the title
1376for ( i = 0, lines = 1; i<strlen(title); i++ )
1377if( title[i] == '\n')
1378lines++;
1379
1380// y position of text is lines in title * height of font
1381position_t pos_text = pos( pos_title.x , pos_title.y + ( font_console.height * lines ));
1382
1383// calculate number of lines in the text
1384for ( i=0, lines = 1; i<strlen(text); i++ )
1385if( text[i] == '\n')
1386lines++;
1387
1388// if text ends with \n strip off
1389if( text[i] == '\n' || text[i] == '\0')
1390lines--;
1391
1392visiblelines = ( ( gui.infobox.height - ( gui.infobox.vborder * 2 ) ) / font_console.height ) - 1;
1393
1394// lets display the text and allow scroll thru using up down / arrows
1395while(1)
1396{
1397// move to current line in text
1398for( offset = 0, i = 0; offset < strlen(text); offset++ )
1399{
1400if( currentline == i)
1401break;
1402if( text[offset] =='\n')
1403i++;
1404}
1405
1406// find last visible line in text and place \0
1407for( i = offset, cnt = 0; i < strlen(text); i++)
1408{
1409if(text[i]=='\n')
1410cnt++;
1411if ( cnt == visiblelines )
1412{
1413text[i]='\0';
1414break;
1415}
1416}
1417
1418fillPixmapWithColor( gui.infobox.pixmap, gui.infobox.bgcolor);
1419
1420makeRoundedCorners( gui.infobox.pixmap);
1421
1422// print the title if present
1423if( title )
1424drawStr(title, &font_console, gui.infobox.pixmap, pos_title);
1425
1426// print the text
1427drawStr( text + offset, &font_console, gui.infobox.pixmap, pos_text);
1428
1429// restore \n in text
1430if ( cnt == visiblelines )
1431text[i] = '\n';
1432
1433position_t pos_indicator = pos( gui.infobox.width - ( images[iTextScrollPrev].image->width - ( gui.infobox.vborder / 2) ), pos_text.y );
1434
1435// draw prev indicator
1436if(offset)
1437{
1438blend( images[iTextScrollPrev].image, gui.infobox.pixmap, centeredAt( images[iTextScrollPrev].image, pos_indicator ));
1439}
1440
1441// draw next indicator
1442if( lines > ( currentline + visiblelines ) )
1443{
1444pos_indicator.y = ( gui.infobox.height - ( ( images[iTextScrollNext].image->width + gui.infobox.vborder ) / 2 ) );
1445blend( images[iTextScrollNext].image, gui.infobox.pixmap, centeredAt( images[iTextScrollNext].image, pos_indicator ) );
1446}
1447
1448gui.bootprompt.draw = false;
1449gui.infobox.draw = true;
1450gui.redraw = true;
1451
1452updateVRAM();
1453
1454key = getc();
1455
1456if( key == kUpArrowkey )
1457if( currentline > 0 )
1458currentline--;
1459
1460if( key == kDownArrowkey )
1461if( lines > ( currentline + visiblelines ) )
1462currentline++;
1463
1464if( key == kEscapeKey || key == 'q' || key == 'Q')
1465{
1466gui.infobox.draw = false;
1467gui.redraw = true;
1468updateVRAM();
1469break;
1470}
1471}
1472}
1473
1474void animateProgressBar()
1475{
1476int y;
1477
1478if( time18() > lasttime)
1479{
1480lasttime = time18();
1481
1482pixmap_t *buffBar = images[iProgressBar].image;
1483
1484uint32_t buff = buffBar->pixels[0].value;
1485
1486memcpy( buffBar->pixels, buffBar->pixels + 1, ( (buffBar->width*buffBar->height) - 1 ) * 4 );
1487
1488for( y = buffBar->height - 1; y > 0; y--)
1489pixel(buffBar, buffBar->width - 1, y) = pixel(buffBar, buffBar->width - 1, y - 1);
1490
1491pixel(buffBar, buffBar->width-1, 0).value = buff;
1492}
1493}
1494
1495void drawProgressBar(pixmap_t *blendInto, uint16_t width, position_t p, uint8_t progress)
1496{
1497if(progress>100)
1498return;
1499
1500p.x = ( p.x - ( width / 2 ) );
1501
1502int todraw = (width * progress) / 100;
1503
1504pixmap_t *buff = images[iProgressBar].image;
1505pixmap_t *buffBG = images[iProgressBarBackground].image;
1506if(!buff || !buffBG)
1507return;
1508
1509pixmap_t progressbar;
1510progressbar.pixels=malloc(width * 4 * buff->height);
1511if(!progressbar.pixels)
1512return;
1513
1514progressbar.width = width;
1515progressbar.height = buff->height;
1516
1517int x=0,x2=0,y=0;
1518
1519for(y=0; y<buff->height; y++)
1520{
1521for(x=0; x<todraw; x++, x2++)
1522{
1523if(x2 == (buff->width-1)) x2=0;
1524pixel(&progressbar, x,y).value = pixel(buff, x2,y).value;
1525}
1526x2=0;
1527}
1528
1529for(y=0; y<buff->height; y++)
1530{
1531for(x=todraw, x2 = 0; x < width - 1; x++, x2++)
1532{
1533if(x2 == (buffBG->width -2 )) x2 = 0;
1534pixel(&progressbar, x,y).value = pixel(buffBG, x2,y).value;
1535}
1536if(progress < 100)
1537pixel(&progressbar, width - 1, y).value = pixel(buffBG, buffBG->width - 1, y).value;
1538if(progress == 0)
1539pixel(&progressbar, 0, y).value = pixel(buffBG, buffBG->width - 1, y).value;
1540x2=0;
1541}
1542
1543blend(&progressbar, blendInto, p);
1544animateProgressBar();
1545free(progressbar.pixels);
1546}
1547
1548void drawInfoMenuItems()
1549{
1550int i,n;
1551
1552position_t position;
1553
1554pixmap_t *selection = images[iMenuSelection].image;
1555
1556pixmap_t *pbuff;
1557
1558fillPixmapWithColor(gui.menu.pixmap, gui.menu.bgcolor);
1559
1560makeRoundedCorners(gui.menu.pixmap);
1561
1562uint8_t offset = infoMenuNativeBoot ? 0 : infoMenuItemsCount - 1;
1563
1564position = pos(0,0);
1565
1566for ( i = 0, n = iMenuBoot; i < infoMenuItemsCount; i++, n++)
1567{
1568if (i == infoMenuSelection)
1569blend(selection, gui.menu.pixmap, position);
1570
1571pbuff = images[n].image;
1572if (offset && i >= INFOMENU_NATIVEBOOT_START && i <= INFOMENU_NATIVEBOOT_END)
1573blend( images[n + (iMenuHelp - iMenuBoot)].image , gui.menu.pixmap,
1574pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
1575else
1576blend( pbuff, gui.menu.pixmap,
1577pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
1578
1579drawStr(infoMenuItems[i].text, &font_console, gui.menu.pixmap,
1580pos(position.x + (pbuff->width + gui.menu.hborder),
1581position.y + ((selection->height - font_console.height) / 2)));
1582position.y += images[iMenuSelection].image->height;
1583
1584}
1585
1586gui.redraw = true;
1587}
1588
1589int drawInfoMenu()
1590{
1591drawInfoMenuItems();
1592
1593gui.menu.draw = true;
1594
1595updateVRAM();
1596
1597return 1;
1598}
1599
1600int updateInfoMenu(int key)
1601{
1602switch (key)
1603{
1604
1605case kUpArrowkey:// up arrow
1606if (infoMenuSelection > 0)
1607{
1608if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_END + 1)
1609infoMenuSelection -= 4;
1610
1611else
1612infoMenuSelection--;
1613drawInfoMenuItems();
1614updateVRAM();
1615
1616} else {
1617
1618gui.menu.draw = false;
1619gui.redraw = true;
1620
1621updateVRAM();
1622
1623return CLOSE_INFO_MENU;
1624}
1625break;
1626
1627case kDownArrowkey:// down arrow
1628if (infoMenuSelection < infoMenuItemsCount - 1)
1629{
1630if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_START - 1)
1631infoMenuSelection += 4;
1632else
1633infoMenuSelection++;
1634drawInfoMenuItems();
1635updateVRAM();
1636}
1637break;
1638
1639case kReturnKey:
1640key = 0;
1641if( infoMenuSelection == MENU_SHOW_MEMORY_INFO )
1642showInfoBox( "Memory Info. Press q to quit.\n", getMemoryInfoString());
1643
1644else if( infoMenuSelection == MENU_SHOW_VIDEO_INFO )
1645showInfoBox( getVBEInfoString(), getVBEModeInfoString() );
1646
1647else if( infoMenuSelection == MENU_SHOW_HELP )
1648showHelp();
1649
1650else
1651{
1652int buff = infoMenuSelection;
1653infoMenuSelection = 0;
1654return buff;
1655}
1656break;
1657}
1658return DO_NOT_BOOT;
1659}
1660
1661uint16_t bootImageWidth = 0;
1662uint16_t bootImageHeight = 0;
1663uint8_t *bootImageData = NULL;
1664static bool usePngImage = true;
1665
1666//==========================================================================
1667// loadBootGraphics
1668static void loadBootGraphics(void)
1669{
1670if (bootImageData != NULL) {
1671return;
1672}
1673
1674char dirspec[256];
1675
1676if ((strlen(theme_name) + 24) > sizeof(dirspec)) {
1677usePngImage = false;
1678return;
1679}
1680sprintf(dirspec, "/Extra/Themes/%s/boot.png", theme_name);
1681if (loadPngImage(dirspec, &bootImageWidth, &bootImageHeight, &bootImageData) != 0) {
1682#ifdef EMBED_THEME
1683 if ((loadEmbeddedPngImage(__boot_png, __boot_png_len, &bootImageWidth, &bootImageHeight, &bootImageData)) != 0)
1684#endif
1685usePngImage = false;
1686}
1687}
1688
1689//==========================================================================
1690// drawBootGraphics
1691void drawBootGraphics(void)
1692{
1693//int pos;
1694int length;
1695const char *dummyVal;
1696bool legacy_logo;
1697uint16_t x, y;
1698
1699if (getBoolForKey("Legacy Logo", &legacy_logo, &bootInfo->bootConfig) && legacy_logo) {
1700usePngImage = false;
1701} else if (bootImageData == NULL) {
1702loadBootGraphics();
1703}
1704
1705/*
1706// parse screen size parameters
1707if (getIntForKey("boot_width", &pos, &bootInfo->themeConfig)) {
1708screen_params[0] = pos;
1709} else {
1710screen_params[0] = DEFAULT_SCREEN_WIDTH;
1711}
1712if (getIntForKey("boot_height", &pos, &bootInfo->themeConfig)) {
1713screen_params[1] = pos;
1714} else {
1715screen_params[1] = DEFAULT_SCREEN_HEIGHT;
1716}
1717screen_params[2] = 32;
1718*/
1719
1720getResolution(&screen_params[0], &screen_params[1], &screen_params[2]);
1721
1722
1723gui.screen.width = screen_params[0];
1724gui.screen.height = screen_params[1];
1725
1726// find best matching vesa mode for our requested width & height
1727getGraphicModeParams(screen_params);
1728
1729if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
1730setVideoMode(GRAPHICS_MODE, 0);
1731}
1732
1733if (getValueForKey("-checkers", &dummyVal, &length, &bootInfo->bootConfig)) {
1734drawCheckerBoard();
1735} else {
1736// Fill the background to 75% grey (same as BootX).
1737drawColorRectangle(0, 0, screen_params[0], screen_params[1], 0x01);
1738}
1739if ((bootImageData) && (usePngImage)) {
1740x = (screen_params[0] - MIN(bootImageWidth, screen_params[0])) / 2;
1741y = (screen_params[1] - MIN(bootImageHeight, screen_params[1])) / 2;
1742
1743// Draw the image in the center of the display.
1744blendImage(x, y, bootImageWidth, bootImageHeight, bootImageData);
1745} else {
1746uint8_t *appleBootPict;
1747bootImageData = NULL;
1748bootImageWidth = kAppleBootWidth;
1749bootImageHeight = kAppleBootHeight;
1750
1751// Prepare the data for the default Apple boot image.
1752appleBootPict = (uint8_t *) decodeRLE(gAppleBootPictRLE, kAppleBootRLEBlocks, bootImageWidth * bootImageHeight);
1753if (appleBootPict) {
1754convertImage(bootImageWidth, bootImageHeight, appleBootPict, &bootImageData);
1755if (bootImageData) {
1756x = (screen_params[0] - MIN(kAppleBootWidth, screen_params[0])) / 2;
1757y = (screen_params[1] - MIN(kAppleBootHeight, screen_params[1])) / 2;
1758drawDataRectangle(x, y, kAppleBootWidth, kAppleBootHeight, bootImageData);
1759free(bootImageData);
1760}
1761free(appleBootPict);
1762}
1763}
1764}
1765

Archive Download this file

Revision: 251