Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 429