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

Archive Download this file

Revision: 2743