2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
32 #include <console/video_console.h>
33 #include <libkern/OSByteOrder.h>
34 #include <kdp/kdp_udp.h>
35 #include <kern/debug.h>
36 #include <mach/mach_time.h>
37 #include <sys/errno.h>
41 extern struct vc_info vinfo
;
42 extern boolean_t panicDialogDesired
;
44 #include "panic_image.c"
46 void panic_ui_initialize(const unsigned char * system_clut
);
47 int panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
);
48 void panic_dialog_get_image( unsigned char ** ptr
, unsigned int * size
);
49 void draw_panic_dialog( void );
50 void panic_dialog_test( void );
52 static int panic_dialog_verify( const struct panicimage
* data
, unsigned int size
);
53 static int pixels_needed_to_blit_digit( int digit
);
54 static void blit_digit( int digit
);
55 static char * strnstr(const char * s
, const char * find
, size_t slen
);
56 static void dim_screen(void);
57 static void panic_blit_rect(unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
58 int transparent
, unsigned char * dataPtr
);
60 static int panic_info_x
;
61 static int panic_info_y
;
63 static const unsigned char * active_clut
= NULL
; /* This is a copy of the active clut */
65 static boolean_t panicDialogDrawn
= FALSE
;
67 static const struct panicimage
* panic_dialog
= NULL
; /* the active panic dialog */
68 static const unsigned char * panic_dialog_data
= NULL
; /* where the image data starts */
69 static const unsigned char * panic_dialog_clut
= NULL
; /* where the clut used for the image starts */
71 static unsigned char * curr_image_ptr
= NULL
; /* If NULL, the default panic dialog is active */
72 static unsigned int curr_image_size
= 0;
75 #define FONT_HEIGHT 16
76 static unsigned short rendered_font
[FONT_HEIGHT
][FONT_WIDTH
];
78 static char versionbuf
[20]; /* ####.###~###\0 */
80 #define isdigit(d) ((d) >= '0' && (d) <= '9')
82 #define CLUT_ENTRIES 256
83 #define CLUT_SIZE (CLUT_ENTRIES * 3)
87 * This routine sets up the default panic dialog
90 extern unsigned char iso_font
[];
91 extern const char version
[];
92 extern unsigned int panic_caller
;
95 panic_ui_initialize(const unsigned char * system_clut
)
100 panic_dialog_set_image( NULL
, 0 );
102 active_clut
= system_clut
;
104 strcpy(vstr
, "custom");
106 /* Convert xnu-####.###.obj~### into ####.###~### */
109 char * versionpos
= strnstr(version
, "xnu-", 20);
116 for (i
=0,len
=4;len
<20;len
++) {
117 if (isdigit(versionpos
[len
]) || versionpos
[len
] == '.') { /* extract ####.###. */
118 vstr
[i
++] = versionpos
[len
];
124 if ( versionpos
[len
-1] == '.' ) /* remove trailing period if present */
127 for (;len
<20;len
++) { /* skip to next digit if present */
128 if ( !isdigit(versionpos
[len
]) )
133 if ( versionpos
[len
-1] == '~' ) { /* extract ~### if present */
134 vstr
[i
++] = versionpos
[len
-1];
135 for (;len
<20;len
++) { /* extract ### */
136 if ( isdigit(versionpos
[len
]) ) {
137 vstr
[i
++] = versionpos
[len
];
148 strcpy(versionbuf
, vstr
);
154 panic_dialog_test( void )
156 boolean_t o_panicDialogDrawn
= panicDialogDrawn
;
157 boolean_t o_panicDialogDesired
= panicDialogDesired
;
158 unsigned int o_logPanicDataToScreen
= logPanicDataToScreen
;
159 unsigned int o_panic_caller
= panic_caller
;
160 unsigned int o_panicDebugging
= panicDebugging
;
163 panicDebugging
= TRUE
;
164 panic_caller
= (unsigned int) __builtin_return_address(0);
165 logPanicDataToScreen
= FALSE
;
166 panicDialogDesired
= TRUE
;
167 panicDialogDrawn
= FALSE
;
171 panicDebugging
= o_panicDebugging
;
172 panic_caller
= o_panic_caller
;
173 logPanicDataToScreen
= o_logPanicDataToScreen
;
174 panicDialogDesired
= o_panicDialogDesired
;
175 panicDialogDrawn
= o_panicDialogDrawn
;
180 draw_panic_dialog( void )
182 if (!panicDialogDrawn
&& panicDialogDesired
) {
183 if ( !logPanicDataToScreen
) {
185 int count
, nibble
, indx
;
186 struct ether_addr kdp_mac_addr
;
187 unsigned int panic_dialog_count
, ip_addr
;
188 char panic_num_chars
[13+8+1], mac_addr_chars
[17+1], ip_addr_chars
[15+1];
192 } panic_dialog_info
[3];
195 /* dim the screen 50% before putting up panic dialog */
198 /* set up to draw background box */
199 /* by locating where the upper left corner is placed */
201 pd_x
= (vinfo
.v_width
/2) - panic_dialog
->pd_width
/2;
202 pd_y
= (vinfo
.v_height
/2) - panic_dialog
->pd_height
/2;
204 /* draw panic dialog at pd_x/pd_y */
205 panic_blit_rect( pd_x
, pd_y
, panic_dialog
->pd_width
, panic_dialog
->pd_height
,
206 0, (unsigned char*) panic_dialog_data
);
208 panic_dialog_count
= 0; /* number of info items to display at the bottom of dialog */
210 if (panicDebugging
) {
216 * don't display the panic caller if it is 0
220 if ( panic_caller
!= 0 ) {
221 /* Calculate the pixels need to generate the panic number */
222 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
224 for ( indx
=1, count
=0; count
< 13; count
++ ) {
225 if ( versionbuf
[count
] == '\0' )
228 panic_num_chars
[indx
++] = versionbuf
[count
];
229 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( versionbuf
[count
] );
232 panic_num_chars
[indx
++] = ':';
233 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
235 for ( count
=8; count
!= 0; count
-- ) {
236 nibble
= (panic_caller
>> ((count
-1)<<2)) &0xF;
237 panic_num_chars
[indx
++] = nibble
;
238 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
241 panic_num_chars
[0] = indx
;
242 panic_dialog_info
[panic_dialog_count
].chars
= panic_num_chars
;
243 panic_dialog_count
++;
249 * if the mac address is not available, then use ff:ff:ff:ff:ff:ff
253 kdp_mac_addr
= kdp_get_mac_addr();
255 /* If no mac_addr has been set, then force to -1 */
256 if( ! (kdp_mac_addr
.ether_addr_octet
[0] || kdp_mac_addr
.ether_addr_octet
[1] || kdp_mac_addr
.ether_addr_octet
[2]
257 || kdp_mac_addr
.ether_addr_octet
[3] || kdp_mac_addr
.ether_addr_octet
[4] || kdp_mac_addr
.ether_addr_octet
[5])) {
258 for (count
= 0; count
< 6; count
++ )
259 kdp_mac_addr
.ether_addr_octet
[count
] = -1;
262 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
264 for (indx
=1, count
=0; count
< 6; count
++ ) {
265 nibble
= (kdp_mac_addr
.ether_addr_octet
[count
] & 0xf0) >> 4;
266 mac_addr_chars
[indx
++] = nibble
;
267 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
269 nibble
= kdp_mac_addr
.ether_addr_octet
[count
] & 0xf;
270 mac_addr_chars
[indx
++] = nibble
;
271 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
274 mac_addr_chars
[indx
++] = ':';
275 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
279 mac_addr_chars
[0] = indx
;
280 panic_dialog_info
[panic_dialog_count
].chars
= mac_addr_chars
;
281 panic_dialog_count
++;
286 * do not display the ip addresses if the machine isn't attachable.
287 * there's no sense in possibly confusing people.
290 if ( (ip_addr
= (unsigned int) ntohl(kdp_get_ip_address())) != 0 ) {
293 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
295 for ( indx
=1, count
=0; count
< 4; count
++ ) {
296 nibble
= (ip_addr
& 0xff000000 ) >> 24;
298 d3
= (nibble
% 10) ; nibble
= nibble
/ 10;
299 d2
= (nibble
% 10) ; nibble
= nibble
/ 10;
303 ip_addr_chars
[indx
++] = d1
;
304 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d1
);
307 ip_addr_chars
[indx
++] = d2
;
308 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d2
);
310 ip_addr_chars
[indx
++] = d3
;
311 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d3
);
314 ip_addr_chars
[indx
++] = '.';
315 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( '.' );
319 ip_addr
= ip_addr
<< 8;
322 ip_addr_chars
[0] = indx
;
323 panic_dialog_info
[panic_dialog_count
].chars
= ip_addr_chars
;
324 panic_dialog_count
++;
328 /* vertical alignment for information to be displayed */
329 panic_info_y
= (vinfo
.v_height
/2) + panic_dialog
->pd_height
/2 - (panic_dialog
->pd_info_height
);
331 /* blit out all the information we gathered */
333 switch ( panic_dialog_count
) {
334 case 1 : /* one item is centered */
335 panic_info_x
= (vinfo
.v_width
/2) - (panic_dialog_info
[0].pixels
/2);
336 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
337 blit_digit(panic_dialog_info
[0].chars
[indx
]);
341 case 2 : /* left centered and right centered */
342 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
)/2;
343 panic_info_x
= ((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
;
345 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
346 blit_digit(panic_dialog_info
[0].chars
[indx
]);
348 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[1].pixels
)/2;
349 panic_info_x
= (vinfo
.v_width
/2) + x2
;
351 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
352 blit_digit(panic_dialog_info
[1].chars
[indx
]);
356 case 3 : /* left centered, middle and right centered */
357 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
358 panic_info_x
= ((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
;
360 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
361 blit_digit(panic_dialog_info
[0].chars
[indx
]);
363 panic_info_x
= (vinfo
.v_width
/2) - (panic_dialog_info
[1].pixels
/2);
365 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
366 blit_digit(panic_dialog_info
[1].chars
[indx
]);
368 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[2].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
369 panic_info_x
= (vinfo
.v_width
/2) + x2
+ (panic_dialog_info
[1].pixels
/2);
371 for (indx
=1; indx
< panic_dialog_info
[2].chars
[0]; indx
++)
372 blit_digit(panic_dialog_info
[2].chars
[indx
]);
376 default : /* nothing */
380 } /* if panic_deugging */
381 } /* if ! logPanicDataToScreen */
382 } /* if ! panicDialogDrawn && ! panicDialogDesired */
384 panicDialogDrawn
= TRUE
;
385 panicDialogDesired
= FALSE
;
390 * This routine installs a new panic dialog
391 * If ptr is NULL, then the default "built-in" panic dialog will be installed.
392 * note: It is the caller that must take care of deallocating memory used for the previous panic dialog
396 panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
)
399 unsigned int newsize
;
400 const struct panicimage
* newimage
;
402 /* if ptr is NULL, restore panic image to built-in default */
404 newimage
= &panic_dialog_default
;
405 newsize
= sizeof(struct panicimage
) + newimage
->pd_dataSize
;
408 newimage
= (struct panicimage
*) ptr
;
412 if ( (error
= panic_dialog_verify( newimage
, newsize
)) )
415 panic_dialog
= newimage
;
416 panic_dialog_data
= &panic_dialog
->data
[0];
417 panic_dialog_clut
= &panic_dialog
->data
[panic_dialog
->pd_dataSize
-CLUT_SIZE
];
419 curr_image_ptr
= (unsigned char *) ptr
;
420 curr_image_size
= size
;
427 * This routines returns the current address of the panic dialog
428 * If the default panic dialog is active, then *ptr will be NULL
432 panic_dialog_get_image( unsigned char ** ptr
, unsigned int * size
)
434 *ptr
= curr_image_ptr
;
435 *size
= curr_image_size
;
440 * This routine verifies the panic dialog image is valid.
444 panic_dialog_verify( const struct panicimage
* newimage
, unsigned int size
)
448 if ( size
< (sizeof(struct panicimage
) + newimage
->pd_dataSize
) )
451 if ( newimage
->pd_tag
!= 'RNMp' )
454 size
= newimage
->pd_dataSize
-CLUT_SIZE
;
455 for (sum
=0,i
=0; i
<size
; i
++) {
456 sum
+= newimage
->data
[i
];
460 if ( sum
!= newimage
->pd_sum
)
468 * Service Routines for managing the panic dialog
472 static const struct rendered_num
* find_rendered_digit( int digit
);
473 static void panic_blit_rect_8( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
474 int transparent
, unsigned char * dataPtr
);
475 static void panic_blit_rect_16( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
476 int transparent
, unsigned char * dataPtr
);
477 static void panic_blit_rect_32( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
478 int transparent
, unsigned char * dataPtr
);
479 static int decode_rle( unsigned char * dataPtr
, unsigned int * quantity
, unsigned int * depth
, unsigned char ** value
);
482 /* Utilities to convert 8 bit/gray */
483 static unsigned int make24bitcolor( unsigned int index
, const unsigned char * clut
);
484 static unsigned char findIndexMatch( unsigned char index
);
485 static unsigned char color24togray8( unsigned int color24
);
486 static unsigned char findbestgray( unsigned int color24
);
487 static int isActiveClutOK( void );
490 pixels_needed_to_blit_digit( int digit
)
496 static const struct rendered_num
*
497 find_rendered_digit( int digit
)
499 //extern unsigned char iso_font[];
500 const struct rendered_num
*digitPtr
;
509 digitPtr
= (const struct rendered_num
*) &iso_font
[digit
* 16];
515 blit_digit( int digit
)
517 unsigned char * raw_data
= (unsigned char *) find_rendered_digit( digit
);
518 unsigned width
= FONT_WIDTH
, height
= FONT_HEIGHT
;
521 for (row
=0; row
<FONT_HEIGHT
; row
++) {
525 bits
= raw_data
[row
];
526 for( j
=FONT_WIDTH
-1; j
>=0; j
--) {
529 rendered_font
[row
][j
] = OSSwapBigToHostInt16(0x0100 | panic_dialog
->pd_info_color
[0]);
531 rendered_font
[row
][j
] = OSSwapBigToHostInt16(0x0100 | panic_dialog
->pd_info_color
[1]);
536 panic_blit_rect( panic_info_x
, panic_info_y
, width
, height
, 255, (unsigned char *) rendered_font
);
537 panic_info_x
+= width
;
542 panic_blit_rect( unsigned int x
, unsigned int y
,
543 unsigned int width
, unsigned int height
,
544 int transparent
, unsigned char * dataPtr
)
549 switch( vinfo
.v_depth
) {
551 panic_blit_rect_8( x
, y
, width
, height
, transparent
, dataPtr
);
554 panic_blit_rect_16( x
, y
, width
, height
, transparent
, dataPtr
);
557 panic_blit_rect_32( x
, y
, width
, height
, transparent
, dataPtr
);
563 * panic_blit_rect_8 decodes the RLE encoded image data on the fly, looks up the
564 * color by indexing into the clut, or attempts to find the best index.
568 panic_blit_rect_8( unsigned int x
, unsigned int y
,
569 unsigned int width
, unsigned int height
,
570 int transparent
, unsigned char * dataPtr
)
572 volatile unsigned char * dst
;
573 unsigned int line
, col
, i
;
574 static int clutOK
= -1;
575 unsigned int data
, quantity
, depth
;
576 unsigned char * value
;
580 clutOK
= isActiveClutOK();
582 dst
= (volatile unsigned char *) (vinfo
.v_baseaddr
+
583 (y
* vinfo
.v_rowbytes
) +
589 for( line
= 0; line
< height
; line
++) {
590 for( col
= 0; col
< width
; col
++) {
593 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
600 data
= findIndexMatch( value
[i
++] );
610 dst
= (volatile unsigned char *) (((int)dst
) + vinfo
.v_rowbytes
);
615 * panic_blit_rect_16 decodes the RLE encoded image data on the fly, looks up the
616 * color by indexing into the clut, uses the top 5 bits to fill in each of the three
617 * pixel values (RGB) and writes each pixel to the screen.
621 panic_blit_rect_16( unsigned int x
, unsigned int y
,
622 unsigned int width
, unsigned int height
,
623 int transparent
, unsigned char * dataPtr
)
626 volatile unsigned short * dst
;
627 unsigned int line
, col
, i
;
628 unsigned int quantity
, index
, data
, depth
;
629 unsigned char * value
;
631 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
632 (y
* vinfo
.v_rowbytes
) +
638 for( line
= 0; line
< height
; line
++) {
639 for( col
= 0; col
< width
; col
++) {
642 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
646 index
= value
[i
++] * 3;
648 data
= ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 0])) << 7)
649 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 1])) << 2)
650 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 2])) >> 3);
660 dst
= (volatile unsigned short *) (((int)dst
) + vinfo
.v_rowbytes
);
665 * panic_blit_rect_32 decodes the RLE encoded image data on the fly, and fills
666 * in each of the three pixel values from the clut (RGB) for each pixel and
667 * writes it to the screen.
671 panic_blit_rect_32( unsigned int x
, unsigned int y
,
672 unsigned int width
, unsigned int height
,
673 int transparent
, unsigned char * dataPtr
)
675 volatile unsigned int * dst
;
676 unsigned int line
, col
, i
;
677 unsigned int quantity
, index
, data
, depth
;
678 unsigned char * value
;
681 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
682 (y
* vinfo
.v_rowbytes
) +
688 for( line
= 0; line
< height
; line
++) {
689 for( col
= 0; col
< width
; col
++) {
692 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
696 index
= value
[i
++] * 3;
698 data
= ( (unsigned int) panic_dialog_clut
[index
+ 0] << 16)
699 | ( (unsigned int) panic_dialog_clut
[index
+ 1] << 8)
700 | ( (unsigned int) panic_dialog_clut
[index
+ 2]);
710 dst
= (volatile unsigned int *) (((int)dst
) + vinfo
.v_rowbytes
);
715 decode_rle decodes a single quantity/value run of a "modified-RLE" encoded
716 image. The encoding works as follows:
718 The run is described in the first byte. If the MSB is zero, then the next seven bits
719 are the quantity of bytes that follow that make up the run of value bytes. (see case 0)
721 If the MSB is set, bits 0-3 are the quantity's least significant 4 bits. If bit 5 is set,
722 then the quantity is further described in the next byte, where an additional 7 bits (4-10)
723 worth of quantity will be found. If the MSB of this byte is set, then an additional
724 7 bits (11-17) worth of quantity will be found in the next byte. This repeats until the MSB of
725 a quantity byte is zero, thus ending the run of quantity bytes.
727 Bits 5/6 of the first byte, describe the number of bytes in the value run following the quantity run.
728 These bits describe value runs of 1 to 4 bytes. And the quantity describe the number of value runs.
731 encodings are: (q = quantity, v = value, c = quantity continues)
733 case 0: [ 0 q6-q0 ] [ v7-v0 ] ... [ v7-v0 ]
734 case 1: [ 1 0 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ]
735 case 2: [ 1 0 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ]
736 case 3: [ 1 1 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
737 case 4: [ 1 1 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
741 decode_rle( unsigned char * dataPtr
, unsigned int * quantity
, unsigned int * depth
, unsigned char ** value
)
744 int i
, runlen
, runsize
;
747 mask
= dataPtr
[i
] & 0xF0;
750 runsize
= ((mask
& 0x60) >> 5) + 1;
751 runlen
= dataPtr
[i
++] & 0x0F;
757 mask
= dataPtr
[i
] & 0x80;
758 runlen
|= ((dataPtr
[i
++] & 0x7F) << shift
);
764 runsize
= dataPtr
[i
++];
769 *value
= &dataPtr
[i
];
778 unsigned long *p
, *endp
, *row
;
779 int col
, rowline
, rowlongs
;
780 register unsigned long mask
;
785 if ( vinfo
.v_depth
== 32 )
787 else if ( vinfo
.v_depth
== 16 )
792 rowline
= vinfo
.v_rowscanbytes
/ 4;
793 rowlongs
= vinfo
.v_rowbytes
/ 4;
795 p
= (unsigned long*) vinfo
.v_baseaddr
;
796 endp
= p
+ (rowlongs
* vinfo
.v_height
);
798 for (row
= p
; row
< endp
; row
+= rowlongs
) {
799 for (p
= &row
[0], col
= 0; col
< rowline
; col
++) {
800 *p
++ = (*p
>> 1) & mask
;
806 /* From user mode Libc - this ought to be in a library */
808 strnstr(const char * s
, const char * find
, size_t slen
)
813 if ((c
= *find
++) != '\0') {
817 if ((sc
= *s
++) == '\0' || slen
-- < 1)
822 } while (strncmp(s
, find
, len
) != 0);
829 * these routines are for converting a color into grayscale
830 * in 8-bit mode, if the active clut is different than the
831 * clut used to create the panic dialog, then we must convert to gray
835 make24bitcolor( unsigned int index
, const unsigned char * clut
)
837 unsigned int color24
= 0;
840 color24
|= clut
[i
+0] << 16;
841 color24
|= clut
[i
+1] << 8;
842 color24
|= clut
[i
+2];
849 findbestgray( unsigned int color24
)
851 unsigned int c24
, rel
, bestindex
=-1, bestgray
= -1;
852 unsigned char gray8
, c8
;
854 #define abs(v) ((v) > 0)?(v):-(v)
856 gray8
= color24togray8( color24
); /* convert the original color into grayscale */
858 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
859 c24
= make24bitcolor( i
, active_clut
);
860 if ( (((c24
>>16)&0xff) != ((c24
>>8)&0xff)) || ((c24
>>8)&0xff) != (c24
& 0xff) )
861 continue; /* only match against grays */
863 c8
= c24
& 0xFF; /* isolate the gray */
865 /* find the gray with the smallest difference */
866 rel
= abs( gray8
- c8
);
867 if ( rel
< bestgray
) {
873 /* Did we fail to find any grays ? */
874 if ( bestindex
== -1 ) {
875 /* someday we should look for the best color match */
876 /* but for now just return the gray as the index */
877 /* at least there might be something readble on the display */
888 color24togray8( unsigned int color24
)
894 R
= (color24
& 0xFF0000) >> 16 ;
895 G
= (color24
& 0xFF00) >> 8 ;
896 B
= (color24
& 0xFF);
898 Gray
= (R
*30) + (G
*59) + (B
*11);
899 gray8
= (unsigned char) ((Gray
+ 50) / 100);
905 findIndexMatch( unsigned char index
)
907 static unsigned int last_in_index
= -1;
908 static unsigned char last_index
;
911 if ( index
== last_in_index
)
914 last_in_index
= index
;
915 sc
= make24bitcolor( index
, panic_dialog_clut
);
916 last_index
= findbestgray( sc
); /* find the nearest matching gray in the active clut */
922 isActiveClutOK( void )
925 int r
= 1; /* assume OK */
927 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
928 if ( panic_dialog_clut
[i
] == active_clut
[i
] ) continue;