Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 175