Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Trunk/i386/boot2/graphics.c

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

Archive Download this file

Revision: 2045