Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: HEAD