Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/CleanCut/i386/boot2/graphics.c

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
46#define MIN(x, y) ((x) < (y) ? (x) : (y))
47
48//==========================================================================
49// getVBEInfoString
50
51char *getVBEInfoString()
52{
53VBEInfoBlock vbeInfo;
54int err, small;
55char *buff = malloc(sizeof(char)*256);
56if(!buff) return 0;
57
58bzero( &vbeInfo, sizeof(vbeInfo) );
59strcpy( (char*)&vbeInfo, "VBE2" );
60err = getVBEInfo( &vbeInfo );
61if (err != errSuccess)
62return 0;
63
64if ( strncmp( (char *)vbeInfo.VESASignature, "VESA", 4 ) )
65return 0;
66
67small = (vbeInfo.TotalMemory < 16);
68
69sprintf(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
76return buff;
77}
78
79//==========================================================================
80//
81
82void
83printVBEModeInfo()
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() );
105printf("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
139char *getVBEModeInfoString()
140{
141VBEInfoBlock 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
152char *buff=malloc(sizeof(char)*3072);
153if(!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 }
174return 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
183static unsigned short
184getVESAModeWithProperties( 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
324static 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
341char * 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
366static int
367setVESAGraphicsMode( unsigned short width,
368 unsigned short height,
369 unsigned char bitsPerPixel,
370 unsigned short refreshRate )
371{
372bool debugInfo = false; //Azi:debuginfo
373extern bool showBootBanner; //||
374 VBEModeInfoBlock minfo;
375 unsigned short mode;
376 unsigned short vesaVersion;
377 int err = errFuncNotSupported;
378
379 do {
380 mode = getVESAModeWithProperties( width, height, bitsPerPixel,
381 maColorModeBit |
382 maModeIsSupportedBit |
383 maGraphicsModeBit |
384 maLinearFrameBufferAvailBit,
385 0,
386 &minfo, &vesaVersion );
387 if ( mode == modeEndOfList )
388 {
389 break;
390 }
391
392//
393// FIXME : generateCRTCTiming() causes crash.
394//
395
396// if ( (vesaVersion >> 8) >= 3 && refreshRate >= 60 &&
397// (gBootMode & kBootModeSafe) == 0 )
398// {
399// VBECRTCInfoBlock timing;
400//
401// // Generate CRTC timing for given refresh rate.
402//
403// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
404// refreshRate, kCRTCParamRefreshRate,
405// &timing );
406//
407// // Find the actual pixel clock supported by the hardware.
408//
409// getVBEPixelClock( mode, &timing.PixelClock );
410//
411// // Re-compute CRTC timing based on actual pixel clock.
412//
413// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
414// timing.PixelClock, kCRTCParamPixelClock,
415// &timing );
416//
417// // Set the video mode and use specified CRTC timing.
418//
419// err = setVBEMode( mode | kLinearFrameBufferBit |
420// kCustomRefreshRateBit, &timing );
421// }
422// else
423// {
424// // Set the mode with default refresh rate.
425//
426// err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
427// }
428
429 // Set the mode with default refresh rate.
430
431 err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
432
433 if ( err != errSuccess )
434 {
435 break;
436 }
437
438 // Set 8-bit color palette.
439
440 if ( minfo.BitsPerPixel == 8 )
441 {
442 VBEPalette palette;
443 setupPalette( &palette, appleClut8 );
444 if ((err = setVBEPalette(palette)) != errSuccess)
445 {
446 break;
447 }
448 }
449
450 // Is this required for buggy Video BIOS implementations?
451 // On which adapter?
452
453 if ( minfo.BytesPerScanline == 0 )
454 minfo.BytesPerScanline = ( minfo.XResolution *
455 minfo.BitsPerPixel ) >> 3;
456
457 // Update KernBootStruct using info provided by the selected
458 // VESA mode.
459
460 bootArgs->Video.v_display = GRAPHICS_MODE;
461 bootArgs->Video.v_width = minfo.XResolution;
462 bootArgs->Video.v_height = minfo.YResolution;
463 bootArgs->Video.v_depth = minfo.BitsPerPixel;
464 bootArgs->Video.v_rowBytes = minfo.BytesPerScanline;
465 bootArgs->Video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
466
467//Azi: mm & attr info on DebugInfo - from AutoResolution branch.
468getBoolForKey(kDebugInfoKey, &debugInfo, &bootInfo->bootConfig);
469
470if (debugInfo && showBootBanner)
471{
472gui.screen.mm = minfo.MemoryModel;
473gui.screen.attr = minfo.ModeAttributes;
474}
475 }
476 while ( 0 );
477
478 return err;
479}
480
481int
482convertImage( unsigned short width,
483 unsigned short height,
484 const unsigned char *imageData,
485 unsigned char **newImageData )
486{
487 int cnt;
488 unsigned char *img = 0;
489 unsigned short *img16;
490 unsigned long *img32;
491
492 switch ( VIDEO(depth) ) {
493 case 16 :
494 img16 = malloc(width * height * 2);
495 if ( !img16 ) break;
496 for (cnt = 0; cnt < (width * height); cnt++)
497 img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16);
498 img = (unsigned char *)img16;
499 break;
500
501 case 32 :
502 img32 = malloc(width * height * 4);
503 if ( !img32 ) break;
504 for (cnt = 0; cnt < (width * height); cnt++)
505 img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32);
506 img = (unsigned char *)img32;
507 break;
508
509 default :
510 img = malloc(width * height);
511 bcopy(imageData, img, width * height);
512 break;
513 }
514 *newImageData = img;
515 return 0;
516}
517
518int loadPngImage(const char *filename, uint16_t *width, uint16_t *height,
519 uint8_t **imageData)
520{
521 uint8_t *pngData = NULL;
522 int pngFile = 0, pngSize;
523 PNG_info_t *info;
524 int error = 0;
525
526 pngFile = open_bvdev("bt(0,0)", filename, 0);
527 if (pngFile == -1) {
528 error = -1;
529 goto failed;
530 }
531 pngSize = file_size(pngFile);
532 if (!pngSize) {
533 error = -1;
534 goto failed;
535 }
536 pngData = malloc(pngSize);
537 if (read(pngFile, (char *) pngData, pngSize) != pngSize) {
538 error = -1;
539 goto failed;
540 }
541
542 PNG_error = -1;
543 info = PNG_decode(pngData, pngSize);
544 if (PNG_error != 0) {
545 error = PNG_error;
546 goto failed;
547 } else if ((info->width > 0xffff) || (info->height > 0xffff)) {
548 error = -1;
549 goto failed;
550 } else if ((info->width * info->height * 4) != info->image->size) {
551 error = -1;
552 goto failed;
553 }
554uint8_t *result = malloc(info->width*4*info->height);
555 *width = info->width;
556 *height = info->height;
557memcpy(result, info->image->data, info->width*4*info->height);
558*imageData = result;
559
560failed:
561png_alloc_free_all();
562 if (pngData)
563 free(pngData);
564 if (pngFile != -1)
565 close(pngFile);
566
567 return error;
568}
569
570int loadEmbeddedPngImage(uint8_t *pngData, int pngSize, uint16_t *width, uint16_t *height, uint8_t **imageData) {
571 PNG_info_t *info;
572 int error = 0;
573
574 PNG_error = -1;
575 info = PNG_decode(pngData, pngSize);
576if (PNG_error != 0) {
577 error = PNG_error;
578 goto failed;
579 } else if ((info->width > 0xffff) || (info->height > 0xffff)) {
580 error = -1;
581 goto failed;
582 } else if ((info->width * info->height * 4) != info->image->size) {
583 error = -1;
584 goto failed;
585 }
586uint8_t *result = malloc(info->width*4*info->height);
587*width = info->width;
588 *height = info->height;
589memcpy(result, info->image->data, info->width*4*info->height);
590*imageData = result;
591
592failed:
593png_alloc_free_all();
594
595 return error;
596}
597
598void blendImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
599 uint8_t *data)
600{
601 uint16_t drawWidth;
602 uint8_t *vram = (uint8_t *) VIDEO(baseAddr) + VIDEO(rowBytes) * y + 4 * x;
603
604 drawWidth = MIN(width, VIDEO(width) - x);
605 height = MIN(height, VIDEO(height) - y);
606 while (height--) {
607switch (VIDEO (depth))
608{
609case 32: /* Optimized version*/
610{
611uint32_t s; uint32_t* d; // Source (img) and destination (bkgd) pixels
612uint32_t a; // Alpha
613uint32_t dstrb, dstg, srcrb, srcg, drb, dg, rb, g, tempB; // Intermediate variables
614uint16_t pos;
615
616for (pos = 0; pos < drawWidth * 4; pos += 4) {
617// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
618s = *((uint32_t*) (data + pos));
619d = (uint32_t*) (vram + pos);
620
621// Flip B and R in source
622// TODO: use XCHG and inline assembly to do this in a faster, saner way
623tempB = (s & 0xFF0000); // save B
624s = (s & 0xFF00FFFF) | ((s & 0xFF) << 16); // put R in B
625s = (s & 0xFFFFFF00) | (tempB >> 16); // put B in R
626
627a = (s >> 24) + 1;
628
629dstrb = *d & 0xFF00FF; dstg = *d & 0xFF00;
630srcrb = s & 0xFF00FF; srcg = s & 0xFF00;
631
632drb = srcrb - dstrb;
633dg = srcg - dstg;
634drb *= a; dg *= a;
635drb >>= 8; dg >>= 8;
636
637rb = (drb + dstrb) & 0xFF00FF;
638g = (dg + dstg) & 0xFF00;
639
640*d = rb | g;
641}
642}
643break;
644
645default: /*Universal version*/
646{
647uint32_t s;
648uint32_t a; // Alpha
649uint32_t dr, dg, db, sr, sg, sb; // Intermediate variables
650uint16_t pos;
651int bpp = (VIDEO (depth) + 7)/8;
652
653for (pos = 0; pos < drawWidth; pos ++) {
654// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
655s = *((uint32_t*) (data + 4*pos));
656
657sb = (s & 0xFF0000) >> 16;
658sg = (s & 0xFF00) >> 8;
659sr = (s & 0xFF);
660
661a = (s >> 24) + 1;
662
663switch (VIDEO (depth))
664{
665case 24:
666db = ((*(uint32_t *)(vram + bpp*pos))&0xff);
667dg = ((*(uint32_t *)(vram + bpp*pos))&0xff00)>>8;
668dr = ((*(uint32_t *)(vram + bpp*pos))&0xff0000)>>16;
669break;
670case 16://16-bit seems to be 15-bit
671/*db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
672dg = ((*(uint16_t *)(vram + bpp*pos))&0x07e0)>>3;
673dr = ((*(uint16_t *)(vram + bpp*pos))&0xf800)>>8;
674break;*/
675case 15:
676db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
677dg = ((*(uint16_t *)(vram + bpp*pos))&0x03e0)>>2;
678dr = ((*(uint16_t *)(vram + bpp*pos))&0x7c00)>>7;
679break;
680default:
681return;
682}
683
684dr = (((sr - dr) * a) >> 8) + dr;
685dg = (((sg - dg) * a) >> 8) + dg;
686db = (((sb - db) * a) >> 8) + db;
687switch (VIDEO (depth))
688{
689case 24:
690*(uint32_t *)(vram + bpp*pos) = (*(uint32_t *)(vram + bpp*pos) &0xff000000)
691| (db&0xff) | ((dg&0xff)<<8) | ((dr&0xff)<<16);
692break;
693case 16:
694//*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xfc)<<3) | ((dr&0xf8)<<8);
695//break;
696case 15:
697*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xf8)<<2) | ((dr&0xf8)<<7);
698break;
699}
700
701}
702}
703break;
704 }
705 vram += VIDEO(rowBytes);
706 data += width * 4;
707 }
708}
709
710void drawCheckerBoard()
711{
712 uint32_t *vram = (uint32_t *) VIDEO(baseAddr);
713 uint16_t x, y;
714 uint8_t color;
715
716 for (y = 0; y < VIDEO(height); y++, vram += VIDEO(width)) {
717 for (x = 0; x < VIDEO(width); x++) {
718 color = 204 + 51 * (((x / 8) % 2) == ((y / 8) % 2));
719 vram[x] = (color << 16) | (color << 8) | color;
720 }
721 }
722}
723
724//==========================================================================
725// LookUpCLUTIndex
726
727unsigned long lookUpCLUTIndex( unsigned char index,
728 unsigned char depth )
729{
730 long result, red, green, blue;
731
732 red = appleClut8[index * 3 + 0];
733 green = appleClut8[index * 3 + 1];
734 blue = appleClut8[index * 3 + 2];
735
736 switch (depth) {
737 case 16 :
738 result = ((red & 0xF8) << 7) |
739 ((green & 0xF8) << 2) |
740 ((blue & 0xF8) >> 3);
741 result |= (result << 16);
742 break;
743
744 case 32 :
745 result = (red << 16) | (green << 8) | blue;
746 break;
747
748 default :
749 result = index | (index << 8);
750 result |= (result << 16);
751 break;
752 }
753
754 return result;
755}
756
757//==========================================================================
758// drawColorRectangle
759
760void * stosl(void * dst, long val, long len)
761{
762 asm volatile ( "rep; stosl"
763 : "=c" (len), "=D" (dst)
764 : "0" (len), "1" (dst), "a" (val)
765 : "memory" );
766
767 return dst;
768}
769
770void drawColorRectangle( unsigned short x,
771 unsigned short y,
772 unsigned short width,
773 unsigned short height,
774 unsigned char colorIndex )
775{
776 long pixelBytes;
777 long color = lookUpCLUTIndex( colorIndex, VIDEO(depth) );
778 char * vram;
779
780 pixelBytes = VIDEO(depth) / 8;
781 vram = (char *) VIDEO(baseAddr) +
782 VIDEO(rowBytes) * y + pixelBytes * x;
783
784 width = MIN(width, VIDEO(width) - x);
785 height = MIN(height, VIDEO(height) - y);
786
787 while ( height-- )
788 {
789 int rem = ( pixelBytes * width ) % 4;
790 if ( rem ) bcopy( &color, vram, rem );
791 stosl( vram + rem, color, pixelBytes * width / 4 );
792 vram += VIDEO(rowBytes);
793 }
794}
795
796//==========================================================================
797// drawDataRectangle
798
799void drawDataRectangle( unsigned short x,
800 unsigned short y,
801 unsigned short width,
802 unsigned short height,
803 unsigned char * data )
804{
805 unsigned short drawWidth;
806 long pixelBytes = VIDEO(depth) / 8;
807 unsigned char * vram = (unsigned char *) VIDEO(baseAddr) +
808 VIDEO(rowBytes) * y + pixelBytes * x;
809
810 drawWidth = MIN(width, VIDEO(width) - x);
811 height = MIN(height, VIDEO(height) - y);
812 while ( height-- ) {
813 bcopy( data, vram, drawWidth * pixelBytes );
814 vram += VIDEO(rowBytes);
815 data += width * pixelBytes;
816 }
817}
818
819void
820loadImageScale (void *input, int iw, int ih, int ip, void *output, int ow, int oh, int op, int or)
821{
822int x,y, off;
823int red=0x7f, green=0x7f, blue=0x7f;
824for (x=0;x<ow;x++)
825for (y=0;y<oh;y++)
826{
827off=(x*iw)/ow+((y*ih)/oh)*iw;
828switch (ip)
829{
830case 16:
831{
832uint16_t val;
833val=((uint16_t *)input)[off];
834red=(val>>7)&0xf8;
835green=(val>>2)&0xf8;
836blue=(val<<3)&0xf8;
837break;
838}
839case 32:
840{
841uint32_t val;
842val=((uint32_t *)input)[off];
843red=(val>>16)&0xff;
844green=(val>>8)&0xff;
845blue=(val)&0xff;
846break;
847}
848}
849char *ptr=(char *)output+x*(op/8)+y*or;
850switch (op)
851{
852case 16:
853*((uint16_t *)ptr) = ((red & 0xF8) << 7) |
854((green & 0xF8) << 2) |
855((blue & 0xF8) >> 3);
856break;
857case 32 :
858*((uint32_t *)ptr) = (red << 16) | (green << 8) | blue;
859break;
860}
861}
862}
863
864DECLARE_IOHIBERNATEPROGRESSALPHA
865
866void drawPreview(void *src, uint8_t * saveunder)
867{
868uint8_t * screen;
869uint32_t rowBytes, pixelShift;
870uint32_t x, y;
871int32_t blob;
872uint32_t alpha, in, color, result;
873uint8_t * out;
874void *uncomp;
875int origwidth, origheight, origbpx;
876uint32_t saveindex[kIOHibernateProgressCount] = { 0 };
877
878if (src && (uncomp=DecompressData(src, &origwidth, &origheight, &origbpx)))
879{
880if (!setVESAGraphicsMode(origwidth, origheight, origbpx, 0))
881if (initGraphicsMode () != errSuccess)
882return;
883screen = (uint8_t *) VIDEO (baseAddr);
884rowBytes = VIDEO (rowBytes);
885loadImageScale (uncomp, origwidth, origheight, origbpx, screen, VIDEO(width), VIDEO(height), VIDEO(depth), VIDEO (rowBytes));
886}
887else
888{
889if (initGraphicsMode () != errSuccess)
890return;
891screen = (uint8_t *) VIDEO (baseAddr);
892rowBytes = VIDEO (rowBytes);
893// Set the screen to 75% grey.
894 drawColorRectangle(0, 0, VIDEO(width), VIDEO(height), 0x01 /* color index */);
895}
896
897
898pixelShift = VIDEO (depth) >> 4;
899if (pixelShift < 1) return;
900
901screen += ((VIDEO (width)
902- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))
903+ (VIDEO (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;
904
905for (y = 0; y < kIOHibernateProgressHeight; y++)
906{
907out = screen + y * rowBytes;
908for (blob = 0; blob < kIOHibernateProgressCount; blob++)
909{
910color = blob ? kIOHibernateProgressDarkGray : kIOHibernateProgressMidGray;
911for (x = 0; x < kIOHibernateProgressWidth; x++)
912{
913alpha = gIOHibernateProgressAlpha[y][x];
914result = color;
915if (alpha)
916{
917if (0xff != alpha)
918{
919if (1 == pixelShift)
920{
921in = *((uint16_t *)out) & 0x1f;// 16
922in = (in << 3) | (in >> 2);
923}
924else
925in = *((uint32_t *)out) & 0xff;// 32
926saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++] = in;
927result = ((255 - alpha) * in + alpha * result + 0xff) >> 8;
928}
929if (1 == pixelShift)
930{
931result >>= 3;
932*((uint16_t *)out) = (result << 10) | (result << 5) | result;// 16
933}
934else
935*((uint32_t *)out) = (result << 16) | (result << 8) | result;// 32
936}
937out += (1 << pixelShift);
938}
939out += (kIOHibernateProgressSpacing << pixelShift);
940}
941}
942}
943
944void updateProgressBar(uint8_t * saveunder, int32_t firstBlob, int32_t select)
945{
946uint8_t * screen;
947uint32_t rowBytes, pixelShift;
948uint32_t x, y;
949int32_t blob, lastBlob;
950uint32_t alpha, in, color, result;
951uint8_t * out;
952uint32_t saveindex[kIOHibernateProgressCount] = { 0 };
953
954pixelShift = VIDEO(depth) >> 4;
955if (pixelShift < 1) return;
956screen = (uint8_t *) VIDEO (baseAddr);
957rowBytes = VIDEO (rowBytes);
958
959screen += ((VIDEO (width)
960- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))
961+ (VIDEO (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;
962
963lastBlob = (select < kIOHibernateProgressCount) ? select : (kIOHibernateProgressCount - 1);
964
965screen += (firstBlob * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << pixelShift;
966
967for (y = 0; y < kIOHibernateProgressHeight; y++)
968{
969out = screen + y * rowBytes;
970for (blob = firstBlob; blob <= lastBlob; blob++)
971{
972color = (blob < select) ? kIOHibernateProgressLightGray : kIOHibernateProgressMidGray;
973for (x = 0; x < kIOHibernateProgressWidth; x++)
974{
975alpha = gIOHibernateProgressAlpha[y][x];
976result = color;
977if (alpha)
978{
979if (0xff != alpha)
980{
981in = saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++];
982result = ((255 - alpha) * in + alpha * result + 0xff) / 255;
983}
984if (1 == pixelShift)
985{
986result >>= 3;
987*((uint16_t *)out) = (result << 10) | (result << 5) | result;// 16
988}
989else
990*((uint32_t *)out) = (result << 16) | (result << 8) | result;// 32
991}
992out += (1 << pixelShift);
993}
994out += (kIOHibernateProgressSpacing << pixelShift);
995}
996}
997}
998
999
1000//==========================================================================
1001// setVESATextMode
1002
1003static int
1004setVESATextMode( unsigned short cols,
1005 unsigned short rows,
1006 unsigned char bitsPerPixel )
1007{
1008 VBEModeInfoBlock minfo;
1009 unsigned short mode = modeEndOfList;
1010
1011 if ( (cols != 80) || (rows != 25) ) // not 80x25 mode
1012 {
1013 mode = getVESAModeWithProperties( cols, rows, bitsPerPixel,
1014 maColorModeBit |
1015 maModeIsSupportedBit,
1016 maGraphicsModeBit,
1017 &minfo, NULL );
1018 }
1019
1020 if ( ( mode == modeEndOfList ) || ( setVBEMode(mode, NULL) != errSuccess ) )
1021 {
1022 video_mode( 2 ); // VGA BIOS, 80x25 text mode.
1023 minfo.XResolution = 80;
1024 minfo.YResolution = 25;
1025 }
1026
1027 // Update KernBootStruct using info provided by the selected
1028 // VESA mode.
1029
1030 bootArgs->Video.v_display = VGA_TEXT_MODE;
1031 bootArgs->Video.v_baseAddr = 0xb8000;
1032 bootArgs->Video.v_width = minfo.XResolution;
1033 bootArgs->Video.v_height = minfo.YResolution;
1034 bootArgs->Video.v_depth = 8;
1035 bootArgs->Video.v_rowBytes = 0x8000;
1036
1037 return errSuccess; // always return success
1038}
1039
1040//==========================================================================
1041// getNumberArrayFromProperty
1042
1043static int
1044getNumberArrayFromProperty( const char * propKey,
1045 unsigned long numbers[],
1046 unsigned long maxArrayCount )
1047{
1048 char * propStr;
1049 unsigned long count = 0;
1050
1051 propStr = newStringForKey( (char *) propKey , &bootInfo->bootConfig );
1052 if ( propStr )
1053 {
1054 char * delimiter = propStr;
1055 char * p = propStr;
1056
1057 while ( count < maxArrayCount && *p != '\0' )
1058 {
1059 unsigned long val = strtoul( p, &delimiter, 10 );
1060 if ( p != delimiter )
1061 {
1062 numbers[count++] = val;
1063 p = delimiter;
1064 }
1065 while ( ( *p != '\0' ) && !isdigit(*p) )
1066 p++;
1067 }
1068
1069 free( propStr );
1070 }
1071
1072 return count;
1073}
1074
1075int initGraphicsMode ()
1076{
1077 unsigned long params[4];
1078 int count;
1079
1080 params[3] = 0;
1081 count = getNumberArrayFromProperty( kGraphicsModeKey, params, 4 );
1082
1083 // Try to find a resolution if "Graphics Mode" setting is not available.
1084 if ( count < 3 )
1085 {
1086 // Use the default resolution if we don't have an initialized GUI.
1087 if (gui.screen.width == 0 || gui.screen.height == 0)
1088 {
1089 gui.screen.width = DEFAULT_SCREEN_WIDTH;
1090 gui.screen.height = DEFAULT_SCREEN_HEIGHT;
1091 }
1092
1093 params[0] = gui.screen.width;
1094 params[1] = gui.screen.height;
1095 params[2] = 32;
1096 }
1097
1098 // Map from pixel format to bits per pixel.
1099
1100 if ( params[2] == 256 ) params[2] = 8;
1101 if ( params[2] == 555 ) params[2] = 16;
1102 if ( params[2] == 888 ) params[2] = 32;
1103
1104return setVESAGraphicsMode( params[0], params[1], params[2], params[3] );
1105}
1106
1107//==========================================================================
1108// setVideoMode
1109//
1110// Set the video mode to VGA_TEXT_MODE or GRAPHICS_MODE.
1111
1112void
1113setVideoMode( int mode, int drawgraphics)
1114{
1115 unsigned long params[4];
1116 int count;
1117 int err = errSuccess;
1118
1119 if ( mode == GRAPHICS_MODE )
1120 {
1121 if ( (err=initGraphicsMode ()) == errSuccess ) {
1122 if (gVerboseMode) {
1123 // Tell the kernel to use text mode on a linear frame buffer display
1124 bootArgs->Video.v_display = FB_TEXT_MODE;
1125 } else {
1126 bootArgs->Video.v_display = GRAPHICS_MODE;
1127 }
1128 }
1129 }
1130
1131 if ( (mode == VGA_TEXT_MODE) || (err != errSuccess) )
1132 {
1133 count = getNumberArrayFromProperty( kTextModeKey, params, 2 );
1134 if ( count < 2 )
1135 {
1136 params[0] = 80; // Default text mode is 80x25.
1137 params[1] = 25;
1138 }
1139
1140setVESATextMode( params[0], params[1], 4 );
1141 bootArgs->Video.v_display = VGA_TEXT_MODE;
1142 }
1143
1144 currentIndicator = 0;
1145}
1146
1147void getGraphicModeParams(unsigned long params[]) {
1148
1149params[3] = 0;
1150
1151VBEModeInfoBlock minfo;
1152
1153 unsigned short vesaVersion;
1154 unsigned short mode = modeEndOfList;
1155
1156getNumberArrayFromProperty( kGraphicsModeKey, params, 4);
1157
1158mode = getVESAModeWithProperties( params[0], params[1], params[2],
1159 maColorModeBit |
1160 maModeIsSupportedBit |
1161 maGraphicsModeBit |
1162 maLinearFrameBufferAvailBit,
1163 0,
1164 &minfo, &vesaVersion );
1165
1166params[0] = minfo.XResolution;
1167params[1] = minfo.YResolution;
1168params[2] = 32;
1169}
1170
1171//==========================================================================
1172// Return the current video mode, VGA_TEXT_MODE or GRAPHICS_MODE.
1173
1174int getVideoMode(void)
1175{
1176 return bootArgs->Video.v_display;
1177}
1178
1179//==========================================================================
1180// Display and clear the activity indicator.
1181
1182static char indicator[] = {'-', '\\', '|', '/', '-', '\\', '|', '/', '\0'};
1183
1184// To prevent a ridiculously fast-spinning indicator,
1185// ensure a minimum of 1/9 sec between animation frames.
1186#define MIN_TICKS 2
1187
1188void
1189spinActivityIndicator(int sectors)
1190{
1191 static unsigned long lastTickTime = 0, currentTickTime;
1192
1193if (previewTotalSectors && previewSaveunder)
1194{
1195int blob, lastBlob;
1196
1197lastBlob = (previewLoadedSectors * kIOHibernateProgressCount) / previewTotalSectors;
1198previewLoadedSectors+=sectors;
1199blob = (previewLoadedSectors * kIOHibernateProgressCount) / previewTotalSectors;
1200
1201if (blob!=lastBlob)
1202updateProgressBar (previewSaveunder, lastBlob, blob);
1203return;
1204}
1205
1206currentTickTime = time18(); // late binding
1207if (currentTickTime < lastTickTime + MIN_TICKS)
1208{
1209return;
1210}
1211else
1212{
1213lastTickTime = currentTickTime;
1214}
1215
1216if (getVideoMode() == VGA_TEXT_MODE)
1217{
1218if (currentIndicator >= sizeof(indicator))
1219{
1220currentIndicator = 0;
1221}
1222putc(indicator[currentIndicator++]);
1223putc('\b');
1224}
1225}
1226
1227void
1228clearActivityIndicator( void )
1229{
1230 if ( getVideoMode() == VGA_TEXT_MODE )
1231 {
1232 putc(' ');
1233putc('\b');
1234 }
1235}
1236
1237

Archive Download this file

Revision: 460