Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 24