Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 106