Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 296