Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 997