Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 130