Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazi/i386/boot2/graphics.c

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

Archive Download this file

Revision: 515