Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2805