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

Archive Download this file

Revision: 467