2 * Copyright (c) 2002-2003 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 <kdp/kdp_udp.h>
32 #include <kern/debug.h>
33 #include <mach/mach_time.h>
34 #include <sys/errno.h>
38 extern struct vc_info vinfo
;
39 extern boolean_t panicDialogDesired
;
41 #include "panic_image.c"
43 void panic_ui_initialize(const unsigned char * system_clut
);
44 int panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
);
45 void panic_dialog_get_image( unsigned char ** ptr
, unsigned int * size
);
46 void draw_panic_dialog( void );
47 void panic_dialog_test( void );
49 static int panic_dialog_verify( const struct panicimage
* data
, unsigned int size
);
50 static int pixels_needed_to_blit_digit( int digit
);
51 static void blit_digit( int digit
);
52 static char * strnstr(const char * s
, const char * find
, size_t slen
);
53 static void dim_screen(void);
54 static void panic_blit_rect(unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
55 int transparent
, unsigned char * dataPtr
);
57 static int panic_info_x
;
58 static int panic_info_y
;
60 static const unsigned char * active_clut
= NULL
; /* This is a copy of the active clut */
62 static boolean_t panicDialogDrawn
= FALSE
;
64 static const struct panicimage
* panic_dialog
= NULL
; /* the active panic dialog */
65 static const unsigned char * panic_dialog_data
= NULL
; /* where the image data starts */
66 static const unsigned char * panic_dialog_clut
= NULL
; /* where the clut used for the image starts */
68 static unsigned char * curr_image_ptr
= NULL
; /* If NULL, the default panic dialog is active */
69 static unsigned int curr_image_size
= 0;
72 #define FONT_HEIGHT 16
73 static unsigned short rendered_font
[FONT_HEIGHT
][FONT_WIDTH
];
75 static char versionbuf
[20]; /* ####.###~###\0 */
77 #define isdigit(d) ((d) >= '0' && (d) <= '9')
79 #define CLUT_ENTRIES 256
80 #define CLUT_SIZE (CLUT_ENTRIES * 3)
84 * This routine sets up the default panic dialog
87 extern unsigned char iso_font
[];
88 extern const char version
[];
89 extern unsigned int panic_caller
;
92 panic_ui_initialize(const unsigned char * system_clut
)
97 panic_dialog_set_image( NULL
, 0 );
99 active_clut
= system_clut
;
101 strcpy(vstr
, "custom");
103 /* Convert xnu-####.###.obj~### into ####.###~### */
106 char * versionpos
= strnstr(version
, "xnu-", 20);
113 for (i
=0,len
=4;len
<20;len
++) {
114 if (isdigit(versionpos
[len
]) || versionpos
[len
] == '.') { /* extract ####.###. */
115 vstr
[i
++] = versionpos
[len
];
121 if ( versionpos
[len
-1] == '.' ) /* remove trailing period if present */
124 for (;len
<20;len
++) { /* skip to next digit if present */
125 if ( !isdigit(versionpos
[len
]) )
130 if ( versionpos
[len
-1] == '~' ) { /* extract ~### if present */
131 vstr
[i
++] = versionpos
[len
-1];
132 for (;len
<20;len
++) { /* extract ### */
133 if ( isdigit(versionpos
[len
]) ) {
134 vstr
[i
++] = versionpos
[len
];
145 strcpy(versionbuf
, vstr
);
151 panic_dialog_test( void )
153 boolean_t o_panicDialogDrawn
= panicDialogDrawn
;
154 boolean_t o_panicDialogDesired
= panicDialogDesired
;
155 unsigned int o_logPanicDataToScreen
= logPanicDataToScreen
;
156 unsigned int o_panic_caller
= panic_caller
;
157 unsigned int o_panicDebugging
= panicDebugging
;
160 panicDebugging
= TRUE
;
161 panic_caller
= (unsigned int) __builtin_return_address(0);
162 logPanicDataToScreen
= FALSE
;
163 panicDialogDesired
= TRUE
;
164 panicDialogDrawn
= FALSE
;
168 panicDebugging
= o_panicDebugging
;
169 panic_caller
= o_panic_caller
;
170 logPanicDataToScreen
= o_logPanicDataToScreen
;
171 panicDialogDesired
= o_panicDialogDesired
;
172 panicDialogDrawn
= o_panicDialogDrawn
;
177 draw_panic_dialog( void )
179 if (!panicDialogDrawn
&& panicDialogDesired
) {
180 if ( !logPanicDataToScreen
) {
182 int count
, nibble
, indx
;
183 struct ether_addr kdp_mac_addr
;
184 unsigned int panic_dialog_count
, ip_addr
;
185 char panic_num_chars
[13+8+1], mac_addr_chars
[17+1], ip_addr_chars
[15+1];
189 } panic_dialog_info
[3];
192 /* dim the screen 50% before putting up panic dialog */
195 /* set up to draw background box */
196 /* by locating where the upper left corner is placed */
198 pd_x
= (vinfo
.v_width
/2) - panic_dialog
->pd_width
/2;
199 pd_y
= (vinfo
.v_height
/2) - panic_dialog
->pd_height
/2;
201 /* draw panic dialog at pd_x/pd_y */
202 panic_blit_rect( pd_x
, pd_y
, panic_dialog
->pd_width
, panic_dialog
->pd_height
,
203 0, (unsigned char*) panic_dialog_data
);
205 panic_dialog_count
= 0; /* number of info items to display at the bottom of dialog */
207 if (panicDebugging
) {
213 * don't display the panic caller if it is 0
217 if ( panic_caller
!= 0 ) {
218 /* Calculate the pixels need to generate the panic number */
219 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
221 for ( indx
=1, count
=0; count
< 13; count
++ ) {
222 if ( versionbuf
[count
] == '\0' )
225 panic_num_chars
[indx
++] = versionbuf
[count
];
226 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( versionbuf
[count
] );
229 panic_num_chars
[indx
++] = ':';
230 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
232 for ( count
=8; count
!= 0; count
-- ) {
233 nibble
= (panic_caller
>> ((count
-1)<<2)) &0xF;
234 panic_num_chars
[indx
++] = nibble
;
235 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
238 panic_num_chars
[0] = indx
;
239 panic_dialog_info
[panic_dialog_count
].chars
= panic_num_chars
;
240 panic_dialog_count
++;
246 * if the mac address is not available, then use ff:ff:ff:ff:ff:ff
250 kdp_mac_addr
= kdp_get_mac_addr();
252 /* If no mac_addr has been set, then force to -1 */
253 if( ! (kdp_mac_addr
.ether_addr_octet
[0] || kdp_mac_addr
.ether_addr_octet
[1] || kdp_mac_addr
.ether_addr_octet
[2]
254 || kdp_mac_addr
.ether_addr_octet
[3] || kdp_mac_addr
.ether_addr_octet
[4] || kdp_mac_addr
.ether_addr_octet
[5])) {
255 for (count
= 0; count
< 6; count
++ )
256 kdp_mac_addr
.ether_addr_octet
[count
] = -1;
259 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
261 for (indx
=1, count
=0; count
< 6; count
++ ) {
262 nibble
= (kdp_mac_addr
.ether_addr_octet
[count
] & 0xf0) >> 4;
263 mac_addr_chars
[indx
++] = nibble
;
264 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
266 nibble
= kdp_mac_addr
.ether_addr_octet
[count
] & 0xf;
267 mac_addr_chars
[indx
++] = nibble
;
268 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
271 mac_addr_chars
[indx
++] = ':';
272 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
276 mac_addr_chars
[0] = indx
;
277 panic_dialog_info
[panic_dialog_count
].chars
= mac_addr_chars
;
278 panic_dialog_count
++;
283 * do not display the ip addresses if the machine isn't attachable.
284 * there's no sense in possibly confusing people.
287 if ( (ip_addr
= (unsigned int) ntohl(kdp_get_ip_address())) != 0 ) {
290 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
292 for ( indx
=1, count
=0; count
< 4; count
++ ) {
293 nibble
= (ip_addr
& 0xff000000 ) >> 24;
295 d3
= (nibble
% 10) ; nibble
= nibble
/ 10;
296 d2
= (nibble
% 10) ; nibble
= nibble
/ 10;
300 ip_addr_chars
[indx
++] = d1
;
301 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d1
);
304 ip_addr_chars
[indx
++] = d2
;
305 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d2
);
307 ip_addr_chars
[indx
++] = d3
;
308 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d3
);
311 ip_addr_chars
[indx
++] = '.';
312 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( '.' );
316 ip_addr
= ip_addr
<< 8;
319 ip_addr_chars
[0] = indx
;
320 panic_dialog_info
[panic_dialog_count
].chars
= ip_addr_chars
;
321 panic_dialog_count
++;
325 /* vertical alignment for information to be displayed */
326 panic_info_y
= (vinfo
.v_height
/2) + panic_dialog
->pd_height
/2 - (panic_dialog
->pd_info_height
);
328 /* blit out all the information we gathered */
330 switch ( panic_dialog_count
) {
331 case 1 : /* one item is centered */
332 panic_info_x
= (vinfo
.v_width
/2) - (panic_dialog_info
[0].pixels
/2);
333 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
334 blit_digit(panic_dialog_info
[0].chars
[indx
]);
338 case 2 : /* left centered and right centered */
339 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
)/2;
340 panic_info_x
= ((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
;
342 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
343 blit_digit(panic_dialog_info
[0].chars
[indx
]);
345 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[1].pixels
)/2;
346 panic_info_x
= (vinfo
.v_width
/2) + x2
;
348 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
349 blit_digit(panic_dialog_info
[1].chars
[indx
]);
353 case 3 : /* left centered, middle and right centered */
354 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
355 panic_info_x
= ((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
;
357 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
358 blit_digit(panic_dialog_info
[0].chars
[indx
]);
360 panic_info_x
= (vinfo
.v_width
/2) - (panic_dialog_info
[1].pixels
/2);
362 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
363 blit_digit(panic_dialog_info
[1].chars
[indx
]);
365 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[2].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
366 panic_info_x
= (vinfo
.v_width
/2) + x2
+ (panic_dialog_info
[1].pixels
/2);
368 for (indx
=1; indx
< panic_dialog_info
[2].chars
[0]; indx
++)
369 blit_digit(panic_dialog_info
[2].chars
[indx
]);
373 default : /* nothing */
377 } /* if panic_deugging */
378 } /* if ! logPanicDataToScreen */
379 } /* if ! panicDialogDrawn && ! panicDialogDesired */
381 panicDialogDrawn
= TRUE
;
382 panicDialogDesired
= FALSE
;
387 * This routine installs a new panic dialog
388 * If ptr is NULL, then the default "built-in" panic dialog will be installed.
389 * note: It is the caller that must take care of deallocating memory used for the previous panic dialog
393 panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
)
396 unsigned int newsize
;
397 const struct panicimage
* newimage
;
399 /* if ptr is NULL, restore panic image to built-in default */
401 newimage
= &panic_dialog_default
;
402 newsize
= sizeof(struct panicimage
) + newimage
->pd_dataSize
;
405 newimage
= (struct panicimage
*) ptr
;
409 if ( (error
= panic_dialog_verify( newimage
, newsize
)) )
412 panic_dialog
= newimage
;
413 panic_dialog_data
= &panic_dialog
->data
[0];
414 panic_dialog_clut
= &panic_dialog
->data
[panic_dialog
->pd_dataSize
-CLUT_SIZE
];
416 curr_image_ptr
= (unsigned char *) ptr
;
417 curr_image_size
= size
;
424 * This routines returns the current address of the panic dialog
425 * If the default panic dialog is active, then *ptr will be NULL
429 panic_dialog_get_image( unsigned char ** ptr
, unsigned int * size
)
431 *ptr
= curr_image_ptr
;
432 *size
= curr_image_size
;
437 * This routine verifies the panic dialog image is valid.
441 panic_dialog_verify( const struct panicimage
* newimage
, unsigned int size
)
445 if ( size
< (sizeof(struct panicimage
) + newimage
->pd_dataSize
) )
448 if ( newimage
->pd_tag
!= 'RNMp' )
451 size
= newimage
->pd_dataSize
-CLUT_SIZE
;
452 for (sum
=0,i
=0; i
<size
; i
++) {
453 sum
+= newimage
->data
[i
];
457 if ( sum
!= newimage
->pd_sum
)
465 * Service Routines for managing the panic dialog
469 static const struct rendered_num
* find_rendered_digit( int digit
);
470 static void panic_blit_rect_8( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
471 int transparent
, unsigned char * dataPtr
);
472 static void panic_blit_rect_16( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
473 int transparent
, unsigned char * dataPtr
);
474 static void panic_blit_rect_32( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
475 int transparent
, unsigned char * dataPtr
);
476 static int decode_rle( unsigned char * dataPtr
, unsigned int * quantity
, unsigned int * depth
, unsigned char ** value
);
479 /* Utilities to convert 8 bit/gray */
480 static unsigned int make24bitcolor( unsigned int index
, const unsigned char * clut
);
481 static unsigned char findIndexMatch( unsigned char index
);
482 static unsigned char color24togray8( unsigned int color24
);
483 static unsigned char findbestgray( unsigned int color24
);
484 static int isActiveClutOK( void );
487 pixels_needed_to_blit_digit( int digit
)
493 static const struct rendered_num
*
494 find_rendered_digit( int digit
)
496 //extern unsigned char iso_font[];
497 const struct rendered_num
*digitPtr
;
506 digitPtr
= (const struct rendered_num
*) &iso_font
[digit
* 16];
512 blit_digit( int digit
)
514 unsigned char * raw_data
= (unsigned char *) find_rendered_digit( digit
);
515 unsigned width
= FONT_WIDTH
, height
= FONT_HEIGHT
;
518 for (row
=0; row
<FONT_HEIGHT
; row
++) {
522 bits
= raw_data
[row
];
523 for( j
=FONT_WIDTH
-1; j
>=0; j
--) {
526 rendered_font
[row
][j
] = 0x0100 | panic_dialog
->pd_info_color
[0];
528 rendered_font
[row
][j
] = 0x0100 | panic_dialog
->pd_info_color
[1];
533 panic_blit_rect( panic_info_x
, panic_info_y
, width
, height
, 255, (unsigned char *) rendered_font
);
534 panic_info_x
+= width
;
539 panic_blit_rect( unsigned int x
, unsigned int y
,
540 unsigned int width
, unsigned int height
,
541 int transparent
, unsigned char * dataPtr
)
546 switch( vinfo
.v_depth
) {
548 panic_blit_rect_8( x
, y
, width
, height
, transparent
, dataPtr
);
551 panic_blit_rect_16( x
, y
, width
, height
, transparent
, dataPtr
);
554 panic_blit_rect_32( x
, y
, width
, height
, transparent
, dataPtr
);
560 * panic_blit_rect_8 decodes the RLE encoded image data on the fly, looks up the
561 * color by indexing into the clut, or attempts to find the best index.
565 panic_blit_rect_8( unsigned int x
, unsigned int y
,
566 unsigned int width
, unsigned int height
,
567 int transparent
, unsigned char * dataPtr
)
569 volatile unsigned char * dst
;
570 unsigned int line
, col
, i
;
571 static int clutOK
= -1;
572 unsigned int data
, quantity
, depth
;
573 unsigned char * value
;
577 clutOK
= isActiveClutOK();
579 dst
= (volatile unsigned char *) (vinfo
.v_baseaddr
+
580 (y
* vinfo
.v_rowbytes
) +
586 for( line
= 0; line
< height
; line
++) {
587 for( col
= 0; col
< width
; col
++) {
590 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
597 data
= findIndexMatch( value
[i
++] );
607 dst
= (volatile unsigned char *) (((int)dst
) + vinfo
.v_rowbytes
);
612 * panic_blit_rect_16 decodes the RLE encoded image data on the fly, looks up the
613 * color by indexing into the clut, uses the top 5 bits to fill in each of the three
614 * pixel values (RGB) and writes each pixel to the screen.
618 panic_blit_rect_16( unsigned int x
, unsigned int y
,
619 unsigned int width
, unsigned int height
,
620 int transparent
, unsigned char * dataPtr
)
623 volatile unsigned short * dst
;
624 unsigned int line
, col
, i
;
625 unsigned int quantity
, index
, data
, depth
;
626 unsigned char * value
;
628 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
629 (y
* vinfo
.v_rowbytes
) +
635 for( line
= 0; line
< height
; line
++) {
636 for( col
= 0; col
< width
; col
++) {
639 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
643 index
= value
[i
++] * 3;
645 data
= ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 0])) << 7)
646 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 1])) << 2)
647 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 2])) >> 3);
657 dst
= (volatile unsigned short *) (((int)dst
) + vinfo
.v_rowbytes
);
662 * panic_blit_rect_32 decodes the RLE encoded image data on the fly, and fills
663 * in each of the three pixel values from the clut (RGB) for each pixel and
664 * writes it to the screen.
668 panic_blit_rect_32( unsigned int x
, unsigned int y
,
669 unsigned int width
, unsigned int height
,
670 int transparent
, unsigned char * dataPtr
)
672 volatile unsigned int * dst
;
673 unsigned int line
, col
, i
;
674 unsigned int quantity
, index
, data
, depth
;
675 unsigned char * value
;
678 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
679 (y
* vinfo
.v_rowbytes
) +
685 for( line
= 0; line
< height
; line
++) {
686 for( col
= 0; col
< width
; col
++) {
689 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
693 index
= value
[i
++] * 3;
695 data
= ( (unsigned int) panic_dialog_clut
[index
+ 0] << 16)
696 | ( (unsigned int) panic_dialog_clut
[index
+ 1] << 8)
697 | ( (unsigned int) panic_dialog_clut
[index
+ 2]);
707 dst
= (volatile unsigned int *) (((int)dst
) + vinfo
.v_rowbytes
);
712 decode_rle decodes a single quantity/value run of a "modified-RLE" encoded
713 image. The encoding works as follows:
715 The run is described in the first byte. If the MSB is zero, then the next seven bits
716 are the quantity of bytes that follow that make up the run of value bytes. (see case 0)
718 If the MSB is set, bits 0-3 are the quantity's least significant 4 bits. If bit 5 is set,
719 then the quantity is further described in the next byte, where an additional 7 bits (4-10)
720 worth of quantity will be found. If the MSB of this byte is set, then an additional
721 7 bits (11-17) worth of quantity will be found in the next byte. This repeats until the MSB of
722 a quantity byte is zero, thus ending the run of quantity bytes.
724 Bits 5/6 of the first byte, describe the number of bytes in the value run following the quantity run.
725 These bits describe value runs of 1 to 4 bytes. And the quantity describe the number of value runs.
728 encodings are: (q = quantity, v = value, c = quantity continues)
730 case 0: [ 0 q6-q0 ] [ v7-v0 ] ... [ v7-v0 ]
731 case 1: [ 1 0 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ]
732 case 2: [ 1 0 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ]
733 case 3: [ 1 1 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
734 case 4: [ 1 1 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
738 decode_rle( unsigned char * dataPtr
, unsigned int * quantity
, unsigned int * depth
, unsigned char ** value
)
741 int i
, runlen
, runsize
;
744 mask
= dataPtr
[i
] & 0xF0;
747 runsize
= ((mask
& 0x60) >> 5) + 1;
748 runlen
= dataPtr
[i
++] & 0x0F;
754 mask
= dataPtr
[i
] & 0x80;
755 runlen
|= ((dataPtr
[i
++] & 0x7F) << shift
);
761 runsize
= dataPtr
[i
++];
766 *value
= &dataPtr
[i
];
775 unsigned long *p
, *endp
, *row
;
776 int col
, rowline
, rowlongs
;
777 register unsigned long mask
;
782 if ( vinfo
.v_depth
== 32 )
784 else if ( vinfo
.v_depth
== 16 )
789 rowline
= vinfo
.v_rowscanbytes
/ 4;
790 rowlongs
= vinfo
.v_rowbytes
/ 4;
792 p
= (unsigned long*) vinfo
.v_baseaddr
;
793 endp
= p
+ (rowlongs
* vinfo
.v_height
);
795 for (row
= p
; row
< endp
; row
+= rowlongs
) {
796 for (p
= &row
[0], col
= 0; col
< rowline
; col
++) {
797 *p
++ = (*p
>> 1) & mask
;
803 /* From user mode Libc - this ought to be in a library */
805 strnstr(const char * s
, const char * find
, size_t slen
)
810 if ((c
= *find
++) != '\0') {
814 if ((sc
= *s
++) == '\0' || slen
-- < 1)
819 } while (strncmp(s
, find
, len
) != 0);
826 * these routines are for converting a color into grayscale
827 * in 8-bit mode, if the active clut is different than the
828 * clut used to create the panic dialog, then we must convert to gray
832 make24bitcolor( unsigned int index
, const unsigned char * clut
)
834 unsigned int color24
= 0;
837 color24
|= clut
[i
+0] << 16;
838 color24
|= clut
[i
+1] << 8;
839 color24
|= clut
[i
+2];
846 findbestgray( unsigned int color24
)
848 unsigned int c24
, rel
, bestindex
=-1, bestgray
= -1;
849 unsigned char gray8
, c8
;
851 #define abs(v) ((v) > 0)?(v):-(v)
853 gray8
= color24togray8( color24
); /* convert the original color into grayscale */
855 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
856 c24
= make24bitcolor( i
, active_clut
);
857 if ( (((c24
>>16)&0xff) != ((c24
>>8)&0xff)) || ((c24
>>8)&0xff) != (c24
& 0xff) )
858 continue; /* only match against grays */
860 c8
= c24
& 0xFF; /* isolate the gray */
862 /* find the gray with the smallest difference */
863 rel
= abs( gray8
- c8
);
864 if ( rel
< bestgray
) {
870 /* Did we fail to find any grays ? */
871 if ( bestindex
== -1 ) {
872 /* someday we should look for the best color match */
873 /* but for now just return the gray as the index */
874 /* at least there might be something readble on the display */
885 color24togray8( unsigned int color24
)
891 R
= (color24
& 0xFF0000) >> 16 ;
892 G
= (color24
& 0xFF00) >> 8 ;
893 B
= (color24
& 0xFF);
895 Gray
= (R
*.30) + (G
*.59) + (B
*.11);
896 gray8
= (unsigned char) ( Gray
+ .5);
902 findIndexMatch( unsigned char index
)
904 static unsigned int last_in_index
= -1;
905 static unsigned char last_index
;
908 if ( index
== last_in_index
)
911 last_in_index
= index
;
912 sc
= make24bitcolor( index
, panic_dialog_clut
);
913 last_index
= findbestgray( sc
); /* find the nearest matching gray in the active clut */
919 isActiveClutOK( void )
922 int r
= 1; /* assume OK */
924 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
925 if ( panic_dialog_clut
[i
] == active_clut
[i
] ) continue;