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

Archive Download this file

Revision: 602