Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 24