Chameleon

Chameleon Svn Source Tree

Root/branches/mozodojo/i386/boot2/graphics.c

  • Property svn:eol-style set to native
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 */
38static int currentIndicator = 0;
39
40int previewTotalSectors = 0;
41int previewLoadedSectors = 0;
42uint8_t *previewSaveunder = 0;
43
44#define VIDEO(x) (bootArgs->Video.v_ ## x)
45#define VIDEOSNOW(x) (bootArgsSnow->Video.v_ ## x)
46
47#define MIN(x, y) ((x) < (y) ? (x) : (y))
48
49//==========================================================================
50// getVBEInfoString
51
52char *getVBEInfoString()
53{
54VBEInfoBlock vbeInfo;
55int err, small;
56char *buff = malloc(sizeof(char)*256);
57if(!buff) return 0;
58
59bzero( &vbeInfo, sizeof(vbeInfo) );
60strcpy( (char*)&vbeInfo, "VBE2" );
61err = getVBEInfo( &vbeInfo );
62if (err != errSuccess)
63return 0;
64
65if ( strncmp( (char *)vbeInfo.VESASignature, "VESA", 4 ) )
66return 0;
67
68small = (vbeInfo.TotalMemory < 16);
69
70sprintf(buff, "VESA v%d.%d %d%s (%s)\n",
71vbeInfo.VESAVersion >> 8,
72vbeInfo.VESAVersion & 0xf,
73small ? (vbeInfo.TotalMemory * 64) : (vbeInfo.TotalMemory / 16),
74small ? "KB" : "MB",
75VBEDecodeFP(const char *, vbeInfo.OEMStringPtr) );
76
77return buff;
78}
79
80//==========================================================================
81//
82
83void
84printVBEModeInfo()
85{
86 VBEInfoBlock vbeInfo;
87 unsigned short * modePtr;
88 VBEModeInfoBlock modeInfo;
89 int err;
90 int line;
91
92 bzero( &vbeInfo, sizeof(vbeInfo) );
93 strcpy( (char*)&vbeInfo, "VBE2" );
94 err = getVBEInfo( &vbeInfo );
95 if ( err != errSuccess )
96 return;
97
98 line = 0;
99
100 // Activate and clear page 1
101 setActiveDisplayPage(1);
102 clearScreenRows(0, 24);
103 setCursorPosition( 0, 0, 1 );
104
105 printf( getVBEInfoString() );
106printf("Video modes supported:\n", VBEDecodeFP(const char *, vbeInfo.OEMStringPtr));
107
108// Loop through the mode list, and find the matching mode.
109
110 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
111 *modePtr != modeEndOfList; modePtr++ )
112 {
113 // Get mode information.
114
115 bzero( &modeInfo, sizeof(modeInfo) );
116 err = getVBEModeInfo( *modePtr, &modeInfo );
117 if ( err != errSuccess )
118 {
119 continue;
120 }
121
122 printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",
123 *modePtr, modeInfo.XResolution, modeInfo.YResolution,
124 modeInfo.BitsPerPixel, modeInfo.MemoryModel,
125 modeInfo.ModeAttributes);
126
127 if (line++ >= 20) {
128 pause();
129 line = 0;
130 clearScreenRows(0, 24);
131 setCursorPosition( 0, 0, 1 );
132 }
133 }
134 if (line != 0) {
135 pause();
136 }
137 setActiveDisplayPage(0);
138}
139
140char *getVBEModeInfoString()
141{
142VBEInfoBlock vbeInfo;
143 unsigned short * modePtr;
144 VBEModeInfoBlock modeInfo;
145 int err;
146
147 bzero( &vbeInfo, sizeof(vbeInfo) );
148 strcpy( (char*)&vbeInfo, "VBE2" );
149 err = getVBEInfo( &vbeInfo );
150 if ( err != errSuccess )
151 return 0;
152
153char *buff=malloc(sizeof(char)*3072);
154if(!buff) return 0;
155
156// Loop through the mode list, and find the matching mode.
157 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
158 *modePtr != modeEndOfList; modePtr++ )
159 {
160 // Get mode information.
161
162 bzero( &modeInfo, sizeof(modeInfo) );
163 err = getVBEModeInfo( *modePtr, &modeInfo );
164 if ( err != errSuccess )
165 {
166 continue;
167 }
168
169 sprintf(buff+strlen(buff), "Mode %x: %dx%dx%d mm:%d attr:%x\n",
170*modePtr, modeInfo.XResolution, modeInfo.YResolution,
171modeInfo.BitsPerPixel, modeInfo.MemoryModel,
172modeInfo.ModeAttributes);
173
174 }
175return buff;
176}
177
178//==========================================================================
179// getVESAModeWithProperties
180//
181// Return the VESA mode that matches the properties specified.
182// If a mode is not found, then return the "best" available mode.
183
184static unsigned short
185getVESAModeWithProperties( unsigned short width,
186 unsigned short height,
187 unsigned char bitsPerPixel,
188 unsigned short attributesSet,
189 unsigned short attributesClear,
190 VBEModeInfoBlock * outModeInfo,
191 unsigned short * vesaVersion )
192{
193 VBEInfoBlock vbeInfo;
194 unsigned short * modePtr;
195 VBEModeInfoBlock modeInfo;
196 unsigned char modeBitsPerPixel;
197 unsigned short matchedMode = modeEndOfList;
198 int err;
199
200 // Clear output mode info.
201
202 bzero( outModeInfo, sizeof(*outModeInfo) );
203
204 // Get VBE controller info containing the list of supported modes.
205
206 bzero( &vbeInfo, sizeof(vbeInfo) );
207 strcpy( (char*)&vbeInfo, "VBE2" );
208 err = getVBEInfo( &vbeInfo );
209 if ( err != errSuccess )
210 {
211 return modeEndOfList;
212 }
213
214 // Report the VESA major/minor version number.
215
216 if (vesaVersion) *vesaVersion = vbeInfo.VESAVersion;
217
218 // Loop through the mode list, and find the matching mode.
219
220 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
221 *modePtr != modeEndOfList; modePtr++ )
222 {
223 // Get mode information.
224
225 bzero( &modeInfo, sizeof(modeInfo) );
226 err = getVBEModeInfo( *modePtr, &modeInfo );
227 if ( err != errSuccess )
228 {
229 continue;
230 }
231
232#if DEBUG
233 printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",
234 *modePtr, modeInfo.XResolution, modeInfo.YResolution,
235 modeInfo.BitsPerPixel, modeInfo.MemoryModel,
236 modeInfo.ModeAttributes);
237#endif
238
239 // Filter out unwanted modes based on mode attributes.
240
241 if ( ( ( modeInfo.ModeAttributes & attributesSet ) != attributesSet )
242|| ( ( modeInfo.ModeAttributes & attributesClear ) != 0 ) )
243 {
244 continue;
245 }
246
247 // Pixel depth in bits.
248
249 modeBitsPerPixel = modeInfo.BitsPerPixel;
250
251 if ( ( modeBitsPerPixel == 4 ) && ( modeInfo.MemoryModel == 0 ) )
252 {
253 // Text mode, 16 colors.
254 }
255 else if ( ( modeBitsPerPixel == 8 ) && ( modeInfo.MemoryModel == 4 ) )
256 {
257 // Packed pixel, 256 colors.
258 }
259 else if ( ( ( modeBitsPerPixel == 16 ) || ( modeBitsPerPixel == 15 ) )
260 && ( modeInfo.MemoryModel == 6 )
261 && ( modeInfo.RedMaskSize == 5 )
262 && ( modeInfo.GreenMaskSize == 5 )
263 && ( modeInfo.BlueMaskSize == 5 ) )
264 {
265 // Direct color, 16 bpp (1:5:5:5).
266 modeInfo.BitsPerPixel = modeBitsPerPixel = 16;
267 }
268 else if ( ( modeBitsPerPixel == 32 )
269 && ( modeInfo.MemoryModel == 6 )
270 && ( modeInfo.RedMaskSize == 8 )
271 && ( modeInfo.GreenMaskSize == 8 )
272 && ( modeInfo.BlueMaskSize == 8 ) )
273 {
274 // Direct color, 32 bpp (8:8:8:8).
275 }
276 else
277 {
278 continue; // Not a supported mode.
279 }
280
281 // Modes larger than the specified dimensions are skipped.
282
283 if ( ( modeInfo.XResolution > width ) ||
284( modeInfo.YResolution > height ) )
285 {
286 continue;
287 }
288
289 // Perfect match, we're done looking.
290
291 if ( ( modeInfo.XResolution == width ) &&
292( modeInfo.YResolution == height ) &&
293( modeBitsPerPixel == bitsPerPixel ) )
294 {
295 matchedMode = *modePtr;
296 bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
297 break;
298 }
299
300 // Save the next "best" mode in case a perfect match is not found.
301
302 if ( modeInfo.XResolution == outModeInfo->XResolution &&
303modeInfo.YResolution == outModeInfo->YResolution &&
304modeBitsPerPixel <= outModeInfo->BitsPerPixel )
305 {
306 continue; // Saved mode has more depth.
307 }
308 if ( modeInfo.XResolution < outModeInfo->XResolution ||
309modeInfo.YResolution < outModeInfo->YResolution ||
310modeBitsPerPixel < outModeInfo->BitsPerPixel )
311 {
312 continue; // Saved mode has more resolution.
313 }
314
315 matchedMode = *modePtr;
316 bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
317 }
318
319 return matchedMode;
320}
321
322//==========================================================================
323// setupPalette
324
325static void setupPalette( VBEPalette * p, const unsigned char * g )
326{
327 int i;
328 unsigned char * source = (unsigned char *) g;
329
330 for (i = 0; i < 256; i++)
331 {
332 (*p)[i] = 0;
333 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 16; // Red
334 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 8; // Green
335 (*p)[i] |= ((unsigned long)((*source++) >> 2)); // Blue
336 }
337}
338
339//==========================================================================
340// Simple decompressor for boot images encoded in RLE format.
341
342char * decodeRLE( const void * rleData, int rleBlocks, int outBytes )
343{
344 char *out, *cp;
345
346 struct RLEBlock {
347 unsigned char count;
348 unsigned char value;
349 } * bp = (struct RLEBlock *) rleData;
350
351 out = cp = malloc( outBytes );
352 if ( out == NULL ) return NULL;
353
354 while ( rleBlocks-- )
355 {
356 memset( cp, bp->value, bp->count );
357 cp += bp->count;
358 bp++;
359 }
360
361 return out;
362}
363
364//==========================================================================
365// setVESAGraphicsMode
366
367static int
368setVESAGraphicsMode( unsigned short width,
369unsigned short height,
370unsigned char bitsPerPixel,
371unsigned short refreshRate )
372{
373 VBEModeInfoBlock minfo;
374 unsigned short mode;
375 unsigned short vesaVersion;
376 int err = errFuncNotSupported;
377
378 do {
379 mode = getVESAModeWithProperties( width, height, bitsPerPixel,
380 maColorModeBit |
381 maModeIsSupportedBit |
382 maGraphicsModeBit |
383 maLinearFrameBufferAvailBit,
384 0,
385 &minfo, &vesaVersion );
386 if ( mode == modeEndOfList )
387 {
388 break;
389 }
390
391//
392// FIXME : generateCRTCTiming() causes crash.
393//
394
395// if ( (vesaVersion >> 8) >= 3 && refreshRate >= 60 &&
396// (gBootMode & kBootModeSafe) == 0 )
397// {
398// VBECRTCInfoBlock timing;
399//
400// // Generate CRTC timing for given refresh rate.
401//
402// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
403// refreshRate, kCRTCParamRefreshRate,
404// &timing );
405//
406// // Find the actual pixel clock supported by the hardware.
407//
408// getVBEPixelClock( mode, &timing.PixelClock );
409//
410// // Re-compute CRTC timing based on actual pixel clock.
411//
412// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
413// timing.PixelClock, kCRTCParamPixelClock,
414// &timing );
415//
416// // Set the video mode and use specified CRTC timing.
417//
418// err = setVBEMode( mode | kLinearFrameBufferBit |
419// kCustomRefreshRateBit, &timing );
420// }
421// else
422// {
423// // Set the mode with default refresh rate.
424//
425// err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
426// }
427
428 // Set the mode with default refresh rate.
429
430 err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
431
432 if ( err != errSuccess )
433 {
434 break;
435 }
436
437 // Set 8-bit color palette.
438
439 if ( minfo.BitsPerPixel == 8 )
440 {
441 VBEPalette palette;
442 setupPalette( &palette, appleClut8 );
443 if ((err = setVBEPalette(palette)) != errSuccess)
444 {
445 break;
446 }
447 }
448
449 // Is this required for buggy Video BIOS implementations?
450 // On which adapter?
451
452 if ( minfo.BytesPerScanline == 0 )
453minfo.BytesPerScanline = ( minfo.XResolution *
454 minfo.BitsPerPixel ) >> 3;
455
456 // Update KernBootStruct using info provided by the selected
457 // VESA mode.
458
459 bootArgs->Video.v_display = GRAPHICS_MODE;
460 bootArgs->Video.v_width = minfo.XResolution;
461 bootArgs->Video.v_height = minfo.YResolution;
462 bootArgs->Video.v_depth = minfo.BitsPerPixel;
463 bootArgs->Video.v_rowBytes = minfo.BytesPerScanline;
464 bootArgs->Video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
465
466 bootArgsSnow->Video.v_display = GRAPHICS_MODE;
467 bootArgsSnow->Video.v_width = minfo.XResolution;
468 bootArgsSnow->Video.v_height = minfo.YResolution;
469 bootArgsSnow->Video.v_depth = minfo.BitsPerPixel;
470 bootArgsSnow->Video.v_rowBytes = minfo.BytesPerScanline;
471 bootArgsSnow->Video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
472 }
473 while ( 0 );
474
475 return err;
476}
477
478int
479convertImage( unsigned short width,
480 unsigned short height,
481 const unsigned char *imageData,
482 unsigned char **newImageData )
483{
484 int cnt;
485 unsigned char *img = 0;
486 unsigned short *img16;
487 unsigned long *img32;
488
489 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
490 {
491switch ( VIDEO(depth) ) {
492case 16 :
493img16 = malloc(width * height * 2);
494if ( !img16 ) break;
495for (cnt = 0; cnt < (width * height); cnt++)
496img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16);
497img = (unsigned char *)img16;
498break;
499
500case 32 :
501img32 = malloc(width * height * 4);
502if ( !img32 ) break;
503for (cnt = 0; cnt < (width * height); cnt++)
504img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32);
505img = (unsigned char *)img32;
506break;
507
508default :
509img = malloc(width * height);
510bcopy(imageData, img, width * height);
511break;
512}
513} else {
514switch ( VIDEOSNOW(depth) )
515{
516case 16 :
517img16 = malloc(width * height * 2);
518if ( !img16 ) break;
519for (cnt = 0; cnt < (width * height); cnt++)
520img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16);
521img = (unsigned char *)img16;
522break;
523
524case 32 :
525img32 = malloc(width * height * 4);
526if ( !img32 ) break;
527for (cnt = 0; cnt < (width * height); cnt++)
528img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32);
529img = (unsigned char *)img32;
530break;
531
532default :
533img = malloc(width * height);
534bcopy(imageData, img, width * height);
535break;
536}
537}
538 *newImageData = img;
539 return 0;
540}
541
542int loadPngImage(const char *filename, uint16_t *width, uint16_t *height,
543 uint8_t **imageData)
544{
545 uint8_t *pngData = NULL;
546 int pngFile = 0, pngSize;
547 PNG_info_t *info;
548 int error = 0;
549
550 pngFile = open_bvdev("bt(0,0)", filename, 0);
551 if (pngFile == -1) {
552 error = -1;
553 goto failed;
554 }
555 pngSize = file_size(pngFile);
556 if (!pngSize) {
557 error = -1;
558 goto failed;
559 }
560 pngData = malloc(pngSize);
561 if (read(pngFile, (char *) pngData, pngSize) != pngSize) {
562 error = -1;
563 goto failed;
564 }
565
566 PNG_error = -1;
567 info = PNG_decode(pngData, pngSize);
568 if (PNG_error != 0) {
569 error = PNG_error;
570 goto failed;
571 } else if ((info->width > 0xffff) || (info->height > 0xffff)) {
572 error = -1;
573 goto failed;
574 } else if ((info->width * info->height * 4) != info->image->size) {
575 error = -1;
576 goto failed;
577 }
578uint8_t *result = malloc(info->width*4*info->height);
579 *width = info->width;
580 *height = info->height;
581memcpy(result, info->image->data, info->width*4*info->height);
582*imageData = result;
583
584failed:
585png_alloc_free_all();
586 if (pngData)
587 free(pngData);
588 if (pngFile != -1)
589 close(pngFile);
590
591 return error;
592}
593
594int loadEmbeddedPngImage(uint8_t *pngData, int pngSize, uint16_t *width, uint16_t *height, uint8_t **imageData) {
595 PNG_info_t *info;
596 int error = 0;
597
598 PNG_error = -1;
599 info = PNG_decode(pngData, pngSize);
600if (PNG_error != 0) {
601 error = PNG_error;
602 goto failed;
603 } else if ((info->width > 0xffff) || (info->height > 0xffff)) {
604 error = -1;
605 goto failed;
606 } else if ((info->width * info->height * 4) != info->image->size) {
607 error = -1;
608 goto failed;
609 }
610uint8_t *result = malloc(info->width*4*info->height);
611*width = info->width;
612 *height = info->height;
613memcpy(result, info->image->data, info->width*4*info->height);
614*imageData = result;
615
616failed:
617png_alloc_free_all();
618
619 return error;
620}
621
622void blendImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
623uint8_t *data)
624{
625 uint16_t drawWidth;
626 uint8_t *vram = NULL;
627 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
628 {
629 vram = (uint8_t *) VIDEO(baseAddr) + VIDEO(rowBytes) * y + 4 * x;
630 drawWidth = MIN(width, VIDEO(width) - x);
631 height = MIN(height, VIDEO(height) - y);
632 } else {
633 vram = (uint8_t *) VIDEOSNOW(baseAddr) + VIDEOSNOW(rowBytes) * y + 4 * x;
634 drawWidth = MIN(width, VIDEOSNOW(width) - x);
635 height = MIN(height, VIDEOSNOW(height) - y);
636 }
637 while (height--) {
638 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
639 {
640switch (VIDEO (depth))
641{
642case 32: /* Optimized version*/
643{
644uint32_t s; uint32_t* d; // Source (img) and destination (bkgd) pixels
645uint32_t a; // Alpha
646uint32_t dstrb, dstg, srcrb, srcg, drb, dg, rb, g, tempB; // Intermediate variables
647uint16_t pos;
648
649for (pos = 0; pos < drawWidth * 4; pos += 4) {
650// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
651s = *((uint32_t*) (data + pos));
652d = (uint32_t*) (vram + pos);
653
654// Flip B and R in source
655// TODO: use XCHG and inline assembly to do this in a faster, saner way
656tempB = (s & 0xFF0000); // save B
657s = (s & 0xFF00FFFF) | ((s & 0xFF) << 16); // put R in B
658s = (s & 0xFFFFFF00) | (tempB >> 16); // put B in R
659
660a = (s >> 24) + 1;
661
662dstrb = *d & 0xFF00FF; dstg = *d & 0xFF00;
663srcrb = s & 0xFF00FF; srcg = s & 0xFF00;
664
665drb = srcrb - dstrb;
666dg = srcg - dstg;
667drb *= a; dg *= a;
668drb >>= 8; dg >>= 8;
669
670rb = (drb + dstrb) & 0xFF00FF;
671g = (dg + dstg) & 0xFF00;
672
673*d = rb | g;
674}
675}
676break;
677
678default: /*Universal version*/
679{
680uint32_t s;
681uint32_t a; // Alpha
682uint32_t dr, dg, db, sr, sg, sb; // Intermediate variables
683uint16_t pos;
684int bpp;
685if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
686bpp = (VIDEO (depth) + 7)/8;
687else
688bpp = (VIDEOSNOW (depth) + 7)/8;
689
690for (pos = 0; pos < drawWidth; pos ++) {
691// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
692s = *((uint32_t*) (data + 4*pos));
693
694sb = (s & 0xFF0000) >> 16;
695sg = (s & 0xFF00) >> 8;
696sr = (s & 0xFF);
697
698a = (s >> 24) + 1;
699
700if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
701{
702switch (VIDEO (depth))
703{
704case 24:
705db = ((*(uint32_t *)(vram + bpp*pos))&0xff);
706dg = ((*(uint32_t *)(vram + bpp*pos))&0xff00)>>8;
707dr = ((*(uint32_t *)(vram + bpp*pos))&0xff0000)>>16;
708break;
709case 16://16-bit seems to be 15-bit
710/*db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
711 dg = ((*(uint16_t *)(vram + bpp*pos))&0x07e0)>>3;
712 dr = ((*(uint16_t *)(vram + bpp*pos))&0xf800)>>8;
713 break;*/
714case 15:
715db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
716dg = ((*(uint16_t *)(vram + bpp*pos))&0x03e0)>>2;
717dr = ((*(uint16_t *)(vram + bpp*pos))&0x7c00)>>7;
718break;
719default:
720return;
721}
722} else {
723switch (VIDEOSNOW (depth))
724{
725case 24:
726db = ((*(uint32_t *)(vram + bpp*pos))&0xff);
727dg = ((*(uint32_t *)(vram + bpp*pos))&0xff00)>>8;
728dr = ((*(uint32_t *)(vram + bpp*pos))&0xff0000)>>16;
729break;
730case 16://16-bit seems to be 15-bit
731/*db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
732 dg = ((*(uint16_t *)(vram + bpp*pos))&0x07e0)>>3;
733 dr = ((*(uint16_t *)(vram + bpp*pos))&0xf800)>>8;
734 break;*/
735case 15:
736db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
737dg = ((*(uint16_t *)(vram + bpp*pos))&0x03e0)>>2;
738dr = ((*(uint16_t *)(vram + bpp*pos))&0x7c00)>>7;
739break;
740default:
741return;
742}
743}
744
745dr = (((sr - dr) * a) >> 8) + dr;
746dg = (((sg - dg) * a) >> 8) + dg;
747db = (((sb - db) * a) >> 8) + db;
748if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
749{
750switch (VIDEO (depth))
751{
752case 24:
753*(uint32_t *)(vram + bpp*pos) = (*(uint32_t *)(vram + bpp*pos) &0xff000000)
754| (db&0xff) | ((dg&0xff)<<8) | ((dr&0xff)<<16);
755break;
756case 16:
757//*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xfc)<<3) | ((dr&0xf8)<<8);
758//break;
759case 15:
760*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xf8)<<2) | ((dr&0xf8)<<7);
761break;
762}
763} else {
764switch (VIDEOSNOW (depth))
765{
766case 24:
767*(uint32_t *)(vram + bpp*pos) = (*(uint32_t *)(vram + bpp*pos) &0xff000000)
768| (db&0xff) | ((dg&0xff)<<8) | ((dr&0xff)<<16);
769break;
770case 16:
771//*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xfc)<<3) | ((dr&0xf8)<<8);
772//break;
773case 15:
774*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xf8)<<2) | ((dr&0xf8)<<7);
775break;
776}
777}
778}
779}
780break;
781}
782} else {
783switch (VIDEOSNOW (depth))
784{
785case 32: /* Optimized version*/
786{
787uint32_t s; uint32_t* d; // Source (img) and destination (bkgd) pixels
788uint32_t a; // Alpha
789uint32_t dstrb, dstg, srcrb, srcg, drb, dg, rb, g, tempB; // Intermediate variables
790uint16_t pos;
791
792for (pos = 0; pos < drawWidth * 4; pos += 4) {
793// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
794s = *((uint32_t*) (data + pos));
795d = (uint32_t*) (vram + pos);
796
797// Flip B and R in source
798// TODO: use XCHG and inline assembly to do this in a faster, saner way
799tempB = (s & 0xFF0000); // save B
800s = (s & 0xFF00FFFF) | ((s & 0xFF) << 16); // put R in B
801s = (s & 0xFFFFFF00) | (tempB >> 16); // put B in R
802
803a = (s >> 24) + 1;
804
805dstrb = *d & 0xFF00FF; dstg = *d & 0xFF00;
806srcrb = s & 0xFF00FF; srcg = s & 0xFF00;
807
808drb = srcrb - dstrb;
809dg = srcg - dstg;
810drb *= a; dg *= a;
811drb >>= 8; dg >>= 8;
812
813rb = (drb + dstrb) & 0xFF00FF;
814g = (dg + dstg) & 0xFF00;
815
816*d = rb | g;
817}
818}
819break;
820default: /*Universal version*/
821{
822uint32_t s;
823uint32_t a; // Alpha
824uint32_t dr, dg, db, sr, sg, sb; // Intermediate variables
825uint16_t pos;
826int bpp;
827if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
828bpp = (VIDEO (depth) + 7)/8;
829else
830bpp = (VIDEOSNOW (depth) + 7)/8;
831
832for (pos = 0; pos < drawWidth; pos ++) {
833// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
834s = *((uint32_t*) (data + 4*pos));
835
836sb = (s & 0xFF0000) >> 16;
837sg = (s & 0xFF00) >> 8;
838sr = (s & 0xFF);
839
840a = (s >> 24) + 1;
841
842if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
843{
844switch (VIDEO (depth))
845{
846case 24:
847db = ((*(uint32_t *)(vram + bpp*pos))&0xff);
848dg = ((*(uint32_t *)(vram + bpp*pos))&0xff00)>>8;
849dr = ((*(uint32_t *)(vram + bpp*pos))&0xff0000)>>16;
850break;
851case 16://16-bit seems to be 15-bit
852/*db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
853 dg = ((*(uint16_t *)(vram + bpp*pos))&0x07e0)>>3;
854 dr = ((*(uint16_t *)(vram + bpp*pos))&0xf800)>>8;
855 break;*/
856case 15:
857db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
858dg = ((*(uint16_t *)(vram + bpp*pos))&0x03e0)>>2;
859dr = ((*(uint16_t *)(vram + bpp*pos))&0x7c00)>>7;
860break;
861default:
862return;
863}
864} else {
865switch (VIDEOSNOW (depth))
866{
867case 24:
868db = ((*(uint32_t *)(vram + bpp*pos))&0xff);
869dg = ((*(uint32_t *)(vram + bpp*pos))&0xff00)>>8;
870dr = ((*(uint32_t *)(vram + bpp*pos))&0xff0000)>>16;
871break;
872case 16://16-bit seems to be 15-bit
873/*db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
874 dg = ((*(uint16_t *)(vram + bpp*pos))&0x07e0)>>3;
875 dr = ((*(uint16_t *)(vram + bpp*pos))&0xf800)>>8;
876 break;*/
877case 15:
878db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
879dg = ((*(uint16_t *)(vram + bpp*pos))&0x03e0)>>2;
880dr = ((*(uint16_t *)(vram + bpp*pos))&0x7c00)>>7;
881break;
882default:
883return;
884}
885}
886
887dr = (((sr - dr) * a) >> 8) + dr;
888dg = (((sg - dg) * a) >> 8) + dg;
889db = (((sb - db) * a) >> 8) + db;
890if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
891{
892switch (VIDEO (depth))
893{
894case 24:
895*(uint32_t *)(vram + bpp*pos) = (*(uint32_t *)(vram + bpp*pos) &0xff000000)
896| (db&0xff) | ((dg&0xff)<<8) | ((dr&0xff)<<16);
897break;
898case 16:
899//*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xfc)<<3) | ((dr&0xf8)<<8);
900//break;
901case 15:
902*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xf8)<<2) | ((dr&0xf8)<<7);
903break;
904}
905} else {
906switch (VIDEOSNOW (depth))
907{
908case 24:
909*(uint32_t *)(vram + bpp*pos) = (*(uint32_t *)(vram + bpp*pos) &0xff000000)
910| (db&0xff) | ((dg&0xff)<<8) | ((dr&0xff)<<16);
911break;
912case 16:
913//*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xfc)<<3) | ((dr&0xf8)<<8);
914//break;
915case 15:
916*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xf8)<<2) | ((dr&0xf8)<<7);
917break;
918}
919}
920}
921}
922break;
923}
924 }
925 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
926 vram += VIDEO(rowBytes);
927 else
928 vram += VIDEOSNOW(rowBytes);
929 data += width * 4;
930 }
931}
932
933void drawCheckerBoard()
934{
935 uint32_t *vram;
936 uint16_t x, y;
937 uint8_t color;
938
939 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
940 vram = (uint32_t *) VIDEO(baseAddr);
941 else
942 vram = (uint32_t *) VIDEOSNOW(baseAddr);
943
944 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
945 {
946for (y = 0; y < VIDEO(height); y++, vram += VIDEO(width)) {
947for (x = 0; x < VIDEO(width); x++) {
948color = 204 + 51 * (((x / 8) % 2) == ((y / 8) % 2));
949vram[x] = (color << 16) | (color << 8) | color;
950}
951}
952} else {
953for (y = 0; y < VIDEOSNOW(height); y++, vram += VIDEOSNOW(width)) {
954for (x = 0; x < VIDEOSNOW(width); x++) {
955color = 204 + 51 * (((x / 8) % 2) == ((y / 8) % 2));
956vram[x] = (color << 16) | (color << 8) | color;
957}
958}
959}
960}
961
962//==========================================================================
963// LookUpCLUTIndex
964
965unsigned long lookUpCLUTIndex( unsigned char index,
966 unsigned char depth )
967{
968 long result, red, green, blue;
969
970 red = appleClut8[index * 3 + 0];
971 green = appleClut8[index * 3 + 1];
972 blue = appleClut8[index * 3 + 2];
973
974 switch (depth) {
975 case 16 :
976 result = ((red & 0xF8) << 7) |
977((green & 0xF8) << 2) |
978((blue & 0xF8) >> 3);
979 result |= (result << 16);
980 break;
981
982 case 32 :
983 result = (red << 16) | (green << 8) | blue;
984 break;
985
986 default :
987 result = index | (index << 8);
988 result |= (result << 16);
989 break;
990 }
991
992 return result;
993}
994
995//==========================================================================
996// drawColorRectangle
997
998void * stosl(void * dst, long val, long len)
999{
1000 asm volatile ( "rep; stosl"
1001 : "=c" (len), "=D" (dst)
1002 : "0" (len), "1" (dst), "a" (val)
1003 : "memory" );
1004
1005 return dst;
1006}
1007
1008void drawColorRectangle( unsigned short x,
1009unsigned short y,
1010unsigned short width,
1011unsigned short height,
1012unsigned char colorIndex )
1013{
1014 long pixelBytes;
1015long color;
1016char * vram;
1017
1018 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
1019 color = lookUpCLUTIndex( colorIndex, VIDEO(depth) );
1020 else
1021 color = lookUpCLUTIndex( colorIndex, VIDEOSNOW(depth) );
1022
1023 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
1024 {
1025pixelBytes = VIDEO(depth) / 8;
1026vram = (char *) VIDEO(baseAddr) +
1027VIDEO(rowBytes) * y + pixelBytes * x;
1028
1029width = MIN(width, VIDEO(width) - x);
1030height = MIN(height, VIDEO(height) - y);
1031} else {
1032pixelBytes = VIDEOSNOW(depth) / 8;
1033vram = (char *) VIDEOSNOW(baseAddr) +
1034VIDEO(rowBytes) * y + pixelBytes * x;
1035
1036width = MIN(width, VIDEOSNOW(width) - x);
1037height = MIN(height, VIDEOSNOW(height) - y);
1038}
1039
1040 while ( height-- )
1041 {
1042 int rem = ( pixelBytes * width ) % 4;
1043 if ( rem ) bcopy( &color, vram, rem );
1044 stosl( vram + rem, color, pixelBytes * width / 4 );
1045 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
1046 vram += VIDEO(rowBytes);
1047 else
1048 vram += VIDEOSNOW(rowBytes);
1049 }
1050}
1051
1052//==========================================================================
1053// drawDataRectangle
1054
1055void drawDataRectangle( unsigned short x,
1056 unsigned short y,
1057 unsigned short width,
1058 unsigned short height,
1059 unsigned char * data )
1060{
1061 unsigned short drawWidth;
1062 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
1063 {
1064long pixelBytes = VIDEO(depth) / 8;
1065unsigned char * vram = (unsigned char *) VIDEO(baseAddr) +
1066 VIDEO(rowBytes) * y + pixelBytes * x;
1067
1068drawWidth = MIN(width, VIDEO(width) - x);
1069height = MIN(height, VIDEO(height) - y);
1070while ( height-- ) {
1071bcopy( data, vram, drawWidth * pixelBytes );
1072vram += VIDEO(rowBytes);
1073data += width * pixelBytes;
1074}
1075} else {
1076long pixelBytes = VIDEOSNOW(depth) / 8;
1077unsigned char * vram = (unsigned char *) VIDEOSNOW(baseAddr) +
1078VIDEOSNOW(rowBytes) * y + pixelBytes * x;
1079
1080drawWidth = MIN(width, VIDEOSNOW(width) - x);
1081height = MIN(height, VIDEOSNOW(height) - y);
1082while ( height-- ) {
1083bcopy( data, vram, drawWidth * pixelBytes );
1084vram += VIDEOSNOW(rowBytes);
1085data += width * pixelBytes;
1086}
1087}
1088}
1089
1090void
1091loadImageScale (void *input, int iw, int ih, int ip, void *output, int ow, int oh, int op, int or)
1092{
1093int x,y, off;
1094int red=0x7f, green=0x7f, blue=0x7f;
1095for (x=0;x<ow;x++)
1096for (y=0;y<oh;y++)
1097{
1098off=(x*iw)/ow+((y*ih)/oh)*iw;
1099switch (ip)
1100{
1101case 16:
1102{
1103uint16_t val;
1104val=((uint16_t *)input)[off];
1105red=(val>>7)&0xf8;
1106green=(val>>2)&0xf8;
1107blue=(val<<3)&0xf8;
1108break;
1109}
1110case 32:
1111{
1112uint32_t val;
1113val=((uint32_t *)input)[off];
1114red=(val>>16)&0xff;
1115green=(val>>8)&0xff;
1116blue=(val)&0xff;
1117break;
1118}
1119}
1120char *ptr=(char *)output+x*(op/8)+y*or;
1121switch (op)
1122{
1123case 16:
1124*((uint16_t *)ptr) = ((red & 0xF8) << 7) |
1125((green & 0xF8) << 2) |
1126((blue & 0xF8) >> 3);
1127break;
1128case 32 :
1129*((uint32_t *)ptr) = (red << 16) | (green << 8) | blue;
1130break;
1131}
1132}
1133}
1134
1135DECLARE_IOHIBERNATEPROGRESSALPHA
1136
1137void drawPreview(void *src, uint8_t * saveunder)
1138{
1139uint8_t * screen;
1140uint32_t rowBytes, pixelShift;
1141uint32_t x, y;
1142int32_t blob;
1143uint32_t alpha, in, color, result;
1144uint8_t * out;
1145void *uncomp;
1146int origwidth, origheight, origbpx;
1147uint32_t saveindex[kIOHibernateProgressCount] = { 0 };
1148
1149if (src && (uncomp=DecompressData(src, &origwidth, &origheight, &origbpx)))
1150{
1151if (!setVESAGraphicsMode(origwidth, origheight, origbpx, 0))
1152if (initGraphicsMode () != errSuccess)
1153return;
1154if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
1155{
1156screen = (uint8_t *) VIDEO (baseAddr);
1157rowBytes = VIDEO (rowBytes);
1158loadImageScale (uncomp, origwidth, origheight, origbpx, screen, VIDEO(width), VIDEO(height), VIDEO(depth), VIDEO (rowBytes));
1159} else {
1160screen = (uint8_t *) VIDEOSNOW (baseAddr);
1161rowBytes = VIDEOSNOW (rowBytes);
1162loadImageScale (uncomp, origwidth, origheight, origbpx, screen, VIDEOSNOW(width), VIDEOSNOW(height), VIDEOSNOW(depth), VIDEOSNOW (rowBytes));
1163}
1164}
1165else
1166{
1167if (initGraphicsMode () != errSuccess)
1168return;
1169 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
1170 {
1171screen = (uint8_t *) VIDEO (baseAddr);
1172rowBytes = VIDEO (rowBytes);
1173// Set the screen to 75% grey.
1174drawColorRectangle(0, 0, VIDEO(width), VIDEO(height), 0x01 /* color index */);
1175} else {
1176screen = (uint8_t *) VIDEOSNOW (baseAddr);
1177rowBytes = VIDEOSNOW (rowBytes);
1178// Set the screen to 75% grey.
1179drawColorRectangle(0, 0, VIDEOSNOW(width), VIDEOSNOW(height), 0x01 /* color index */);
1180}
1181}
1182
1183if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
1184pixelShift = VIDEO (depth) >> 4;
1185else
1186pixelShift = VIDEOSNOW (depth) >> 4;
1187if (pixelShift < 1) return;
1188
1189 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
1190 {
1191screen += ((VIDEO (width)
1192- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))
1193+ (VIDEO (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;
1194} else {
1195screen += ((VIDEOSNOW (width)
1196- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))
1197+ (VIDEOSNOW (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;
1198}
1199
1200for (y = 0; y < kIOHibernateProgressHeight; y++)
1201{
1202out = screen + y * rowBytes;
1203for (blob = 0; blob < kIOHibernateProgressCount; blob++)
1204{
1205color = blob ? kIOHibernateProgressDarkGray : kIOHibernateProgressMidGray;
1206for (x = 0; x < kIOHibernateProgressWidth; x++)
1207{
1208alpha = gIOHibernateProgressAlpha[y][x];
1209result = color;
1210if (alpha)
1211{
1212if (0xff != alpha)
1213{
1214if (1 == pixelShift)
1215{
1216in = *((uint16_t *)out) & 0x1f;// 16
1217in = (in << 3) | (in >> 2);
1218}
1219else
1220in = *((uint32_t *)out) & 0xff;// 32
1221saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++] = in;
1222result = ((255 - alpha) * in + alpha * result + 0xff) >> 8;
1223}
1224if (1 == pixelShift)
1225{
1226result >>= 3;
1227*((uint16_t *)out) = (result << 10) | (result << 5) | result;// 16
1228}
1229else
1230*((uint32_t *)out) = (result << 16) | (result << 8) | result;// 32
1231}
1232out += (1 << pixelShift);
1233}
1234out += (kIOHibernateProgressSpacing << pixelShift);
1235}
1236}
1237}
1238
1239void updateProgressBar(uint8_t * saveunder, int32_t firstBlob, int32_t select)
1240{
1241uint8_t * screen;
1242uint32_t rowBytes, pixelShift;
1243uint32_t x, y;
1244int32_t blob, lastBlob;
1245uint32_t alpha, in, color, result;
1246uint8_t * out;
1247uint32_t saveindex[kIOHibernateProgressCount] = { 0 };
1248
1249 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
1250pixelShift = VIDEO(depth) >> 4;
1251else
1252pixelShift = VIDEOSNOW(depth) >> 4;
1253if (pixelShift < 1) return;
1254 if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
1255 {
1256screen = (uint8_t *) VIDEO (baseAddr);
1257rowBytes = VIDEO (rowBytes);
1258
1259screen += ((VIDEO (width)
1260- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))
1261+ (VIDEO (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;
1262} else {
1263screen = (uint8_t *) VIDEOSNOW (baseAddr);
1264rowBytes = VIDEOSNOW (rowBytes);
1265
1266screen += ((VIDEOSNOW (width)
1267- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))
1268+ (VIDEOSNOW (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;
1269}
1270
1271lastBlob = (select < kIOHibernateProgressCount) ? select : (kIOHibernateProgressCount - 1);
1272
1273screen += (firstBlob * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << pixelShift;
1274
1275for (y = 0; y < kIOHibernateProgressHeight; y++)
1276{
1277out = screen + y * rowBytes;
1278for (blob = firstBlob; blob <= lastBlob; blob++)
1279{
1280color = (blob < select) ? kIOHibernateProgressLightGray : kIOHibernateProgressMidGray;
1281for (x = 0; x < kIOHibernateProgressWidth; x++)
1282{
1283alpha = gIOHibernateProgressAlpha[y][x];
1284result = color;
1285if (alpha)
1286{
1287if (0xff != alpha)
1288{
1289in = saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++];
1290result = ((255 - alpha) * in + alpha * result + 0xff) / 255;
1291}
1292if (1 == pixelShift)
1293{
1294result >>= 3;
1295*((uint16_t *)out) = (result << 10) | (result << 5) | result;// 16
1296}
1297else
1298*((uint32_t *)out) = (result << 16) | (result << 8) | result;// 32
1299}
1300out += (1 << pixelShift);
1301}
1302out += (kIOHibernateProgressSpacing << pixelShift);
1303}
1304}
1305}
1306
1307
1308//==========================================================================
1309// setVESATextMode
1310
1311static int
1312setVESATextMode( unsigned short cols,
1313unsigned short rows,
1314unsigned char bitsPerPixel )
1315{
1316 VBEModeInfoBlock minfo;
1317 unsigned short mode = modeEndOfList;
1318
1319 if ( (cols != 80) || (rows != 25) ) // not 80x25 mode
1320 {
1321 mode = getVESAModeWithProperties( cols, rows, bitsPerPixel,
1322 maColorModeBit |
1323 maModeIsSupportedBit,
1324 maGraphicsModeBit,
1325 &minfo, NULL );
1326 }
1327
1328 if ( ( mode == modeEndOfList ) || ( setVBEMode(mode, NULL) != errSuccess ) )
1329 {
1330 video_mode( 2 ); // VGA BIOS, 80x25 text mode.
1331 minfo.XResolution = 80;
1332 minfo.YResolution = 25;
1333 }
1334
1335 // Update KernBootStruct using info provided by the selected
1336 // VESA mode.
1337
1338 bootArgs->Video.v_display = VGA_TEXT_MODE;
1339 bootArgs->Video.v_baseAddr = 0xb8000;
1340 bootArgs->Video.v_width = minfo.XResolution;
1341 bootArgs->Video.v_height = minfo.YResolution;
1342 bootArgs->Video.v_depth = 8;
1343 bootArgs->Video.v_rowBytes = 0x8000;
1344
1345 bootArgsSnow->Video.v_display = VGA_TEXT_MODE;
1346 bootArgsSnow->Video.v_baseAddr = 0xb8000;
1347 bootArgsSnow->Video.v_width = minfo.XResolution;
1348 bootArgsSnow->Video.v_height = minfo.YResolution;
1349 bootArgsSnow->Video.v_depth = 8;
1350 bootArgsSnow->Video.v_rowBytes = 0x8000;
1351
1352 return errSuccess; // always return success
1353}
1354
1355//==========================================================================
1356// getNumberArrayFromProperty
1357
1358static int
1359getNumberArrayFromProperty( const char * propKey,
1360 unsigned long numbers[],
1361 unsigned long maxArrayCount )
1362{
1363 char * propStr;
1364 unsigned long count = 0;
1365
1366 propStr = newStringForKey( (char *) propKey , &bootInfo->bootConfig );
1367 if ( propStr )
1368 {
1369 char * delimiter = propStr;
1370 char * p = propStr;
1371
1372 while ( count < maxArrayCount && *p != '\0' )
1373 {
1374 unsigned long val = strtoul( p, &delimiter, 10 );
1375 if ( p != delimiter )
1376 {
1377 numbers[count++] = val;
1378 p = delimiter;
1379 }
1380 while ( ( *p != '\0' ) && !isdigit(*p) )
1381 p++;
1382 }
1383
1384 free( propStr );
1385 }
1386
1387 return count;
1388}
1389
1390int initGraphicsMode ()
1391{
1392unsigned long params[4];
1393int count;
1394
1395params[3] = 0;
1396count = getNumberArrayFromProperty( kGraphicsModeKey, params, 4 );
1397
1398// Try to find a resolution if "Graphics Mode" setting is not available.
1399if ( count < 3 )
1400{
1401// Use the default resolution if we don't have an initialized GUI.
1402if (gui.screen.width == 0 || gui.screen.height == 0)
1403{
1404gui.screen.width = DEFAULT_SCREEN_WIDTH;
1405gui.screen.height = DEFAULT_SCREEN_HEIGHT;
1406}
1407
1408params[0] = gui.screen.width;
1409params[1] = gui.screen.height;
1410params[2] = 32;
1411}
1412
1413// Map from pixel format to bits per pixel.
1414
1415if ( params[2] == 256 ) params[2] = 8;
1416if ( params[2] == 555 ) params[2] = 16;
1417if ( params[2] == 888 ) params[2] = 32;
1418
1419return setVESAGraphicsMode( params[0], params[1], params[2], params[3] );
1420}
1421
1422//==========================================================================
1423// setVideoMode
1424//
1425// Set the video mode to VGA_TEXT_MODE or GRAPHICS_MODE.
1426
1427void
1428setVideoMode( int mode, int drawgraphics)
1429{
1430 unsigned long params[4];
1431 int count;
1432 int err = errSuccess;
1433
1434 if ( mode == GRAPHICS_MODE )
1435 {
1436 if ( (err=initGraphicsMode ()) == errSuccess ) {
1437if (gVerboseMode) {
1438// Tell the kernel to use text mode on a linear frame buffer display
1439bootArgs->Video.v_display = FB_TEXT_MODE;
1440bootArgsSnow->Video.v_display = FB_TEXT_MODE;
1441} else {
1442bootArgs->Video.v_display = GRAPHICS_MODE;
1443bootArgsSnow->Video.v_display = GRAPHICS_MODE;
1444}
1445}
1446 }
1447
1448 if ( (mode == VGA_TEXT_MODE) || (err != errSuccess) )
1449 {
1450 count = getNumberArrayFromProperty( kTextModeKey, params, 2 );
1451 if ( count < 2 )
1452 {
1453 params[0] = 80; // Default text mode is 80x25.
1454 params[1] = 25;
1455 }
1456
1457setVESATextMode( params[0], params[1], 4 );
1458 bootArgs->Video.v_display = VGA_TEXT_MODE;
1459 bootArgsSnow->Video.v_display = VGA_TEXT_MODE;
1460 }
1461
1462 currentIndicator = 0;
1463}
1464
1465void getGraphicModeParams(unsigned long params[]) {
1466
1467params[3] = 0;
1468
1469VBEModeInfoBlock minfo;
1470
1471 unsigned short vesaVersion;
1472 unsigned short mode = modeEndOfList;
1473
1474getNumberArrayFromProperty( kGraphicsModeKey, params, 4);
1475
1476mode = getVESAModeWithProperties( params[0], params[1], params[2],
1477 maColorModeBit |
1478 maModeIsSupportedBit |
1479 maGraphicsModeBit |
1480 maLinearFrameBufferAvailBit,
1481 0,
1482 &minfo, &vesaVersion );
1483
1484params[0] = minfo.XResolution;
1485params[1] = minfo.YResolution;
1486params[2] = 32;
1487}
1488
1489//==========================================================================
1490// Return the current video mode, VGA_TEXT_MODE or GRAPHICS_MODE.
1491
1492int getVideoMode(void)
1493{
1494if ((gMacOSVersion[0] == '1') && (gMacOSVersion[1] == '0') && (gMacOSVersion[2] == '.') && (gMacOSVersion[3] >= '7'))
1495 return bootArgs->Video.v_display;
1496
1497 return bootArgsSnow->Video.v_display;
1498}
1499
1500//==========================================================================
1501// Display and clear the activity indicator.
1502
1503static char indicator[] = {'-', '\\', '|', '/', '-', '\\', '|', '/', '\0'};
1504
1505// To prevent a ridiculously fast-spinning indicator,
1506// ensure a minimum of 1/9 sec between animation frames.
1507#define MIN_TICKS 2
1508
1509void
1510spinActivityIndicator(int sectors)
1511{
1512 static unsigned long lastTickTime = 0, currentTickTime;
1513
1514if (previewTotalSectors && previewSaveunder)
1515{
1516int blob, lastBlob;
1517
1518lastBlob = (previewLoadedSectors * kIOHibernateProgressCount) / previewTotalSectors;
1519previewLoadedSectors+=sectors;
1520blob = (previewLoadedSectors * kIOHibernateProgressCount) / previewTotalSectors;
1521
1522if (blob!=lastBlob)
1523updateProgressBar (previewSaveunder, lastBlob, blob);
1524return;
1525}
1526
1527currentTickTime = time18(); // late binding
1528if (currentTickTime < lastTickTime + MIN_TICKS)
1529{
1530return;
1531}
1532else
1533{
1534lastTickTime = currentTickTime;
1535}
1536
1537if (getVideoMode() == VGA_TEXT_MODE)
1538{
1539if (currentIndicator >= sizeof(indicator))
1540{
1541currentIndicator = 0;
1542}
1543putc(indicator[currentIndicator++]);
1544putc('\b');
1545}
1546}
1547
1548void
1549clearActivityIndicator( void )
1550{
1551 if ( getVideoMode() == VGA_TEXT_MODE )
1552 {
1553putc(' ');
1554putc('\b');
1555 }
1556}
1557
1558

Archive Download this file

Revision: 755