Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 132