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

Archive Download this file

Revision: 1055