Root/
Source at commit 2381 created 10 years 21 days ago. By ifabio, Apply patch: (Credits to Thomas Jansen aka tja) - Reading options from all devices during boot. The options for the boot menu are only read from the devices rd(0,0) or bt(0,0). Consequently, boot menu options (e.g. "Quiet Boot", "Timeout", etc.) in plists on other devices (like most users have) are ignored. This patch extends the list of paths to search for the options plist on all devices that can be found. | |
---|---|
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 "term.h"␊ |
13 | #include "appleboot.h"␊ |
14 | #include "vers.h"␊ |
15 | ␊ |
16 | #define IMG_REQUIRED -1␊ |
17 | #define THEME_NAME_DEFAULT␉"Default"␊ |
18 | static const char *theme_name = THEME_NAME_DEFAULT;␊ |
19 | ␊ |
20 | #ifdef CONFIG_EMBED_THEME␊ |
21 | #include "art.h"␊ |
22 | #endif␊ |
23 | ␊ |
24 | #define LOADPNG(img, alt_img) if (loadThemeImage(#img, alt_img) != 0) { return 1; }␊ |
25 | ␊ |
26 | #define VIDEO(x) (bootArgs->Video.v_ ## x)␊ |
27 | ␊ |
28 | #define vram VIDEO(baseAddr)␊ |
29 | ␊ |
30 | #define TAB_PIXELS_WIDTH (font->chars[0]->width * 4) // tab = 4 spaces␊ |
31 | ␊ |
32 | int lasttime = 0; // we need this for animating maybe␊ |
33 | ␊ |
34 | ␊ |
35 | /*␊ |
36 | * ATTENTION: the enum and the following array images[] MUST match !!!␊ |
37 | */␊ |
38 | enum {␊ |
39 | iBackground = 0,␊ |
40 | iLogo,␊ |
41 | ␊ |
42 | iDeviceGeneric,␊ |
43 | iDeviceGeneric_o,␊ |
44 | iDeviceHFS,␊ |
45 | iDeviceHFS_o,␊ |
46 | iDeviceHFS_ML,␊ |
47 | iDeviceHFS_ML_o,␊ |
48 | iDeviceHFS_Lion,␊ |
49 | iDeviceHFS_Lion_o,␊ |
50 | iDeviceHFS_SL,␊ |
51 | iDeviceHFS_SL_o,␊ |
52 | iDeviceHFS_Leo,␊ |
53 | iDeviceHFS_Leo_o,␊ |
54 | iDeviceHFS_Tiger,␊ |
55 | iDeviceHFS_Tiger_o,␊ |
56 | iDeviceHFSRAID,␊ |
57 | iDeviceHFSRAID_o,␊ |
58 | iDeviceHFSRAID_ML,␊ |
59 | iDeviceHFSRAID_ML_o,␊ |
60 | iDeviceHFSRAID_Lion,␊ |
61 | iDeviceHFSRAID_Lion_o,␊ |
62 | iDeviceHFSRAID_SL,␊ |
63 | iDeviceHFSRAID_SL_o,␊ |
64 | iDeviceHFSRAID_Leo,␊ |
65 | iDeviceHFSRAID_Leo_o,␊ |
66 | iDeviceHFSRAID_Tiger,␊ |
67 | iDeviceHFSRAID_Tiger_o,␊ |
68 | iDeviceEXT3,␊ |
69 | iDeviceEXT3_o,␊ |
70 | iDeviceFreeBSD, /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
71 | iDeviceFreeBSD_o, /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
72 | iDeviceOpenBSD, /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
73 | iDeviceOpenBSD_o, /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
74 | iDeviceBEFS, /* Haiku detection and Icon credits to scorpius */␊ |
75 | iDeviceBEFS_o, /* Haiku detection and Icon credits to scorpius */␊ |
76 | iDeviceFAT,␊ |
77 | iDeviceFAT_o,␊ |
78 | iDeviceFAT16,␊ |
79 | iDeviceFAT16_o,␊ |
80 | iDeviceFAT32,␊ |
81 | iDeviceFAT32_o,␊ |
82 | iDeviceNTFS,␊ |
83 | iDeviceNTFS_o,␊ |
84 | iDeviceCDROM,␊ |
85 | iDeviceCDROM_o,␊ |
86 | ␊ |
87 | iSelection,␊ |
88 | iDeviceScrollPrev,␊ |
89 | iDeviceScrollNext,␊ |
90 | ␊ |
91 | iMenuBoot,␊ |
92 | iMenuVerbose,␊ |
93 | iMenuIgnoreCaches,␊ |
94 | iMenuSingleUser,␊ |
95 | iMenuMemoryInfo,␊ |
96 | iMenuVideoInfo,␊ |
97 | iMenuHelp,␊ |
98 | iMenuVerboseDisabled,␊ |
99 | iMenuIgnoreCachesDisabled,␊ |
100 | iMenuSingleUserDisabled,␊ |
101 | iMenuSelection,␊ |
102 | ␊ |
103 | iProgressBar,␊ |
104 | iProgressBarBackground,␊ |
105 | ␊ |
106 | iTextScrollPrev,␊ |
107 | iTextScrollNext,␊ |
108 | ␊ |
109 | iFontConsole,␊ |
110 | iFontSmall,␊ |
111 | };␊ |
112 | ␊ |
113 | image_t images[] = {␊ |
114 | {.name = "background", .image = NULL},␊ |
115 | {.name = "logo", .image = NULL},␊ |
116 | ␊ |
117 | {.name = "device_generic", .image = NULL},␊ |
118 | {.name = "device_generic_o", .image = NULL},␊ |
119 | {.name = "device_hfsplus", .image = NULL},␊ |
120 | {.name = "device_hfsplus_o", .image = NULL},␊ |
121 | {.name = "device_hfsplus_ml", .image = NULL},␊ |
122 | {.name = "device_hfsplus_ml_o", .image = NULL},␊ |
123 | {.name = "device_hfsplus_lion", .image = NULL},␊ |
124 | {.name = "device_hfsplus_lion_o", .image = NULL},␊ |
125 | {.name = "device_hfsplus_sl", .image = NULL},␊ |
126 | {.name = "device_hfsplus_sl_o", .image = NULL},␊ |
127 | {.name = "device_hfsplus_leo", .image = NULL},␊ |
128 | {.name = "device_hfsplus_leo_o", .image = NULL},␊ |
129 | {.name = "device_hfsplus_tiger", .image = NULL},␊ |
130 | {.name = "device_hfsplus_tiger_o", .image = NULL},␊ |
131 | ␊ |
132 | {.name = "device_hfsraid", .image = NULL},␊ |
133 | {.name = "device_hfsraid_o", .image = NULL},␊ |
134 | {.name = "device_hfsraid_ml", .image = NULL},␊ |
135 | {.name = "device_hfsraid_ml_o", .image = NULL},␊ |
136 | {.name = "device_hfsraid_lion", .image = NULL},␊ |
137 | {.name = "device_hfsraid_lion_o", .image = NULL},␊ |
138 | {.name = "device_hfsraid_sl", .image = NULL},␊ |
139 | {.name = "device_hfsraid_sl_o", .image = NULL},␊ |
140 | {.name = "device_hfsraid_leo", .image = NULL},␊ |
141 | {.name = "device_hfsraid_leo_o", .image = NULL},␊ |
142 | {.name = "device_hfsraid_tiger", .image = NULL},␊ |
143 | {.name = "device_hfsraid_tiger_o", .image = NULL},␊ |
144 | {.name = "device_ext3", .image = NULL},␊ |
145 | {.name = "device_ext3_o", .image = NULL},␊ |
146 | {.name = "device_freebsd", .image = NULL}, /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
147 | {.name = "device_freebsd_o", .image = NULL}, /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
148 | {.name = "device_openbsd", .image = NULL}, /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
149 | {.name = "device_openbsd_o", .image = NULL}, /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
150 | {.name = "device_befs", .image = NULL}, /* Haiku detection and Icon credits to scorpius */␊ |
151 | {.name = "device_befs_o", .image = NULL}, /* Haiku detection and Icon credits to scorpius */␊ |
152 | {.name = "device_fat", .image = NULL},␊ |
153 | {.name = "device_fat_o", .image = NULL},␊ |
154 | {.name = "device_fat16", .image = NULL},␊ |
155 | {.name = "device_fat16_o", .image = NULL},␊ |
156 | {.name = "device_fat32", .image = NULL},␊ |
157 | {.name = "device_fat32_o", .image = NULL},␊ |
158 | {.name = "device_ntfs", .image = NULL},␊ |
159 | {.name = "device_ntfs_o", .image = NULL},␊ |
160 | {.name = "device_cdrom", .image = NULL},␊ |
161 | {.name = "device_cdrom_o", .image = NULL},␊ |
162 | ␊ |
163 | {.name = "device_selection", .image = NULL},␊ |
164 | {.name = "device_scroll_prev", .image = NULL},␊ |
165 | {.name = "device_scroll_next", .image = NULL},␊ |
166 | ␊ |
167 | {.name = "menu_boot", .image = NULL},␊ |
168 | {.name = "menu_verbose", .image = NULL},␊ |
169 | {.name = "menu_ignore_caches", .image = NULL},␊ |
170 | {.name = "menu_single_user", .image = NULL},␊ |
171 | {.name = "menu_memory_info", .image = NULL},␊ |
172 | {.name = "menu_video_info", .image = NULL},␊ |
173 | {.name = "menu_help", .image = NULL},␊ |
174 | {.name = "menu_verbose_disabled", .image = NULL},␊ |
175 | {.name = "menu_ignore_caches_disabled", .image = NULL},␊ |
176 | {.name = "menu_single_user_disabled", .image = NULL},␊ |
177 | {.name = "menu_selection", .image = NULL},␊ |
178 | ␊ |
179 | {.name = "progress_bar", .image = NULL},␊ |
180 | {.name = "progress_bar_background", .image = NULL},␊ |
181 | ␊ |
182 | {.name = "text_scroll_prev", .image = NULL},␊ |
183 | {.name = "text_scroll_next", .image = NULL},␊ |
184 | ␊ |
185 | {.name = "font_console", .image = NULL},␊ |
186 | {.name = "font_small", .image = NULL},␊ |
187 | };␊ |
188 | ␊ |
189 | int imageCnt = 0;␊ |
190 | ␊ |
191 | extern int␉gDeviceCount;␊ |
192 | extern int␉selectIndex;␊ |
193 | ␊ |
194 | extern MenuItem *menuItems;␊ |
195 | ␊ |
196 | //char prompt[BOOT_STRING_LEN];␊ |
197 | extern char gBootArgs[BOOT_STRING_LEN];␊ |
198 | ␊ |
199 | char prompt_text[] = "boot: ";␊ |
200 | ␊ |
201 | menuitem_t infoMenuItems[] =␊ |
202 | {␊ |
203 | ␉{ .text = "Boot" },␊ |
204 | ␉{ .text = "Boot Verbose" },␊ |
205 | ␉{ .text = "Boot Ignore Caches" },␊ |
206 | ␉{ .text = "Boot Single User" },␊ |
207 | ␉{ .text = "Memory Info" },␊ |
208 | ␉{ .text = "Video Info" },␊ |
209 | ␉{ .text = "Help" }␊ |
210 | };␊ |
211 | ␊ |
212 | int initFont(font_t *font, image_t *image);␊ |
213 | int destroyFont(font_t *font);␊ |
214 | void colorFont(font_t *font, uint32_t color);␊ |
215 | void makeRoundedCorners(pixmap_t *p);␊ |
216 | ␊ |
217 | static int infoMenuSelection = 0;␊ |
218 | static int infoMenuItemsCount = sizeof(infoMenuItems)/sizeof(infoMenuItems[0]);␊ |
219 | ␊ |
220 | static bool infoMenuNativeBoot = false;␊ |
221 | ␊ |
222 | // here we store the used screen resolution␊ |
223 | static unsigned long screen_params[4] = {DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT, 32, 0};␊ |
224 | ␊ |
225 | static int getImageIndexByName(const char *name)␊ |
226 | {␊ |
227 | int i;␊ |
228 | ␉for (i = 0; i < sizeof(images) / sizeof(images[0]); i++)␊ |
229 | ␉{␊ |
230 | ␉ if (strcmp(name, images[i].name) == 0)␊ |
231 | ␉ return i; // found the name␊ |
232 | ␉}␊ |
233 | ␉return -1;␊ |
234 | }␊ |
235 | ␊ |
236 | #ifdef CONFIG_EMBED_THEME␊ |
237 | static int getEmbeddedImageIndexByName(const char *name)␊ |
238 | {␊ |
239 | ␉int upperLimit = sizeof(embeddedImages) / sizeof(embeddedImages[0]) - 1;␊ |
240 | ␉int lowerLimit = 0;␊ |
241 | ␉int compareIndex = (upperLimit - lowerLimit) >> 1; // Midpoint␊ |
242 | ␉int result;␊ |
243 | ␉␊ |
244 | ␉// NOTE: This algorithm assumes that the embedded images are sorted.␊ |
245 | ␉// This is currently done using the make file. If the array is␊ |
246 | ␉// generated manualy, this *will* fail to work properly.␊ |
247 | ␉while((result = strcmp(name, embeddedImages[compareIndex].name)) != 0)␊ |
248 | ␉{␊ |
249 | ␉␉if (result > 0)␉// We need to search a HIGHER index␊ |
250 | ␉␉{␊ |
251 | ␉␉␉if (compareIndex != lowerLimit)␊ |
252 | ␉␉␉{␊ |
253 | ␉␉␉␉lowerLimit = compareIndex;␊ |
254 | ␉␉␉}␊ |
255 | ␉␉␉else␊ |
256 | ␉␉␉{␊ |
257 | ␉␉␉␉return -1;␊ |
258 | ␉␉␉}␊ |
259 | ␉␉␉compareIndex = (upperLimit + lowerLimit + 1) >> 1;␉// Midpoint, round up␊ |
260 | ␉␉}␊ |
261 | ␉␉else // We Need to search a LOWER index␊ |
262 | ␉␉{␊ |
263 | ␉␉␉if (compareIndex != upperLimit)␊ |
264 | ␉␉␉{␊ |
265 | ␉␉␉␉upperLimit = compareIndex;␊ |
266 | ␉␉␉}␊ |
267 | ␉␉␉else␊ |
268 | ␉␉␉{␊ |
269 | ␉␉␉␉return -1;␊ |
270 | ␉␉␉}␊ |
271 | ␉␉␉compareIndex = (upperLimit + lowerLimit) >> 1;␉// Midpoint, round down␊ |
272 | ␉␉}␊ |
273 | ␉}␊ |
274 | ␉return compareIndex;␊ |
275 | }␊ |
276 | #endif␊ |
277 | ␊ |
278 | static int loadThemeImage(const char *image, int alt_image)␊ |
279 | {␊ |
280 | ␉char␉␉dirspec[256];␊ |
281 | ␉int ␉␉i;␊ |
282 | #ifdef CONFIG_EMBED_THEME␊ |
283 | ␉int ␉␉e;␊ |
284 | #endif␊ |
285 | ␉uint16_t␉width;␊ |
286 | ␉uint16_t␉height;␊ |
287 | ␉uint8_t␉␉*imagedata;␊ |
288 | ␊ |
289 | ␉if ((strlen(image) + strlen(theme_name) + 20) > sizeof(dirspec))␊ |
290 | ␉␉return 1;␊ |
291 | ␉if ((i = getImageIndexByName(image)) < 0)␊ |
292 | ␉␉return 1;␊ |
293 | ␉if (!images[i].image && !(images[i].image = malloc(sizeof(pixmap_t))))␊ |
294 | ␉␉return 1;␊ |
295 | sprintf(dirspec, "/Extra/Themes/%s/%s.png", theme_name, image);␊ |
296 | width = 0;␊ |
297 | height = 0;␊ |
298 | imagedata = NULL;␊ |
299 | if ((loadPngImage(dirspec, &width, &height, &imagedata)) == 0)␊ |
300 | {␊ |
301 | images[i].image->width = width;␊ |
302 | images[i].image->height = height;␊ |
303 | images[i].image->pixels = (pixel_t *)imagedata;␊ |
304 | flipRB(images[i].image);␊ |
305 | return 0;␊ |
306 | }␊ |
307 | #ifdef CONFIG_EMBED_THEME␊ |
308 | else if ((e = getEmbeddedImageIndexByName(image)) >= 0)␊ |
309 | {␊ |
310 | unsigned char *embed_data;␊ |
311 | unsigned int embed_size;␊ |
312 | embed_data = embeddedImages[e].pngdata;␊ |
313 | embed_size = *embeddedImages[e].length;␊ |
314 | ␊ |
315 | if (loadEmbeddedPngImage(embed_data, embed_size, &width, &height, &imagedata) == 0)␊ |
316 | {␊ |
317 | images[i].image->width = width;␊ |
318 | images[i].image->height = height;␊ |
319 | images[i].image->pixels = (pixel_t *)imagedata;␊ |
320 | flipRB(images[i].image);␊ |
321 | return 0;␊ |
322 | }␊ |
323 | }␊ |
324 | #endif␊ |
325 | else if (alt_image != IMG_REQUIRED && is_image_loaded(alt_image))␊ |
326 | {␊ |
327 | // Using the passed alternate image for non-mandatory images.␊ |
328 | // We don't clone the already existing pixmap, but using its properties instead!␊ |
329 | images[i].image->width = images[alt_image].image->width;␊ |
330 | images[i].image->height = images[alt_image].image->height;␊ |
331 | images[i].image->pixels = images[alt_image].image->pixels;␊ |
332 | return 0;␊ |
333 | }␊ |
334 | ␊ |
335 | ␉// If we got here it's an error␊ |
336 | #ifndef CONFIG_EMBED_THEME␊ |
337 | ␉printf("ERROR: GUI: could not open '%s/%s.png'!\n", theme_name, image);␊ |
338 | ␉sleep(2);␊ |
339 | #endif␊ |
340 | ␉free(images[i].image);␊ |
341 | ␉images[i].image = NULL;␊ |
342 | ␉return 1;␊ |
343 | }␊ |
344 | ␊ |
345 | static int loadGraphics(void)␊ |
346 | {␊ |
347 | ␉LOADPNG(background, IMG_REQUIRED);␊ |
348 | ␉LOADPNG(logo, IMG_REQUIRED);␊ |
349 | ␊ |
350 | ␉LOADPNG(device_generic, IMG_REQUIRED);␊ |
351 | ␉LOADPNG(device_generic_o, iDeviceGeneric);␊ |
352 | ␉LOADPNG(device_hfsplus, iDeviceGeneric);␊ |
353 | ␉LOADPNG(device_hfsplus_o, iDeviceHFS);␊ |
354 | ␉LOADPNG(device_hfsplus_ml, iDeviceHFS);␊ |
355 | ␉LOADPNG(device_hfsplus_ml_o, iDeviceHFS_ML);␊ |
356 | ␉LOADPNG(device_hfsplus_lion, iDeviceHFS);␊ |
357 | ␉LOADPNG(device_hfsplus_lion_o, iDeviceHFS_Lion);␊ |
358 | ␉LOADPNG(device_hfsplus_sl, iDeviceHFS);␊ |
359 | ␉LOADPNG(device_hfsplus_sl_o, iDeviceHFS_SL);␊ |
360 | ␉LOADPNG(device_hfsplus_leo, iDeviceHFS);␊ |
361 | ␉LOADPNG(device_hfsplus_leo_o, iDeviceHFS_Leo);␊ |
362 | ␉LOADPNG(device_hfsplus_tiger, iDeviceHFS);␊ |
363 | ␉LOADPNG(device_hfsplus_tiger_o, iDeviceHFS_Tiger);␊ |
364 | ␊ |
365 | ␉LOADPNG(device_hfsraid, iDeviceHFS);␊ |
366 | ␉LOADPNG(device_hfsraid_o, iDeviceHFSRAID);␊ |
367 | ␉LOADPNG(device_hfsraid_ml, iDeviceHFSRAID);␊ |
368 | ␉LOADPNG(device_hfsraid_ml_o, iDeviceHFSRAID_ML);␊ |
369 | ␉LOADPNG(device_hfsraid_lion, iDeviceHFSRAID);␊ |
370 | ␉LOADPNG(device_hfsraid_lion_o, iDeviceHFSRAID_Lion);␊ |
371 | ␉LOADPNG(device_hfsraid_sl, iDeviceHFSRAID);␊ |
372 | ␉LOADPNG(device_hfsraid_sl_o, iDeviceHFSRAID_SL);␊ |
373 | ␉LOADPNG(device_hfsraid_leo, iDeviceHFSRAID);␊ |
374 | ␉LOADPNG(device_hfsraid_leo_o, iDeviceHFSRAID_Leo);␊ |
375 | ␉LOADPNG(device_hfsraid_tiger, iDeviceHFSRAID);␊ |
376 | ␉LOADPNG(device_hfsraid_tiger_o, iDeviceHFSRAID_Tiger);␊ |
377 | ␉LOADPNG(device_ext3, iDeviceGeneric);␊ |
378 | ␉LOADPNG(device_ext3_o, iDeviceEXT3);␊ |
379 | ␉LOADPNG(device_freebsd, iDeviceGeneric); /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
380 | ␉LOADPNG(device_freebsd_o, iDeviceFreeBSD); /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
381 | ␉LOADPNG(device_openbsd, iDeviceGeneric); /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
382 | ␉LOADPNG(device_openbsd_o, iDeviceOpenBSD); /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
383 | ␉LOADPNG(device_befs, iDeviceGeneric); /* Haiku detection and Icon credits to scorpius */␊ |
384 | ␉LOADPNG(device_befs_o, iDeviceBEFS); /* Haiku detection and Icon credits to scorpius */␊ |
385 | ␉LOADPNG(device_fat, iDeviceGeneric);␊ |
386 | ␉LOADPNG(device_fat_o, iDeviceFAT);␊ |
387 | ␉LOADPNG(device_fat16, iDeviceFAT);␊ |
388 | ␉LOADPNG(device_fat16_o, iDeviceFAT16);␊ |
389 | ␉LOADPNG(device_fat32, iDeviceFAT);␊ |
390 | ␉LOADPNG(device_fat32_o, iDeviceFAT32);␊ |
391 | ␉LOADPNG(device_ntfs, iDeviceGeneric);␊ |
392 | ␉LOADPNG(device_ntfs_o, iDeviceNTFS);␊ |
393 | ␉LOADPNG(device_cdrom, iDeviceGeneric);␊ |
394 | ␉LOADPNG(device_cdrom_o, iDeviceCDROM);␊ |
395 | ␊ |
396 | ␉LOADPNG(device_selection, IMG_REQUIRED);␊ |
397 | ␉LOADPNG(device_scroll_prev, IMG_REQUIRED);␊ |
398 | ␉LOADPNG(device_scroll_next, IMG_REQUIRED);␊ |
399 | ␊ |
400 | ␉LOADPNG(menu_boot, IMG_REQUIRED);␊ |
401 | ␉LOADPNG(menu_verbose, IMG_REQUIRED);␊ |
402 | ␉LOADPNG(menu_ignore_caches, IMG_REQUIRED);␊ |
403 | ␉LOADPNG(menu_single_user, IMG_REQUIRED);␊ |
404 | ␉LOADPNG(menu_memory_info, IMG_REQUIRED);␊ |
405 | ␉LOADPNG(menu_video_info, IMG_REQUIRED);␊ |
406 | ␉LOADPNG(menu_help, IMG_REQUIRED);␊ |
407 | ␉LOADPNG(menu_verbose_disabled, IMG_REQUIRED);␊ |
408 | ␉LOADPNG(menu_ignore_caches_disabled, IMG_REQUIRED);␊ |
409 | ␉LOADPNG(menu_single_user_disabled, IMG_REQUIRED);␊ |
410 | ␉LOADPNG(menu_selection, IMG_REQUIRED);␊ |
411 | ␊ |
412 | ␉LOADPNG(progress_bar, IMG_REQUIRED);␊ |
413 | ␉LOADPNG(progress_bar_background, IMG_REQUIRED);␊ |
414 | ␊ |
415 | ␉LOADPNG(text_scroll_prev, IMG_REQUIRED);␊ |
416 | ␉LOADPNG(text_scroll_next, IMG_REQUIRED);␊ |
417 | ␊ |
418 | ␉LOADPNG(font_console, IMG_REQUIRED);␊ |
419 | ␉LOADPNG(font_small, IMG_REQUIRED);␊ |
420 | ␊ |
421 | ␉initFont( &font_console, &images[iFontConsole]);␊ |
422 | ␉initFont( &font_small, &images[iFontSmall]);␊ |
423 | ␊ |
424 | ␉return 0;␊ |
425 | }␊ |
426 | ␊ |
427 | static int unloadGraphics(void)␊ |
428 | {␊ |
429 | int i;␊ |
430 | ␊ |
431 | destroyFont(&font_console);␊ |
432 | destroyFont(&font_small);␊ |
433 | ␉for (i = 0; i < sizeof(images) / sizeof(images[0]); i++)␊ |
434 | ␉{␊ |
435 | ␉ if (images[i].image)␊ |
436 | ␉ {␊ |
437 | ␉ ␉if (images[i].image->pixels) free(images[i].image->pixels);␊ |
438 | ␉ ␉free (images[i].image);␊ |
439 | ␉ ␉images[i].image = 0;␊ |
440 | ␉ }␊ |
441 | ␉}␊ |
442 | ␉return 0;␊ |
443 | }␊ |
444 | ␊ |
445 | int freeBackBuffer( window_t *window )␊ |
446 | {␊ |
447 | if (gui.backbuffer && gui.backbuffer->pixels)␊ |
448 | {␊ |
449 | free(gui.backbuffer->pixels);␊ |
450 | free(gui.backbuffer);␊ |
451 | gui.backbuffer = 0;␊ |
452 | return 0;␊ |
453 | }␊ |
454 | ␊ |
455 | return 1;␊ |
456 | }␊ |
457 | ␊ |
458 | pixmap_t *getCroppedPixmapAtPosition( pixmap_t *from, position_t pos, uint16_t width, uint16_t height )␊ |
459 | {␊ |
460 | ␉␊ |
461 | ␉pixmap_t *cropped = malloc( sizeof( pixmap_t ) );␊ |
462 | ␉if( !cropped )␊ |
463 | ␉␉return 0;␊ |
464 | ␉cropped->pixels = malloc( width * height * 4 );␊ |
465 | ␉if ( !cropped->pixels )␊ |
466 | ␉␉return 0;␊ |
467 | ␉␊ |
468 | ␉cropped->width = width;␊ |
469 | ␉cropped->height = height;␊ |
470 | ␉␊ |
471 | ␉int destx = 0, desty = 0;␊ |
472 | ␉int srcx = pos.x, srcy = pos.y;␊ |
473 | ␉␊ |
474 | ␉for( ; desty < height; desty++, srcy++)␊ |
475 | ␉{␊ |
476 | ␉␉for( destx = 0, srcx = pos.x; destx < width; destx++, srcx++ )␊ |
477 | ␉␉{␊ |
478 | ␉␉␉pixel( cropped, destx, desty ).value = pixel( from, srcx, srcy ).value;␊ |
479 | ␉␉}␊ |
480 | ␉}␊ |
481 | ␉return cropped;␊ |
482 | }␊ |
483 | ␊ |
484 | int createBackBuffer( window_t *window )␊ |
485 | {␊ |
486 | ␉gui.backbuffer = malloc(sizeof(pixmap_t));␊ |
487 | ␉if(!gui.backbuffer)␊ |
488 | ␉{␊ |
489 | ␉␉return 1;␊ |
490 | ␉}␊ |
491 | ␉gui.backbuffer->pixels = malloc( window->width * window->height * 4 );␊ |
492 | ␉if(!gui.backbuffer->pixels)␊ |
493 | ␉{␊ |
494 | ␉␉free(gui.backbuffer);␊ |
495 | ␉␉gui.backbuffer = 0;␊ |
496 | ␉␉return 1;␊ |
497 | ␉}␊ |
498 | ␉␊ |
499 | ␉gui.backbuffer->width = gui.screen.width;␊ |
500 | ␉gui.backbuffer->height = gui.screen.height;␊ |
501 | ␊ |
502 | ␉return 0;␊ |
503 | }␊ |
504 | ␊ |
505 | int createWindowBuffer( window_t *window )␊ |
506 | {␊ |
507 | ␉window->pixmap = malloc(sizeof(pixmap_t));␊ |
508 | ␉if(!window->pixmap)␊ |
509 | ␉{␊ |
510 | ␉␉return 1;␊ |
511 | ␉}␊ |
512 | ␊ |
513 | ␉window->pixmap->pixels = malloc( window->width * window->height * 4 );␊ |
514 | ␉if(!window->pixmap->pixels)␊ |
515 | ␉{␊ |
516 | ␉␉free(window->pixmap);␊ |
517 | ␉␉window->pixmap = 0;␊ |
518 | ␉␉return 1;␊ |
519 | ␉}␊ |
520 | ␉␊ |
521 | ␉window->pixmap->width = window->width;␊ |
522 | ␉window->pixmap->height = window->height;␊ |
523 | ␊ |
524 | ␉return 0;␊ |
525 | }␊ |
526 | ␊ |
527 | int freeWindowBuffer( window_t *window )␊ |
528 | {␊ |
529 | ␉if (window->pixmap && window->pixmap->pixels)␊ |
530 | {␊ |
531 | ␉␉free(window->pixmap->pixels);␊ |
532 | ␉␉free(window->pixmap);␊ |
533 | ␉␉return 0;␊ |
534 | ␉}␊ |
535 | ␊ |
536 | ␉return 1;␊ |
537 | }␊ |
538 | ␊ |
539 | void fillPixmapWithColor(pixmap_t *pm, uint32_t color)␊ |
540 | {␊ |
541 | ␉int x,y;␊ |
542 | ␉␊ |
543 | ␉// fill with given color AARRGGBB␊ |
544 | ␉for( x=0; x < pm->width; x++ )␊ |
545 | ␉␉for( y=0; y< pm->height; y++)␊ |
546 | ␉␉␉pixel(pm,x,y).value = color;␊ |
547 | }␊ |
548 | ␊ |
549 | void drawBackground()␊ |
550 | {␊ |
551 | ␉// reset text cursor␊ |
552 | ␉gui.screen.cursor.x = gui.screen.hborder;␊ |
553 | ␉gui.screen.cursor.y = gui.screen.vborder;␊ |
554 | ␉␊ |
555 | ␉fillPixmapWithColor( gui.screen.pixmap, gui.screen.bgcolor);␊ |
556 | ␉␊ |
557 | ␉// draw background.png into background buffer␊ |
558 | ␉blend( images[iBackground].image, gui.screen.pixmap, gui.background.pos );␊ |
559 | ␉␊ |
560 | ␉// draw logo.png into background buffer␊ |
561 | ␉if (gui.logo.draw)␊ |
562 | ␉{␊ |
563 | ␉blend( images[iLogo].image, gui.screen.pixmap, gui.logo.pos);␊ |
564 | ␉}␊ |
565 | ␉␊ |
566 | ␉memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );␊ |
567 | }␊ |
568 | ␊ |
569 | void setupDeviceList(config_file_t *theme)␊ |
570 | {␊ |
571 | ␉unsigned int pixel;␊ |
572 | ␉int␉alpha;␉␉␉␉// transparency level 0 (obligue) - 255 (transparent)␊ |
573 | ␉uint32_t color;␉␉␉// color value formatted RRGGBB␊ |
574 | ␉int val, len;␊ |
575 | ␉const char *string;␉␊ |
576 | ␊ |
577 | ␉if(getIntForKey("devices_max_visible", &val, theme ))␊ |
578 | ␉␉gui.maxdevices = MIN( val, gDeviceCount );␊ |
579 | ␊ |
580 | ␉if(getIntForKey("devices_iconspacing", &val, theme ))␊ |
581 | ␉␉gui.devicelist.iconspacing = val;␊ |
582 | ␊ |
583 | ␉// check layout for horizontal or vertical␊ |
584 | ␉gui.layout = HorizontalLayout;␊ |
585 | ␉if(getValueForKey( "devices_layout", &string, &len, theme)) {␊ |
586 | ␉␉if (!strcmp (string, "vertical")) {␊ |
587 | ␉␉␉gui.layout = VerticalLayout;␊ |
588 | ␉␉}␊ |
589 | ␉}␊ |
590 | ␊ |
591 | ␉switch (gui.layout) {␊ |
592 | ␉case VerticalLayout:␊ |
593 | ␉␉gui.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);␊ |
594 | ␉␉gui.devicelist.width = (images[iSelection].image->width + gui.devicelist.iconspacing);␊ |
595 | ␊ |
596 | ␉␉if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , images[iSelection].image->width ) )␊ |
597 | ␉␉␉gui.devicelist.pos.x = pixel;␊ |
598 | ␊ |
599 | ␉␉if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , gui.devicelist.height ) )␊ |
600 | ␉␉␉gui.devicelist.pos.y = pixel;␊ |
601 | ␉␉break;␊ |
602 | ␊ |
603 | ␉case HorizontalLayout:␊ |
604 | ␉default:␊ |
605 | ␉␉gui.devicelist.width = ((images[iSelection].image->width + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->width + images[iDeviceScrollNext].image->width) + gui.devicelist.iconspacing);␊ |
606 | ␉␉gui.devicelist.height = (images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing);␊ |
607 | ␊ |
608 | ␉␉if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , gui.devicelist.width ) )␊ |
609 | ␉␉␉gui.devicelist.pos.x = pixel;␊ |
610 | ␉␉else␊ |
611 | ␉␉␉gui.devicelist.pos.x = ( gui.screen.width - gui.devicelist.width ) / 2;␊ |
612 | ␉␉␊ |
613 | ␉␉if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , images[iSelection].image->height ) )␊ |
614 | ␉␉␉gui.devicelist.pos.y = pixel;␊ |
615 | ␉␉else␊ |
616 | ␉␉␉gui.devicelist.pos.y = ( gui.screen.height - gui.devicelist.height ) / 2;␊ |
617 | ␉␉break;␊ |
618 | ␉}␊ |
619 | ␊ |
620 | ␉if(getColorForKey("devices_bgcolor", &color, theme))␊ |
621 | ␉␉gui.devicelist.bgcolor = (color & 0x00FFFFFF);␊ |
622 | ␊ |
623 | ␉if(getIntForKey("devices_transparency", &alpha, theme))␊ |
624 | ␉␉gui.devicelist.bgcolor = gui.devicelist.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);␊ |
625 | ␊ |
626 | ␉if (gui.devicelist.pixmap)␊ |
627 | ␉{␊ |
628 | ␉ freeWindowBuffer(&gui.devicelist);␊ |
629 | createWindowBuffer(&gui.devicelist);␊ |
630 | }␊ |
631 | }␊ |
632 | ␊ |
633 | void loadThemeValues(config_file_t *theme)␊ |
634 | {␊ |
635 | ␉unsigned int screen_width = gui.screen.width;␊ |
636 | ␉unsigned int screen_height = gui.screen.height;␊ |
637 | ␉unsigned int pixel;␊ |
638 | ␉int␉alpha;␉␉␉␉// transparency level 0 (obligue) - 255 (transparent)␊ |
639 | ␉uint32_t color;␉␉␉// color value formatted RRGGBB␊ |
640 | ␉int val;␊ |
641 | ␊ |
642 | ␉/*␊ |
643 | ␉ * Parse screen parameters␊ |
644 | ␉ */␊ |
645 | ␉if(getColorForKey("screen_bgcolor", &color, theme ))␊ |
646 | ␉␉gui.screen.bgcolor = (color & 0x00FFFFFF);␊ |
647 | ␊ |
648 | ␉if(getIntForKey("screen_textmargin_h", &val, theme))␊ |
649 | ␉␉gui.screen.hborder = MIN( gui.screen.width , val );␊ |
650 | ␊ |
651 | ␉if(getIntForKey("screen_textmargin_v", &val, theme))␊ |
652 | ␉␉gui.screen.vborder = MIN( gui.screen.height , val );␊ |
653 | ␊ |
654 | ␉/*␊ |
655 | ␉ * Parse background parameters␊ |
656 | ␉ */␊ |
657 | ␉if(getDimensionForKey("background_pos_x", &pixel, theme, screen_width , images[iBackground].image->width ) )␊ |
658 | ␉␉gui.background.pos.x = pixel;␊ |
659 | ␊ |
660 | ␉if(getDimensionForKey("background_pos_y", &pixel, theme, screen_height , images[iBackground].image->height ) )␊ |
661 | ␉␉gui.background.pos.y = pixel;␊ |
662 | ␊ |
663 | ␉/*␊ |
664 | ␉ * Parse logo parameters␊ |
665 | ␉ */␊ |
666 | ␉if(getDimensionForKey("logo_pos_x", &pixel, theme, screen_width , images[iLogo].image->width ) )␊ |
667 | ␉␉gui.logo.pos.x = pixel;␊ |
668 | ␊ |
669 | ␉if(getDimensionForKey("logo_pos_y", &pixel, theme, screen_height , images[iLogo].image->height ) )␊ |
670 | ␉␉gui.logo.pos.y = pixel;␊ |
671 | ␊ |
672 | ␉/*␊ |
673 | ␉ * Parse progress bar parameters␊ |
674 | ␉ */␊ |
675 | ␉if(getDimensionForKey("progressbar_pos_x", &pixel, theme, screen_width , 0 ) )␊ |
676 | ␉␉gui.progressbar.pos.x = pixel;␊ |
677 | ␊ |
678 | ␉if(getDimensionForKey("progressbar_pos_y", &pixel, theme, screen_height , 0 ) )␊ |
679 | ␉␉gui.progressbar.pos.y = pixel;␊ |
680 | ␊ |
681 | ␉/*␊ |
682 | ␉ * Parse countdown text parameters␊ |
683 | ␉ */␊ |
684 | ␉if(getDimensionForKey("countdown_pos_x", &pixel, theme, screen_width , 0 ) )␊ |
685 | ␉␉gui.countdown.pos.x = pixel;␊ |
686 | ␊ |
687 | ␉if(getDimensionForKey("countdown_pos_y", &pixel, theme, screen_height , 0 ) )␊ |
688 | ␉␉gui.countdown.pos.y = pixel;␊ |
689 | ␊ |
690 | /*␊ |
691 | ␉ * Parse devicelist parameters␊ |
692 | ␉ */␊ |
693 | ␉setupDeviceList(theme);␊ |
694 | ␊ |
695 | ␉/*␊ |
696 | ␉ * Parse infobox parameters␊ |
697 | ␉ */␊ |
698 | ␉if(getIntForKey("infobox_width", &val, theme))␊ |
699 | ␉␉gui.infobox.width = MIN( screen_width , val );␊ |
700 | ␊ |
701 | ␉if(getIntForKey("infobox_height", &val, theme))␊ |
702 | ␉␉gui.infobox.height = MIN( screen_height , val );␊ |
703 | ␊ |
704 | ␉if(getDimensionForKey("infobox_pos_x", &pixel, theme, screen_width , gui.infobox.width ) )␊ |
705 | ␉␉gui.infobox.pos.x = pixel;␊ |
706 | ␊ |
707 | ␉if(getDimensionForKey("infobox_pos_y", &pixel, theme, screen_height , gui.infobox.height ) )␊ |
708 | ␉␉gui.infobox.pos.y = pixel;␊ |
709 | ␊ |
710 | ␉if(getIntForKey("infobox_textmargin_h", &val, theme))␊ |
711 | ␉␉gui.infobox.hborder = MIN( gui.infobox.width , val );␊ |
712 | ␊ |
713 | ␉if(getIntForKey("infobox_textmargin_v", &val, theme))␊ |
714 | ␉␉gui.infobox.vborder = MIN( gui.infobox.height , val );␊ |
715 | ␊ |
716 | ␉if(getColorForKey("infobox_bgcolor", &color, theme))␊ |
717 | ␉␉gui.infobox.bgcolor = (color & 0x00FFFFFF);␊ |
718 | ␊ |
719 | ␉if(getIntForKey("infobox_transparency", &alpha, theme))␊ |
720 | ␉␉gui.infobox.bgcolor = gui.infobox.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);␊ |
721 | ␊ |
722 | ␉/*␊ |
723 | ␉ * Parse menu parameters␊ |
724 | ␉ */␊ |
725 | ␉if(getDimensionForKey("menu_width", &pixel, theme, gui.screen.width , 0 ) )␊ |
726 | ␉␉gui.menu.width = pixel;␊ |
727 | ␉else␊ |
728 | ␉␉gui.menu.width = images[iMenuSelection].image->width;␊ |
729 | ␊ |
730 | ␉if(getDimensionForKey("menu_height", &pixel, theme, gui.screen.height , 0 ) )␊ |
731 | ␉␉gui.menu.height = pixel;␊ |
732 | ␉else␊ |
733 | ␉␉gui.menu.height = (infoMenuItemsCount) * images[iMenuSelection].image->height;␊ |
734 | ␊ |
735 | ␉if(getDimensionForKey("menu_pos_x", &pixel, theme, screen_width , gui.menu.width ) )␊ |
736 | ␉␉gui.menu.pos.x = pixel;␊ |
737 | ␊ |
738 | ␉if(getDimensionForKey("menu_pos_y", &pixel, theme, screen_height , gui.menu.height ) )␊ |
739 | ␉␉gui.menu.pos.y = pixel;␊ |
740 | ␊ |
741 | ␉if(getIntForKey("menu_textmargin_h", &val, theme))␊ |
742 | ␉␉gui.menu.hborder = MIN( gui.menu.width , val );␊ |
743 | ␊ |
744 | ␉if(getIntForKey("menu_textmargin_v", &val, theme))␊ |
745 | ␉␉gui.menu.vborder = MIN( gui.menu.height , val );␊ |
746 | ␊ |
747 | ␉if(getColorForKey("menu_bgcolor", &color, theme))␊ |
748 | ␉␉gui.menu.bgcolor = (color & 0x00FFFFFF);␊ |
749 | ␊ |
750 | ␉if(getIntForKey("menu_transparency", &alpha, theme))␊ |
751 | ␉␉gui.menu.bgcolor = gui.menu.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);␉␉␊ |
752 | ␊ |
753 | ␉/*␊ |
754 | ␉ * Parse bootprompt parameters␊ |
755 | ␉ */␊ |
756 | ␉if(getDimensionForKey("bootprompt_width", &pixel, theme, screen_width , 0 ) )␊ |
757 | ␉␉gui.bootprompt.width = pixel;␊ |
758 | ␊ |
759 | ␉if(getIntForKey("bootprompt_height", &val, theme))␊ |
760 | ␉␉gui.bootprompt.height = MIN( screen_height , val );␊ |
761 | ␊ |
762 | ␉if(getDimensionForKey("bootprompt_pos_x", &pixel, theme, screen_width , gui.bootprompt.width ) )␊ |
763 | ␉␉gui.bootprompt.pos.x = pixel;␊ |
764 | ␊ |
765 | ␉if(getDimensionForKey("bootprompt_pos_y", &pixel, theme, screen_height , gui.bootprompt.height ) )␊ |
766 | ␉␉gui.bootprompt.pos.y = pixel;␊ |
767 | ␊ |
768 | ␉if(getIntForKey("bootprompt_textmargin_h", &val, theme))␊ |
769 | ␉␉gui.bootprompt.hborder = MIN( gui.bootprompt.width , val );␊ |
770 | ␊ |
771 | ␉if(getIntForKey("bootprompt_textmargin_v", &val, theme))␊ |
772 | ␉␉gui.bootprompt.vborder = MIN( gui.bootprompt.height , val );␊ |
773 | ␊ |
774 | ␉if(getColorForKey("bootprompt_bgcolor", &color, theme))␊ |
775 | ␉␉gui.bootprompt.bgcolor = (color & 0x00FFFFFF);␊ |
776 | ␊ |
777 | ␉if(getIntForKey("bootprompt_transparency", &alpha, theme))␊ |
778 | ␉␉gui.bootprompt.bgcolor = gui.bootprompt.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);␊ |
779 | ␊ |
780 | ␉if(getColorForKey("font_small_color", &color, theme))␊ |
781 | ␉␉gui.screen.font_small_color = (color & 0x00FFFFFF);␊ |
782 | ␊ |
783 | ␉if(getColorForKey("font_console_color", &color, theme))␊ |
784 | ␉␉gui.screen.font_console_color = (color & 0x00FFFFFF);␊ |
785 | }␊ |
786 | ␊ |
787 | int initGUI(void)␊ |
788 | {␊ |
789 | ␉int␉␉val;␊ |
790 | ␉int␉len;␊ |
791 | ␉char␉dirspec[256];␊ |
792 | ␊ |
793 | ␉getValueForKey( "Theme", &theme_name, &len, &bootInfo->chameleonConfig );␊ |
794 | ␉if ((strlen(theme_name) + 27) > sizeof(dirspec)) {␊ |
795 | ␉␉return 1;␊ |
796 | ␉}␊ |
797 | ␉sprintf(dirspec, "/Extra/Themes/%s/theme.plist", theme_name);␊ |
798 | ␉if (loadConfigFile(dirspec, &bootInfo->themeConfig) != 0) {␊ |
799 | #ifdef CONFIG_EMBED_THEME␊ |
800 | config_file_t␉*config;␊ |
801 | ␊ |
802 | config = &bootInfo->themeConfig;␊ |
803 | if (ParseXMLFile((char *)__theme_plist, &config->dictionary) != 0) {␊ |
804 | return 1;␊ |
805 | }␊ |
806 | #else␊ |
807 | ␉␉return 1;␊ |
808 | #endif␊ |
809 | ␉}␊ |
810 | ␉// parse display size parameters␊ |
811 | ␉if (getIntForKey("screen_width", &val, &bootInfo->themeConfig) && val > 0) {␊ |
812 | ␉␉screen_params[0] = val;␊ |
813 | ␉}␊ |
814 | ␉if (getIntForKey("screen_height", &val, &bootInfo->themeConfig) && val > 0) {␊ |
815 | ␉␉screen_params[1] = val;␊ |
816 | ␉}␊ |
817 | ␊ |
818 | ␉// Initalizing GUI strucutre.␊ |
819 | ␉bzero(&gui, sizeof(gui_t));␊ |
820 | ␉␊ |
821 | ␉// find best matching vesa mode for our requested width & height␊ |
822 | ␉getGraphicModeParams(screen_params);␊ |
823 | ␊ |
824 | ␉// set our screen structure with the mode width & height␊ |
825 | ␉gui.screen.width = screen_params[0];␉␊ |
826 | ␉gui.screen.height = screen_params[1];␊ |
827 | ␊ |
828 | ␉// load graphics otherwise fail and return␊ |
829 | ␉if (loadGraphics() == 0) {␊ |
830 | ␉␉loadThemeValues(&bootInfo->themeConfig);␊ |
831 | ␉␉colorFont(&font_small, gui.screen.font_small_color);␊ |
832 | ␉␉colorFont(&font_console, gui.screen.font_console_color);␊ |
833 | ␊ |
834 | ␉␉// create the screen & window buffers␊ |
835 | ␉␉if (createBackBuffer(&gui.screen) == 0) {␊ |
836 | ␉␉␉if (createWindowBuffer(&gui.screen) == 0) {␊ |
837 | ␉␉␉␉if (createWindowBuffer(&gui.devicelist) == 0) {␊ |
838 | ␉␉␉␉␉if (createWindowBuffer(&gui.bootprompt) == 0) {␊ |
839 | ␉␉␉␉␉␉if (createWindowBuffer(&gui.infobox) == 0) {␊ |
840 | ␉␉␉␉␉␉␉if (createWindowBuffer(&gui.menu) == 0) {␊ |
841 | ␉␉␉␉␉␉␉ gui.logo.draw = true;␊ |
842 | ␉␉␉␉␉␉␉␉drawBackground();␊ |
843 | ␉␉␉␉␉␉␉␉// lets copy the screen into the back buffer␊ |
844 | ␉␉␉␉␉␉␉␉memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );␊ |
845 | ␉␉␉␉␉␉␉␉setVideoMode( GRAPHICS_MODE, 0 );␊ |
846 | ␉␉␉␉␉␉␉␉gui.initialised = true;␊ |
847 | ␉␉␉␉␉␉␉␉return 0;␊ |
848 | ␉␉␉␉␉␉␉}␊ |
849 | ␉␉␉␉␉␉}␊ |
850 | ␉␉␉␉␉}␊ |
851 | ␉␉␉␉}␊ |
852 | ␉␉␉}␊ |
853 | ␉␉}␊ |
854 | ␉}␊ |
855 | ␊ |
856 | // not available memory, freeing resources␊ |
857 | freeWindowBuffer(&gui.menu);␊ |
858 | freeWindowBuffer(&gui.infobox);␊ |
859 | freeWindowBuffer(&gui.bootprompt);␊ |
860 | freeWindowBuffer(&gui.devicelist);␊ |
861 | freeWindowBuffer(&gui.screen);␊ |
862 | freeBackBuffer(&gui.screen);␊ |
863 | unloadGraphics();␊ |
864 | ␊ |
865 | ␉return 1;␊ |
866 | }␊ |
867 | ␊ |
868 | bool is_image_loaded(int i)␊ |
869 | {␉␊ |
870 | ␉return (images[i].image != NULL) ? true : false;␊ |
871 | }␊ |
872 | ␊ |
873 | void drawDeviceIcon(BVRef device, pixmap_t *buffer, position_t p, bool isSelected)␊ |
874 | {␊ |
875 | ␉int devicetype;␊ |
876 | ␊ |
877 | ␉if( diskIsCDROM(device) )␊ |
878 | ␉␉devicetype = iDeviceCDROM;␉␉␉␉// Use CDROM icon␊ |
879 | ␉else␊ |
880 | ␉{␊ |
881 | ␉␉switch (device->part_type)␊ |
882 | ␉␉{␊ |
883 | ␉␉␉case kPartitionTypeHFS:␊ |
884 | ␉␉␉{␊ |
885 | ␉␉␉␉// Use HFS or HFSRAID icon depending on bvr flags. Fallbacks are handled by alt_image above.␊ |
886 | ␉␉␉␉switch (device->OSVersion[3]) {␊ |
887 | ␉␉␉␉␉case '8':␊ |
888 | ␉␉␉␉␉␉devicetype = (device->flags & kBVFlagBooter ? iDeviceHFSRAID_ML : iDeviceHFS_ML);␊ |
889 | ␉␉␉␉␉␉break;␊ |
890 | ␉␉␉␉␉case '7':␊ |
891 | ␉␉␉␉␉␉devicetype = (device->flags & kBVFlagBooter ? iDeviceHFSRAID_Lion : iDeviceHFS_Lion);␊ |
892 | ␉␉␉␉␉␉break;␊ |
893 | ␉␉␉␉␉case '6':␊ |
894 | ␉␉␉␉␉␉devicetype = (device->flags & kBVFlagBooter ? iDeviceHFSRAID_SL : iDeviceHFS_SL);␊ |
895 | ␉␉␉␉␉␉break;␊ |
896 | ␉␉␉␉␉case '5':␊ |
897 | ␉␉␉␉␉␉devicetype = (device->flags & kBVFlagBooter ? iDeviceHFSRAID_Leo : iDeviceHFS_Leo);␊ |
898 | ␉␉␉␉␉␉break;␊ |
899 | ␉␉␉␉␉case '4':␊ |
900 | ␉␉␉␉␉␉devicetype = (device->flags & kBVFlagBooter ? iDeviceHFSRAID_Tiger : iDeviceHFS_Tiger);␊ |
901 | ␉␉␉␉␉␉break;␊ |
902 | ␉␉␉␉␉default:␊ |
903 | ␉␉␉␉␉␉devicetype = (device->flags & kBVFlagBooter ? iDeviceHFSRAID : iDeviceHFS);␊ |
904 | ␉␉␉␉␉␉break;␊ |
905 | ␉␉␉␉}␊ |
906 | ␉␉␉␉␊ |
907 | ␉␉␉␉break;␊ |
908 | ␉␉␉␉␊ |
909 | ␉␉␉}␉␉␉␉␊ |
910 | ␉␉␉case kPartitionTypeHPFS:␊ |
911 | ␉␉␉␉devicetype = iDeviceNTFS;␉␉// Use HPFS / NTFS icon␊ |
912 | ␉␉␉␉break;␊ |
913 | ␊ |
914 | ␉␉␉case kPartitionTypeFAT16:␊ |
915 | ␉␉␉␉devicetype = iDeviceFAT16;␉␉// Use FAT16 icon␊ |
916 | ␉␉␉␉break;␊ |
917 | ␊ |
918 | ␉␉␉case kPartitionTypeFAT32:␊ |
919 | ␉␉␉␉devicetype = iDeviceFAT32;␉␉// Use FAT32 icon␊ |
920 | ␉␉␉␉break;␊ |
921 | ␊ |
922 | ␉␉␉case kPartitionTypeEXT3:␊ |
923 | ␉␉␉␉devicetype = iDeviceEXT3;␉␉// Use EXT2/3 icon␊ |
924 | ␉␉␉␉break;␊ |
925 | ␊ |
926 | ␉␉␉case kPartitionTypeFreeBSD: /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
927 | ␉␉␉␉devicetype = iDeviceFreeBSD;␉␉// Use FreeBSD icon␊ |
928 | ␉␉␉␉break;␊ |
929 | ␊ |
930 | ␉␉␉case kPartitionTypeOpenBSD: /* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */␊ |
931 | ␉␉␉␉devicetype = iDeviceOpenBSD;␉␉// Use OpenBSD icon␊ |
932 | ␉␉␉␉break;␊ |
933 | ␊ |
934 | ␉␉␉case kPartitionTypeBEFS: /* Haiku detection and Icon credits to scorpius */␊ |
935 | ␉␉␉␉devicetype = iDeviceBEFS;␉␉// Use BEFS / Haiku icon␊ |
936 | ␉␉␉␉break;␊ |
937 | ␊ |
938 | ␉␉␉default:␊ |
939 | ␉␉␉␉devicetype = iDeviceGeneric;␉// Use Generic icon␊ |
940 | ␉␉␉␉break;␊ |
941 | ␉␉}␊ |
942 | ␉}␊ |
943 | ␉␊ |
944 | ␉// Draw the selection image and use the next (device_*_o) image for the selected item.␊ |
945 | ␉if (isSelected)␊ |
946 | ␉{␊ |
947 | ␉␉blend(images[iSelection].image, buffer, centeredAt(images[iSelection].image, p));␊ |
948 | ␉␉devicetype++; // select override image ␊ |
949 | ␉}␊ |
950 | ␊ |
951 | ␉// draw icon␊ |
952 | ␉blend(images[devicetype].image, buffer, centeredAt(images[devicetype].image, p));␊ |
953 | ␉␊ |
954 | ␉p.y += (images[iSelection].image->height / 2) + font_console.chars[0]->height;␊ |
955 | ␉␊ |
956 | ␉// draw volume label ␊ |
957 | ␉drawStrCenteredAt( device->label, &font_small, buffer, p);␉␊ |
958 | ␊ |
959 | }␊ |
960 | ␊ |
961 | void drawDeviceList (int start, int end, int selection)␊ |
962 | {␊ |
963 | ␉int␉␉␉i;␊ |
964 | ␉bool␉␉shoWinfo = false;␊ |
965 | ␉extern bool showBootBanner;␊ |
966 | ␉position_t␉p, p_prev, p_next;␊ |
967 | ␊ |
968 | ␉//uint8_t␉maxDevices = MIN( gui.maxdevices, menucount );␊ |
969 | ␊ |
970 | ␉fillPixmapWithColor( gui.devicelist.pixmap, gui.devicelist.bgcolor);␊ |
971 | ␊ |
972 | ␉makeRoundedCorners( gui.devicelist.pixmap);␊ |
973 | ␊ |
974 | ␉switch (gui.layout)␊ |
975 | ␉{␊ |
976 | ␊ |
977 | ␉␉case VerticalLayout:␊ |
978 | ␉␉␉p.x = (gui.devicelist.width /2);␊ |
979 | ␉␉␉p.y = ( ( images[iSelection].image->height / 2 ) + images[iDeviceScrollPrev].image->height + gui.devicelist.iconspacing );␊ |
980 | ␊ |
981 | ␉␉␉// place scroll indicators at top & bottom edges␊ |
982 | ␉␉␉p_prev = pos ( gui.devicelist.width / 2 , gui.devicelist.iconspacing );␊ |
983 | ␉␉␉p_next = pos ( p_prev.x, gui.devicelist.height - gui.devicelist.iconspacing );␊ |
984 | ␉␉␉␊ |
985 | ␉␉␉break;␊ |
986 | ␉␉␉␊ |
987 | ␉␉default:␉// use Horizontal layout as the default␊ |
988 | ␊ |
989 | ␉␉case HorizontalLayout:␊ |
990 | ␉␉␉p.x = (gui.devicelist.width - ( gui.devicelist.width / gui.maxdevices ) * gui.maxdevices ) / 2 + ( images[iSelection].image->width / 2) + images[iDeviceScrollPrev].image->width + gui.devicelist.iconspacing;␊ |
991 | ␉␉␉p.y = ((gui.devicelist.height - font_console.chars[0]->height ) - images[iSelection].image->height) / 2 + ( images[iSelection].image->height / 2 );␊ |
992 | ␊ |
993 | ␉␉␉// place scroll indicators at left & right edges␊ |
994 | ␉␉␉p_prev = pos ( images[iDeviceScrollPrev].image->width / 2 + gui.devicelist.iconspacing / 2, gui.devicelist.height / 2 );␊ |
995 | ␉␉␉p_next = pos ( gui.devicelist.width - ( images[iDeviceScrollNext].image->width / 2 + gui.devicelist.iconspacing / 2), gui.devicelist.height / 2 );␊ |
996 | ␉␉␉␊ |
997 | ␉␉␉break;␊ |
998 | ␉␉␉␊ |
999 | ␉}␊ |
1000 | ␉␊ |
1001 | ␉// draw visible device icons␊ |
1002 | ␉for (i = 0; i < gui.maxdevices; i++)␊ |
1003 | ␉{␊ |
1004 | ␉␉BVRef param = menuItems[start + i].param;␊ |
1005 | ␊ |
1006 | bool isSelected = ((start + i) == selection) ? true : false;␊ |
1007 | ␉␉if (isSelected)␊ |
1008 | ␉␉{␊ |
1009 | if (param->flags & kBVFlagNativeBoot)␊ |
1010 | {␊ |
1011 | infoMenuNativeBoot = true;␊ |
1012 | }␊ |
1013 | else␊ |
1014 | {␊ |
1015 | infoMenuNativeBoot = false;␊ |
1016 | if(infoMenuSelection >= INFOMENU_NATIVEBOOT_START && infoMenuSelection <= INFOMENU_NATIVEBOOT_END)␊ |
1017 | infoMenuSelection = 0;␊ |
1018 | }␊ |
1019 | ␊ |
1020 | ␉␉␉if (gui.menu.draw)␊ |
1021 | ␉␉␉␉drawInfoMenuItems();␊ |
1022 | ␉␉␉␊ |
1023 | ␉␉␉getBoolForKey(kShowInfoKey, &shoWinfo, &bootInfo->chameleonConfig);␊ |
1024 | ␉␉␉␊ |
1025 | ␉␉␉if (shoWinfo && showBootBanner)␊ |
1026 | ␉␉␉{␊ |
1027 | ␉␉␉␉gui.debug.cursor = pos( 10, 100);␊ |
1028 | ␉␉␉␉dprintf( &gui.screen, "label: %s\n", param->label );␊ |
1029 | ␉␉␉␉dprintf( &gui.screen, "biosdev: 0x%x\n", param->biosdev );␊ |
1030 | ␉␉␉␉dprintf( &gui.screen, "type: 0x%x\n", param->type );␊ |
1031 | ␉␉␉␉dprintf( &gui.screen, "flags: 0x%x\n", param->flags );␊ |
1032 | ␉␉␉␉dprintf( &gui.screen, "part_no: %d\n", param->part_no );␊ |
1033 | ␉␉␉␉dprintf( &gui.screen, "part_boff: 0x%x\n", param->part_boff );␊ |
1034 | ␉␉␉␉dprintf( &gui.screen, "part_type: 0x%x\n", param->part_type );␊ |
1035 | ␉␉␉␉dprintf( &gui.screen, "bps: 0x%x\n", param->bps );␊ |
1036 | ␉␉␉␉dprintf( &gui.screen, "name: %s\n", param->name );␊ |
1037 | ␉␉␉␉dprintf( &gui.screen, "type_name: %s\n", param->type_name );␊ |
1038 | ␉␉␉␉dprintf( &gui.screen, "modtime: %d\n", param->modTime );␊ |
1039 | //␉␉␉␉// res␊ |
1040 | ␉␉␉␉dprintf( &gui.screen, "width: %d\n", gui.screen.width );␊ |
1041 | ␉␉␉␉dprintf( &gui.screen, "height: %d\n", gui.screen.height );␊ |
1042 | //␉␉␉␉dprintf( &gui.screen, "attr: 0x%x\n", gui.screen.attr ); //Azi: reminder␊ |
1043 | //␉␉␉␉dprintf( &gui.screen, "mm: %d\n", gui.screen.mm );␊ |
1044 | ␉␉␉}␊ |
1045 | ␉␉}␊ |
1046 | ␉␉␊ |
1047 | ␉␉drawDeviceIcon( param, gui.devicelist.pixmap, p, isSelected);␊ |
1048 | ␉␉␊ |
1049 | ␉␉if (gui.layout == HorizontalLayout)␊ |
1050 | ␉␉{␊ |
1051 | ␉␉␉p.x += images[iSelection].image->width + gui.devicelist.iconspacing; ␊ |
1052 | ␉␉}␊ |
1053 | ␉␉if (gui.layout == VerticalLayout)␊ |
1054 | ␉␉{␊ |
1055 | ␉␉␉p.y += ( images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing ); ␊ |
1056 | ␉␉}␊ |
1057 | ␉}␊ |
1058 | ␊ |
1059 | ␉// draw prev indicator␊ |
1060 | ␉if (start)␊ |
1061 | ␉␉blend( images[iDeviceScrollPrev].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollPrev].image, p_prev ) );␊ |
1062 | ␊ |
1063 | ␉// draw next indicator␊ |
1064 | ␉if ( end < gDeviceCount - 1 )␊ |
1065 | ␉␉blend( images[iDeviceScrollNext].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollNext].image, p_next ) );␊ |
1066 | ␊ |
1067 | ␉gui.redraw = true;␊ |
1068 | ␉␊ |
1069 | ␉updateVRAM();␊ |
1070 | ␉␊ |
1071 | }␊ |
1072 | ␊ |
1073 | void clearGraphicBootPrompt()␊ |
1074 | {␊ |
1075 | ␉// clear text buffer␊ |
1076 | ␉//prompt[0] = '\0';␊ |
1077 | ␉//prompt_pos=0;␊ |
1078 | ␊ |
1079 | ␉␊ |
1080 | ␉if(␉gui.bootprompt.draw == true )␊ |
1081 | ␉{␊ |
1082 | ␉␉gui.bootprompt.draw = false;␊ |
1083 | ␉␉gui.redraw = true;␊ |
1084 | ␉␉// this causes extra frames to be drawn␊ |
1085 | ␉␉//updateVRAM();␊ |
1086 | ␉}␊ |
1087 | ␊ |
1088 | ␉return;␊ |
1089 | }␊ |
1090 | ␊ |
1091 | void updateGraphicBootPrompt()␊ |
1092 | {␊ |
1093 | ␉fillPixmapWithColor( gui.bootprompt.pixmap, gui.bootprompt.bgcolor);␊ |
1094 | ␊ |
1095 | ␉makeRoundedCorners( gui.bootprompt.pixmap);␊ |
1096 | ␊ |
1097 | ␉position_t p_text = pos( gui.bootprompt.hborder , ( ( gui.bootprompt.height - font_console.chars[0]->height) ) / 2 );␊ |
1098 | ␊ |
1099 | ␉// print the boot prompt text␊ |
1100 | ␉drawStr(prompt_text, &font_console, gui.bootprompt.pixmap, p_text);␊ |
1101 | ␉␊ |
1102 | ␉// get the position of the end of the boot prompt text to display user input␊ |
1103 | ␉position_t p_prompt = pos( p_text.x + ( ( strlen(prompt_text) ) * font_console.chars[0]->width ), p_text.y );␊ |
1104 | ␉␊ |
1105 | ␉drawStr( gBootArgs, &font_console, gui.bootprompt.pixmap, p_prompt);␊ |
1106 | ␊ |
1107 | ␉gui.menu.draw = false;␊ |
1108 | ␉gui.bootprompt.draw = true;␊ |
1109 | ␉gui.redraw = true;␊ |
1110 | ␉␊ |
1111 | ␉updateVRAM();␊ |
1112 | ␉␊ |
1113 | ␉return;␊ |
1114 | }␊ |
1115 | ␊ |
1116 | static inline␊ |
1117 | void vramwrite (void *data, int width, int height)␊ |
1118 | {␊ |
1119 | ␉if (VIDEO (depth) == 32 && VIDEO (rowBytes) == gui.backbuffer->width * 4)␊ |
1120 | ␉␉memcpy((uint8_t *)vram, gui.backbuffer->pixels, VIDEO (rowBytes)*VIDEO (height));␊ |
1121 | ␉else␊ |
1122 | ␉{␊ |
1123 | ␉␉uint32_t r, g, b;␊ |
1124 | ␉␉int i, j;␊ |
1125 | ␉␉for (i = 0; i < VIDEO (height); i++)␊ |
1126 | ␉␉␉for (j = 0; j < VIDEO (width); j++)␊ |
1127 | ␉␉␉{␊ |
1128 | ␉␉␉␉b = ((uint8_t *) data)[4*i*width + 4*j];␊ |
1129 | ␉␉␉␉g = ((uint8_t *) data)[4*i*width + 4*j + 1];␊ |
1130 | ␉␉␉␉r = ((uint8_t *) data)[4*i*width + 4*j + 2];␊ |
1131 | ␉␉␉␉switch (VIDEO (depth))␊ |
1132 | ␉␉␉␉{␊ |
1133 | ␉␉␉␉␉case 32:␊ |
1134 | ␉␉␉␉␉␉*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*4) = (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);␊ |
1135 | ␉␉␉␉␉␉break;␊ |
1136 | ␉␉␉␉␉case 24:␊ |
1137 | ␉␉␉␉␉␉*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3) = ((*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3))&0xff000000)␊ |
1138 | ␉␉␉␉␉␉| (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);␊ |
1139 | ␉␉␉␉␉␉break;␊ |
1140 | ␉␉␉␉␉case 16:␊ |
1141 | ␉␉␉␉␉␉// Somehow 16-bit is always 15-bits really␊ |
1142 | ␉␉␉␉␉␉//␉␉␉␉␉␉*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xfc)<<3) | ((r&0xf8)<<8);␊ |
1143 | ␉␉␉␉␉␉//␉␉␉␉␉␉break;␉␉␉␉␉␉␉␊ |
1144 | ␉␉␉␉␉case 15:␊ |
1145 | ␉␉␉␉␉␉*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xf8)<<2) | ((r&0xf8)<<7);␊ |
1146 | ␉␉␉␉␉␉break;␉␊ |
1147 | ␉␉␉␉}␊ |
1148 | ␉␉␉}␊ |
1149 | ␉}␊ |
1150 | }␊ |
1151 | ␊ |
1152 | void updateVRAM()␊ |
1153 | {␊ |
1154 | ␉if (gui.redraw)␊ |
1155 | ␉{␊ |
1156 | ␉␉if (gui.devicelist.draw)␊ |
1157 | ␉␉␉blend( gui.devicelist.pixmap, gui.backbuffer, gui.devicelist.pos );␊ |
1158 | ␊ |
1159 | ␉␉if (gui.bootprompt.draw)␊ |
1160 | ␉␉␉blend( gui.bootprompt.pixmap, gui.backbuffer, gui.bootprompt.pos );␊ |
1161 | ␊ |
1162 | ␉␉if (gui.menu.draw)␊ |
1163 | ␉␉␉blend( gui.menu.pixmap, gui.backbuffer, gui.menu.pos );␊ |
1164 | ␉␉␊ |
1165 | ␉␉if (gui.infobox.draw)␊ |
1166 | ␉␉␉blend( gui.infobox.pixmap, gui.backbuffer, gui.infobox.pos );␊ |
1167 | ␉}␊ |
1168 | ␊ |
1169 | ␉vramwrite ( gui.backbuffer->pixels, gui.backbuffer->width, gui.backbuffer->height );␊ |
1170 | ␊ |
1171 | ␉if (gui.redraw)␊ |
1172 | ␉{␊ |
1173 | ␉␉memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );␊ |
1174 | ␉␉gui.redraw = false;␊ |
1175 | ␉}␊ |
1176 | }␊ |
1177 | ␊ |
1178 | struct putc_info //Azi: exists on console.c & printf.c␊ |
1179 | {␊ |
1180 | char * str;␊ |
1181 | char * last_str;␊ |
1182 | };␊ |
1183 | ␊ |
1184 | static int␊ |
1185 | sputc(int c, struct putc_info * pi) //Azi: same as above␊ |
1186 | {␊ |
1187 | if (pi->last_str)␊ |
1188 | if (pi->str == pi->last_str) {␊ |
1189 | *(pi->str) = '\0';␊ |
1190 | return 0;␊ |
1191 | }␊ |
1192 | *(pi->str)++ = c;␊ |
1193 | return c;␊ |
1194 | }␊ |
1195 | ␊ |
1196 | int gprintf( window_t * window, const char * fmt, ...)␊ |
1197 | {␊ |
1198 | ␉char *formattedtext;␊ |
1199 | ␊ |
1200 | ␉va_list ap;␊ |
1201 | ␉␊ |
1202 | ␉struct putc_info pi;␊ |
1203 | ␊ |
1204 | ␉if ((formattedtext = malloc(1024)) != NULL) {␊ |
1205 | ␉␉// format the text␊ |
1206 | ␉␉va_start(ap, fmt);␊ |
1207 | ␉␉pi.str = formattedtext;␊ |
1208 | ␉␉pi.last_str = 0;␊ |
1209 | ␉␉prf(fmt, ap, sputc, &pi);␊ |
1210 | ␉␉*pi.str = '\0';␊ |
1211 | ␉␉va_end(ap);␊ |
1212 | ␉␉␊ |
1213 | ␉␉position_t␉origin, cursor, bounds;␊ |
1214 | ␊ |
1215 | ␉␉int i;␊ |
1216 | ␉␉int character;␊ |
1217 | ␊ |
1218 | ␉␉origin.x = MAX( window->cursor.x, window->hborder );␊ |
1219 | ␉␉origin.y = MAX( window->cursor.y, window->vborder );␊ |
1220 | ␉␉␊ |
1221 | ␉␉bounds.x = ( window->width - window->hborder );␊ |
1222 | ␉␉bounds.y = ( window->height - window->vborder );␊ |
1223 | ␉␉␊ |
1224 | ␉␉cursor = origin;␊ |
1225 | ␊ |
1226 | ␉␉font_t *font = &font_console;␊ |
1227 | ␊ |
1228 | ␉␉for( i=0; i< strlen(formattedtext); i++ )␊ |
1229 | ␉␉{␊ |
1230 | ␉␉␉character = formattedtext[i];␊ |
1231 | ␉␉␉␊ |
1232 | ␉␉␉character -= 32;␊ |
1233 | ␊ |
1234 | ␉␉␉// newline ?␊ |
1235 | ␉␉␉if( formattedtext[i] == '\n' )␊ |
1236 | ␉␉␉{␊ |
1237 | ␉␉␉␉cursor.x = window->hborder;␊ |
1238 | ␉␉␉␉cursor.y += font->height;␊ |
1239 | ␊ |
1240 | ␉␉␉␉if ( cursor.y > bounds.y )␊ |
1241 | ␉␉␉␉␉cursor.y = origin.y;␊ |
1242 | ␊ |
1243 | ␉␉␉␉continue;␊ |
1244 | ␉␉␉}␊ |
1245 | ␊ |
1246 | ␉␉␉// tab ?␊ |
1247 | ␉␉␉if( formattedtext[i] == '\t' )␊ |
1248 | ␉␉␉␉cursor.x += ( font->chars[0]->width * 5 );␊ |
1249 | ␉␉␉␊ |
1250 | ␉␉␉// draw the character␊ |
1251 | ␉␉␉if( font->chars[character])␊ |
1252 | ␉␉␉␉blend(font->chars[character], window->pixmap, cursor);␊ |
1253 | ␊ |
1254 | ␉␉␉cursor.x += font->chars[character]->width;␊ |
1255 | ␊ |
1256 | ␉␉␉// check x pos and do newline␊ |
1257 | ␉␉␉if ( cursor.x > bounds.x )␊ |
1258 | ␉␉␉{␊ |
1259 | ␉␉␉␉cursor.x = origin.x;␊ |
1260 | ␉␉␉␉cursor.y += font->height;␊ |
1261 | ␉␉␉}␊ |
1262 | ␉␉␉␊ |
1263 | ␉␉␉// check y pos and reset to origin.y␊ |
1264 | ␉␉␉if ( cursor.y > bounds.y )␊ |
1265 | ␉␉␉␉cursor.y = origin.y;␊ |
1266 | ␉␉}␊ |
1267 | ␊ |
1268 | ␉␉// update cursor postition␊ |
1269 | ␉␉window->cursor = cursor;␊ |
1270 | ␉␉␊ |
1271 | ␉␉free(formattedtext);␊ |
1272 | ␉␉␊ |
1273 | ␉␉return 0;␊ |
1274 | ␊ |
1275 | ␉}␊ |
1276 | ␉return 1;␊ |
1277 | }␊ |
1278 | ␊ |
1279 | int dprintf( window_t * window, const char * fmt, ...)␊ |
1280 | {␊ |
1281 | ␉char *formattedtext;␊ |
1282 | ␉␊ |
1283 | ␉va_list ap;␊ |
1284 | ␉␊ |
1285 | ␉//window = &gui.debug;␊ |
1286 | ␉␊ |
1287 | ␉struct putc_info pi;␊ |
1288 | ␉␊ |
1289 | ␉if ((formattedtext = malloc(1024)) != NULL) {␊ |
1290 | ␉␉// format the text␊ |
1291 | ␉␉va_start(ap, fmt);␊ |
1292 | ␉␉pi.str = formattedtext;␊ |
1293 | ␉␉pi.last_str = 0;␊ |
1294 | ␉␉prf(fmt, ap, sputc, &pi);␊ |
1295 | ␉␉*pi.str = '\0';␊ |
1296 | ␉␉va_end(ap);␊ |
1297 | ␉␉␊ |
1298 | ␉␉position_t␉origin, cursor, bounds;␊ |
1299 | ␉␉␊ |
1300 | ␉␉int i;␊ |
1301 | ␉␉int character;␊ |
1302 | ␉␉␊ |
1303 | ␉␉origin.x = MAX( gui.debug.cursor.x, window->hborder );␊ |
1304 | ␉␉origin.y = MAX( gui.debug.cursor.y, window->vborder );␊ |
1305 | ␉␉␊ |
1306 | ␉␉bounds.x = ( window->width - window->hborder );␊ |
1307 | ␉␉bounds.y = ( window->height - window->vborder );␊ |
1308 | ␉␉␊ |
1309 | ␉␉cursor = origin;␊ |
1310 | ␉␉␊ |
1311 | ␉␉font_t *font = &font_console;␊ |
1312 | ␉␉␊ |
1313 | ␉␉for( i=0; i< strlen(formattedtext); i++ )␊ |
1314 | ␉␉{␊ |
1315 | ␉␉␉character = formattedtext[i];␊ |
1316 | ␉␉␉␊ |
1317 | ␉␉␉character -= 32;␊ |
1318 | ␉␉␉␊ |
1319 | ␉␉␉// newline ?␊ |
1320 | ␉␉␉if( formattedtext[i] == '\n' )␊ |
1321 | ␉␉␉{␊ |
1322 | ␉␉␉␉cursor.x = window->hborder;␊ |
1323 | ␉␉␉␉cursor.y += font->height;␊ |
1324 | ␉␉␉␉␊ |
1325 | ␉␉␉␉if ( cursor.y > bounds.y )␊ |
1326 | ␉␉␉␉␉cursor.y = origin.y;␊ |
1327 | ␉␉␉␉␊ |
1328 | ␉␉␉␉continue;␊ |
1329 | ␉␉␉}␊ |
1330 | ␉␉␉␊ |
1331 | ␉␉␉// tab ?␊ |
1332 | ␉␉␉if( formattedtext[i] == '\t' )␊ |
1333 | ␉␉␉␉cursor.x += ( font->chars[0]->width * 5 );␊ |
1334 | ␉␉␉␊ |
1335 | ␉␉␉// draw the character␊ |
1336 | ␉␉␉if( font->chars[character])␊ |
1337 | ␉␉␉␉blend(font->chars[character], gui.backbuffer, cursor);␊ |
1338 | ␊ |
1339 | ␉␉␉cursor.x += font->chars[character]->width;␊ |
1340 | ␉␉␉␊ |
1341 | ␉␉␉// check x pos and do newline␊ |
1342 | ␉␉␉if ( cursor.x > bounds.x )␊ |
1343 | ␉␉␉{␊ |
1344 | ␉␉␉␉cursor.x = origin.x;␊ |
1345 | ␉␉␉␉cursor.y += font->height;␊ |
1346 | ␉␉␉}␊ |
1347 | ␉␉␉␊ |
1348 | ␉␉␉// check y pos and reset to origin.y␊ |
1349 | ␉␉␉if ( cursor.y > bounds.y )␊ |
1350 | ␉␉␉␉cursor.y = origin.y;␊ |
1351 | ␉␉}␊ |
1352 | ␉␉␊ |
1353 | ␉␉// update cursor postition␊ |
1354 | ␉␉gui.debug.cursor = cursor;␊ |
1355 | ␉␉␊ |
1356 | ␉␉free(formattedtext);␊ |
1357 | ␉␉␊ |
1358 | ␉␉return 0;␊ |
1359 | ␉␉␊ |
1360 | ␉}␊ |
1361 | ␉return 1;␊ |
1362 | }␊ |
1363 | ␊ |
1364 | int vprf(const char * fmt, va_list ap)␊ |
1365 | {␊ |
1366 | ␉int i;␊ |
1367 | ␉int character;␊ |
1368 | ␊ |
1369 | ␉char *formattedtext;␊ |
1370 | ␉window_t *window = &gui.screen;␊ |
1371 | ␉struct putc_info pi;␊ |
1372 | ␉␊ |
1373 | ␉position_t␉origin, cursor, bounds;␊ |
1374 | ␉font_t *font = &font_console;␊ |
1375 | ␉␊ |
1376 | ␉if ((formattedtext = malloc(1024)) != NULL) {␊ |
1377 | ␉␉// format the text␊ |
1378 | ␉␉pi.str = formattedtext;␊ |
1379 | ␉␉pi.last_str = 0;␊ |
1380 | ␉␉prf(fmt, ap, sputc, &pi);␊ |
1381 | ␉␉*pi.str = '\0';␊ |
1382 | ␉␉␊ |
1383 | ␉␉origin.x = MAX( window->cursor.x, window->hborder );␊ |
1384 | ␉␉origin.y = MAX( window->cursor.y, window->vborder );␊ |
1385 | ␉␉bounds.x = ( window->width - ( window->hborder * 2 ) );␊ |
1386 | ␉␉bounds.y = ( window->height - ( window->vborder * 2 ) );␊ |
1387 | ␉␉cursor = origin;␊ |
1388 | ␊ |
1389 | ␉␉for( i=0; i< strlen(formattedtext); i++ )␊ |
1390 | ␉␉{␊ |
1391 | ␉␉␉character = formattedtext[i];␊ |
1392 | ␉␉␉character -= 32;␊ |
1393 | ␉␉␉␊ |
1394 | ␉␉␉// newline ?␊ |
1395 | ␉␉␉if( formattedtext[i] == '\n' )␊ |
1396 | ␉␉␉{␊ |
1397 | ␉␉␉␉cursor.x = window->hborder;␊ |
1398 | ␉␉␉␉cursor.y += font->height;␊ |
1399 | ␉␉␉␉if ( cursor.y > bounds.y )␊ |
1400 | ␉␉␉␉{␊ |
1401 | ␉␉␉␉␉gui.redraw = true;␊ |
1402 | ␉␉␉␉␉updateVRAM();␊ |
1403 | ␉␉␉␉␉cursor.y = window->vborder;␊ |
1404 | ␉␉␉␉}␊ |
1405 | ␉␉␉␉window->cursor.y = cursor.y;␊ |
1406 | ␉␉␉␉continue;␊ |
1407 | ␉␉␉}␊ |
1408 | ␊ |
1409 | ␉␉␉// tab ?␊ |
1410 | ␉␉␉if( formattedtext[i] == '\t' )␊ |
1411 | ␉␉␉{␊ |
1412 | ␉␉␉␉cursor.x = ( cursor.x / ( font->chars[0]->width * 8 ) + 1 ) * ( font->chars[0]->width * 8 );␊ |
1413 | ␉␉␉␉continue;␊ |
1414 | ␉␉␉}␊ |
1415 | ␉␉␉cursor.x += font->chars[character]->width;␊ |
1416 | ␉␉␉␊ |
1417 | ␉␉␉// check x pos and do newline␊ |
1418 | ␉␉␉if ( cursor.x > bounds.x )␊ |
1419 | ␉␉␉{␊ |
1420 | ␉␉␉␉cursor.x = origin.x;␊ |
1421 | ␉␉␉␉cursor.y += font->height;␊ |
1422 | ␉␉␉}␊ |
1423 | ␊ |
1424 | ␉␉␉// check y pos and reset to origin.y␊ |
1425 | ␉␉␉if ( cursor.y > ( bounds.y + font->chars[0]->height) )␊ |
1426 | ␉␉␉{␊ |
1427 | ␉␉␉␉gui.redraw = true;␊ |
1428 | ␉␉␉␉updateVRAM();␊ |
1429 | ␉␉␉␉cursor.y = window->vborder;␊ |
1430 | ␉␉␉}␊ |
1431 | ␉␉␉// draw the character␊ |
1432 | ␉␉␉if( font->chars[character])␊ |
1433 | ␉␉␉␉blend(font->chars[character], gui.backbuffer, cursor);␊ |
1434 | ␉␉}␊ |
1435 | ␉␉// save cursor postition␊ |
1436 | ␉␉window->cursor.x = cursor.x;␊ |
1437 | ␉␉updateVRAM();␊ |
1438 | ␉␉free(formattedtext);␊ |
1439 | ␉␉return 0;␊ |
1440 | ␉}␊ |
1441 | ␉return 1;␊ |
1442 | }␊ |
1443 | ␊ |
1444 | pixmap_t* charToPixmap(unsigned char ch, font_t *font) {␊ |
1445 | ␉unsigned int cha = (unsigned int)ch - 32;␊ |
1446 | ␉if (cha >= font->count)␊ |
1447 | ␉␉// return ? if the font for the char doesn't exists␊ |
1448 | ␉␉cha = '?' - 32;␊ |
1449 | ␊ |
1450 | ␉return font->chars[cha] ? font->chars[cha] : NULL;␊ |
1451 | }␊ |
1452 | ␊ |
1453 | position_t drawChar(unsigned char ch, font_t *font, pixmap_t *blendInto, position_t p) {␊ |
1454 | ␉pixmap_t* pm = charToPixmap(ch, font);␊ |
1455 | ␉if (pm && ((p.x + pm->width) < blendInto->width))␊ |
1456 | ␉{␊ |
1457 | ␉␉blend(pm, blendInto, p);␊ |
1458 | ␉␉return pos(p.x + pm->width, p.y);␊ |
1459 | ␉}␊ |
1460 | ␉else␊ |
1461 | ␉␉return p;␊ |
1462 | }␊ |
1463 | ␊ |
1464 | void drawStr(char *ch, font_t *font, pixmap_t *blendInto, position_t p)␊ |
1465 | {␊ |
1466 | ␉int i=0;␊ |
1467 | ␉position_t current_pos = pos(p.x, p.y);␊ |
1468 | ␉␊ |
1469 | ␉for (i=0; i < strlen(ch); i++)␊ |
1470 | ␉{␊ |
1471 | ␉␉// newline ?␊ |
1472 | ␉␉if ( ch[i] == '\n' )␊ |
1473 | ␉␉{␊ |
1474 | ␉␉␉current_pos.x = p.x;␊ |
1475 | ␉␉␉current_pos.y += font->height;␊ |
1476 | ␉␉␉continue;␊ |
1477 | ␉␉}␊ |
1478 | ␉␉␊ |
1479 | ␉␉// tab ?␊ |
1480 | ␉␉if ( ch[i] == '\t' )␊ |
1481 | ␉␉{␊ |
1482 | ␉␉␉current_pos.x += TAB_PIXELS_WIDTH;␊ |
1483 | ␉␉␉continue;␊ |
1484 | ␉␉}␊ |
1485 | ␉␉␊ |
1486 | ␉␉current_pos = drawChar(ch[i], font, blendInto, current_pos);␊ |
1487 | ␉}␊ |
1488 | }␊ |
1489 | ␊ |
1490 | void drawStrCenteredAt(char *text, font_t *font, pixmap_t *blendInto, position_t p)␊ |
1491 | {␊ |
1492 | ␉int i = 0;␊ |
1493 | ␉int width = 0;␊ |
1494 | ␉int max_width = 0;␊ |
1495 | ␉int height = font->height;␊ |
1496 | ␊ |
1497 | ␉// calculate the width in pixels␊ |
1498 | ␉for (i=0; i < strlen(text); i++) {␊ |
1499 | ␉␉if (text[i] == '\n')␊ |
1500 | ␉␉{␊ |
1501 | ␉␉␉width = 0;␊ |
1502 | ␉␉␉height += font->height;␊ |
1503 | ␉␉}␊ |
1504 | ␉␉else if (text[i] == '\t')␊ |
1505 | ␉␉␉width += TAB_PIXELS_WIDTH;␊ |
1506 | ␉␉else␊ |
1507 | ␉␉{␊ |
1508 | ␉␉␉pixmap_t* pm = charToPixmap(text[i], font);␊ |
1509 | ␉␉␉if (pm)␊ |
1510 | ␉␉␉␉width += pm->width;␊ |
1511 | ␉␉}␊ |
1512 | ␉␉if (width > max_width)␊ |
1513 | ␉␉␉max_width = width;␊ |
1514 | ␉}␊ |
1515 | ␊ |
1516 | ␉p.x = ( p.x - ( max_width / 2 ) );␊ |
1517 | ␉p.y = ( p.y - ( height / 2 ) );␊ |
1518 | ␉␊ |
1519 | ␉drawStr(text, font, blendInto, p);␊ |
1520 | }␊ |
1521 | ␊ |
1522 | int destroyFont(font_t *font)␊ |
1523 | {␊ |
1524 | int i;␊ |
1525 | for (i = 0; i < CHARACTERS_COUNT; i++)␊ |
1526 | {␊ |
1527 | if (font->chars[i])␊ |
1528 | {␊ |
1529 | if (font->chars[i]->pixels) free (font->chars[i]->pixels);␊ |
1530 | free (font->chars[i]);␊ |
1531 | font->chars[i] = 0;␊ |
1532 | }␊ |
1533 | }␊ |
1534 | return 0;␊ |
1535 | }␊ |
1536 | ␊ |
1537 | int initFont(font_t *font, image_t *data)␊ |
1538 | {␊ |
1539 | ␉unsigned int x = 0, y = 0, x2 = 0, x3 = 0;␊ |
1540 | ␉␊ |
1541 | ␉int start = 0, end = 0, count = 0, space = 0;␊ |
1542 | ␉␊ |
1543 | ␉bool monospaced = false;␊ |
1544 | ␉␊ |
1545 | ␉font->height = data->image->height;␊ |
1546 | ␊ |
1547 | ␉for( x = 0; x < data->image->width && count < CHARACTERS_COUNT; x++)␊ |
1548 | ␉{␊ |
1549 | ␉␉start = end;␊ |
1550 | ␊ |
1551 | ␉␉// if the pixel is red we've reached the end of the char␊ |
1552 | ␉␉if( pixel( data->image, x, 0 ).value == 0xFFFF0000)␊ |
1553 | ␉␉{␊ |
1554 | ␉␉␉end = x + 1;␊ |
1555 | ␊ |
1556 | ␉␉␉if( (font->chars[count] = malloc(sizeof(pixmap_t)) ) )␊ |
1557 | ␉␉␉{␊ |
1558 | ␉␉␉␉font->chars[count]->width = ( end - start) - 1;␊ |
1559 | ␉␉␉␉font->chars[count]->height = font->height;␊ |
1560 | ␉␉␉␊ |
1561 | ␉␉␉␉if ( ( font->chars[count]->pixels = malloc( font->chars[count]->width * data->image->height * 4) ) )␊ |
1562 | ␉␉␉␉{␊ |
1563 | ␉␉␉␉␉space += ( font->chars[count]->width * data->image->height * 4 );␊ |
1564 | ␉␉␉␉␉// we skip the first line because there are just the red pixels for the char width␊ |
1565 | ␉␉␉␉␉for( y = 1; y< (font->height); y++)␊ |
1566 | ␉␉␉␉␉{␊ |
1567 | ␉␉␉␉␉␉for( x2 = start, x3 = 0; x2 < end; x2++, x3++)␊ |
1568 | ␉␉␉␉␉␉{␊ |
1569 | ␉␉␉␉␉␉␉pixel( font->chars[count], x3, y ) = pixel( data->image, x2, y );␊ |
1570 | ␉␉␉␉␉␉}␉␊ |
1571 | ␉␉␉␉␉}␊ |
1572 | ␉␉␉␉␉␊ |
1573 | ␉␉␉␉␉// check if font is monospaced␊ |
1574 | ␉␉␉␉␉if( ( count > 0 ) && ( font->width != font->chars[count]->width ) )␊ |
1575 | ␉␉␉␉␉␉monospaced = true;␊ |
1576 | ␊ |
1577 | ␉␉␉␉␉font->width = font->chars[count]->width;␊ |
1578 | ␉␉␉␉␉␊ |
1579 | ␉␉␉␉␉count++;␊ |
1580 | ␉␉␉␉}␊ |
1581 | ␉␉␉}␊ |
1582 | ␉␉}␊ |
1583 | ␉}␊ |
1584 | ␊ |
1585 | ␉for (x = count; x < CHARACTERS_COUNT; x++)␊ |
1586 | ␉␉font->chars[x] = NULL;␊ |
1587 | ␊ |
1588 | ␉if(monospaced)␊ |
1589 | ␉␉font->width = 0;␊ |
1590 | ␊ |
1591 | ␉font->count = count;␊ |
1592 | ␊ |
1593 | ␉return 0;␊ |
1594 | }␊ |
1595 | ␊ |
1596 | void colorFont(font_t *font, uint32_t color)␊ |
1597 | {␊ |
1598 | ␉if( !color )␊ |
1599 | ␉␉return;␊ |
1600 | ␉␊ |
1601 | ␉int x, y, width, height;␊ |
1602 | ␉int count = 0;␊ |
1603 | ␉pixel_t *buff;␊ |
1604 | ␉␊ |
1605 | ␉while( font->chars[count++] )␊ |
1606 | ␉{␊ |
1607 | ␉␉width = font->chars[count-1]->width;␊ |
1608 | ␉␉height = font->chars[count-1]->height;␊ |
1609 | ␉␉for( y = 0; y < height; y++ )␊ |
1610 | ␉␉{␊ |
1611 | ␉␉␉for( x = 0; x < width; x++ )␊ |
1612 | ␉␉␉{␊ |
1613 | ␉␉␉␉buff = &(pixel( font->chars[count-1], x, y ));␊ |
1614 | ␉␉␉␉if( buff->ch.a )␊ |
1615 | ␉␉␉␉{␊ |
1616 | ␉␉␉␉␉buff->ch.r = (color & 0xFFFF0000) >> 16;␊ |
1617 | ␉␉␉␉␉buff->ch.g = (color & 0xFF00FF00) >> 8;␊ |
1618 | ␉␉␉␉␉buff->ch.b = (color & 0xFF0000FF);␊ |
1619 | ␉␉␉␉}␊ |
1620 | ␉␉␉}␊ |
1621 | ␉␉}␊ |
1622 | ␉}␊ |
1623 | }␊ |
1624 | ␊ |
1625 | void makeRoundedCorners(pixmap_t *p)␊ |
1626 | {␊ |
1627 | ␉int x,y;␊ |
1628 | ␉int width=p->width-1;␊ |
1629 | ␉int height=p->height-1;␊ |
1630 | ␉␊ |
1631 | ␉// 10px rounded corner alpha values␊ |
1632 | ␉uint8_t roundedCorner[10][10] =␊ |
1633 | ␉{␊ |
1634 | ␉␉{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0xC0, 0xFF},␊ |
1635 | ␉␉{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF},␊ |
1636 | ␉␉{ 0x00, 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},␊ |
1637 | ␉␉{ 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},␊ |
1638 | ␉␉{ 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},␊ |
1639 | ␉␉{ 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},␊ |
1640 | ␉␉{ 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},␊ |
1641 | ␉␉{ 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},␊ |
1642 | ␉␉{ 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},␊ |
1643 | ␉␉{ 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}␊ |
1644 | ␉};␊ |
1645 | ␉␊ |
1646 | ␉uint8_t alpha=0;␊ |
1647 | ␉␊ |
1648 | ␉for( y=0; y<10; y++)␊ |
1649 | ␉{␊ |
1650 | ␉␉for( x=0; x<10; x++)␊ |
1651 | ␉␉{␊ |
1652 | ␉␉␉// skip if the pixel should be visible␊ |
1653 | ␉␉␉if(roundedCorner[y][x] != 0xFF) ␊ |
1654 | ␉␉␉{ ␊ |
1655 | ␉␉␉␉alpha = ( roundedCorner[y][x] ? (uint8_t) (roundedCorner[y][x] * pixel(p, x, y).ch.a) / 255 : 0 );␊ |
1656 | ␉␉␉␉// Upper left corner␊ |
1657 | ␉␉␉␉pixel(p, x, y).ch.a = alpha;␊ |
1658 | ␊ |
1659 | ␉␉␉␉// upper right corner␊ |
1660 | ␉␉␉␉pixel(p, width-x,y).ch.a = alpha;␊ |
1661 | ␊ |
1662 | ␉␉␉␉// lower left corner␊ |
1663 | ␉␉␉␉pixel(p, x, height-y).ch.a = alpha;␊ |
1664 | ␊ |
1665 | ␉␉␉␉// lower right corner␊ |
1666 | ␉␉␉␉pixel(p, width-x, height-y).ch.a = alpha;␊ |
1667 | ␉␉␉}␊ |
1668 | ␉␉}␊ |
1669 | ␉}␊ |
1670 | }␊ |
1671 | ␊ |
1672 | void showInfoBox(char *title, char *text_orig)␊ |
1673 | {␊ |
1674 | ␉char* text;␊ |
1675 | ␉int i, key, lines, visiblelines;␊ |
1676 | ␊ |
1677 | ␉int currentline=0;␊ |
1678 | ␉int cnt=0;␊ |
1679 | ␉int offset=0;␊ |
1680 | ␉␊ |
1681 | ␉if( !title || !text_orig )␊ |
1682 | ␉␉return;␊ |
1683 | ␉␊ |
1684 | ␉// Create a copy so that we don't mangle the original␊ |
1685 | ␉text = malloc(strlen(text_orig) + 1);␊ |
1686 | ␉strcpy(text, text_orig);␊ |
1687 | ␉␊ |
1688 | ␉␊ |
1689 | ␉position_t pos_title = pos ( gui.infobox.vborder, gui.infobox.vborder );␊ |
1690 | ␊ |
1691 | ␉// calculate number of lines in the title␊ |
1692 | ␉for ( i = 0, lines = 1; i<strlen(title); i++ )␊ |
1693 | ␉␉if( title[i] == '\n')␊ |
1694 | ␉␉␉lines++;␊ |
1695 | ␉␊ |
1696 | ␉// y position of text is lines in title * height of font␊ |
1697 | ␉position_t pos_text = pos( pos_title.x , pos_title.y + ( font_console.height * lines ));␊ |
1698 | ␉␊ |
1699 | ␉// calculate number of lines in the text␊ |
1700 | ␉for ( i=0, lines = 1; i<strlen(text); i++ )␊ |
1701 | ␉␉if( text[i] == '\n')␊ |
1702 | ␉␉␉lines++;␊ |
1703 | ␉␊ |
1704 | ␉// if text ends with \n strip off␊ |
1705 | ␉if( text[i] == '\n' || text[i] == '\0')␊ |
1706 | ␉␉lines--;␊ |
1707 | ␉␊ |
1708 | ␉visiblelines = ( ( gui.infobox.height - ( gui.infobox.vborder * 2 ) ) / font_console.height ) - 1;␊ |
1709 | ␉␊ |
1710 | ␉// lets display the text and allow scroll thru using up down / arrows␊ |
1711 | ␉while(1)␊ |
1712 | ␉{␊ |
1713 | ␉␉// move to current line in text␊ |
1714 | ␉␉for( offset = 0, i = 0; offset < strlen(text); offset++ )␊ |
1715 | ␉␉{␊ |
1716 | ␉␉␉if( currentline == i)␊ |
1717 | ␉␉␉␉break;␊ |
1718 | ␉␉␉if( text[offset] =='\n')␊ |
1719 | ␉␉␉␉i++;␊ |
1720 | ␉␉}␊ |
1721 | ␊ |
1722 | ␉␉// find last visible line in text and place \0␊ |
1723 | ␉␉for( i = offset, cnt = 0; i < strlen(text); i++)␊ |
1724 | ␉␉{␊ |
1725 | ␉␉␉if(text[i]=='\n')␊ |
1726 | ␉␉␉␉cnt++;␊ |
1727 | ␉␉␉if ( cnt == visiblelines )␊ |
1728 | ␉␉␉{␊ |
1729 | ␉␉␉␉text[i]='\0';␊ |
1730 | ␉␉␉␉break;␊ |
1731 | ␉␉␉}␊ |
1732 | ␉␉}␊ |
1733 | ␊ |
1734 | ␉␉fillPixmapWithColor( gui.infobox.pixmap, gui.infobox.bgcolor);␊ |
1735 | ␊ |
1736 | ␉␉makeRoundedCorners( gui.infobox.pixmap);␊ |
1737 | ␊ |
1738 | ␉␉// print the title if present␊ |
1739 | ␉␉if( title )␊ |
1740 | ␉␉␉drawStr(title, &font_console, gui.infobox.pixmap, pos_title);␊ |
1741 | ␊ |
1742 | ␉␉// print the text␊ |
1743 | ␉␉drawStr( text + offset, &font_console, gui.infobox.pixmap, pos_text);␊ |
1744 | ␊ |
1745 | ␉␉// restore \n in text␊ |
1746 | ␉␉if ( cnt == visiblelines )␊ |
1747 | ␉␉␉text[i] = '\n';␊ |
1748 | ␉␉␊ |
1749 | ␉␉position_t pos_indicator = pos( gui.infobox.width - ( images[iTextScrollPrev].image->width - ( gui.infobox.vborder / 2) ), pos_text.y );␊ |
1750 | ␉␉␊ |
1751 | ␉␉// draw prev indicator␊ |
1752 | ␉␉if(offset)␊ |
1753 | ␉␉{␊ |
1754 | ␉␉␉blend( images[iTextScrollPrev].image, gui.infobox.pixmap, centeredAt( images[iTextScrollPrev].image, pos_indicator ));␊ |
1755 | ␉␉}␊ |
1756 | ␉␉␊ |
1757 | ␉␉// draw next indicator␊ |
1758 | ␉␉if( lines > ( currentline + visiblelines ) )␊ |
1759 | ␉␉{␊ |
1760 | ␉␉␉pos_indicator.y = ( gui.infobox.height - ( ( images[iTextScrollNext].image->width + gui.infobox.vborder ) / 2 ) );␊ |
1761 | ␉␉␉blend( images[iTextScrollNext].image, gui.infobox.pixmap, centeredAt( images[iTextScrollNext].image, pos_indicator ) );␊ |
1762 | ␉␉}␊ |
1763 | ␊ |
1764 | ␉␉gui.bootprompt.draw = false;␊ |
1765 | ␉␉gui.infobox.draw = true;␊ |
1766 | ␉␉gui.redraw = true;␊ |
1767 | ␉␉␊ |
1768 | ␉␉updateVRAM();␊ |
1769 | ␉␉␊ |
1770 | ␉␉key = getchar();␊ |
1771 | ␉␉␉␊ |
1772 | ␉␉if( key == KEY_UP )␊ |
1773 | ␉␉␉if( currentline > 0 )␊ |
1774 | ␉␉␉␉currentline--;␊ |
1775 | ␊ |
1776 | ␉␉if( key == KEY_DOWN )␊ |
1777 | ␉␉␉if( lines > ( currentline + visiblelines ) )␊ |
1778 | ␉␉␉␉currentline++;␊ |
1779 | ␊ |
1780 | ␉␉if( key == KEY_ESC || key == 'q' || key == 'Q')␊ |
1781 | ␉␉{␊ |
1782 | ␉␉␉gui.infobox.draw = false;␊ |
1783 | ␉␉␉gui.redraw = true;␊ |
1784 | ␉␉␉updateVRAM();␊ |
1785 | ␉␉␉break;␊ |
1786 | ␉␉}␊ |
1787 | ␊ |
1788 | ␉␉if(key == ' ') // spacebar = next page␊ |
1789 | ␉␉{␊ |
1790 | ␉␉␉if( lines > ( currentline + visiblelines ) ) ␊ |
1791 | ␉␉␉␉currentline += visiblelines;␊ |
1792 | ␉␉␉␊ |
1793 | ␉␉␉if(lines < (currentline + visiblelines))␊ |
1794 | ␉␉␉␉currentline = lines - visiblelines;␊ |
1795 | ␉␉}␊ |
1796 | ␉}␊ |
1797 | }␊ |
1798 | ␊ |
1799 | void animateProgressBar()␊ |
1800 | {␊ |
1801 | ␉int y;␊ |
1802 | ␉␊ |
1803 | ␉if( time18() > lasttime)␊ |
1804 | ␉{␊ |
1805 | ␉␉lasttime = time18();␊ |
1806 | ␊ |
1807 | ␉␉pixmap_t *buffBar = images[iProgressBar].image;␊ |
1808 | ␊ |
1809 | ␉␉uint32_t buff = buffBar->pixels[0].value;␊ |
1810 | ␉␊ |
1811 | ␉␉memcpy( buffBar->pixels, buffBar->pixels + 1, ( (buffBar->width*buffBar->height) - 1 ) * 4 );␊ |
1812 | ␊ |
1813 | ␉␉for( y = buffBar->height - 1; y > 0; y--)␊ |
1814 | ␉␉␉pixel(buffBar, buffBar->width - 1, y) = pixel(buffBar, buffBar->width - 1, y - 1);␊ |
1815 | ␊ |
1816 | ␉␉pixel(buffBar, buffBar->width-1, 0).value = buff;␊ |
1817 | ␉}␊ |
1818 | }␊ |
1819 | ␊ |
1820 | void drawProgressBar(pixmap_t *blendInto, uint16_t width, position_t p, uint8_t progress)␊ |
1821 | {␊ |
1822 | ␉if(progress>100)␊ |
1823 | ␉␉return;␊ |
1824 | ␉␊ |
1825 | ␉p.x = ( p.x - ( width / 2 ) );␊ |
1826 | ␊ |
1827 | ␉int todraw = (width * progress) / 100;␊ |
1828 | ␊ |
1829 | ␉pixmap_t *buff = images[iProgressBar].image;␊ |
1830 | ␉pixmap_t *buffBG = images[iProgressBarBackground].image;␊ |
1831 | ␉if(!buff || !buffBG)␊ |
1832 | ␉␉return;␊ |
1833 | ␉␊ |
1834 | ␉pixmap_t progressbar;␊ |
1835 | ␉progressbar.pixels=malloc(width * 4 * buff->height);␊ |
1836 | ␉if(!progressbar.pixels)␊ |
1837 | ␉␉return; ␊ |
1838 | ␉␊ |
1839 | ␉progressbar.width = width;␊ |
1840 | ␉progressbar.height = buff->height;␊ |
1841 | ␊ |
1842 | ␉int x=0,x2=0,y=0;␊ |
1843 | ␉␊ |
1844 | ␉for(y=0; y<buff->height; y++)␊ |
1845 | ␉{␊ |
1846 | ␉␉for(x=0; x<todraw; x++, x2++)␊ |
1847 | ␉␉{␊ |
1848 | ␉␉␉if(x2 == (buff->width-1)) x2=0;␊ |
1849 | ␉␉␉pixel(&progressbar, x,y).value = pixel(buff, x2,y).value;␊ |
1850 | ␉␉}␊ |
1851 | ␉␉x2=0;␊ |
1852 | ␉}␊ |
1853 | ␊ |
1854 | ␉for(y=0; y<buff->height; y++)␊ |
1855 | ␉{␊ |
1856 | ␉␉for(x=todraw, x2 = 0; x < width - 1; x++, x2++)␊ |
1857 | ␉␉{␊ |
1858 | ␉␉␉if(x2 == (buffBG->width -2 )) x2 = 0;␊ |
1859 | ␉␉␉pixel(&progressbar, x,y).value = pixel(buffBG, x2,y).value;␊ |
1860 | ␉␉}␊ |
1861 | ␉␉if(progress < 100)␊ |
1862 | ␉␉␉pixel(&progressbar, width - 1, y).value = pixel(buffBG, buffBG->width - 1, y).value;␊ |
1863 | ␉␉if(progress == 0)␊ |
1864 | ␉␉␉pixel(&progressbar, 0, y).value = pixel(buffBG, buffBG->width - 1, y).value;␊ |
1865 | ␉␉x2=0;␊ |
1866 | ␉}␊ |
1867 | ␊ |
1868 | ␉blend(&progressbar, blendInto, p);␊ |
1869 | ␉animateProgressBar();␊ |
1870 | ␉free(progressbar.pixels);␊ |
1871 | }␊ |
1872 | ␊ |
1873 | void drawInfoMenuItems()␊ |
1874 | {␊ |
1875 | ␉int i,n;␊ |
1876 | ␉␊ |
1877 | ␉position_t position;␊ |
1878 | ␉␊ |
1879 | ␉pixmap_t *selection = images[iMenuSelection].image;␊ |
1880 | ␉␊ |
1881 | ␉pixmap_t *pbuff;␊ |
1882 | ␊ |
1883 | ␉fillPixmapWithColor(gui.menu.pixmap, gui.menu.bgcolor);␊ |
1884 | ␊ |
1885 | ␉makeRoundedCorners(gui.menu.pixmap);␊ |
1886 | ␉␊ |
1887 | ␉uint8_t offset = infoMenuNativeBoot ? 0 : infoMenuItemsCount - 1;␊ |
1888 | ␊ |
1889 | ␉position = pos(0,0);␊ |
1890 | ␉␊ |
1891 | ␉for ( i = 0, n = iMenuBoot; i < infoMenuItemsCount; i++, n++)␊ |
1892 | ␉{␊ |
1893 | ␉␉if (i == infoMenuSelection)␊ |
1894 | ␉␉{␊ |
1895 | ␉␉␉blend(selection, gui.menu.pixmap, position);␊ |
1896 | ␉␉}␊ |
1897 | ␊ |
1898 | ␉␉pbuff = images[n].image;␊ |
1899 | ␉␉if (offset && i >= INFOMENU_NATIVEBOOT_START && i <= INFOMENU_NATIVEBOOT_END)␊ |
1900 | ␉␉{␊ |
1901 | ␉␉␉blend( images[n + (iMenuHelp - iMenuBoot)].image , gui.menu.pixmap, ␊ |
1902 | ␉␉␉␉pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));␊ |
1903 | ␉␉}␊ |
1904 | ␉␉else␊ |
1905 | ␉␉{␊ |
1906 | ␉␉␉blend( pbuff, gui.menu.pixmap, ␊ |
1907 | ␉␉␉␉pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));␊ |
1908 | ␉␉}␊ |
1909 | ␊ |
1910 | ␉␉drawStr(infoMenuItems[i].text, &font_console, gui.menu.pixmap, ␊ |
1911 | ␉␉␉pos(position.x + (pbuff->width + gui.menu.hborder), ␊ |
1912 | ␉␉␉␉position.y + ((selection->height - font_console.height) / 2)));␊ |
1913 | ␉␉position.y += images[iMenuSelection].image->height;␊ |
1914 | ␉␊ |
1915 | ␉}␊ |
1916 | ␉␊ |
1917 | ␉gui.redraw = true;␊ |
1918 | }␊ |
1919 | ␊ |
1920 | int drawInfoMenu()␊ |
1921 | {␊ |
1922 | ␉drawInfoMenuItems();␊ |
1923 | ␊ |
1924 | ␉gui.menu.draw = true;␊ |
1925 | ␊ |
1926 | ␉updateVRAM();␊ |
1927 | ␉␊ |
1928 | ␉return 1;␊ |
1929 | }␊ |
1930 | ␊ |
1931 | int updateInfoMenu(int key)␊ |
1932 | {␊ |
1933 | ␉switch (key)␊ |
1934 | ␉{␊ |
1935 | ␊ |
1936 | ␉␉case KEY_UP:␉// up arrow␊ |
1937 | ␉␉␉if (infoMenuSelection > 0)␊ |
1938 | ␉␉␉{␊ |
1939 | ␉␉␉␉if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_END + 1)␊ |
1940 | ␉␉␉␉{␊ |
1941 | ␉␉␉␉␉infoMenuSelection -= 4;␊ |
1942 | ␉␉␉␉}␊ |
1943 | ␉␉␉␉else␊ |
1944 | ␉␉␉␉{␊ |
1945 | ␉␉␉␉␉infoMenuSelection--;␊ |
1946 | ␉␉␉␉}␊ |
1947 | ␉␉␉␉drawInfoMenuItems();␊ |
1948 | ␉␉␉␉updateVRAM();␊ |
1949 | ␊ |
1950 | ␉␉␉}␊ |
1951 | ␉␉␉else␊ |
1952 | ␉␉␉{␊ |
1953 | ␊ |
1954 | ␉␉␉␉gui.menu.draw = false;␊ |
1955 | ␉␉␉␉gui.redraw = true;␊ |
1956 | ␊ |
1957 | ␉␉␉␉updateVRAM();␊ |
1958 | ␉␉␉␉␊ |
1959 | ␉␉␉␉return CLOSE_INFO_MENU;␊ |
1960 | ␉␉␉}␊ |
1961 | ␉␉␉break;␊ |
1962 | ␊ |
1963 | ␉␉case KEY_DOWN:␉// down arrow␊ |
1964 | ␉␉␉if (infoMenuSelection < infoMenuItemsCount - 1)␊ |
1965 | ␉␉␉{␊ |
1966 | ␉␉␉␉if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_START - 1)␊ |
1967 | ␉␉␉␉␉infoMenuSelection += 4;␊ |
1968 | ␉␉␉␉else␊ |
1969 | ␉␉␉␉␉infoMenuSelection++;␊ |
1970 | ␉␉␉␉drawInfoMenuItems();␊ |
1971 | ␉␉␉␉updateVRAM();␊ |
1972 | ␉␉␉}␊ |
1973 | ␉␉␉break;␊ |
1974 | ␊ |
1975 | ␉␉case KEY_ENTER:␊ |
1976 | ␉␉␉key = 0;␊ |
1977 | ␉␉␉if( infoMenuSelection == MENU_SHOW_MEMORY_INFO )␊ |
1978 | ␉␉␉␉showInfoBox( "Memory Info. Press q to quit.\n", getMemoryInfoString());␊ |
1979 | ␊ |
1980 | ␉␉␉else if( infoMenuSelection == MENU_SHOW_VIDEO_INFO )␊ |
1981 | ␉␉␉␉showInfoBox( getVBEInfoString(), getVBEModeInfoString() );␊ |
1982 | ␉␉␉␊ |
1983 | ␉␉␉else if( infoMenuSelection == MENU_SHOW_HELP )␊ |
1984 | ␉␉␉␉showHelp();␊ |
1985 | ␊ |
1986 | ␉␉␉else␊ |
1987 | ␉␉␉{␊ |
1988 | ␉␉␉␉int buff = infoMenuSelection;␊ |
1989 | ␉␉␉␉infoMenuSelection = 0;␊ |
1990 | ␉␉␉␉return buff;␊ |
1991 | ␉␉␉}␊ |
1992 | ␉␉␉break;␊ |
1993 | ␉}␊ |
1994 | ␉return DO_NOT_BOOT;␊ |
1995 | }␊ |
1996 | ␊ |
1997 | uint16_t bootImageWidth = 0; ␊ |
1998 | uint16_t bootImageHeight = 0; ␊ |
1999 | uint8_t *bootImageData = NULL; ␊ |
2000 | static bool usePngImage = true;␊ |
2001 | ␊ |
2002 | //==========================================================================␊ |
2003 | // loadBootGraphics␊ |
2004 | static void loadBootGraphics(void)␊ |
2005 | {␊ |
2006 | ␉if (bootImageData != NULL) {␊ |
2007 | ␉␉return;␊ |
2008 | ␉}␊ |
2009 | ␊ |
2010 | ␉char dirspec[256];␊ |
2011 | ␊ |
2012 | ␉if ((strlen(theme_name) + 24) > sizeof(dirspec)) {␊ |
2013 | ␉␉usePngImage = false; ␊ |
2014 | ␉␉return;␊ |
2015 | ␉}␊ |
2016 | ␉sprintf(dirspec, "/Extra/Themes/%s/boot.png", theme_name);␊ |
2017 | ␉if (loadPngImage(dirspec, &bootImageWidth, &bootImageHeight, &bootImageData) != 0) {␊ |
2018 | #ifdef CONFIG_EMBED_THEME␊ |
2019 | ␉if ((loadEmbeddedPngImage(__boot_png, __boot_png_len, &bootImageWidth, &bootImageHeight, &bootImageData)) != 0)␊ |
2020 | #endif␊ |
2021 | ␉␉usePngImage = false; ␊ |
2022 | ␉}␊ |
2023 | }␊ |
2024 | ␊ |
2025 | //==========================================================================␊ |
2026 | // drawBootGraphics␊ |
2027 | void drawBootGraphics(void)␊ |
2028 | {␊ |
2029 | ␉int pos;␊ |
2030 | ␉int length;␊ |
2031 | ␉const char *dummyVal;␊ |
2032 | ␉int oldScreenWidth, oldScreenHeight;␊ |
2033 | ␉bool legacy_logo;␊ |
2034 | ␉uint16_t x, y; ␊ |
2035 | ␉␊ |
2036 | ␉if (getBoolForKey("Legacy Logo", &legacy_logo, &bootInfo->chameleonConfig) && legacy_logo) {␊ |
2037 | ␉␉usePngImage = false; ␊ |
2038 | ␉} else if (bootImageData == NULL) {␊ |
2039 | ␉␉loadBootGraphics();␊ |
2040 | ␉}␊ |
2041 | ␊ |
2042 | ␉// parse screen size parameters␊ |
2043 | ␉if (getIntForKey("boot_width", &pos, &bootInfo->themeConfig) && pos > 0) {␊ |
2044 | ␉␉screen_params[0] = pos;␊ |
2045 | ␉} else {␊ |
2046 | ␉␉screen_params[0] = DEFAULT_SCREEN_WIDTH;␊ |
2047 | ␉}␊ |
2048 | ␉if (getIntForKey("boot_height", &pos, &bootInfo->themeConfig) && pos > 0) {␊ |
2049 | ␉␉screen_params[1] = pos;␊ |
2050 | ␉} else {␊ |
2051 | ␉␉screen_params[1] = DEFAULT_SCREEN_HEIGHT;␊ |
2052 | ␉}␊ |
2053 | ␊ |
2054 | // Save current screen resolution.␊ |
2055 | ␉oldScreenWidth = gui.screen.width;␊ |
2056 | ␉oldScreenHeight = gui.screen.height;␊ |
2057 | ␊ |
2058 | ␉gui.screen.width = screen_params[0];␊ |
2059 | ␉gui.screen.height = screen_params[1];␊ |
2060 | ␊ |
2061 | ␉// find best matching vesa mode for our requested width & height␊ |
2062 | ␉getGraphicModeParams(screen_params);␊ |
2063 | ␊ |
2064 | // Set graphics mode if the booter was in text mode or the screen resolution has changed.␊ |
2065 | ␉if (bootArgs->Video.v_display == VGA_TEXT_MODE␊ |
2066 | ␉␉|| (screen_params[0] != oldScreenWidth && screen_params[1] != oldScreenHeight) )␊ |
2067 | ␉{␊ |
2068 | ␉␉setVideoMode(GRAPHICS_MODE, 0);␊ |
2069 | ␉}␊ |
2070 | ␊ |
2071 | ␉if (getValueForKey("-checkers", &dummyVal, &length, &bootInfo->chameleonConfig)) {␊ |
2072 | ␉␉drawCheckerBoard();␊ |
2073 | ␉} else {␊ |
2074 | ␉␉// Fill the background to 75% grey (same as BootX). ␊ |
2075 | ␉␉drawColorRectangle(0, 0, screen_params[0], screen_params[1], 0x01); ␊ |
2076 | ␉}␊ |
2077 | ␉if ((bootImageData) && (usePngImage)) { ␊ |
2078 | ␉␉x = (screen_params[0] - MIN(bootImageWidth, screen_params[0])) / 2; ␊ |
2079 | ␉␉y = (screen_params[1] - MIN(bootImageHeight, screen_params[1])) / 2; ␊ |
2080 | ␊ |
2081 | ␉␉// Draw the image in the center of the display. ␊ |
2082 | ␉␉blendImage(x, y, bootImageWidth, bootImageHeight, bootImageData); ␊ |
2083 | ␉} else { ␊ |
2084 | ␉␉uint8_t *appleBootPict; ␊ |
2085 | ␉␉bootImageData = NULL; ␊ |
2086 | ␉␉bootImageWidth = kAppleBootWidth; ␊ |
2087 | ␉␉bootImageHeight = kAppleBootHeight; ␊ |
2088 | ␊ |
2089 | ␉␉// Prepare the data for the default Apple boot image. ␊ |
2090 | ␉␉appleBootPict = (uint8_t *) decodeRLE(gAppleBootPictRLE, kAppleBootRLEBlocks, bootImageWidth * bootImageHeight); ␊ |
2091 | ␉␉if (appleBootPict) { ␊ |
2092 | ␉␉␉convertImage(bootImageWidth, bootImageHeight, appleBootPict, &bootImageData); ␊ |
2093 | ␉␉␉if (bootImageData) {␉␊ |
2094 | ␉␉␉␉x = (screen_params[0] - MIN(kAppleBootWidth, screen_params[0])) / 2; ␊ |
2095 | ␉␉␉␉y = (screen_params[1] - MIN(kAppleBootHeight, screen_params[1])) / 2; ␊ |
2096 | ␉␉␉␉drawDataRectangle(x, y, kAppleBootWidth, kAppleBootHeight, bootImageData);␊ |
2097 | ␉␉␉␉free(bootImageData);␊ |
2098 | ␉␉␉}␊ |
2099 | ␉␉␉free(appleBootPict); ␊ |
2100 | ␉␉} ␊ |
2101 | ␉} ␊ |
2102 | }␊ |
2103 |