Root/
Source at commit 214 created 13 years 5 months ago. By ifabio, update to chameleon trunk 630, and now the pakage folder is the same as blackosx branch, also add Icon "building" into buildpkg script, and add mint theme info into the English localizable.strings. | |
---|---|
1 | /*␊ |
2 | * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * @APPLE_LICENSE_HEADER_START@␊ |
5 | * ␊ |
6 | * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights␊ |
7 | * Reserved. This file contains Original Code and/or Modifications of␊ |
8 | * Original Code as defined in and that are subject to the Apple Public␊ |
9 | * Source License Version 2.0 (the "License"). You may not use this file␊ |
10 | * except in compliance with the License. Please obtain a copy of the␊ |
11 | * License at http://www.apple.com/publicsource and read it before using␊ |
12 | * this file.␊ |
13 | * ␊ |
14 | * The Original Code and all software distributed under the License are␊ |
15 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the␊ |
19 | * License for the specific language governing rights and limitations␊ |
20 | * under the License.␊ |
21 | * ␊ |
22 | * @APPLE_LICENSE_HEADER_END@␊ |
23 | */␊ |
24 | /*␊ |
25 | * Copyright 1993 NeXT, Inc.␊ |
26 | * All rights reserved.␊ |
27 | */␊ |
28 | ␊ |
29 | #include "boot.h"␊ |
30 | #include "vbe.h"␊ |
31 | #include "appleClut8.h"␊ |
32 | #include "gui.h"␊ |
33 | #include "IOHibernatePrivate.h"␊ |
34 | ␊ |
35 | /*␊ |
36 | * for spinning disk␊ |
37 | */␊ |
38 | static int currentIndicator = 0;␊ |
39 | ␊ |
40 | int previewTotalSectors = 0;␊ |
41 | int previewLoadedSectors = 0;␊ |
42 | uint8_t *previewSaveunder = 0;␊ |
43 | ␊ |
44 | #define VIDEO(x) (bootArgs->Video.v_ ## x)␊ |
45 | ␊ |
46 | #define MIN(x, y) ((x) < (y) ? (x) : (y))␊ |
47 | ␊ |
48 | //==========================================================================␊ |
49 | // getVBEInfoString␊ |
50 | ␊ |
51 | char *getVBEInfoString()␊ |
52 | {␊ |
53 | ␉VBEInfoBlock vbeInfo;␊ |
54 | ␉int err, small;␊ |
55 | ␉char *buff = malloc(sizeof(char)*256);␊ |
56 | ␉if(!buff) return 0;␊ |
57 | ␉␊ |
58 | ␉bzero( &vbeInfo, sizeof(vbeInfo) );␊ |
59 | ␉strcpy( (char*)&vbeInfo, "VBE2" );␊ |
60 | ␉err = getVBEInfo( &vbeInfo );␊ |
61 | ␉if (err != errSuccess)␊ |
62 | ␉␉return 0;␊ |
63 | ␉␊ |
64 | ␉if ( strncmp( (char *)vbeInfo.VESASignature, "VESA", 4 ) )␊ |
65 | ␉␉return 0;␊ |
66 | ␉␊ |
67 | ␉small = (vbeInfo.TotalMemory < 16);␊ |
68 | ␉␊ |
69 | ␉sprintf(buff, "VESA v%d.%d %d%s (%s)\n",␊ |
70 | vbeInfo.VESAVersion >> 8,␊ |
71 | vbeInfo.VESAVersion & 0xf,␊ |
72 | small ? (vbeInfo.TotalMemory * 64) : (vbeInfo.TotalMemory / 16),␊ |
73 | small ? "KB" : "MB",␊ |
74 | VBEDecodeFP(const char *, vbeInfo.OEMStringPtr) );␊ |
75 | ␊ |
76 | ␉return buff;␊ |
77 | }␊ |
78 | ␊ |
79 | //==========================================================================␊ |
80 | //␊ |
81 | ␊ |
82 | void ␊ |
83 | printVBEModeInfo()␊ |
84 | {␊ |
85 | VBEInfoBlock vbeInfo;␊ |
86 | unsigned short * modePtr;␊ |
87 | VBEModeInfoBlock modeInfo;␊ |
88 | int err;␊ |
89 | int line;␊ |
90 | ␊ |
91 | ␉bzero( &vbeInfo, sizeof(vbeInfo) );␊ |
92 | strcpy( (char*)&vbeInfo, "VBE2" );␊ |
93 | err = getVBEInfo( &vbeInfo );␊ |
94 | if ( err != errSuccess )␊ |
95 | return;␊ |
96 | ␊ |
97 | line = 0;␊ |
98 | ␊ |
99 | // Activate and clear page 1␊ |
100 | setActiveDisplayPage(1);␊ |
101 | clearScreenRows(0, 24);␊ |
102 | setCursorPosition( 0, 0, 1 );␊ |
103 | ␊ |
104 | printf( getVBEInfoString() );␊ |
105 | ␉printf("Video modes supported:\n", VBEDecodeFP(const char *, vbeInfo.OEMStringPtr));␊ |
106 | ␊ |
107 | // Loop through the mode list, and find the matching mode.␊ |
108 | ␊ |
109 | for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );␊ |
110 | *modePtr != modeEndOfList; modePtr++ )␊ |
111 | {␊ |
112 | // Get mode information.␊ |
113 | ␊ |
114 | bzero( &modeInfo, sizeof(modeInfo) );␊ |
115 | err = getVBEModeInfo( *modePtr, &modeInfo );␊ |
116 | if ( err != errSuccess )␊ |
117 | {␊ |
118 | continue;␊ |
119 | }␊ |
120 | ␊ |
121 | printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",␊ |
122 | *modePtr, modeInfo.XResolution, modeInfo.YResolution,␊ |
123 | modeInfo.BitsPerPixel, modeInfo.MemoryModel,␊ |
124 | modeInfo.ModeAttributes);␊ |
125 | ␊ |
126 | if (line++ >= 20) {␊ |
127 | pause();␊ |
128 | line = 0;␊ |
129 | clearScreenRows(0, 24);␊ |
130 | setCursorPosition( 0, 0, 1 );␊ |
131 | }␊ |
132 | } ␊ |
133 | if (line != 0) {␊ |
134 | pause();␊ |
135 | }␊ |
136 | setActiveDisplayPage(0);␊ |
137 | }␊ |
138 | ␊ |
139 | char *getVBEModeInfoString()␊ |
140 | {␊ |
141 | ␉VBEInfoBlock vbeInfo;␊ |
142 | unsigned short * modePtr;␊ |
143 | VBEModeInfoBlock modeInfo;␊ |
144 | int err;␊ |
145 | ␊ |
146 | ␉bzero( &vbeInfo, sizeof(vbeInfo) );␊ |
147 | strcpy( (char*)&vbeInfo, "VBE2" );␊ |
148 | err = getVBEInfo( &vbeInfo );␊ |
149 | if ( err != errSuccess )␊ |
150 | return 0;␊ |
151 | ␉␊ |
152 | ␉char *buff=malloc(sizeof(char)*3072);␊ |
153 | ␉if(!buff) return 0;␊ |
154 | ␊ |
155 | ␉// Loop through the mode list, and find the matching mode.␊ |
156 | for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );␊ |
157 | *modePtr != modeEndOfList; modePtr++ )␊ |
158 | {␊ |
159 | // Get mode information.␊ |
160 | ␊ |
161 | bzero( &modeInfo, sizeof(modeInfo) );␊ |
162 | err = getVBEModeInfo( *modePtr, &modeInfo );␊ |
163 | if ( err != errSuccess )␊ |
164 | {␊ |
165 | continue;␊ |
166 | }␊ |
167 | ␊ |
168 | sprintf(buff+strlen(buff), "Mode %x: %dx%dx%d mm:%d attr:%x\n",␊ |
169 | *modePtr, modeInfo.XResolution, modeInfo.YResolution,␊ |
170 | modeInfo.BitsPerPixel, modeInfo.MemoryModel,␊ |
171 | modeInfo.ModeAttributes);␊ |
172 | ␊ |
173 | } ␊ |
174 | ␉return buff;␊ |
175 | }␊ |
176 | ␊ |
177 | //==========================================================================␊ |
178 | // getVESAModeWithProperties␊ |
179 | //␊ |
180 | // Return the VESA mode that matches the properties specified.␊ |
181 | // If a mode is not found, then return the "best" available mode.␊ |
182 | ␊ |
183 | static unsigned short␊ |
184 | getVESAModeWithProperties( unsigned short width,␊ |
185 | unsigned short height,␊ |
186 | unsigned char bitsPerPixel,␊ |
187 | unsigned short attributesSet,␊ |
188 | unsigned short attributesClear,␊ |
189 | VBEModeInfoBlock * outModeInfo,␊ |
190 | unsigned short * vesaVersion )␊ |
191 | {␊ |
192 | VBEInfoBlock vbeInfo;␊ |
193 | unsigned short * modePtr;␊ |
194 | VBEModeInfoBlock modeInfo;␊ |
195 | unsigned char modeBitsPerPixel;␊ |
196 | unsigned short matchedMode = modeEndOfList;␊ |
197 | int err;␊ |
198 | ␊ |
199 | // Clear output mode info.␊ |
200 | ␊ |
201 | bzero( outModeInfo, sizeof(*outModeInfo) );␊ |
202 | ␊ |
203 | // Get VBE controller info containing the list of supported modes.␊ |
204 | ␊ |
205 | bzero( &vbeInfo, sizeof(vbeInfo) );␊ |
206 | strcpy( (char*)&vbeInfo, "VBE2" );␊ |
207 | err = getVBEInfo( &vbeInfo );␊ |
208 | if ( err != errSuccess )␊ |
209 | {␊ |
210 | return modeEndOfList;␊ |
211 | }␊ |
212 | ␊ |
213 | // Report the VESA major/minor version number.␊ |
214 | ␊ |
215 | if (vesaVersion) *vesaVersion = vbeInfo.VESAVersion;␊ |
216 | ␊ |
217 | // Loop through the mode list, and find the matching mode.␊ |
218 | ␊ |
219 | for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );␊ |
220 | *modePtr != modeEndOfList; modePtr++ )␊ |
221 | {␊ |
222 | // Get mode information.␊ |
223 | ␊ |
224 | bzero( &modeInfo, sizeof(modeInfo) );␊ |
225 | err = getVBEModeInfo( *modePtr, &modeInfo );␊ |
226 | if ( err != errSuccess )␊ |
227 | {␊ |
228 | continue;␊ |
229 | }␊ |
230 | ␊ |
231 | #if DEBUG␊ |
232 | printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",␊ |
233 | *modePtr, modeInfo.XResolution, modeInfo.YResolution,␊ |
234 | modeInfo.BitsPerPixel, modeInfo.MemoryModel,␊ |
235 | modeInfo.ModeAttributes);␊ |
236 | #endif␊ |
237 | ␊ |
238 | // Filter out unwanted modes based on mode attributes.␊ |
239 | ␊ |
240 | if ( ( ( modeInfo.ModeAttributes & attributesSet ) != attributesSet )␊ |
241 | || ( ( modeInfo.ModeAttributes & attributesClear ) != 0 ) )␊ |
242 | {␊ |
243 | continue;␊ |
244 | }␊ |
245 | ␊ |
246 | // Pixel depth in bits.␊ |
247 | ␊ |
248 | modeBitsPerPixel = modeInfo.BitsPerPixel;␊ |
249 | ␊ |
250 | if ( ( modeBitsPerPixel == 4 ) && ( modeInfo.MemoryModel == 0 ) )␊ |
251 | {␊ |
252 | // Text mode, 16 colors.␊ |
253 | }␊ |
254 | else if ( ( modeBitsPerPixel == 8 ) && ( modeInfo.MemoryModel == 4 ) )␊ |
255 | {␊ |
256 | // Packed pixel, 256 colors.␊ |
257 | }␊ |
258 | else if ( ( ( modeBitsPerPixel == 16 ) || ( modeBitsPerPixel == 15 ) )␊ |
259 | && ( modeInfo.MemoryModel == 6 )␊ |
260 | && ( modeInfo.RedMaskSize == 5 )␊ |
261 | && ( modeInfo.GreenMaskSize == 5 )␊ |
262 | && ( modeInfo.BlueMaskSize == 5 ) )␊ |
263 | {␊ |
264 | // Direct color, 16 bpp (1:5:5:5).␊ |
265 | modeInfo.BitsPerPixel = modeBitsPerPixel = 16;␊ |
266 | }␊ |
267 | else if ( ( modeBitsPerPixel == 32 )␊ |
268 | && ( modeInfo.MemoryModel == 6 )␊ |
269 | && ( modeInfo.RedMaskSize == 8 )␊ |
270 | && ( modeInfo.GreenMaskSize == 8 )␊ |
271 | && ( modeInfo.BlueMaskSize == 8 ) )␊ |
272 | {␊ |
273 | // Direct color, 32 bpp (8:8:8:8).␊ |
274 | }␊ |
275 | else␊ |
276 | {␊ |
277 | continue; // Not a supported mode.␊ |
278 | }␊ |
279 | ␊ |
280 | // Modes larger than the specified dimensions are skipped.␊ |
281 | ␊ |
282 | if ( ( modeInfo.XResolution > width ) ||␊ |
283 | ( modeInfo.YResolution > height ) )␊ |
284 | {␊ |
285 | continue;␊ |
286 | }␊ |
287 | ␊ |
288 | // Perfect match, we're done looking.␊ |
289 | ␊ |
290 | if ( ( modeInfo.XResolution == width ) &&␊ |
291 | ( modeInfo.YResolution == height ) &&␊ |
292 | ( modeBitsPerPixel == bitsPerPixel ) )␊ |
293 | {␊ |
294 | matchedMode = *modePtr;␊ |
295 | bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );␊ |
296 | break;␊ |
297 | }␊ |
298 | ␊ |
299 | // Save the next "best" mode in case a perfect match is not found.␊ |
300 | ␊ |
301 | if ( modeInfo.XResolution == outModeInfo->XResolution &&␊ |
302 | modeInfo.YResolution == outModeInfo->YResolution &&␊ |
303 | modeBitsPerPixel <= outModeInfo->BitsPerPixel )␊ |
304 | {␊ |
305 | continue; // Saved mode has more depth.␊ |
306 | }␊ |
307 | if ( modeInfo.XResolution < outModeInfo->XResolution ||␊ |
308 | modeInfo.YResolution < outModeInfo->YResolution ||␊ |
309 | modeBitsPerPixel < outModeInfo->BitsPerPixel )␊ |
310 | {␊ |
311 | continue; // Saved mode has more resolution.␊ |
312 | }␊ |
313 | ␊ |
314 | matchedMode = *modePtr;␊ |
315 | bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );␊ |
316 | }␊ |
317 | ␊ |
318 | return matchedMode;␊ |
319 | }␊ |
320 | ␊ |
321 | //==========================================================================␊ |
322 | // setupPalette␊ |
323 | ␊ |
324 | static void setupPalette( VBEPalette * p, const unsigned char * g )␊ |
325 | {␊ |
326 | int i;␊ |
327 | unsigned char * source = (unsigned char *) g;␊ |
328 | ␊ |
329 | for (i = 0; i < 256; i++)␊ |
330 | {␊ |
331 | (*p)[i] = 0;␊ |
332 | (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 16; // Red␊ |
333 | (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 8; // Green␊ |
334 | (*p)[i] |= ((unsigned long)((*source++) >> 2)); // Blue␊ |
335 | }␊ |
336 | }␊ |
337 | ␊ |
338 | //==========================================================================␊ |
339 | // Simple decompressor for boot images encoded in RLE format.␊ |
340 | ␊ |
341 | char * decodeRLE( const void * rleData, int rleBlocks, int outBytes )␊ |
342 | {␊ |
343 | char *out, *cp;␊ |
344 | ␊ |
345 | struct RLEBlock {␊ |
346 | unsigned char count;␊ |
347 | unsigned char value;␊ |
348 | } * bp = (struct RLEBlock *) rleData;␊ |
349 | ␊ |
350 | out = cp = malloc( outBytes );␊ |
351 | if ( out == NULL ) return NULL;␊ |
352 | ␊ |
353 | while ( rleBlocks-- )␊ |
354 | {␊ |
355 | memset( cp, bp->value, bp->count );␊ |
356 | cp += bp->count;␊ |
357 | bp++;␊ |
358 | }␊ |
359 | ␊ |
360 | return out;␊ |
361 | }␊ |
362 | ␊ |
363 | //==========================================================================␊ |
364 | // setVESAGraphicsMode␊ |
365 | ␊ |
366 | static int␊ |
367 | setVESAGraphicsMode( unsigned short width,␊ |
368 | unsigned short height,␊ |
369 | unsigned char bitsPerPixel,␊ |
370 | unsigned short refreshRate )␊ |
371 | {␊ |
372 | VBEModeInfoBlock minfo;␊ |
373 | unsigned short mode;␊ |
374 | unsigned short vesaVersion;␊ |
375 | int err = errFuncNotSupported;␊ |
376 | ␊ |
377 | do {␊ |
378 | mode = getVESAModeWithProperties( width, height, bitsPerPixel,␊ |
379 | maColorModeBit |␊ |
380 | maModeIsSupportedBit |␊ |
381 | maGraphicsModeBit |␊ |
382 | maLinearFrameBufferAvailBit,␊ |
383 | 0,␊ |
384 | &minfo, &vesaVersion );␊ |
385 | if ( mode == modeEndOfList )␊ |
386 | {␊ |
387 | break;␊ |
388 | }␊ |
389 | ␊ |
390 | //␊ |
391 | // FIXME : generateCRTCTiming() causes crash.␊ |
392 | //␊ |
393 | ␊ |
394 | // if ( (vesaVersion >> 8) >= 3 && refreshRate >= 60 &&␊ |
395 | // (gBootMode & kBootModeSafe) == 0 )␊ |
396 | // {␊ |
397 | // VBECRTCInfoBlock timing;␊ |
398 | // ␊ |
399 | // // Generate CRTC timing for given refresh rate.␊ |
400 | // ␊ |
401 | // generateCRTCTiming( minfo.XResolution, minfo.YResolution,␊ |
402 | // refreshRate, kCRTCParamRefreshRate,␊ |
403 | // &timing );␊ |
404 | // ␊ |
405 | // // Find the actual pixel clock supported by the hardware.␊ |
406 | // ␊ |
407 | // getVBEPixelClock( mode, &timing.PixelClock );␊ |
408 | // ␊ |
409 | // // Re-compute CRTC timing based on actual pixel clock.␊ |
410 | // ␊ |
411 | // generateCRTCTiming( minfo.XResolution, minfo.YResolution,␊ |
412 | // timing.PixelClock, kCRTCParamPixelClock,␊ |
413 | // &timing );␊ |
414 | // ␊ |
415 | // // Set the video mode and use specified CRTC timing.␊ |
416 | // ␊ |
417 | // err = setVBEMode( mode | kLinearFrameBufferBit |␊ |
418 | // kCustomRefreshRateBit, &timing );␊ |
419 | // }␊ |
420 | // else␊ |
421 | // {␊ |
422 | // // Set the mode with default refresh rate.␊ |
423 | // ␊ |
424 | // err = setVBEMode( mode | kLinearFrameBufferBit, NULL );␊ |
425 | // }␊ |
426 | ␊ |
427 | // Set the mode with default refresh rate.␊ |
428 | ␊ |
429 | err = setVBEMode( mode | kLinearFrameBufferBit, NULL );␊ |
430 | ␊ |
431 | if ( err != errSuccess )␊ |
432 | {␊ |
433 | break;␊ |
434 | }␊ |
435 | ␊ |
436 | // Set 8-bit color palette.␊ |
437 | ␊ |
438 | if ( minfo.BitsPerPixel == 8 )␊ |
439 | {␊ |
440 | VBEPalette palette;␊ |
441 | setupPalette( &palette, appleClut8 );␊ |
442 | if ((err = setVBEPalette(palette)) != errSuccess)␊ |
443 | {␊ |
444 | break;␊ |
445 | }␊ |
446 | }␊ |
447 | ␊ |
448 | // Is this required for buggy Video BIOS implementations?␊ |
449 | // On which adapter?␊ |
450 | ␊ |
451 | if ( minfo.BytesPerScanline == 0 )␊ |
452 | minfo.BytesPerScanline = ( minfo.XResolution *␊ |
453 | minfo.BitsPerPixel ) >> 3;␊ |
454 | ␊ |
455 | // Update KernBootStruct using info provided by the selected␊ |
456 | // VESA mode.␊ |
457 | ␊ |
458 | bootArgs->Video.v_display = GRAPHICS_MODE;␊ |
459 | bootArgs->Video.v_width = minfo.XResolution;␊ |
460 | bootArgs->Video.v_height = minfo.YResolution;␊ |
461 | bootArgs->Video.v_depth = minfo.BitsPerPixel;␊ |
462 | bootArgs->Video.v_rowBytes = minfo.BytesPerScanline;␊ |
463 | bootArgs->Video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);␊ |
464 | ␊ |
465 | }␊ |
466 | while ( 0 );␊ |
467 | ␊ |
468 | return err;␊ |
469 | }␊ |
470 | ␊ |
471 | int␊ |
472 | convertImage( unsigned short width,␊ |
473 | unsigned short height,␊ |
474 | const unsigned char *imageData,␊ |
475 | unsigned char **newImageData )␊ |
476 | {␊ |
477 | int cnt;␊ |
478 | unsigned char *img = 0;␊ |
479 | unsigned short *img16;␊ |
480 | unsigned long *img32;␊ |
481 | ␊ |
482 | switch ( VIDEO(depth) ) {␊ |
483 | case 16 :␊ |
484 | img16 = malloc(width * height * 2);␊ |
485 | if ( !img16 ) break;␊ |
486 | for (cnt = 0; cnt < (width * height); cnt++)␊ |
487 | img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16);␊ |
488 | img = (unsigned char *)img16;␊ |
489 | break;␊ |
490 | ␊ |
491 | case 32 :␊ |
492 | img32 = malloc(width * height * 4);␊ |
493 | if ( !img32 ) break;␊ |
494 | for (cnt = 0; cnt < (width * height); cnt++)␊ |
495 | img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32);␊ |
496 | img = (unsigned char *)img32;␊ |
497 | break;␊ |
498 | ␊ |
499 | default :␊ |
500 | img = malloc(width * height);␊ |
501 | bcopy(imageData, img, width * height);␊ |
502 | break;␊ |
503 | }␊ |
504 | *newImageData = img;␊ |
505 | return 0;␊ |
506 | }␊ |
507 | ␊ |
508 | int loadPngImage(const char *filename, uint16_t *width, uint16_t *height,␊ |
509 | uint8_t **imageData)␊ |
510 | {␊ |
511 | uint8_t *pngData = NULL;␊ |
512 | int pngFile = 0, pngSize;␊ |
513 | PNG_info_t *info;␊ |
514 | int error = 0;␊ |
515 | ␊ |
516 | pngFile = open_bvdev("bt(0,0)", filename, 0);␊ |
517 | if (pngFile == -1) {␊ |
518 | error = -1;␊ |
519 | goto failed;␊ |
520 | }␊ |
521 | pngSize = file_size(pngFile);␊ |
522 | if (!pngSize) {␊ |
523 | error = -1;␊ |
524 | goto failed;␊ |
525 | }␊ |
526 | pngData = malloc(pngSize);␊ |
527 | if (read(pngFile, (char *) pngData, pngSize) != pngSize) {␊ |
528 | error = -1;␊ |
529 | goto failed;␊ |
530 | }␊ |
531 | ␊ |
532 | PNG_error = -1;␊ |
533 | info = PNG_decode(pngData, pngSize);␊ |
534 | if (PNG_error != 0) {␊ |
535 | error = PNG_error;␊ |
536 | goto failed;␊ |
537 | } else if ((info->width > 0xffff) || (info->height > 0xffff)) {␊ |
538 | error = -1;␊ |
539 | goto failed;␊ |
540 | } else if ((info->width * info->height * 4) != info->image->size) {␊ |
541 | error = -1;␊ |
542 | goto failed;␊ |
543 | }␊ |
544 | ␉uint8_t *result = malloc(info->width*4*info->height);␊ |
545 | *width = info->width;␊ |
546 | *height = info->height;␊ |
547 | ␉memcpy(result, info->image->data, info->width*4*info->height);␊ |
548 | ␉*imageData = result;␊ |
549 | ␊ |
550 | failed:␊ |
551 | ␉png_alloc_free_all();␊ |
552 | if (pngData)␊ |
553 | free(pngData);␊ |
554 | if (pngFile != -1)␊ |
555 | close(pngFile);␊ |
556 | ␊ |
557 | return error;␊ |
558 | }␊ |
559 | ␊ |
560 | int loadEmbeddedPngImage(uint8_t *pngData, int pngSize, uint16_t *width, uint16_t *height, uint8_t **imageData) {␊ |
561 | PNG_info_t *info;␊ |
562 | int error = 0;␊ |
563 | ␉␊ |
564 | PNG_error = -1;␊ |
565 | info = PNG_decode(pngData, pngSize);␊ |
566 | ␉if (PNG_error != 0) {␊ |
567 | error = PNG_error;␊ |
568 | goto failed;␊ |
569 | } else if ((info->width > 0xffff) || (info->height > 0xffff)) {␊ |
570 | error = -1;␊ |
571 | goto failed;␊ |
572 | } else if ((info->width * info->height * 4) != info->image->size) {␊ |
573 | error = -1;␊ |
574 | goto failed;␊ |
575 | }␊ |
576 | ␉uint8_t *result = malloc(info->width*4*info->height);␊ |
577 | ␉*width = info->width;␊ |
578 | *height = info->height;␊ |
579 | ␉memcpy(result, info->image->data, info->width*4*info->height);␊ |
580 | ␉*imageData = result;␊ |
581 | ␊ |
582 | failed:␊ |
583 | ␉png_alloc_free_all();␊ |
584 | ␊ |
585 | return error;␊ |
586 | }␊ |
587 | ␊ |
588 | void blendImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height,␊ |
589 | uint8_t *data)␊ |
590 | {␊ |
591 | uint16_t drawWidth;␊ |
592 | uint8_t *vram = (uint8_t *) VIDEO(baseAddr) + VIDEO(rowBytes) * y + 4 * x;␊ |
593 | ␊ |
594 | drawWidth = MIN(width, VIDEO(width) - x);␊ |
595 | height = MIN(height, VIDEO(height) - y);␊ |
596 | while (height--) {␊ |
597 | ␉␉switch (VIDEO (depth))␊ |
598 | ␉␉{␊ |
599 | ␉␉␉case 32: /* Optimized version*/␊ |
600 | ␉␉␉{␊ |
601 | ␉␉␉␉uint32_t s; uint32_t* d; // Source (img) and destination (bkgd) pixels␊ |
602 | ␉␉␉␉uint32_t a; // Alpha␊ |
603 | ␉␉␉␉uint32_t dstrb, dstg, srcrb, srcg, drb, dg, rb, g, tempB; // Intermediate variables␊ |
604 | ␉␉␉␉uint16_t pos;␊ |
605 | ␉␉␉␉␊ |
606 | ␉␉␉␉for (pos = 0; pos < drawWidth * 4; pos += 4) {␊ |
607 | ␉␉␉␉␉// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html␊ |
608 | ␉␉␉␉␉s = *((uint32_t*) (data + pos));␊ |
609 | ␉␉␉␉␉d = (uint32_t*) (vram + pos);␊ |
610 | ␊ |
611 | ␉␉␉␉␉// Flip B and R in source␊ |
612 | ␉␉␉␉␉// TODO: use XCHG and inline assembly to do this in a faster, saner way␊ |
613 | ␉␉␉␉␉tempB = (s & 0xFF0000); // save B␊ |
614 | ␉␉␉␉␉s = (s & 0xFF00FFFF) | ((s & 0xFF) << 16); // put R in B␊ |
615 | ␉␉␉␉␉s = (s & 0xFFFFFF00) | (tempB >> 16); // put B in R␊ |
616 | ␊ |
617 | ␉␉␉␉␉a = (s >> 24) + 1;␊ |
618 | ␊ |
619 | ␉␉␉␉␉dstrb = *d & 0xFF00FF; dstg = *d & 0xFF00;␊ |
620 | ␉␉␉␉␉srcrb = s & 0xFF00FF; srcg = s & 0xFF00;␊ |
621 | ␊ |
622 | ␉␉␉␉␉drb = srcrb - dstrb;␊ |
623 | ␉␉␉␉␉dg = srcg - dstg;␊ |
624 | ␉␉␉␉␉drb *= a; dg *= a;␊ |
625 | ␉␉␉␉␉drb >>= 8; dg >>= 8;␊ |
626 | ␊ |
627 | ␉␉␉␉␉rb = (drb + dstrb) & 0xFF00FF;␊ |
628 | ␉␉␉␉␉g = (dg + dstg) & 0xFF00;␊ |
629 | ␊ |
630 | ␉␉␉␉␉*d = rb | g;␊ |
631 | ␉␉␉␉}␊ |
632 | ␉␉␉}␊ |
633 | ␉␉␉break;␊ |
634 | ␉␉␉␉␊ |
635 | ␉␉␉default: /*Universal version*/␊ |
636 | ␉␉␉{␊ |
637 | ␉␉␉␉uint32_t s; ␊ |
638 | ␉␉␉␉uint32_t a; // Alpha␊ |
639 | ␉␉␉␉uint32_t dr, dg, db, sr, sg, sb; // Intermediate variables␊ |
640 | ␉␉␉␉uint16_t pos;␊ |
641 | ␉␉␉␉int bpp = (VIDEO (depth) + 7)/8;␊ |
642 | ␉␉␉␉␊ |
643 | ␉␉␉␉for (pos = 0; pos < drawWidth; pos ++) {␊ |
644 | ␉␉␉␉␉// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html␊ |
645 | ␉␉␉␉␉s = *((uint32_t*) (data + 4*pos));␊ |
646 | ␉␉␉␉␉␊ |
647 | ␉␉␉␉␉sb = (s & 0xFF0000) >> 16;␊ |
648 | ␉␉␉␉␉sg = (s & 0xFF00) >> 8;␊ |
649 | ␉␉␉␉␉sr = (s & 0xFF);␊ |
650 | ␉␉␉␉␉␊ |
651 | ␉␉␉␉␉a = (s >> 24) + 1;␊ |
652 | ␉␉␉␉␉␊ |
653 | ␉␉␉␉␉switch (VIDEO (depth))␊ |
654 | ␉␉␉␉␉{␊ |
655 | ␉␉␉␉␉␉case 24:␊ |
656 | ␉␉␉␉␉␉␉db = ((*(uint32_t *)(vram + bpp*pos))&0xff);␊ |
657 | ␉␉␉␉␉␉␉dg = ((*(uint32_t *)(vram + bpp*pos))&0xff00)>>8;␊ |
658 | ␉␉␉␉␉␉␉dr = ((*(uint32_t *)(vram + bpp*pos))&0xff0000)>>16;␊ |
659 | ␉␉␉␉␉␉␉break;␊ |
660 | ␉␉␉␉␉␉case 16://16-bit seems to be 15-bit␊ |
661 | /*␉␉␉␉␉␉␉db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;␊ |
662 | ␉␉␉␉␉␉␉dg = ((*(uint16_t *)(vram + bpp*pos))&0x07e0)>>3;␊ |
663 | ␉␉␉␉␉␉␉dr = ((*(uint16_t *)(vram + bpp*pos))&0xf800)>>8;␊ |
664 | ␉␉␉␉␉␉␉break;␉␉␉␉␉␉␉*/␊ |
665 | ␉␉␉␉␉␉case 15:␊ |
666 | ␉␉␉␉␉␉␉db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;␊ |
667 | ␉␉␉␉␉␉␉dg = ((*(uint16_t *)(vram + bpp*pos))&0x03e0)>>2;␊ |
668 | ␉␉␉␉␉␉␉dr = ((*(uint16_t *)(vram + bpp*pos))&0x7c00)>>7;␊ |
669 | ␉␉␉␉␉␉␉break;␉␉␊ |
670 | ␉␉␉␉␉␉default:␊ |
671 | ␉␉␉␉␉␉␉return;␊ |
672 | ␉␉␉␉␉}␊ |
673 | ␊ |
674 | ␉␉␉␉␉dr = (((sr - dr) * a) >> 8) + dr;␊ |
675 | ␉␉␉␉␉dg = (((sg - dg) * a) >> 8) + dg;␊ |
676 | ␉␉␉␉␉db = (((sb - db) * a) >> 8) + db;␊ |
677 | ␉␉␉␉␉switch (VIDEO (depth))␊ |
678 | ␉␉␉␉␉{␊ |
679 | ␉␉␉␉␉␉case 24:␊ |
680 | ␉␉␉␉␉␉␉*(uint32_t *)(vram + bpp*pos) = (*(uint32_t *)(vram + bpp*pos) &0xff000000)␊ |
681 | ␉␉␉␉␉␉␉| (db&0xff) | ((dg&0xff)<<8) | ((dr&0xff)<<16);␊ |
682 | ␉␉␉␉␉␉␉break;␊ |
683 | ␉␉␉␉␉␉case 16:␊ |
684 | //␉␉␉␉␉␉␉*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xfc)<<3) | ((dr&0xf8)<<8);␊ |
685 | //␉␉␉␉␉␉␉break;␉␉␉␉␉␉␉␊ |
686 | ␉␉␉␉␉␉case 15:␊ |
687 | ␉␉␉␉␉␉␉*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xf8)<<2) | ((dr&0xf8)<<7);␊ |
688 | ␉␉␉␉␉␉␉break;␉␉␉␉␉␉␉␉␉␉␉␉␉␉␊ |
689 | ␉␉␉␉␉}␊ |
690 | ␉␉␉␉␉␊ |
691 | ␉␉␉␉}␉␉␉␉␊ |
692 | ␉␉␉}␊ |
693 | ␉␉␉break;␊ |
694 | }␊ |
695 | vram += VIDEO(rowBytes);␊ |
696 | data += width * 4;␊ |
697 | }␊ |
698 | }␊ |
699 | ␊ |
700 | void drawCheckerBoard()␊ |
701 | {␊ |
702 | uint32_t *vram = (uint32_t *) VIDEO(baseAddr);␊ |
703 | uint16_t x, y;␊ |
704 | uint8_t color;␊ |
705 | ␊ |
706 | for (y = 0; y < VIDEO(height); y++, vram += VIDEO(width)) {␊ |
707 | for (x = 0; x < VIDEO(width); x++) {␊ |
708 | color = 204 + 51 * (((x / 8) % 2) == ((y / 8) % 2));␊ |
709 | vram[x] = (color << 16) | (color << 8) | color;␊ |
710 | }␊ |
711 | }␊ |
712 | }␊ |
713 | ␊ |
714 | //==========================================================================␊ |
715 | // LookUpCLUTIndex␊ |
716 | ␊ |
717 | unsigned long lookUpCLUTIndex( unsigned char index,␊ |
718 | unsigned char depth )␊ |
719 | {␊ |
720 | long result, red, green, blue;␊ |
721 | ␊ |
722 | red = appleClut8[index * 3 + 0];␊ |
723 | green = appleClut8[index * 3 + 1];␊ |
724 | blue = appleClut8[index * 3 + 2];␊ |
725 | ␊ |
726 | switch (depth) {␊ |
727 | case 16 :␊ |
728 | result = ((red & 0xF8) << 7) | ␊ |
729 | ((green & 0xF8) << 2) |␊ |
730 | ((blue & 0xF8) >> 3);␊ |
731 | result |= (result << 16);␊ |
732 | break;␊ |
733 | ␊ |
734 | case 32 :␊ |
735 | result = (red << 16) | (green << 8) | blue;␊ |
736 | break;␊ |
737 | ␊ |
738 | default :␊ |
739 | result = index | (index << 8);␊ |
740 | result |= (result << 16);␊ |
741 | break;␊ |
742 | }␊ |
743 | ␊ |
744 | return result;␊ |
745 | }␊ |
746 | ␊ |
747 | //==========================================================================␊ |
748 | // drawColorRectangle␊ |
749 | ␊ |
750 | void * stosl(void * dst, long val, long len)␊ |
751 | {␊ |
752 | asm volatile ( "rep; stosl"␊ |
753 | : "=c" (len), "=D" (dst)␊ |
754 | : "0" (len), "1" (dst), "a" (val)␊ |
755 | : "memory" );␊ |
756 | ␊ |
757 | return dst;␊ |
758 | }␊ |
759 | ␊ |
760 | void drawColorRectangle( unsigned short x,␊ |
761 | unsigned short y,␊ |
762 | unsigned short width,␊ |
763 | unsigned short height,␊ |
764 | unsigned char colorIndex )␊ |
765 | {␊ |
766 | long pixelBytes;␊ |
767 | long color = lookUpCLUTIndex( colorIndex, VIDEO(depth) );␊ |
768 | char * vram;␊ |
769 | ␊ |
770 | pixelBytes = VIDEO(depth) / 8;␊ |
771 | vram = (char *) VIDEO(baseAddr) +␊ |
772 | VIDEO(rowBytes) * y + pixelBytes * x;␊ |
773 | ␊ |
774 | width = MIN(width, VIDEO(width) - x);␊ |
775 | height = MIN(height, VIDEO(height) - y);␊ |
776 | ␊ |
777 | while ( height-- )␊ |
778 | {␊ |
779 | int rem = ( pixelBytes * width ) % 4;␊ |
780 | if ( rem ) bcopy( &color, vram, rem );␊ |
781 | stosl( vram + rem, color, pixelBytes * width / 4 );␊ |
782 | vram += VIDEO(rowBytes);␊ |
783 | }␊ |
784 | }␊ |
785 | ␊ |
786 | //==========================================================================␊ |
787 | // drawDataRectangle␊ |
788 | ␊ |
789 | void drawDataRectangle( unsigned short x,␊ |
790 | unsigned short y,␊ |
791 | unsigned short width,␊ |
792 | unsigned short height,␊ |
793 | unsigned char * data )␊ |
794 | {␊ |
795 | unsigned short drawWidth;␊ |
796 | long pixelBytes = VIDEO(depth) / 8;␊ |
797 | unsigned char * vram = (unsigned char *) VIDEO(baseAddr) +␊ |
798 | VIDEO(rowBytes) * y + pixelBytes * x;␊ |
799 | ␊ |
800 | drawWidth = MIN(width, VIDEO(width) - x);␊ |
801 | height = MIN(height, VIDEO(height) - y);␊ |
802 | while ( height-- ) {␊ |
803 | bcopy( data, vram, drawWidth * pixelBytes );␊ |
804 | vram += VIDEO(rowBytes);␊ |
805 | data += width * pixelBytes;␊ |
806 | }␊ |
807 | }␊ |
808 | ␊ |
809 | void␊ |
810 | loadImageScale (void *input, int iw, int ih, int ip, void *output, int ow, int oh, int op, int or)␊ |
811 | {␊ |
812 | ␉int x,y, off;␊ |
813 | ␉int red=0x7f, green=0x7f, blue=0x7f;␊ |
814 | ␉for (x=0;x<ow;x++)␊ |
815 | ␉␉for (y=0;y<oh;y++)␊ |
816 | ␉␉{␊ |
817 | ␉␉␉off=(x*iw)/ow+((y*ih)/oh)*iw;␊ |
818 | ␉␉␉switch (ip)␊ |
819 | ␉␉␉{␊ |
820 | ␉␉␉␉case 16:␊ |
821 | ␉␉␉␉{␊ |
822 | ␉␉␉␉␉uint16_t val;␊ |
823 | ␉␉␉␉␉val=((uint16_t *)input)[off];␊ |
824 | ␉␉␉␉␉red=(val>>7)&0xf8;␊ |
825 | ␉␉␉␉␉green=(val>>2)&0xf8;␊ |
826 | ␉␉␉␉␉blue=(val<<3)&0xf8;␊ |
827 | ␉␉␉␉␉break;␉␉␊ |
828 | ␉␉␉␉}␊ |
829 | ␉␉␉␉case 32:␊ |
830 | ␉␉␉␉{␊ |
831 | ␉␉␉␉␉uint32_t val;␊ |
832 | ␉␉␉␉␉val=((uint32_t *)input)[off];␊ |
833 | ␉␉␉␉␉red=(val>>16)&0xff;␊ |
834 | ␉␉␉␉␉green=(val>>8)&0xff;␊ |
835 | ␉␉␉␉␉blue=(val)&0xff;␊ |
836 | ␉␉␉␉␉break;␊ |
837 | ␉␉␉␉}␉␉␉␉␊ |
838 | ␉␉␉}␊ |
839 | ␉␉␉char *ptr=(char *)output+x*(op/8)+y*or;␊ |
840 | ␉␉␉switch (op)␊ |
841 | ␉␉␉{␊ |
842 | ␉␉␉␉case 16:␊ |
843 | ␉␉␉␉␉*((uint16_t *)ptr) = ((red & 0xF8) << 7) | ␊ |
844 | ␉␉␉␉␉((green & 0xF8) << 2) |␊ |
845 | ␉␉␉␉␉((blue & 0xF8) >> 3);␊ |
846 | ␉␉␉␉␉break;␊ |
847 | ␉␉␉␉case 32 :␊ |
848 | ␉␉␉␉␉*((uint32_t *)ptr) = (red << 16) | (green << 8) | blue;␊ |
849 | ␉␉␉␉␉break;␊ |
850 | ␉␉␉}␊ |
851 | ␉␉}␊ |
852 | }␊ |
853 | ␊ |
854 | DECLARE_IOHIBERNATEPROGRESSALPHA␊ |
855 | ␊ |
856 | void drawPreview(void *src, uint8_t * saveunder)␊ |
857 | {␊ |
858 | ␉uint8_t * screen;␊ |
859 | ␉uint32_t rowBytes, pixelShift;␊ |
860 | ␉uint32_t x, y;␊ |
861 | ␉int32_t blob;␊ |
862 | ␉uint32_t alpha, in, color, result;␊ |
863 | ␉uint8_t * out;␊ |
864 | ␉void *uncomp;␊ |
865 | ␉int origwidth, origheight, origbpx;␊ |
866 | ␉uint32_t saveindex[kIOHibernateProgressCount] = { 0 };␊ |
867 | ␉␉␊ |
868 | ␉if (src && (uncomp=DecompressData(src, &origwidth, &origheight, &origbpx)))␊ |
869 | ␉{␊ |
870 | ␉␉if (!setVESAGraphicsMode(origwidth, origheight, origbpx, 0))␊ |
871 | ␉␉␉if (initGraphicsMode () != errSuccess)␊ |
872 | ␉␉␉␉return;␊ |
873 | ␉␉screen = (uint8_t *) VIDEO (baseAddr);␊ |
874 | ␉␉rowBytes = VIDEO (rowBytes);␊ |
875 | ␉␉loadImageScale (uncomp, origwidth, origheight, origbpx, screen, VIDEO(width), VIDEO(height), VIDEO(depth), VIDEO (rowBytes));␊ |
876 | ␉}␊ |
877 | ␉else␊ |
878 | ␉{␊ |
879 | ␉␉if (initGraphicsMode () != errSuccess)␊ |
880 | ␉␉␉return;␊ |
881 | ␉␉screen = (uint8_t *) VIDEO (baseAddr);␊ |
882 | ␉␉rowBytes = VIDEO (rowBytes);␊ |
883 | ␉␉// Set the screen to 75% grey.␊ |
884 | drawColorRectangle(0, 0, VIDEO(width), VIDEO(height), 0x01 /* color index */);␊ |
885 | ␉}␊ |
886 | ␉␊ |
887 | ␉␊ |
888 | ␉pixelShift = VIDEO (depth) >> 4;␊ |
889 | ␉if (pixelShift < 1) return;␊ |
890 | ␉␊ |
891 | ␉screen += ((VIDEO (width) ␊ |
892 | ␉␉␉␉- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))␊ |
893 | ␉+ (VIDEO (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;␊ |
894 | ␉␊ |
895 | ␉for (y = 0; y < kIOHibernateProgressHeight; y++)␊ |
896 | ␉{␊ |
897 | ␉␉out = screen + y * rowBytes;␊ |
898 | ␉␉for (blob = 0; blob < kIOHibernateProgressCount; blob++)␊ |
899 | ␉␉{␊ |
900 | ␉␉␉color = blob ? kIOHibernateProgressDarkGray : kIOHibernateProgressMidGray;␊ |
901 | ␉␉␉for (x = 0; x < kIOHibernateProgressWidth; x++)␊ |
902 | ␉␉␉{␊ |
903 | ␉␉␉␉alpha = gIOHibernateProgressAlpha[y][x];␊ |
904 | ␉␉␉␉result = color;␊ |
905 | ␉␉␉␉if (alpha)␊ |
906 | ␉␉␉␉{␊ |
907 | ␉␉␉␉␉if (0xff != alpha)␊ |
908 | ␉␉␉␉␉{␊ |
909 | ␉␉␉␉␉␉if (1 == pixelShift)␊ |
910 | ␉␉␉␉␉␉{␊ |
911 | ␉␉␉␉␉␉␉in = *((uint16_t *)out) & 0x1f;␉// 16␊ |
912 | ␉␉␉␉␉␉␉in = (in << 3) | (in >> 2);␊ |
913 | ␉␉␉␉␉␉}␊ |
914 | ␉␉␉␉␉␉else␊ |
915 | ␉␉␉␉␉␉␉in = *((uint32_t *)out) & 0xff;␉// 32␊ |
916 | ␉␉␉␉␉␉saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++] = in;␊ |
917 | ␉␉␉␉␉␉result = ((255 - alpha) * in + alpha * result + 0xff) >> 8;␊ |
918 | ␉␉␉␉␉}␊ |
919 | ␉␉␉␉␉if (1 == pixelShift)␊ |
920 | ␉␉␉␉␉{␊ |
921 | ␉␉␉␉␉␉result >>= 3;␊ |
922 | ␉␉␉␉␉␉*((uint16_t *)out) = (result << 10) | (result << 5) | result;␉// 16␊ |
923 | ␉␉␉␉␉}␊ |
924 | ␉␉␉␉␉else␊ |
925 | ␉␉␉␉␉␉*((uint32_t *)out) = (result << 16) | (result << 8) | result;␉// 32␊ |
926 | ␉␉␉␉}␊ |
927 | ␉␉␉␉out += (1 << pixelShift);␊ |
928 | ␉␉␉}␊ |
929 | ␉␉␉out += (kIOHibernateProgressSpacing << pixelShift);␊ |
930 | ␉␉}␊ |
931 | ␉}␊ |
932 | }␊ |
933 | ␊ |
934 | void updateProgressBar(uint8_t * saveunder, int32_t firstBlob, int32_t select)␊ |
935 | {␊ |
936 | ␉uint8_t * screen;␊ |
937 | ␉uint32_t rowBytes, pixelShift;␊ |
938 | ␉uint32_t x, y;␊ |
939 | ␉int32_t blob, lastBlob;␊ |
940 | ␉uint32_t alpha, in, color, result;␊ |
941 | ␉uint8_t * out;␊ |
942 | ␉uint32_t saveindex[kIOHibernateProgressCount] = { 0 };␊ |
943 | ␉␊ |
944 | ␉pixelShift = VIDEO(depth) >> 4;␊ |
945 | ␉if (pixelShift < 1) return;␊ |
946 | ␉screen = (uint8_t *) VIDEO (baseAddr);␊ |
947 | ␉rowBytes = VIDEO (rowBytes);␊ |
948 | ␉␊ |
949 | ␉screen += ((VIDEO (width) ␊ |
950 | ␉␉␉␉- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))␊ |
951 | ␉+ (VIDEO (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;␊ |
952 | ␉␊ |
953 | ␉lastBlob = (select < kIOHibernateProgressCount) ? select : (kIOHibernateProgressCount - 1);␊ |
954 | ␉␊ |
955 | ␉screen += (firstBlob * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << pixelShift;␊ |
956 | ␉␊ |
957 | ␉for (y = 0; y < kIOHibernateProgressHeight; y++)␊ |
958 | ␉{␊ |
959 | ␉␉out = screen + y * rowBytes;␊ |
960 | ␉␉for (blob = firstBlob; blob <= lastBlob; blob++)␊ |
961 | ␉␉{␊ |
962 | ␉␉␉color = (blob < select) ? kIOHibernateProgressLightGray : kIOHibernateProgressMidGray;␊ |
963 | ␉␉␉for (x = 0; x < kIOHibernateProgressWidth; x++)␊ |
964 | ␉␉␉{␊ |
965 | ␉␉␉␉alpha = gIOHibernateProgressAlpha[y][x];␊ |
966 | ␉␉␉␉result = color;␊ |
967 | ␉␉␉␉if (alpha)␊ |
968 | ␉␉␉␉{␊ |
969 | ␉␉␉␉␉if (0xff != alpha)␊ |
970 | ␉␉␉␉␉{␊ |
971 | ␉␉␉␉␉␉in = saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++];␊ |
972 | ␉␉␉␉␉␉result = ((255 - alpha) * in + alpha * result + 0xff) / 255;␊ |
973 | ␉␉␉␉␉}␊ |
974 | ␉␉␉␉␉if (1 == pixelShift)␊ |
975 | ␉␉␉␉␉{␊ |
976 | ␉␉␉␉␉␉result >>= 3;␊ |
977 | ␉␉␉␉␉␉*((uint16_t *)out) = (result << 10) | (result << 5) | result;␉// 16␊ |
978 | ␉␉␉␉␉}␊ |
979 | ␉␉␉␉␉else␊ |
980 | ␉␉␉␉␉␉*((uint32_t *)out) = (result << 16) | (result << 8) | result;␉// 32␊ |
981 | ␉␉␉␉}␊ |
982 | ␉␉␉␉out += (1 << pixelShift);␊ |
983 | ␉␉␉}␊ |
984 | ␉␉␉out += (kIOHibernateProgressSpacing << pixelShift);␊ |
985 | ␉␉}␊ |
986 | ␉}␊ |
987 | }␊ |
988 | ␊ |
989 | ␊ |
990 | //==========================================================================␊ |
991 | // setVESATextMode␊ |
992 | ␊ |
993 | static int␊ |
994 | setVESATextMode( unsigned short cols,␊ |
995 | unsigned short rows,␊ |
996 | unsigned char bitsPerPixel )␊ |
997 | {␊ |
998 | VBEModeInfoBlock minfo;␊ |
999 | unsigned short mode = modeEndOfList;␊ |
1000 | ␊ |
1001 | if ( (cols != 80) || (rows != 25) ) // not 80x25 mode␊ |
1002 | {␊ |
1003 | mode = getVESAModeWithProperties( cols, rows, bitsPerPixel,␊ |
1004 | maColorModeBit |␊ |
1005 | maModeIsSupportedBit,␊ |
1006 | maGraphicsModeBit,␊ |
1007 | &minfo, NULL );␊ |
1008 | }␊ |
1009 | ␊ |
1010 | if ( ( mode == modeEndOfList ) || ( setVBEMode(mode, NULL) != errSuccess ) )␊ |
1011 | {␊ |
1012 | video_mode( 2 ); // VGA BIOS, 80x25 text mode.␊ |
1013 | minfo.XResolution = 80;␊ |
1014 | minfo.YResolution = 25;␊ |
1015 | }␊ |
1016 | ␊ |
1017 | // Update KernBootStruct using info provided by the selected␊ |
1018 | // VESA mode.␊ |
1019 | ␊ |
1020 | bootArgs->Video.v_display = VGA_TEXT_MODE;␊ |
1021 | bootArgs->Video.v_baseAddr = 0xb8000;␊ |
1022 | bootArgs->Video.v_width = minfo.XResolution;␊ |
1023 | bootArgs->Video.v_height = minfo.YResolution;␊ |
1024 | bootArgs->Video.v_depth = 8;␊ |
1025 | bootArgs->Video.v_rowBytes = 0x8000;␊ |
1026 | ␊ |
1027 | return errSuccess; // always return success␊ |
1028 | }␊ |
1029 | ␊ |
1030 | //==========================================================================␊ |
1031 | // getNumberArrayFromProperty␊ |
1032 | ␊ |
1033 | static int␊ |
1034 | getNumberArrayFromProperty( const char * propKey,␊ |
1035 | unsigned long numbers[],␊ |
1036 | unsigned long maxArrayCount )␊ |
1037 | {␊ |
1038 | char * propStr;␊ |
1039 | unsigned long count = 0;␊ |
1040 | ␊ |
1041 | propStr = newStringForKey( (char *) propKey , &bootInfo->bootConfig );␊ |
1042 | if ( propStr )␊ |
1043 | {␊ |
1044 | char * delimiter = propStr;␊ |
1045 | char * p = propStr;␊ |
1046 | ␊ |
1047 | while ( count < maxArrayCount && *p != '\0' )␊ |
1048 | {␊ |
1049 | unsigned long val = strtoul( p, &delimiter, 10 );␊ |
1050 | if ( p != delimiter )␊ |
1051 | {␊ |
1052 | numbers[count++] = val;␊ |
1053 | p = delimiter;␊ |
1054 | }␊ |
1055 | while ( ( *p != '\0' ) && !isdigit(*p) )␊ |
1056 | p++;␊ |
1057 | }␊ |
1058 | ␊ |
1059 | free( propStr );␊ |
1060 | }␊ |
1061 | ␊ |
1062 | return count;␊ |
1063 | }␊ |
1064 | ␊ |
1065 | int initGraphicsMode ()␊ |
1066 | {␊ |
1067 | unsigned long params[4];␊ |
1068 | int count;␊ |
1069 | ␊ |
1070 | params[3] = 0;␊ |
1071 | count = getNumberArrayFromProperty( kGraphicsModeKey, params, 4 );␊ |
1072 | ␊ |
1073 | // Try to find a resolution if "Graphics Mode" setting is not available.␊ |
1074 | if ( count < 3 )␊ |
1075 | {␊ |
1076 | // Use the default resolution if we don't have an initialized GUI.␊ |
1077 | if (gui.screen.width == 0 || gui.screen.height == 0)␊ |
1078 | {␊ |
1079 | gui.screen.width = DEFAULT_SCREEN_WIDTH;␉␊ |
1080 | gui.screen.height = DEFAULT_SCREEN_HEIGHT;␊ |
1081 | }␊ |
1082 | ␊ |
1083 | params[0] = gui.screen.width;␊ |
1084 | params[1] = gui.screen.height;␊ |
1085 | params[2] = 32;␊ |
1086 | }␊ |
1087 | ␊ |
1088 | // Map from pixel format to bits per pixel.␊ |
1089 | ␊ |
1090 | if ( params[2] == 256 ) params[2] = 8;␊ |
1091 | if ( params[2] == 555 ) params[2] = 16;␊ |
1092 | if ( params[2] == 888 ) params[2] = 32;␊ |
1093 | ␊ |
1094 | ␉return setVESAGraphicsMode( params[0], params[1], params[2], params[3] );␉␊ |
1095 | }␊ |
1096 | ␊ |
1097 | //==========================================================================␊ |
1098 | // setVideoMode␊ |
1099 | //␊ |
1100 | // Set the video mode to VGA_TEXT_MODE or GRAPHICS_MODE.␊ |
1101 | ␊ |
1102 | void␊ |
1103 | setVideoMode( int mode, int drawgraphics)␊ |
1104 | {␊ |
1105 | unsigned long params[4];␊ |
1106 | int count;␊ |
1107 | int err = errSuccess;␊ |
1108 | ␊ |
1109 | if ( mode == GRAPHICS_MODE )␊ |
1110 | {␊ |
1111 | ␉␉if ( (err=initGraphicsMode ()) == errSuccess ) {␊ |
1112 | if (gVerboseMode) {␊ |
1113 | // Tell the kernel to use text mode on a linear frame buffer display␊ |
1114 | bootArgs->Video.v_display = FB_TEXT_MODE;␊ |
1115 | } else {␊ |
1116 | bootArgs->Video.v_display = GRAPHICS_MODE;␊ |
1117 | }␊ |
1118 | }␊ |
1119 | }␊ |
1120 | ␊ |
1121 | if ( (mode == VGA_TEXT_MODE) || (err != errSuccess) )␊ |
1122 | {␊ |
1123 | count = getNumberArrayFromProperty( kTextModeKey, params, 2 );␊ |
1124 | if ( count < 2 )␊ |
1125 | {␊ |
1126 | params[0] = 80; // Default text mode is 80x25.␊ |
1127 | params[1] = 25;␊ |
1128 | }␊ |
1129 | ␊ |
1130 | ␉␉setVESATextMode( params[0], params[1], 4 );␊ |
1131 | bootArgs->Video.v_display = VGA_TEXT_MODE;␊ |
1132 | }␊ |
1133 | ␊ |
1134 | currentIndicator = 0;␊ |
1135 | }␊ |
1136 | ␊ |
1137 | void getGraphicModeParams(unsigned long params[]) {␊ |
1138 | ␊ |
1139 | ␉params[3] = 0;␊ |
1140 | ␊ |
1141 | ␉VBEModeInfoBlock minfo;␊ |
1142 | ␊ |
1143 | unsigned short vesaVersion;␊ |
1144 | unsigned short mode = modeEndOfList;␊ |
1145 | ␉␊ |
1146 | ␉getNumberArrayFromProperty( kGraphicsModeKey, params, 4);␊ |
1147 | ␊ |
1148 | ␉mode = getVESAModeWithProperties( params[0], params[1], params[2],␊ |
1149 | ␉␉␉␉␉␉␉␉␉ maColorModeBit |␊ |
1150 | ␉␉␉␉␉␉␉␉␉ maModeIsSupportedBit |␊ |
1151 | ␉␉␉␉␉␉␉␉␉ maGraphicsModeBit |␊ |
1152 | ␉␉␉␉␉␉␉␉␉ maLinearFrameBufferAvailBit,␊ |
1153 | ␉␉␉␉␉␉␉␉␉ 0,␊ |
1154 | ␉␉␉␉␉␉␉␉␉ &minfo, &vesaVersion );␊ |
1155 | ␉␊ |
1156 | ␉params[0] = minfo.XResolution;␊ |
1157 | ␉params[1] = minfo.YResolution;␊ |
1158 | ␉params[2] = 32;␊ |
1159 | }␊ |
1160 | ␉␊ |
1161 | //==========================================================================␊ |
1162 | // Return the current video mode, VGA_TEXT_MODE or GRAPHICS_MODE.␊ |
1163 | ␊ |
1164 | int getVideoMode(void)␊ |
1165 | {␊ |
1166 | return bootArgs->Video.v_display;␊ |
1167 | }␊ |
1168 | ␊ |
1169 | //==========================================================================␊ |
1170 | // Display and clear the activity indicator.␊ |
1171 | ␊ |
1172 | static char indicator[] = {'-', '\\', '|', '/', '-', '\\', '|', '/', '\0'};␊ |
1173 | ␊ |
1174 | // To prevent a ridiculously fast-spinning indicator,␊ |
1175 | // ensure a minimum of 1/9 sec between animation frames.␊ |
1176 | #define MIN_TICKS 2␊ |
1177 | ␊ |
1178 | void␊ |
1179 | spinActivityIndicator(int sectors)␊ |
1180 | {␊ |
1181 | static unsigned long lastTickTime = 0, currentTickTime;␊ |
1182 | ␊ |
1183 | ␉if (previewTotalSectors && previewSaveunder)␊ |
1184 | ␉{␊ |
1185 | ␉␉int blob, lastBlob;␊ |
1186 | ␊ |
1187 | ␉␉lastBlob = (previewLoadedSectors * kIOHibernateProgressCount) / previewTotalSectors;␊ |
1188 | ␉␉previewLoadedSectors+=sectors;␊ |
1189 | ␉␉blob = (previewLoadedSectors * kIOHibernateProgressCount) / previewTotalSectors;␊ |
1190 | ␉␉␊ |
1191 | ␉␉if (blob!=lastBlob)␊ |
1192 | ␉␉␉updateProgressBar (previewSaveunder, lastBlob, blob);␊ |
1193 | ␉␉return;␊ |
1194 | ␉}␊ |
1195 | ␊ |
1196 | ␉currentTickTime = time18(); // late binding␊ |
1197 | ␉if (currentTickTime < lastTickTime + MIN_TICKS)␊ |
1198 | ␉{␊ |
1199 | ␉␉return;␊ |
1200 | ␉}␊ |
1201 | ␉else␊ |
1202 | ␉{␊ |
1203 | ␉␉lastTickTime = currentTickTime;␊ |
1204 | ␉}␊ |
1205 | ␉␊ |
1206 | ␉if (getVideoMode() == VGA_TEXT_MODE)␊ |
1207 | ␉{␊ |
1208 | ␉␉if (currentIndicator >= sizeof(indicator))␊ |
1209 | ␉␉{␊ |
1210 | ␉␉␉currentIndicator = 0;␊ |
1211 | ␉␉}␊ |
1212 | ␉␉putc(indicator[currentIndicator++]);␊ |
1213 | ␉␉putc('\b');␊ |
1214 | ␉}␊ |
1215 | }␊ |
1216 | ␊ |
1217 | void␊ |
1218 | clearActivityIndicator( void )␊ |
1219 | {␊ |
1220 | if ( getVideoMode() == VGA_TEXT_MODE )␊ |
1221 | {␊ |
1222 | ␉␉putc(' ');␊ |
1223 | ␉␉putc('\b');␊ |
1224 | }␊ |
1225 | }␊ |
1226 | ␊ |
1227 |