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
434//Azi: who? who is about to set?? :P
435PRINT("Is about to set mode #%d with resolution %dx%d\n", mode, minfo.XResolution, minfo.YResolution);
436//getc(); //Azi: boot hangs, on the second call (like "old" Wait=y issue and usb fixes).
437sleep(2);
438#endif
439 // Set the mode with default refresh rate.
440 err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
441
442 if ( err != errSuccess )
443 {
444#ifdef AUTORES_DEBUG
445PRINT("setVBEMode failed to set mode %d (%dx%d) with error #%d\n",
446 mode, minfo.XResolution, minfo.YResolution, err);
447sleep(2); //Azi: i suppose the same as above.
448#endif
449 break;
450 }
451
452 // Set 8-bit color palette.
453
454 if ( minfo.BitsPerPixel == 8 )
455 {
456 VBEPalette palette;
457 setupPalette( &palette, appleClut8 ); //Azi:autoresolution - check this stuff, appleClut8
458 if ((err = setVBEPalette(palette)) != errSuccess)
459 {
460 break;
461 }
462 }
463
464 // Is this required for buggy Video BIOS implementations?
465 // On which adapter?
466
467 if ( minfo.BytesPerScanline == 0 )
468 minfo.BytesPerScanline = ( minfo.XResolution *
469 minfo.BitsPerPixel ) >> 3;
470
471 // Update KernBootStruct using info provided by the selected
472 // VESA mode.
473
474 bootArgs->Video.v_display = GRAPHICS_MODE;
475 bootArgs->Video.v_width = minfo.XResolution;
476 bootArgs->Video.v_height = minfo.YResolution;
477 bootArgs->Video.v_depth = minfo.BitsPerPixel;
478 bootArgs->Video.v_rowBytes = minfo.BytesPerScanline;
479 bootArgs->Video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
480//Azi:autoresolution
481#ifdef AUTORES_DEBUG //Azi: changed from if to ifdef
482gui.screen.mm= minfo.MemoryModel;
483gui.screen.attr= minfo.ModeAttributes;
484#endif
485 }
486 while ( 0 );
487
488 return err;
489}
490
491int
492convertImage( unsigned short width,
493 unsigned short height,
494 const unsigned char *imageData,
495 unsigned char **newImageData )
496{
497 int cnt;
498 unsigned char *img = 0;
499 unsigned short *img16;
500 unsigned long *img32;
501
502 switch ( VIDEO(depth) ) {
503 case 16 :
504 img16 = malloc(width * height * 2);
505 if ( !img16 ) break;
506 for (cnt = 0; cnt < (width * height); cnt++)
507 img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16);
508 img = (unsigned char *)img16;
509 break;
510
511 case 32 :
512 img32 = malloc(width * height * 4);
513 if ( !img32 ) break;
514 for (cnt = 0; cnt < (width * height); cnt++)
515 img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32);
516 img = (unsigned char *)img32;
517 break;
518
519 default :
520 img = malloc(width * height);
521 bcopy(imageData, img, width * height);
522 break;
523 }
524 *newImageData = img;
525 return 0;
526}
527
528int loadPngImage(const char *filename, uint16_t *width, uint16_t *height,
529 uint8_t **imageData)
530{
531 uint8_t *pngData = NULL;
532 int pngFile = 0, pngSize;
533 PNG_info_t *info;
534 int error = 0;
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
1053//static Azi:autoresolution
1054int getNumberArrayFromProperty( 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
1114return 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
1150setVESATextMode( 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
1216currentTickTime = time18(); // late binding
1217if (currentTickTime < lastTickTime + MIN_TICKS)
1218{
1219return;
1220}
1221else
1222{
1223lastTickTime = currentTickTime;
1224}
1225
1226if (getVideoMode() == VGA_TEXT_MODE)
1227{
1228if (currentIndicator >= sizeof(indicator))
1229{
1230currentIndicator = 0;
1231}
1232putchar(indicator[currentIndicator++]);
1233putchar('\b');
1234}
1235}
1236
1237void
1238clearActivityIndicator( void )
1239{
1240 if ( getVideoMode() == VGA_TEXT_MODE )
1241 {
1242putchar(' ');
1243putchar('\b');
1244 }
1245}
1246
1247

Archive Download this file

Revision: 946