Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 131