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

Archive Download this file

Revision: 479