Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 705