Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazileon/i386/boot2/graphics.c

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

Archive Download this file

Revision: 381