2 * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 #include <console/video_console.h>
31 #include <libkern/OSByteOrder.h>
32 #include <kdp/kdp_udp.h>
33 #include <kern/debug.h>
34 #include <mach/mach_time.h>
35 #include <sys/errno.h>
37 #include <machine/machlimits.h>
38 #include <pexpert/pexpert.h>
40 extern struct vc_info vinfo
;
41 extern boolean_t panicDialogDesired
;
43 #include "panic_image.c"
45 void panic_ui_initialize(const unsigned char * system_clut
);
46 int panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
);
47 void panic_dialog_get_image(const unsigned char **ptr
, unsigned int *size
);
48 void draw_panic_dialog( void );
49 void panic_dialog_test( void );
51 static int panic_dialog_verify( const struct panicimage
* data
, unsigned int size
);
52 static int pixels_needed_to_blit_digit( int digit
);
53 static void blit_digit( int digit
);
54 static const char * strnstr(const char * s
, const char * find
, size_t slen
);
55 static void panic_blit_rect(unsigned int x
, unsigned int y
, unsigned int width
,
56 unsigned int height
, int transparent
,
57 const unsigned char * dataPtr
);
59 static int panic_info_x
;
60 static int panic_info_y
;
62 static const unsigned char * active_clut
= NULL
; /* This is a copy of the active clut */
64 static boolean_t panicDialogDrawn
= FALSE
;
66 static const struct panicimage
* panic_dialog
= NULL
; /* the active panic dialog */
67 static const unsigned char * panic_dialog_data
= NULL
; /* where the image data starts */
68 static const unsigned char * panic_dialog_clut
= NULL
; /* where the clut used for the image starts */
70 static const unsigned char *curr_image_ptr
; /* If NULL, the default panic
72 static unsigned int curr_image_size
= 0;
75 #define FONT_HEIGHT 16
76 static unsigned short rendered_font
[FONT_HEIGHT
][FONT_WIDTH
];
78 #define VERSIONBUF_LEN 20
79 static char versionbuf
[VERSIONBUF_LEN
]; /* ####.###~###\0 */
81 #define isdigit(d) ((d) >= '0' && (d) <= '9')
83 #define CLUT_ENTRIES 256
84 #define CLUT_SIZE (CLUT_ENTRIES * 3)
88 * This routine sets up the default panic dialog
91 extern unsigned char iso_font
[];
92 extern const char version
[];
95 panic_ui_initialize(const unsigned char * system_clut
)
97 char vstr
[VERSIONBUF_LEN
];
99 panic_dialog_set_image( NULL
, 0 );
101 active_clut
= system_clut
;
103 strlcpy(vstr
, "custom", VERSIONBUF_LEN
);
105 /* Convert xnu-####.###.obj~### into ####.###~### */
108 const char *versionpos
= strnstr(version
, "xnu-", VERSIONBUF_LEN
);
115 for (i
= 0, len
= 4; len
< VERSIONBUF_LEN
; len
++) {
116 if (isdigit(versionpos
[len
]) || versionpos
[len
] == '.') { /* extract ####.###. */
117 vstr
[i
++] = versionpos
[len
];
123 if ( versionpos
[len
-1] == '.' ) /* remove trailing period if present */
126 for (; len
< VERSIONBUF_LEN
; len
++) { /* skip to next digit if present */
127 if ( !isdigit(versionpos
[len
]) )
132 if ( versionpos
[len
-1] == '~' ) { /* extract ~### if present */
133 vstr
[i
++] = versionpos
[len
-1];
134 for (; len
< VERSIONBUF_LEN
; len
++) { /* extract ### */
135 if ( isdigit(versionpos
[len
]) ) {
136 vstr
[i
++] = versionpos
[len
];
147 strlcpy(versionbuf
, vstr
, VERSIONBUF_LEN
);
153 panic_dialog_test( void )
155 boolean_t o_panicDialogDrawn
= panicDialogDrawn
;
156 boolean_t o_panicDialogDesired
= panicDialogDesired
;
157 unsigned int o_logPanicDataToScreen
= logPanicDataToScreen
;
158 unsigned long o_panic_caller
= panic_caller
;
159 unsigned int o_panicDebugging
= panicDebugging
;
161 panicDebugging
= TRUE
;
162 panic_caller
= (unsigned long)(char *)__builtin_return_address(0);
163 logPanicDataToScreen
= FALSE
;
164 panicDialogDesired
= TRUE
;
165 panicDialogDrawn
= FALSE
;
169 panicDebugging
= o_panicDebugging
;
170 panic_caller
= o_panic_caller
;
171 logPanicDataToScreen
= o_logPanicDataToScreen
;
172 panicDialogDesired
= o_panicDialogDesired
;
173 panicDialogDrawn
= o_panicDialogDrawn
;
178 draw_panic_dialog( void )
180 if (!panicDialogDrawn
&& panicDialogDesired
) {
181 if ( !logPanicDataToScreen
) {
183 int count
, nibble
, indx
;
184 struct ether_addr kdp_mac_addr
;
185 unsigned int panic_dialog_count
, ip_addr
;
186 char panic_num_chars
[13+8+1], mac_addr_chars
[17+1], ip_addr_chars
[15+1];
190 } panic_dialog_info
[3];
193 /* dim the screen 50% before putting up panic dialog */
196 /* set up to draw background box */
197 /* by locating where the upper left corner is placed */
199 pd_x
= (int)((vinfo
.v_width
/2) - panic_dialog
->pd_width
/2);
200 pd_y
= (int)((vinfo
.v_height
/2) - panic_dialog
->pd_height
/2);
202 /* draw panic dialog at pd_x/pd_y */
203 panic_blit_rect(pd_x
, pd_y
, panic_dialog
->pd_width
,
204 panic_dialog
->pd_height
, 0,
207 panic_dialog_count
= 0; /* number of info items to display at the bottom of dialog */
209 if (panicDebugging
) {
215 * don't display the panic caller if it is 0
219 if ( panic_caller
!= 0 ) {
220 /* Calculate the pixels need to generate the panic number */
221 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
223 for ( indx
=1, count
=0; count
< 13; count
++ ) {
224 if ( versionbuf
[count
] == '\0' )
227 panic_num_chars
[indx
++] = versionbuf
[count
];
228 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( versionbuf
[count
] );
231 panic_num_chars
[indx
++] = ':';
232 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
234 for ( count
=8; count
!= 0; count
-- ) {
235 nibble
= (int)((panic_caller
>> ((count
-1)<<2)) &0xF);
236 panic_num_chars
[indx
++] = nibble
;
237 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
240 panic_num_chars
[0] = indx
;
241 panic_dialog_info
[panic_dialog_count
].chars
= panic_num_chars
;
242 panic_dialog_count
++;
248 * if the mac address is not available, then use ff:ff:ff:ff:ff:ff
252 kdp_mac_addr
= kdp_get_mac_addr();
254 /* If no mac_addr has been set, then force to -1 */
255 if( ! (kdp_mac_addr
.ether_addr_octet
[0] || kdp_mac_addr
.ether_addr_octet
[1] || kdp_mac_addr
.ether_addr_octet
[2]
256 || kdp_mac_addr
.ether_addr_octet
[3] || kdp_mac_addr
.ether_addr_octet
[4] || kdp_mac_addr
.ether_addr_octet
[5])) {
257 for (count
= 0; count
< 6; count
++ )
258 kdp_mac_addr
.ether_addr_octet
[count
] = -1;
261 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
263 for (indx
=1, count
=0; count
< 6; count
++ ) {
264 nibble
= (kdp_mac_addr
.ether_addr_octet
[count
] & 0xf0) >> 4;
265 mac_addr_chars
[indx
++] = nibble
;
266 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
268 nibble
= kdp_mac_addr
.ether_addr_octet
[count
] & 0xf;
269 mac_addr_chars
[indx
++] = nibble
;
270 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
273 mac_addr_chars
[indx
++] = ':';
274 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
278 mac_addr_chars
[0] = indx
;
279 panic_dialog_info
[panic_dialog_count
].chars
= mac_addr_chars
;
280 panic_dialog_count
++;
285 * do not display the ip addresses if the machine isn't attachable.
286 * there's no sense in possibly confusing people.
289 if ( (ip_addr
= (unsigned int) ntohl(kdp_get_ip_address())) != 0 ) {
292 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
294 for ( indx
=1, count
=0; count
< 4; count
++ ) {
295 nibble
= (ip_addr
& 0xff000000 ) >> 24;
297 d3
= (nibble
% 10) ; nibble
= nibble
/ 10;
298 d2
= (nibble
% 10) ; nibble
= nibble
/ 10;
302 ip_addr_chars
[indx
++] = d1
;
303 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d1
);
306 ip_addr_chars
[indx
++] = d2
;
307 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d2
);
309 ip_addr_chars
[indx
++] = d3
;
310 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d3
);
313 ip_addr_chars
[indx
++] = '.';
314 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( '.' );
318 ip_addr
= ip_addr
<< 8;
321 ip_addr_chars
[0] = indx
;
322 panic_dialog_info
[panic_dialog_count
].chars
= ip_addr_chars
;
323 panic_dialog_count
++;
327 /* vertical alignment for information to be displayed */
328 panic_info_y
= (int)((vinfo
.v_height
/2) + panic_dialog
->pd_height
/2 - (panic_dialog
->pd_info_height
));
330 /* blit out all the information we gathered */
332 switch ( panic_dialog_count
) {
333 case 1 : /* one item is centered */
334 panic_info_x
= (int)((vinfo
.v_width
/2) - (panic_dialog_info
[0].pixels
/2));
335 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
336 blit_digit(panic_dialog_info
[0].chars
[indx
]);
340 case 2 : /* left centered and right centered */
341 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
)/2;
342 panic_info_x
= (int)(((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
);
344 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
345 blit_digit(panic_dialog_info
[0].chars
[indx
]);
347 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[1].pixels
)/2;
348 panic_info_x
= (int)((vinfo
.v_width
/2) + x2
);
350 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
351 blit_digit(panic_dialog_info
[1].chars
[indx
]);
355 case 3 : /* left centered, middle and right centered */
356 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
357 panic_info_x
= (int)(((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
);
359 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
360 blit_digit(panic_dialog_info
[0].chars
[indx
]);
362 panic_info_x
= (int)((vinfo
.v_width
/2) - (panic_dialog_info
[1].pixels
/2));
364 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
365 blit_digit(panic_dialog_info
[1].chars
[indx
]);
367 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[2].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
368 panic_info_x
= (int)((vinfo
.v_width
/2) + x2
+ (panic_dialog_info
[1].pixels
/2));
370 for (indx
=1; indx
< panic_dialog_info
[2].chars
[0]; indx
++)
371 blit_digit(panic_dialog_info
[2].chars
[indx
]);
375 default : /* nothing */
379 } /* if panic_deugging */
380 } /* if ! logPanicDataToScreen */
381 } /* if ! panicDialogDrawn && ! panicDialogDesired */
383 panicDialogDrawn
= TRUE
;
384 panicDialogDesired
= FALSE
;
389 * This routine installs a new panic dialog
390 * If ptr is NULL, then the default "built-in" panic dialog will be installed.
391 * note: It is the caller that must take care of deallocating memory used for the previous panic dialog
395 panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
)
398 unsigned int newsize
;
399 const struct panicimage
* newimage
;
401 /* if ptr is NULL, restore panic image to built-in default */
403 newimage
= &panic_dialog_default
;
404 newsize
= (unsigned int)(sizeof(struct panicimage
) + newimage
->pd_dataSize
);
407 newimage
= (const struct panicimage
*)ptr
;
411 if ( (error
= panic_dialog_verify( newimage
, newsize
)) )
414 panic_dialog
= newimage
;
415 panic_dialog_data
= &panic_dialog
->data
[0];
416 panic_dialog_clut
= &panic_dialog
->data
[panic_dialog
->pd_dataSize
-CLUT_SIZE
];
418 curr_image_ptr
= ptr
;
419 curr_image_size
= size
;
426 * This routines returns the current address of the panic dialog
427 * If the default panic dialog is active, then *ptr will be NULL
431 panic_dialog_get_image(const unsigned char ** ptr
, unsigned int * size
)
433 *ptr
= curr_image_ptr
;
434 *size
= curr_image_size
;
439 * This routine verifies the panic dialog image is valid.
443 panic_dialog_verify( const struct panicimage
* newimage
, unsigned int size
)
447 if ( size
< (sizeof(struct panicimage
) + newimage
->pd_dataSize
) )
450 if ( newimage
->pd_tag
!= 0x524E4D70 /* 'RNMp' */ )
453 size
= newimage
->pd_dataSize
-CLUT_SIZE
;
454 for (sum
=0,i
=0; i
<size
; i
++) {
455 sum
+= newimage
->data
[i
];
459 if ( sum
!= newimage
->pd_sum
)
467 * Service Routines for managing the panic dialog
471 static const struct rendered_num
* find_rendered_digit( int digit
);
472 static void panic_blit_rect_8(unsigned int x
, unsigned int y
,
473 unsigned int width
, unsigned int height
,
474 int transparent
, const unsigned char *dataPtr
);
475 static void panic_blit_rect_16(unsigned int x
, unsigned int y
,
476 unsigned int width
, unsigned int height
,
477 int transparent
, const unsigned char *dataPtr
);
478 static void panic_blit_rect_32(unsigned int x
, unsigned int y
,
479 unsigned int width
, unsigned int height
,
480 int transparent
, const unsigned char *dataPtr
);
481 static void panic_blit_rect_30(unsigned int x
, unsigned int y
,
482 unsigned int width
, unsigned int height
,
483 int transparent
, const unsigned char *dataPtr
);
484 static int decode_rle(const unsigned char *dataPtr
,
485 unsigned int *quantity
, unsigned int *depth
,
486 const unsigned char **value
);
489 /* Utilities to convert 8 bit/gray */
490 static unsigned int make24bitcolor( unsigned int index
, const unsigned char * clut
);
491 static unsigned char findIndexMatch( unsigned char index
);
492 static unsigned char color24togray8( unsigned int color24
);
493 static unsigned char findbestgray( unsigned int color24
);
494 static int isActiveClutOK( void );
497 pixels_needed_to_blit_digit(__unused
int digit
)
503 static const struct rendered_num
*
504 find_rendered_digit( int digit
)
506 //extern unsigned char iso_font[];
507 const struct rendered_num
*digitPtr
;
516 digitPtr
= (const struct rendered_num
*) &iso_font
[digit
* 16];
522 blit_digit( int digit
)
524 const unsigned char *raw_data
=
525 (const unsigned char *)find_rendered_digit(digit
);
526 unsigned width
= FONT_WIDTH
, height
= FONT_HEIGHT
;
529 for (row
=0; row
<FONT_HEIGHT
; row
++) {
533 bits
= raw_data
[row
];
534 for( j
=FONT_WIDTH
-1; j
>=0; j
--) {
537 rendered_font
[row
][j
] = OSSwapBigToHostInt16(0x0100 | panic_dialog
->pd_info_color
[0]);
539 rendered_font
[row
][j
] = OSSwapBigToHostInt16(0x0100 | panic_dialog
->pd_info_color
[1]);
544 panic_blit_rect( panic_info_x
, panic_info_y
, width
, height
, 255, (unsigned char *) rendered_font
);
545 panic_info_x
+= width
;
550 panic_blit_rect(unsigned int x
, unsigned int y
, unsigned int width
,
551 unsigned int height
, int transparent
,
552 const unsigned char *dataPtr
)
557 switch( vinfo
.v_depth
) {
559 panic_blit_rect_8( x
, y
, width
, height
, transparent
, dataPtr
);
562 panic_blit_rect_16( x
, y
, width
, height
, transparent
, dataPtr
);
565 panic_blit_rect_32( x
, y
, width
, height
, transparent
, dataPtr
);
568 panic_blit_rect_30( x
, y
, width
, height
, transparent
, dataPtr
);
574 * panic_blit_rect_8 decodes the RLE encoded image data on the fly, looks up the
575 * color by indexing into the clut, or attempts to find the best index.
579 panic_blit_rect_8(unsigned int x
, unsigned int y
, unsigned int width
,
580 unsigned int height
, __unused
int transparent
,
581 const unsigned char * dataPtr
)
583 volatile unsigned char * dst
;
584 unsigned int line
, col
, i
;
585 static int clutOK
= -1;
586 unsigned int data
, quantity
, depth
;
587 const unsigned char *value
;
591 clutOK
= isActiveClutOK();
593 dst
= (volatile unsigned char *) (vinfo
.v_baseaddr
+
594 (y
* vinfo
.v_rowbytes
) +
600 for( line
= 0; line
< height
; line
++) {
601 for( col
= 0; col
< width
; col
++) {
604 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
611 data
= findIndexMatch( value
[i
++] );
621 dst
= (volatile unsigned char *) (((uintptr_t)dst
) + vinfo
.v_rowbytes
);
626 * panic_blit_rect_16 decodes the RLE encoded image data on the fly, looks up the
627 * color by indexing into the clut, uses the top 5 bits to fill in each of the three
628 * pixel values (RGB) and writes each pixel to the screen.
632 panic_blit_rect_16(unsigned int x
, unsigned int y
, unsigned int width
,
633 unsigned int height
, __unused
int transparent
,
634 const unsigned char *dataPtr
)
637 volatile unsigned short * dst
;
638 unsigned int line
, col
, i
;
639 unsigned int quantity
, index
, data
, depth
;
640 const unsigned char *value
;
642 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
643 (y
* vinfo
.v_rowbytes
) +
649 for( line
= 0; line
< height
; line
++) {
650 for( col
= 0; col
< width
; col
++) {
653 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
657 index
= value
[i
++] * 3;
659 data
= ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 0])) << 7)
660 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 1])) << 2)
661 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 2])) >> 3);
671 dst
= (volatile unsigned short *) (((uintptr_t)dst
) + vinfo
.v_rowbytes
);
676 * panic_blit_rect_32 decodes the RLE encoded image data on the fly, and fills
677 * in each of the three pixel values from the clut (RGB) for each pixel and
678 * writes it to the screen.
682 panic_blit_rect_32(unsigned int x
, unsigned int y
, unsigned int width
,
683 unsigned int height
, __unused
int transparent
,
684 const unsigned char *dataPtr
)
686 volatile unsigned int * dst
;
687 unsigned int line
, col
, i
;
688 unsigned int quantity
, index
, data
, depth
;
689 const unsigned char *value
;
692 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
693 (y
* vinfo
.v_rowbytes
) +
699 for( line
= 0; line
< height
; line
++) {
700 for( col
= 0; col
< width
; col
++) {
703 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
707 index
= value
[i
++] * 3;
709 data
= ( (unsigned int) panic_dialog_clut
[index
+ 0] << 16)
710 | ( (unsigned int) panic_dialog_clut
[index
+ 1] << 8)
711 | ( (unsigned int) panic_dialog_clut
[index
+ 2]);
721 dst
= (volatile unsigned int *) (((uintptr_t)dst
) + vinfo
.v_rowbytes
);
726 * panic_blit_rect_30 decodes the RLE encoded image data on the fly, and fills
727 * in each of the three pixel values from the clut (RGB) for each pixel and
728 * writes it to the screen.
732 panic_blit_rect_30(unsigned int x
, unsigned int y
, unsigned int width
,
733 unsigned int height
, __unused
int transparent
,
734 const unsigned char *dataPtr
)
736 volatile unsigned int * dst
;
737 unsigned int line
, col
, i
;
738 unsigned int quantity
, index
, data
, depth
;
739 const unsigned char *value
;
742 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
743 (y
* vinfo
.v_rowbytes
) +
749 for( line
= 0; line
< height
; line
++) {
750 for( col
= 0; col
< width
; col
++) {
753 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
757 index
= value
[i
++] * 3;
758 in
= panic_dialog_clut
[index
+ 0];
759 data
= (in
<< 2) | (in
>> 6);
761 in
= panic_dialog_clut
[index
+ 1];
762 data
|= (in
<< (2 + 10)) | ((3 << 10) & (in
<< 4));
764 in
= panic_dialog_clut
[index
+ 2];
765 data
|= (in
<< (2 + 20)) | ((3 << 20) & (in
<< 14));
775 dst
= (volatile unsigned int *) (((uintptr_t)dst
) + vinfo
.v_rowbytes
);
781 decode_rle decodes a single quantity/value run of a "modified-RLE" encoded
782 image. The encoding works as follows:
784 The run is described in the first byte. If the MSB is zero, then the next seven bits
785 are the quantity of bytes that follow that make up the run of value bytes. (see case 0)
787 If the MSB is set, bits 0-3 are the quantity's least significant 4 bits. If bit 5 is set,
788 then the quantity is further described in the next byte, where an additional 7 bits (4-10)
789 worth of quantity will be found. If the MSB of this byte is set, then an additional
790 7 bits (11-17) worth of quantity will be found in the next byte. This repeats until the MSB of
791 a quantity byte is zero, thus ending the run of quantity bytes.
793 Bits 5/6 of the first byte, describe the number of bytes in the value run following the quantity run.
794 These bits describe value runs of 1 to 4 bytes. And the quantity describe the number of value runs.
797 encodings are: (q = quantity, v = value, c = quantity continues)
799 case 0: [ 0 q6-q0 ] [ v7-v0 ] ... [ v7-v0 ]
800 case 1: [ 1 0 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ]
801 case 2: [ 1 0 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ]
802 case 3: [ 1 1 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
803 case 4: [ 1 1 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
807 decode_rle(const unsigned char *dataPtr
, unsigned int *quantity
,
808 unsigned int *depth
, const unsigned char **value
)
811 int i
, runlen
, runsize
;
814 mask
= dataPtr
[i
] & 0xF0;
817 runsize
= ((mask
& 0x60) >> 5) + 1;
818 runlen
= dataPtr
[i
++] & 0x0F;
824 mask
= dataPtr
[i
] & 0x80;
825 runlen
|= ((dataPtr
[i
++] & 0x7F) << shift
);
831 runsize
= dataPtr
[i
++];
836 *value
= &dataPtr
[i
];
842 /* From user mode Libc - this ought to be in a library */
844 strnstr(const char * s
, const char * find
, size_t slen
)
849 if ((c
= *find
++) != '\0') {
853 if ((sc
= *s
++) == '\0' || slen
-- < 1)
858 } while (strncmp(s
, find
, len
) != 0);
865 * these routines are for converting a color into grayscale
866 * in 8-bit mode, if the active clut is different than the
867 * clut used to create the panic dialog, then we must convert to gray
871 make24bitcolor( unsigned int index
, const unsigned char * clut
)
873 unsigned int color24
= 0;
876 color24
|= clut
[i
+0] << 16;
877 color24
|= clut
[i
+1] << 8;
878 color24
|= clut
[i
+2];
885 findbestgray( unsigned int color24
)
887 unsigned int c24
, rel
, bestindex
=-1, bestgray
= -1;
888 unsigned char gray8
, c8
;
890 #define abs(v) ((v) > 0)?(v):-(v)
892 gray8
= color24togray8( color24
); /* convert the original color into grayscale */
894 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
895 c24
= make24bitcolor( i
, active_clut
);
896 if ( (((c24
>>16)&0xff) != ((c24
>>8)&0xff)) || ((c24
>>8)&0xff) != (c24
& 0xff) )
897 continue; /* only match against grays */
899 c8
= c24
& 0xFF; /* isolate the gray */
901 /* find the gray with the smallest difference */
902 rel
= abs( gray8
- c8
);
903 if ( rel
< bestgray
) {
909 /* Did we fail to find any grays ? */
910 if (ULONG_MAX
== bestindex
) {
911 /* someday we should look for the best color match */
912 /* but for now just return the gray as the index */
913 /* at least there might be something readble on the display */
924 color24togray8( unsigned int color24
)
930 R
= (color24
& 0xFF0000) >> 16 ;
931 G
= (color24
& 0xFF00) >> 8 ;
932 B
= (color24
& 0xFF);
934 Gray
= (R
*30) + (G
*59) + (B
*11);
935 gray8
= (unsigned char) ((Gray
+ 50) / 100);
941 findIndexMatch( unsigned char index
)
943 static unsigned int last_in_index
= -1;
944 static unsigned char last_index
;
947 if ( index
== last_in_index
)
950 last_in_index
= index
;
951 sc
= make24bitcolor( index
, panic_dialog_clut
);
952 last_index
= findbestgray( sc
); /* find the nearest matching gray in the active clut */
958 isActiveClutOK( void )
961 int r
= 1; /* assume OK */
963 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
964 if ( panic_dialog_clut
[i
] == active_clut
[i
] ) continue;