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

Archive Download this file

Revision: 709