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

Archive Download this file

Revision: 457