Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 815