Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazi/i386/boot2/graphics.c

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

Archive Download this file

Revision: 490