Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2769