Chameleon

Chameleon Svn Source Tree

Root/branches/andyvand/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 printf("(Press a key to continue...)");
128 getc();
129 line = 0;
130 clearScreenRows(0, 24);
131 setCursorPosition( 0, 0, 1 );
132 }
133 }
134 if (line != 0) {
135 printf("(Press a key to continue...)");
136 getc();
137 }
138 setActiveDisplayPage(0);
139}
140
141char *getVBEModeInfoString()
142{
143VBEInfoBlock vbeInfo;
144 unsigned short * modePtr;
145 VBEModeInfoBlock modeInfo;
146 int err;
147
148 bzero( &vbeInfo, sizeof(vbeInfo) );
149 strcpy( (char*)&vbeInfo, "VBE2" );
150 err = getVBEInfo( &vbeInfo );
151 if ( err != errSuccess )
152 return 0;
153
154char *buff=malloc(sizeof(char)*3072);
155if(!buff) return 0;
156
157// Loop through the mode list, and find the matching mode.
158 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
159 *modePtr != modeEndOfList; modePtr++ )
160 {
161 // Get mode information.
162
163 bzero( &modeInfo, sizeof(modeInfo) );
164 err = getVBEModeInfo( *modePtr, &modeInfo );
165 if ( err != errSuccess )
166 {
167 continue;
168 }
169
170 sprintf(buff+strlen(buff), "Mode %x: %dx%dx%d mm:%d attr:%x\n",
171 *modePtr, modeInfo.XResolution, modeInfo.YResolution,
172 modeInfo.BitsPerPixel, modeInfo.MemoryModel,
173 modeInfo.ModeAttributes);
174
175 }
176return buff;
177}
178
179//==========================================================================
180// getVESAModeWithProperties
181//
182// Return the VESA mode that matches the properties specified.
183// If a mode is not found, then return the "best" available mode.
184
185static unsigned short
186getVESAModeWithProperties( unsigned short width,
187 unsigned short height,
188 unsigned char bitsPerPixel,
189 unsigned short attributesSet,
190 unsigned short attributesClear,
191 VBEModeInfoBlock * outModeInfo,
192 unsigned short * vesaVersion )
193{
194 VBEInfoBlock vbeInfo;
195 unsigned short * modePtr;
196 VBEModeInfoBlock modeInfo;
197 unsigned char modeBitsPerPixel;
198 unsigned short matchedMode = modeEndOfList;
199 int err;
200
201 // Clear output mode info.
202
203 bzero( outModeInfo, sizeof(*outModeInfo) );
204
205 // Get VBE controller info containing the list of supported modes.
206
207 bzero( &vbeInfo, sizeof(vbeInfo) );
208 strcpy( (char*)&vbeInfo, "VBE2" );
209 err = getVBEInfo( &vbeInfo );
210 if ( err != errSuccess )
211 {
212 return modeEndOfList;
213 }
214
215 // Report the VESA major/minor version number.
216
217 if (vesaVersion) *vesaVersion = vbeInfo.VESAVersion;
218
219 // Loop through the mode list, and find the matching mode.
220
221 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
222 *modePtr != modeEndOfList; modePtr++ )
223 {
224 // Get mode information.
225
226 bzero( &modeInfo, sizeof(modeInfo) );
227 err = getVBEModeInfo( *modePtr, &modeInfo );
228 if ( err != errSuccess )
229 {
230 continue;
231 }
232
233#if DEBUG
234 printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",
235 *modePtr, modeInfo.XResolution, modeInfo.YResolution,
236 modeInfo.BitsPerPixel, modeInfo.MemoryModel,
237 modeInfo.ModeAttributes);
238#endif
239
240 // Filter out unwanted modes based on mode attributes.
241
242 if ( ( ( modeInfo.ModeAttributes & attributesSet ) != attributesSet )
243 || ( ( modeInfo.ModeAttributes & attributesClear ) != 0 ) )
244 {
245 continue;
246 }
247
248 // Pixel depth in bits.
249
250 modeBitsPerPixel = modeInfo.BitsPerPixel;
251
252 if ( ( modeBitsPerPixel == 4 ) && ( modeInfo.MemoryModel == 0 ) )
253 {
254 // Text mode, 16 colors.
255 }
256 else if ( ( modeBitsPerPixel == 8 ) && ( modeInfo.MemoryModel == 4 ) )
257 {
258 // Packed pixel, 256 colors.
259 }
260 else if ( ( ( modeBitsPerPixel == 16 ) || ( modeBitsPerPixel == 15 ) )
261 && ( modeInfo.MemoryModel == 6 )
262 && ( modeInfo.RedMaskSize == 5 )
263 && ( modeInfo.GreenMaskSize == 5 )
264 && ( modeInfo.BlueMaskSize == 5 ) )
265 {
266 // Direct color, 16 bpp (1:5:5:5).
267 modeInfo.BitsPerPixel = modeBitsPerPixel = 16;
268 }
269 else if ( ( modeBitsPerPixel == 32 )
270 && ( modeInfo.MemoryModel == 6 )
271 && ( modeInfo.RedMaskSize == 8 )
272 && ( modeInfo.GreenMaskSize == 8 )
273 && ( modeInfo.BlueMaskSize == 8 ) )
274 {
275 // Direct color, 32 bpp (8:8:8:8).
276 }
277 else
278 {
279 continue; // Not a supported mode.
280 }
281
282 // Modes larger than the specified dimensions are skipped.
283
284 if ( ( modeInfo.XResolution > width ) ||
285 ( modeInfo.YResolution > height ) )
286 {
287 continue;
288 }
289
290 // Perfect match, we're done looking.
291
292 if ( ( modeInfo.XResolution == width ) &&
293 ( modeInfo.YResolution == height ) &&
294 ( modeBitsPerPixel == bitsPerPixel ) )
295 {
296 matchedMode = *modePtr;
297 bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
298 break;
299 }
300
301 // Save the next "best" mode in case a perfect match is not found.
302
303 if ( modeInfo.XResolution == outModeInfo->XResolution &&
304 modeInfo.YResolution == outModeInfo->YResolution &&
305 modeBitsPerPixel <= outModeInfo->BitsPerPixel )
306 {
307 continue; // Saved mode has more depth.
308 }
309 if ( modeInfo.XResolution < outModeInfo->XResolution ||
310 modeInfo.YResolution < outModeInfo->YResolution ||
311 modeBitsPerPixel < outModeInfo->BitsPerPixel )
312 {
313 continue; // Saved mode has more resolution.
314 }
315
316 matchedMode = *modePtr;
317 bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
318 }
319
320 return matchedMode;
321}
322
323//==========================================================================
324// setupPalette
325
326static void setupPalette( VBEPalette * p, const unsigned char * g )
327{
328 int i;
329 unsigned char * source = (unsigned char *) g;
330
331 for (i = 0; i < 256; i++)
332 {
333 (*p)[i] = 0;
334 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 16; // Red
335 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 8; // Green
336 (*p)[i] |= ((unsigned long)((*source++) >> 2)); // Blue
337 }
338}
339
340//==========================================================================
341// Simple decompressor for boot images encoded in RLE format.
342
343char * decodeRLE( const void * rleData, int rleBlocks, int outBytes )
344{
345 char *out, *cp;
346
347 struct RLEBlock {
348 unsigned char count;
349 unsigned char value;
350 } * bp = (struct RLEBlock *) rleData;
351
352 out = cp = malloc( outBytes );
353 if ( out == NULL ) return NULL;
354
355 while ( rleBlocks-- )
356 {
357 memset( cp, bp->value, bp->count );
358 cp += bp->count;
359 bp++;
360 }
361
362 return out;
363}
364
365//==========================================================================
366// setVESAGraphicsMode
367
368static int
369setVESAGraphicsMode( unsigned short width,
370 unsigned short height,
371 unsigned char bitsPerPixel,
372 unsigned short refreshRate )
373{
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 }
468 while ( 0 );
469
470 return err;
471}
472
473int
474convertImage( unsigned short width,
475 unsigned short height,
476 const unsigned char *imageData,
477 unsigned char **newImageData )
478{
479 int cnt;
480 unsigned char *img = 0;
481 unsigned short *img16;
482 unsigned long *img32;
483
484 switch ( VIDEO(depth) ) {
485 case 16 :
486 img16 = malloc(width * height * 2);
487 if ( !img16 ) break;
488 for (cnt = 0; cnt < (width * height); cnt++)
489 img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16);
490 img = (unsigned char *)img16;
491 break;
492
493 case 32 :
494 img32 = malloc(width * height * 4);
495 if ( !img32 ) break;
496 for (cnt = 0; cnt < (width * height); cnt++)
497 img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32);
498 img = (unsigned char *)img32;
499 break;
500
501 default :
502 img = malloc(width * height);
503 bcopy(imageData, img, width * height);
504 break;
505 }
506 *newImageData = img;
507 return 0;
508}
509
510int loadPngImage(const char *filename, uint16_t *width, uint16_t *height,
511 uint8_t **imageData)
512{
513 uint8_t *pngData = NULL;
514 int pngFile = 0, pngSize;
515 PNG_info_t *info;
516 int error = 0;
517
518 pngFile = open_bvdev("bt(0,0)", filename, 0);
519 if (pngFile == -1) {
520 error = -1;
521 goto failed;
522 }
523 pngSize = file_size(pngFile);
524 if (!pngSize) {
525 error = -1;
526 goto failed;
527 }
528 pngData = malloc(pngSize);
529 if (read(pngFile, (char *) pngData, pngSize) != pngSize) {
530 error = -1;
531 goto failed;
532 }
533
534 PNG_error = -1;
535 info = PNG_decode(pngData, pngSize);
536 if (PNG_error != 0) {
537 error = PNG_error;
538 goto failed;
539 } else if ((info->width > 0xffff) || (info->height > 0xffff)) {
540 error = -1;
541 goto failed;
542 } else if ((info->width * info->height * 4) != info->image->size) {
543 error = -1;
544 goto failed;
545 }
546uint8_t *result = malloc(info->width*4*info->height);
547 *width = info->width;
548 *height = info->height;
549memcpy(result, info->image->data, info->width*4*info->height);
550*imageData = result;
551
552failed:
553png_alloc_free_all();
554 if (pngData)
555 free(pngData);
556 if (pngFile != -1)
557 close(pngFile);
558
559 return error;
560}
561
562int loadEmbeddedPngImage(uint8_t *pngData, int pngSize, uint16_t *width, uint16_t *height, uint8_t **imageData) {
563 PNG_info_t *info;
564 int error = 0;
565
566 PNG_error = -1;
567 info = PNG_decode(pngData, pngSize);
568if (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
587 return error;
588}
589
590void blendImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
591 uint8_t *data)
592{
593 uint16_t drawWidth;
594 uint8_t *vram = (uint8_t *) VIDEO(baseAddr) + VIDEO(rowBytes) * y + 4 * x;
595
596 drawWidth = MIN(width, VIDEO(width) - x);
597 height = MIN(height, VIDEO(height) - y);
598 while (height--) {
599switch (VIDEO (depth))
600{
601case 32: /* Optimized version*/
602{
603uint32_t s; uint32_t* d; // Source (img) and destination (bkgd) pixels
604uint32_t a; // Alpha
605uint32_t dstrb, dstg, srcrb, srcg, drb, dg, rb, g, tempB; // Intermediate variables
606uint16_t pos;
607
608for (pos = 0; pos < drawWidth * 4; pos += 4) {
609// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
610s = *((uint32_t*) (data + pos));
611d = (uint32_t*) (vram + pos);
612
613// Flip B and R in source
614// TODO: use XCHG and inline assembly to do this in a faster, saner way
615tempB = (s & 0xFF0000); // save B
616s = (s & 0xFF00FFFF) | ((s & 0xFF) << 16); // put R in B
617s = (s & 0xFFFFFF00) | (tempB >> 16); // put B in R
618
619a = (s >> 24) + 1;
620
621dstrb = *d & 0xFF00FF; dstg = *d & 0xFF00;
622srcrb = s & 0xFF00FF; srcg = s & 0xFF00;
623
624drb = srcrb - dstrb;
625dg = srcg - dstg;
626drb *= a; dg *= a;
627drb >>= 8; dg >>= 8;
628
629rb = (drb + dstrb) & 0xFF00FF;
630g = (dg + dstg) & 0xFF00;
631
632*d = rb | g;
633}
634}
635break;
636
637default: /*Universal version*/
638{
639uint32_t s;
640uint32_t a; // Alpha
641uint32_t dr, dg, db, sr, sg, sb; // Intermediate variables
642uint16_t pos;
643int bpp = (VIDEO (depth) + 7)/8;
644
645for (pos = 0; pos < drawWidth; pos ++) {
646// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
647s = *((uint32_t*) (data + 4*pos));
648
649sb = (s & 0xFF0000) >> 16;
650sg = (s & 0xFF00) >> 8;
651sr = (s & 0xFF);
652
653a = (s >> 24) + 1;
654
655switch (VIDEO (depth))
656{
657case 24:
658db = ((*(uint32_t *)(vram + bpp*pos))&0xff);
659dg = ((*(uint32_t *)(vram + bpp*pos))&0xff00)>>8;
660dr = ((*(uint32_t *)(vram + bpp*pos))&0xff0000)>>16;
661break;
662case 16://16-bit seems to be 15-bit
663/*db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
664dg = ((*(uint16_t *)(vram + bpp*pos))&0x07e0)>>3;
665dr = ((*(uint16_t *)(vram + bpp*pos))&0xf800)>>8;
666break;*/
667case 15:
668db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
669dg = ((*(uint16_t *)(vram + bpp*pos))&0x03e0)>>2;
670dr = ((*(uint16_t *)(vram + bpp*pos))&0x7c00)>>7;
671break;
672default:
673return;
674}
675
676dr = (((sr - dr) * a) >> 8) + dr;
677dg = (((sg - dg) * a) >> 8) + dg;
678db = (((sb - db) * a) >> 8) + db;
679switch (VIDEO (depth))
680{
681case 24:
682*(uint32_t *)(vram + bpp*pos) = (*(uint32_t *)(vram + bpp*pos) &0xff000000)
683| (db&0xff) | ((dg&0xff)<<8) | ((dr&0xff)<<16);
684break;
685case 16:
686//*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xfc)<<3) | ((dr&0xf8)<<8);
687//break;
688case 15:
689*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xf8)<<2) | ((dr&0xf8)<<7);
690break;
691}
692
693}
694}
695break;
696 }
697 vram += VIDEO(rowBytes);
698 data += width * 4;
699 }
700}
701
702void drawCheckerBoard()
703{
704 uint32_t *vram = (uint32_t *) VIDEO(baseAddr);
705 uint16_t x, y;
706 uint8_t color;
707
708 for (y = 0; y < VIDEO(height); y++, vram += VIDEO(width)) {
709 for (x = 0; x < VIDEO(width); x++) {
710 color = 204 + 51 * (((x / 8) % 2) == ((y / 8) % 2));
711 vram[x] = (color << 16) | (color << 8) | color;
712 }
713 }
714}
715
716//==========================================================================
717// LookUpCLUTIndex
718
719unsigned long lookUpCLUTIndex( unsigned char index,
720 unsigned char depth )
721{
722 long result, red, green, blue;
723
724 red = appleClut8[index * 3 + 0];
725 green = appleClut8[index * 3 + 1];
726 blue = appleClut8[index * 3 + 2];
727
728 switch (depth) {
729 case 16 :
730 result = ((red & 0xF8) << 7) |
731 ((green & 0xF8) << 2) |
732 ((blue & 0xF8) >> 3);
733 result |= (result << 16);
734 break;
735
736 case 32 :
737 result = (red << 16) | (green << 8) | blue;
738 break;
739
740 default :
741 result = index | (index << 8);
742 result |= (result << 16);
743 break;
744 }
745
746 return result;
747}
748
749//==========================================================================
750// drawColorRectangle
751
752void * stosl(void * dst, long val, long len)
753{
754 asm volatile ( "rep; stosl"
755 : "=c" (len), "=D" (dst)
756 : "0" (len), "1" (dst), "a" (val)
757 : "memory" );
758
759 return dst;
760}
761
762void drawColorRectangle( unsigned short x,
763 unsigned short y,
764 unsigned short width,
765 unsigned short height,
766 unsigned char colorIndex )
767{
768 long pixelBytes;
769 long color = lookUpCLUTIndex( colorIndex, VIDEO(depth) );
770 char * vram;
771
772 pixelBytes = VIDEO(depth) / 8;
773 vram = (char *) VIDEO(baseAddr) +
774 VIDEO(rowBytes) * y + pixelBytes * x;
775
776 width = MIN(width, VIDEO(width) - x);
777 height = MIN(height, VIDEO(height) - y);
778
779 while ( height-- )
780 {
781 int rem = ( pixelBytes * width ) % 4;
782 if ( rem ) bcopy( &color, vram, rem );
783 stosl( vram + rem, color, pixelBytes * width / 4 );
784 vram += VIDEO(rowBytes);
785 }
786}
787
788//==========================================================================
789// drawDataRectangle
790
791void drawDataRectangle( unsigned short x,
792 unsigned short y,
793 unsigned short width,
794 unsigned short height,
795 unsigned char * data )
796{
797 unsigned short drawWidth;
798 long pixelBytes = VIDEO(depth) / 8;
799 unsigned char * vram = (unsigned char *) VIDEO(baseAddr) +
800 VIDEO(rowBytes) * y + pixelBytes * x;
801
802 drawWidth = MIN(width, VIDEO(width) - x);
803 height = MIN(height, VIDEO(height) - y);
804 while ( height-- ) {
805 bcopy( data, vram, drawWidth * pixelBytes );
806 vram += VIDEO(rowBytes);
807 data += width * pixelBytes;
808 }
809}
810
811void
812loadImageScale (void *input, int iw, int ih, int ip, void *output, int ow, int oh, int op, int or)
813{
814int x,y, off;
815int red=0x7f, green=0x7f, blue=0x7f;
816for (x=0;x<ow;x++)
817for (y=0;y<oh;y++)
818{
819off=(x*iw)/ow+((y*ih)/oh)*iw;
820switch (ip)
821{
822case 16:
823{
824uint16_t val;
825val=((uint16_t *)input)[off];
826red=(val>>7)&0xf8;
827green=(val>>2)&0xf8;
828blue=(val<<3)&0xf8;
829break;
830}
831case 32:
832{
833uint32_t val;
834val=((uint32_t *)input)[off];
835red=(val>>16)&0xff;
836green=(val>>8)&0xff;
837blue=(val)&0xff;
838break;
839}
840}
841char *ptr=(char *)output+x*(op/8)+y*or;
842switch (op)
843{
844case 16:
845*((uint16_t *)ptr) = ((red & 0xF8) << 7) |
846((green & 0xF8) << 2) |
847((blue & 0xF8) >> 3);
848break;
849case 32 :
850*((uint32_t *)ptr) = (red << 16) | (green << 8) | blue;
851break;
852}
853}
854}
855
856DECLARE_IOHIBERNATEPROGRESSALPHA
857
858void drawPreview(void *src, uint8_t * saveunder)
859{
860uint8_t * screen;
861uint32_t rowBytes, pixelShift;
862uint32_t x, y;
863int32_t blob;
864uint32_t alpha, in, color, result;
865uint8_t * out;
866void *uncomp;
867int origwidth, origheight, origbpx;
868uint32_t saveindex[kIOHibernateProgressCount] = { 0 };
869
870if (src && (uncomp=DecompressData(src, &origwidth, &origheight, &origbpx)))
871{
872if (!setVESAGraphicsMode(origwidth, origheight, origbpx, 0))
873if (initGraphicsMode () != errSuccess)
874return;
875screen = (uint8_t *) VIDEO (baseAddr);
876rowBytes = VIDEO (rowBytes);
877loadImageScale (uncomp, origwidth, origheight, origbpx, screen, VIDEO(width), VIDEO(height), VIDEO(depth), VIDEO (rowBytes));
878}
879else
880{
881if (initGraphicsMode () != errSuccess)
882return;
883screen = (uint8_t *) VIDEO (baseAddr);
884rowBytes = VIDEO (rowBytes);
885// Set the screen to 75% grey.
886 drawColorRectangle(0, 0, VIDEO(width), VIDEO(height), 0x01 /* color index */);
887}
888
889
890pixelShift = VIDEO (depth) >> 4;
891if (pixelShift < 1) return;
892
893screen += ((VIDEO (width)
894- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))
895+ (VIDEO (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;
896
897for (y = 0; y < kIOHibernateProgressHeight; y++)
898{
899out = screen + y * rowBytes;
900for (blob = 0; blob < kIOHibernateProgressCount; blob++)
901{
902color = blob ? kIOHibernateProgressDarkGray : kIOHibernateProgressMidGray;
903for (x = 0; x < kIOHibernateProgressWidth; x++)
904{
905alpha = gIOHibernateProgressAlpha[y][x];
906result = color;
907if (alpha)
908{
909if (0xff != alpha)
910{
911if (1 == pixelShift)
912{
913in = *((uint16_t *)out) & 0x1f;// 16
914in = (in << 3) | (in >> 2);
915}
916else
917in = *((uint32_t *)out) & 0xff;// 32
918saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++] = in;
919result = ((255 - alpha) * in + alpha * result + 0xff) >> 8;
920}
921if (1 == pixelShift)
922{
923result >>= 3;
924*((uint16_t *)out) = (result << 10) | (result << 5) | result;// 16
925}
926else
927*((uint32_t *)out) = (result << 16) | (result << 8) | result;// 32
928}
929out += (1 << pixelShift);
930}
931out += (kIOHibernateProgressSpacing << pixelShift);
932}
933}
934}
935
936void updateProgressBar(uint8_t * saveunder, int32_t firstBlob, int32_t select)
937{
938uint8_t * screen;
939uint32_t rowBytes, pixelShift;
940uint32_t x, y;
941int32_t blob, lastBlob;
942uint32_t alpha, in, color, result;
943uint8_t * out;
944uint32_t saveindex[kIOHibernateProgressCount] = { 0 };
945
946pixelShift = VIDEO(depth) >> 4;
947if (pixelShift < 1) return;
948screen = (uint8_t *) VIDEO (baseAddr);
949rowBytes = VIDEO (rowBytes);
950
951screen += ((VIDEO (width)
952- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))
953+ (VIDEO (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;
954
955lastBlob = (select < kIOHibernateProgressCount) ? select : (kIOHibernateProgressCount - 1);
956
957screen += (firstBlob * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << pixelShift;
958
959for (y = 0; y < kIOHibernateProgressHeight; y++)
960{
961out = screen + y * rowBytes;
962for (blob = firstBlob; blob <= lastBlob; blob++)
963{
964color = (blob < select) ? kIOHibernateProgressLightGray : kIOHibernateProgressMidGray;
965for (x = 0; x < kIOHibernateProgressWidth; x++)
966{
967alpha = gIOHibernateProgressAlpha[y][x];
968result = color;
969if (alpha)
970{
971if (0xff != alpha)
972{
973in = saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++];
974result = ((255 - alpha) * in + alpha * result + 0xff) / 255;
975}
976if (1 == pixelShift)
977{
978result >>= 3;
979*((uint16_t *)out) = (result << 10) | (result << 5) | result;// 16
980}
981else
982*((uint32_t *)out) = (result << 16) | (result << 8) | result;// 32
983}
984out += (1 << pixelShift);
985}
986out += (kIOHibernateProgressSpacing << pixelShift);
987}
988}
989}
990
991
992//==========================================================================
993// setVESATextMode
994
995static int
996setVESATextMode( unsigned short cols,
997 unsigned short rows,
998 unsigned char bitsPerPixel )
999{
1000 VBEModeInfoBlock minfo;
1001 unsigned short mode = modeEndOfList;
1002
1003 if ( (cols != 80) || (rows != 25) ) // not 80x25 mode
1004 {
1005 mode = getVESAModeWithProperties( cols, rows, bitsPerPixel,
1006 maColorModeBit |
1007 maModeIsSupportedBit,
1008 maGraphicsModeBit,
1009 &minfo, NULL );
1010 }
1011
1012 if ( ( mode == modeEndOfList ) || ( setVBEMode(mode, NULL) != errSuccess ) )
1013 {
1014 video_mode( 2 ); // VGA BIOS, 80x25 text mode.
1015 minfo.XResolution = 80;
1016 minfo.YResolution = 25;
1017 }
1018
1019 // Update KernBootStruct using info provided by the selected
1020 // VESA mode.
1021
1022 bootArgs->Video.v_display = VGA_TEXT_MODE;
1023 bootArgs->Video.v_baseAddr = 0xb8000;
1024 bootArgs->Video.v_width = minfo.XResolution;
1025 bootArgs->Video.v_height = minfo.YResolution;
1026 bootArgs->Video.v_depth = 8;
1027 bootArgs->Video.v_rowBytes = 0x8000;
1028
1029 return errSuccess; // always return success
1030}
1031
1032//==========================================================================
1033// getNumberArrayFromProperty
1034
1035static int
1036getNumberArrayFromProperty( const char * propKey,
1037 unsigned long numbers[],
1038 unsigned long maxArrayCount )
1039{
1040 char * propStr;
1041 unsigned long count = 0;
1042
1043 propStr = newStringForKey( (char *) propKey , &bootInfo->bootConfig );
1044 if ( propStr )
1045 {
1046 char * delimiter = propStr;
1047 char * p = propStr;
1048
1049 while ( count < maxArrayCount && *p != '\0' )
1050 {
1051 unsigned long val = strtoul( p, &delimiter, 10 );
1052 if ( p != delimiter )
1053 {
1054 numbers[count++] = val;
1055 p = delimiter;
1056 }
1057 while ( ( *p != '\0' ) && !isdigit(*p) )
1058 p++;
1059 }
1060
1061 free( propStr );
1062 }
1063
1064 return count;
1065}
1066
1067int initGraphicsMode ()
1068{
1069 unsigned long params[4];
1070 int count;
1071
1072 params[3] = 0;
1073 count = getNumberArrayFromProperty( kGraphicsModeKey, params, 4 );
1074
1075 // Try to find a resolution if "Graphics Mode" setting is not available.
1076 if ( count < 3 )
1077 {
1078 // Use the default resolution if we don't have an initialized GUI.
1079 if (gui.screen.width == 0 || gui.screen.height == 0)
1080 {
1081 gui.screen.width = DEFAULT_SCREEN_WIDTH;
1082 gui.screen.height = DEFAULT_SCREEN_HEIGHT;
1083 }
1084
1085 params[0] = gui.screen.width;
1086 params[1] = gui.screen.height;
1087 params[2] = 32;
1088 }
1089
1090 // Map from pixel format to bits per pixel.
1091
1092 if ( params[2] == 256 ) params[2] = 8;
1093 if ( params[2] == 555 ) params[2] = 16;
1094 if ( params[2] == 888 ) params[2] = 32;
1095
1096return setVESAGraphicsMode( params[0], params[1], params[2], params[3] );
1097}
1098
1099//==========================================================================
1100// setVideoMode
1101//
1102// Set the video mode to VGA_TEXT_MODE or GRAPHICS_MODE.
1103
1104void
1105setVideoMode( int mode, int drawgraphics)
1106{
1107 unsigned long params[4];
1108 int count;
1109 int err = errSuccess;
1110
1111 if ( mode == GRAPHICS_MODE )
1112 {
1113 if ( (err=initGraphicsMode ()) == errSuccess ) {
1114 if (gVerboseMode) {
1115 // Tell the kernel to use text mode on a linear frame buffer display
1116 bootArgs->Video.v_display = FB_TEXT_MODE;
1117 } else {
1118 bootArgs->Video.v_display = GRAPHICS_MODE;
1119 }
1120 }
1121 }
1122
1123 if ( (mode == VGA_TEXT_MODE) || (err != errSuccess) )
1124 {
1125 count = getNumberArrayFromProperty( kTextModeKey, params, 2 );
1126 if ( count < 2 )
1127 {
1128 params[0] = 80; // Default text mode is 80x25.
1129 params[1] = 25;
1130 }
1131
1132 setVESATextMode( params[0], params[1], 4 );
1133 bootArgs->Video.v_display = VGA_TEXT_MODE;
1134 }
1135
1136 currentIndicator = 0;
1137}
1138
1139void getGraphicModeParams(unsigned long params[]) {
1140
1141params[3] = 0;
1142
1143VBEModeInfoBlock minfo;
1144
1145 unsigned short vesaVersion;
1146 unsigned short mode = modeEndOfList;
1147
1148getNumberArrayFromProperty( kGraphicsModeKey, params, 4);
1149
1150mode = getVESAModeWithProperties( params[0], params[1], params[2],
1151 maColorModeBit |
1152 maModeIsSupportedBit |
1153 maGraphicsModeBit |
1154 maLinearFrameBufferAvailBit,
1155 0,
1156 &minfo, &vesaVersion );
1157
1158params[0] = minfo.XResolution;
1159params[1] = minfo.YResolution;
1160params[2] = 32;
1161}
1162
1163//==========================================================================
1164// Return the current video mode, VGA_TEXT_MODE or GRAPHICS_MODE.
1165
1166int getVideoMode(void)
1167{
1168 return bootArgs->Video.v_display;
1169}
1170
1171//==========================================================================
1172// Display and clear the activity indicator.
1173
1174static char indicator[] = {'-', '\\', '|', '/', '-', '\\', '|', '/', '\0'};
1175#define kNumIndicators (sizeof(indicator) - 1)
1176
1177// To prevent a ridiculously fast-spinning indicator,
1178// ensure a minimum of 1/9 sec between animation frames.
1179#define MIN_TICKS 2
1180
1181void
1182spinActivityIndicator(int sectors)
1183{
1184 static unsigned long lastTickTime = 0;
1185 unsigned long currentTickTime = time18();
1186 static char string[3] = {'\0', '\b', '\0'};
1187
1188if (previewTotalSectors && previewSaveunder)
1189{
1190int blob, lastBlob;
1191
1192lastBlob = (previewLoadedSectors * kIOHibernateProgressCount) / previewTotalSectors;
1193previewLoadedSectors+=sectors;
1194blob = (previewLoadedSectors * kIOHibernateProgressCount) / previewTotalSectors;
1195
1196if (blob!=lastBlob)
1197updateProgressBar (previewSaveunder, lastBlob, blob);
1198return;
1199}
1200
1201if (currentTickTime < lastTickTime + MIN_TICKS)
1202 return;
1203 else
1204 lastTickTime = currentTickTime;
1205
1206 if ( getVideoMode() == VGA_TEXT_MODE )
1207 {
1208 if (currentIndicator >= kNumIndicators) currentIndicator = 0;
1209 string[0] = indicator[currentIndicator++];
1210 verbose(string);
1211 }
1212}
1213
1214void
1215clearActivityIndicator( void )
1216{
1217 if ( getVideoMode() == VGA_TEXT_MODE )
1218 {
1219 printf(" \b");
1220 }
1221}
1222
1223

Archive Download this file

Revision: 67