]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/console/panic_dialog.c
xnu-1456.1.26.tar.gz
[apple/xnu.git] / osfmk / console / panic_dialog.c
index 1cf72878091c0668693ae15cc17bc40c5a8edc01..29fa14890254216eb551ba9362fb28f2c2ecb0ae 100644 (file)
 /*
 /*
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved.
  *
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
  * 
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
 #include <vc.h>
  */
 
 #include <vc.h>
-
 #include <console/video_console.h>
 #include <console/video_console.h>
+#include <libkern/OSByteOrder.h>
 #include <kdp/kdp_udp.h>
 #include <kern/debug.h>
 #include <kdp/kdp_udp.h>
 #include <kern/debug.h>
-
-#include "panic_image.c"
-#include "rendered_numbers.c"
+#include <mach/mach_time.h>
+#include <sys/errno.h>
+#include <string.h>
+#include <machine/machlimits.h>
 
 extern struct vc_info vinfo;
 extern boolean_t panicDialogDesired;
 
 
 extern struct vc_info vinfo;
 extern boolean_t panicDialogDesired;
 
-/* panic image clut */
-static const unsigned char *clut = NULL;
-extern void panic_ui_initialize(const unsigned char * system_clut);
-
-/* We use this standard MacOS clut as a fallback */
-static const unsigned char appleClut8[ 256 * 3 ] = { 
-// 00
-       0xFF,0xFF,0xFF, 0xFF,0xFF,0xCC, 0xFF,0xFF,0x99, 0xFF,0xFF,0x66,
-       0xFF,0xFF,0x33, 0xFF,0xFF,0x00, 0xFF,0xCC,0xFF, 0xFF,0xCC,0xCC,
-       0xFF,0xCC,0x99, 0xFF,0xCC,0x66, 0xFF,0xCC,0x33, 0xFF,0xCC,0x00,
-       0xFF,0x99,0xFF, 0xFF,0x99,0xCC, 0xFF,0x99,0x99, 0xFF,0x99,0x66,
-// 10
-       0xFF,0x99,0x33, 0xFF,0x99,0x00, 0xFF,0x66,0xFF, 0xFF,0x66,0xCC,
-       0xFF,0x66,0x99, 0xFF,0x66,0x66, 0xFF,0x66,0x33, 0xFF,0x66,0x00,
-       0xFF,0x33,0xFF, 0xFF,0x33,0xCC, 0xFF,0x33,0x99, 0xFF,0x33,0x66,
-       0xFF,0x33,0x33, 0xFF,0x33,0x00, 0xFF,0x00,0xFF, 0xFF,0x00,0xCC,
-// 20
-       0xFF,0x00,0x99, 0xFF,0x00,0x66, 0xFF,0x00,0x33, 0xFF,0x00,0x00,
-       0xCC,0xFF,0xFF, 0xCC,0xFF,0xCC, 0xCC,0xFF,0x99, 0xCC,0xFF,0x66,
-       0xCC,0xFF,0x33, 0xCC,0xFF,0x00, 0xCC,0xCC,0xFF, 0xCC,0xCC,0xCC,
-       0xCC,0xCC,0x99, 0xCC,0xCC,0x66, 0xCC,0xCC,0x33, 0xCC,0xCC,0x00,
-// 30
-       0xCC,0x99,0xFF, 0xCC,0x99,0xCC, 0xCC,0x99,0x99, 0xCC,0x99,0x66,
-       0xCC,0x99,0x33, 0xCC,0x99,0x00, 0xCC,0x66,0xFF, 0xCC,0x66,0xCC,
-       0xCC,0x66,0x99, 0xCC,0x66,0x66, 0xCC,0x66,0x33, 0xCC,0x66,0x00,
-       0xCC,0x33,0xFF, 0xCC,0x33,0xCC, 0xCC,0x33,0x99, 0xCC,0x33,0x66,
-// 40
-       0xCC,0x33,0x33, 0xCC,0x33,0x00, 0xCC,0x00,0xFF, 0xCC,0x00,0xCC,
-       0xCC,0x00,0x99, 0xCC,0x00,0x66, 0xCC,0x00,0x33, 0xCC,0x00,0x00,
-       0x99,0xFF,0xFF, 0x99,0xFF,0xCC, 0x99,0xFF,0x99, 0x99,0xFF,0x66,
-       0x99,0xFF,0x33, 0x99,0xFF,0x00, 0x99,0xCC,0xFF, 0x99,0xCC,0xCC,
-// 50
-       0x99,0xCC,0x99, 0x99,0xCC,0x66, 0x99,0xCC,0x33, 0x99,0xCC,0x00,
-       0x99,0x99,0xFF, 0x99,0x99,0xCC, 0x99,0x99,0x99, 0x99,0x99,0x66,
-       0x99,0x99,0x33, 0x99,0x99,0x00, 0x99,0x66,0xFF, 0x99,0x66,0xCC,
-       0x99,0x66,0x99, 0x99,0x66,0x66, 0x99,0x66,0x33, 0x99,0x66,0x00,
-// 60
-       0x99,0x33,0xFF, 0x99,0x33,0xCC, 0x99,0x33,0x99, 0x99,0x33,0x66,
-       0x99,0x33,0x33, 0x99,0x33,0x00, 0x99,0x00,0xFF, 0x99,0x00,0xCC,
-       0x99,0x00,0x99, 0x99,0x00,0x66, 0x99,0x00,0x33, 0x99,0x00,0x00,
-       0x66,0xFF,0xFF, 0x66,0xFF,0xCC, 0x66,0xFF,0x99, 0x66,0xFF,0x66,
-// 70
-       0x66,0xFF,0x33, 0x66,0xFF,0x00, 0x66,0xCC,0xFF, 0x66,0xCC,0xCC,
-       0x66,0xCC,0x99, 0x66,0xCC,0x66, 0x66,0xCC,0x33, 0x66,0xCC,0x00,
-       0x66,0x99,0xFF, 0x66,0x99,0xCC, 0x66,0x99,0x99, 0x66,0x99,0x66,
-       0x66,0x99,0x33, 0x66,0x99,0x00, 0x66,0x66,0xFF, 0x66,0x66,0xCC,
-// 80
-       0x66,0x66,0x99, 0x66,0x66,0x66, 0x66,0x66,0x33, 0x66,0x66,0x00,
-       0x66,0x33,0xFF, 0x66,0x33,0xCC, 0x66,0x33,0x99, 0x66,0x33,0x66,
-       0x66,0x33,0x33, 0x66,0x33,0x00, 0x66,0x00,0xFF, 0x66,0x00,0xCC,
-       0x66,0x00,0x99, 0x66,0x00,0x66, 0x66,0x00,0x33, 0x66,0x00,0x00,
-// 90
-       0x33,0xFF,0xFF, 0x33,0xFF,0xCC, 0x33,0xFF,0x99, 0x33,0xFF,0x66,
-       0x33,0xFF,0x33, 0x33,0xFF,0x00, 0x33,0xCC,0xFF, 0x33,0xCC,0xCC,
-       0x33,0xCC,0x99, 0x33,0xCC,0x66, 0x33,0xCC,0x33, 0x33,0xCC,0x00,
-       0x33,0x99,0xFF, 0x33,0x99,0xCC, 0x33,0x99,0x99, 0x33,0x99,0x66,
-// a0
-       0x33,0x99,0x33, 0x33,0x99,0x00, 0x33,0x66,0xFF, 0x33,0x66,0xCC,
-       0x33,0x66,0x99, 0x33,0x66,0x66, 0x33,0x66,0x33, 0x33,0x66,0x00,
-       0x33,0x33,0xFF, 0x33,0x33,0xCC, 0x33,0x33,0x99, 0x33,0x33,0x66,
-       0x33,0x33,0x33, 0x33,0x33,0x00, 0x33,0x00,0xFF, 0x33,0x00,0xCC,
-// b0
-       0x33,0x00,0x99, 0x33,0x00,0x66, 0x33,0x00,0x33, 0x33,0x00,0x00,
-       0x00,0xFF,0xFF, 0x00,0xFF,0xCC, 0x00,0xFF,0x99, 0x00,0xFF,0x66,
-       0x00,0xFF,0x33, 0x00,0xFF,0x00, 0x00,0xCC,0xFF, 0x00,0xCC,0xCC,
-       0x00,0xCC,0x99, 0x00,0xCC,0x66, 0x00,0xCC,0x33, 0x00,0xCC,0x00,
-// c0
-       0x00,0x99,0xFF, 0x00,0x99,0xCC, 0x00,0x99,0x99, 0x00,0x99,0x66,
-       0x00,0x99,0x33, 0x00,0x99,0x00, 0x00,0x66,0xFF, 0x00,0x66,0xCC,
-       0x00,0x66,0x99, 0x00,0x66,0x66, 0x00,0x66,0x33, 0x00,0x66,0x00,
-       0x00,0x33,0xFF, 0x00,0x33,0xCC, 0x00,0x33,0x99, 0x00,0x33,0x66,
-// d0
-       0x00,0x33,0x33, 0x00,0x33,0x00, 0x00,0x00,0xFF, 0x00,0x00,0xCC,
-       0x00,0x00,0x99, 0x00,0x00,0x66, 0x00,0x00,0x33, 0xEE,0x00,0x00,
-       0xDD,0x00,0x00, 0xBB,0x00,0x00, 0xAA,0x00,0x00, 0x88,0x00,0x00,
-       0x77,0x00,0x00, 0x55,0x00,0x00, 0x44,0x00,0x00, 0x22,0x00,0x00,
-// e0
-       0x11,0x00,0x00, 0x00,0xEE,0x00, 0x00,0xDD,0x00, 0x00,0xBB,0x00,
-       0x00,0xAA,0x00, 0x00,0x88,0x00, 0x00,0x77,0x00, 0x00,0x55,0x00,
-       0x00,0x44,0x00, 0x00,0x22,0x00, 0x00,0x11,0x00, 0x00,0x00,0xEE,
-       0x00,0x00,0xDD, 0x00,0x00,0xBB, 0x00,0x00,0xAA, 0x00,0x00,0x88,
-// f0
-       0x00,0x00,0x77, 0x00,0x00,0x55, 0x00,0x00,0x44, 0x00,0x00,0x22,
-       0x00,0x00,0x11, 0xEE,0xEE,0xEE, 0xDD,0xDD,0xDD, 0xBB,0xBB,0xBB,
-       0xAA,0xAA,0xAA, 0x88,0x88,0x88, 0x77,0x77,0x77, 0x55,0x55,0x55,
-       0x44,0x44,0x44, 0x22,0x22,0x22, 0x11,0x11,0x11, 0x00,0x00,0x00
-};
-
-
-/* panic dialog and info saving */
-static int mac_addr_digit_x;
-static int mac_addr_digit_y;
+#include "panic_image.c"
+
+void panic_ui_initialize(const unsigned char * system_clut);
+int panic_dialog_set_image( const unsigned char * ptr, unsigned int size );
+void panic_dialog_get_image(const unsigned char **ptr, unsigned int *size);
+void draw_panic_dialog( void );
+void panic_dialog_test( void );
+
+static int panic_dialog_verify( const struct panicimage * data, unsigned int size );
+static int pixels_needed_to_blit_digit( int digit );
 static void blit_digit( int digit );
 static void blit_digit( int digit );
+static const char * strnstr(const char * s, const char * find, size_t slen);
+void dim_screen(void);
+static void panic_blit_rect(unsigned int x, unsigned int y, unsigned int width,
+                           unsigned int height, int transparent,
+                           const unsigned char * dataPtr);
+
+static int panic_info_x;
+static int panic_info_y;
+
+static const unsigned char * active_clut = NULL;                       /* This is a copy of the active clut */
+
 static boolean_t panicDialogDrawn = FALSE;
 
 static boolean_t panicDialogDrawn = FALSE;
 
-static void 
-panic_blit_rect(       unsigned int x, unsigned int y,
-                       unsigned int width, unsigned int height,
-                       int transparent, unsigned char * dataPtr );
-                       
-static void 
-panic_blit_rect_8(     unsigned int x, unsigned int y,
-                       unsigned int width, unsigned int height,
-                       int transparent, unsigned char * dataPtr );
-                       
-static void 
-panic_blit_rect_16(    unsigned int x, unsigned int y,
-                       unsigned int width, unsigned int height,
-                       int transparent, unsigned char * dataPtr );
-                       
-static void 
-panic_blit_rect_32(    unsigned int x, unsigned int y,
-                       unsigned int width, unsigned int height,
-                       int transparent, unsigned char * dataPtr );
+static const struct panicimage * panic_dialog = NULL;          /* the active panic dialog */
+static const unsigned char * panic_dialog_data = NULL;         /* where the image data starts */
+static const unsigned char * panic_dialog_clut = NULL;         /* where the clut used for the image starts */
 
 
-static void 
-dim_screen(void);
+static const unsigned char *curr_image_ptr; /* If NULL, the default panic
+                                              dialog is active */
+static unsigned int curr_image_size = 0;
 
 
-static void 
-dim_screen_16(void);
+#define FONT_WIDTH     8
+#define FONT_HEIGHT    16
+static unsigned short rendered_font[FONT_HEIGHT][FONT_WIDTH];
 
 
-static void 
-dim_screen_32(void);
+#define VERSIONBUF_LEN 20
+static char versionbuf[VERSIONBUF_LEN];                /* ####.###~###\0 */
 
 
-static int 
-decode_rle( unsigned char * dataPtr, unsigned int * quantity, unsigned int * value );
+#define isdigit(d) ((d) >= '0' && (d) <= '9')
 
 
-void 
+#define CLUT_ENTRIES   256
+#define CLUT_SIZE              (CLUT_ENTRIES * 3)
+
+
+/*
+ * This routine sets up the default panic dialog
+ */
+
+extern unsigned char iso_font[];
+extern const char version[];
+
+void
 panic_ui_initialize(const unsigned char * system_clut)
 {
 panic_ui_initialize(const unsigned char * system_clut)
 {
-       clut = system_clut;
+       char vstr[VERSIONBUF_LEN];
+
+       panic_dialog_set_image( NULL, 0 );
+
+       active_clut = system_clut;
+
+       strlcpy(vstr, "custom", VERSIONBUF_LEN);
+
+       /* Convert xnu-####.###.obj~### into ####.###~### */
+
+       if (version[0]) {
+               const char *versionpos = strnstr(version, "xnu-", VERSIONBUF_LEN);
+
+               if (versionpos) {
+                       int len, i;
+
+                       vstr[0] = '\0';
+
+                       for (i = 0, len = 4; len < VERSIONBUF_LEN; len++) {
+                               if (isdigit(versionpos[len]) || versionpos[len] == '.') {       /* extract ####.###. */
+                                       vstr[i++] = versionpos[len];
+                                       continue;
+                               }
+                               break;
+                       }
+
+                       if ( versionpos[len-1] == '.' )                 /* remove trailing period if present */
+                               i--;
+
+                       for (; len < VERSIONBUF_LEN; len++) {                                           /* skip to next digit if present */
+                               if ( !isdigit(versionpos[len]) )
+                                       continue;
+                               break;
+                       }
+
+                       if ( versionpos[len-1] == '~' ) {                               /* extract ~### if present */
+                               vstr[i++] = versionpos[len-1];
+                               for (; len < VERSIONBUF_LEN; len++) {                                           /* extract ### */
+                                       if ( isdigit(versionpos[len]) ) {
+                                               vstr[i++] = versionpos[len];
+                                               continue;
+                                       }
+                                       break;
+                               }
+                       }
+
+                       vstr[i] = '\0';
+               }
+       }
+
+       strlcpy(versionbuf, vstr, VERSIONBUF_LEN);
 }
 
 }
 
+
+
+void
+panic_dialog_test( void )
+{
+       boolean_t o_panicDialogDrawn = panicDialogDrawn;
+       boolean_t o_panicDialogDesired = panicDialogDesired;
+       unsigned int o_logPanicDataToScreen = logPanicDataToScreen;
+       unsigned long o_panic_caller = panic_caller;
+       unsigned int o_panicDebugging = panicDebugging;
+
+       panicDebugging = TRUE;
+       panic_caller = (unsigned long)(char *)__builtin_return_address(0);
+       logPanicDataToScreen = FALSE;
+       panicDialogDesired = TRUE;
+       panicDialogDrawn = FALSE;
+
+       draw_panic_dialog();
+
+       panicDebugging = o_panicDebugging;
+       panic_caller = o_panic_caller;
+       logPanicDataToScreen = o_logPanicDataToScreen;
+       panicDialogDesired = o_panicDialogDesired;
+       panicDialogDrawn = o_panicDialogDrawn;
+}
+
+
 void 
 draw_panic_dialog( void )
 {
 void 
 draw_panic_dialog( void )
 {
-       int pd_x,pd_y, iconx, icony, tx_line, tx_col;
-       int line_width = 1;
-       int f1, f2, d1, d2, d3, rem;
-       char *pair = "ff";
-       int count = 0;
-       char digit;
-       int nibble;
-       char colon = ':';
-       char dot = '.';
-       struct ether_addr kdp_mac_addr  = kdp_get_mac_addr();
-       unsigned int ip_addr = (unsigned int) ntohl(kdp_get_ip_address());
-
-       if (!panicDialogDrawn && panicDialogDesired)
-       {
-               if ( !logPanicDataToScreen )
-               {
+       if (!panicDialogDrawn && panicDialogDesired) {
+               if ( !logPanicDataToScreen ) {
+                       int pd_x, pd_y;
+                       int count, nibble, indx;
+                       struct ether_addr kdp_mac_addr;
+                       unsigned int panic_dialog_count, ip_addr;
+                       char panic_num_chars[13+8+1], mac_addr_chars[17+1], ip_addr_chars[15+1];
+                       struct {
+                                       int     pixels;
+                                       char * chars;
+                       } panic_dialog_info[3];
+
 
                        /* dim the screen 50% before putting up panic dialog */
                        dim_screen();
 
                        /* set up to draw background box */
 
                        /* dim the screen 50% before putting up panic dialog */
                        dim_screen();
 
                        /* set up to draw background box */
-                       pd_x = (vinfo.v_width/2) - panic_dialog.pd_width/2;
-                       pd_y = (vinfo.v_height/2) - panic_dialog.pd_height/2;
+                       /* by locating where the upper left corner is placed */
+
+                       pd_x = (int)((vinfo.v_width/2) - panic_dialog->pd_width/2);
+                       pd_y = (int)((vinfo.v_height/2) - panic_dialog->pd_height/2);
                
                
-                       /*  draw image  */
-                       panic_blit_rect( pd_x, pd_y, panic_dialog.pd_width, panic_dialog.pd_height, 0, (unsigned char*) panic_dialog.image_pixel_data);
+                       /*  draw panic dialog at pd_x/pd_y */
+                       panic_blit_rect(pd_x, pd_y, panic_dialog->pd_width,
+                                       panic_dialog->pd_height, 0,
+                                       panic_dialog_data);
                
                
-                       /* do not display the mac and ip addresses if the machine isn't attachable. */
-                       /* there's no sense in possibly confusing people. */
-                       if (panicDebugging)
-                       {
+                       panic_dialog_count = 0;         /* number of info items to display at the bottom of dialog */
+
+                       if (panicDebugging) {
+                               int x1, x2;
+
+                               /*
+                                * PANIC CALLER
+                                *
+                                *  don't display the panic caller if it is 0
+                                *
+                                */
+
+                               if ( panic_caller != 0 ) {
+                                       /* Calculate the pixels need to generate the panic number */ 
+                                       panic_dialog_info[panic_dialog_count].pixels = 0;
+
+                                       for ( indx=1, count=0; count < 13; count++ ) {
+                                               if ( versionbuf[count] == '\0' )
+                                                       break;
+
+                                               panic_num_chars[indx++] = versionbuf[count];
+                                               panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( versionbuf[count] );
+                                       }
+
+                                       panic_num_chars[indx++] = ':';
+                                       panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( ':' );
+
+                                       for ( count=8; count != 0; count-- ) {
+                                               nibble = (int)((panic_caller >> ((count-1)<<2)) &0xF);
+                                               panic_num_chars[indx++] = nibble;
+                                               panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( nibble );
+                                       }
+                               
+                                       panic_num_chars[0] = indx;
+                                       panic_dialog_info[panic_dialog_count].chars = panic_num_chars;
+                                       panic_dialog_count++;
+                               }
                
                
-                               /* offset for mac address text */
-                               mac_addr_digit_x = (vinfo.v_width/2) - 130; /* use 62 if no ip */
-                               mac_addr_digit_y = (vinfo.v_height/2) + panic_dialog.pd_height/2 - 20;
+                               /*
+                                * MAC ADDRESS
+                                *
+                                * if the mac address is not available, then use ff:ff:ff:ff:ff:ff
+                                *
+                                */
+
+                               kdp_mac_addr  = kdp_get_mac_addr();
                
                
-                               if(kdp_mac_addr.ether_addr_octet[0] || kdp_mac_addr.ether_addr_octet[1]|| kdp_mac_addr.ether_addr_octet[2]
-                                       || kdp_mac_addr.ether_addr_octet[3] || kdp_mac_addr.ether_addr_octet[4] || kdp_mac_addr.ether_addr_octet[5])
-                               {
-                                       /* blit the digits for mac address */
+                               /* If no mac_addr has been set, then force to -1 */
+                               if( ! (kdp_mac_addr.ether_addr_octet[0] || kdp_mac_addr.ether_addr_octet[1] || kdp_mac_addr.ether_addr_octet[2]
+                                       || kdp_mac_addr.ether_addr_octet[3] || kdp_mac_addr.ether_addr_octet[4] || kdp_mac_addr.ether_addr_octet[5])) {
                                        for (count = 0; count < 6; count++ )
                                        for (count = 0; count < 6; count++ )
-                                       {
-                                               nibble =  (kdp_mac_addr.ether_addr_octet[count] & 0xf0) >> 4;
-                                               digit = nibble < 10 ? nibble + '0':nibble - 10 + 'a';
-                                               blit_digit(digit);
-                               
-                                               nibble =  kdp_mac_addr.ether_addr_octet[count] & 0xf;
-                                               digit = nibble < 10 ? nibble + '0':nibble - 10 + 'a';
-                                               blit_digit(digit);
-                                               if( count < 5 )
-                                                       blit_digit( colon );
-                                       }
+                                               kdp_mac_addr.ether_addr_octet[count] = -1;
                                }
                                }
-                               else    /* blit the ff's */
-                               {
-                                       for( count = 0; count < 6; count++ )
-                                       {
-                                               digit = pair[0];
-                                               blit_digit(digit);
-                                               digit = pair[1];
-                                               blit_digit(digit);
-                                               if( count < 5 )
-                                                       blit_digit( colon );
+
+                               panic_dialog_info[panic_dialog_count].pixels = 0;
+
+                               for (indx=1, count=0; count < 6; count++ ) {
+                                       nibble =  (kdp_mac_addr.ether_addr_octet[count] & 0xf0) >> 4;
+                                       mac_addr_chars[indx++] = nibble;
+                                       panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( nibble );
+                               
+                                       nibble =  kdp_mac_addr.ether_addr_octet[count] & 0xf;
+                                       mac_addr_chars[indx++] = nibble;
+                                       panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( nibble );
+
+                                       if( count < 5 ) {
+                                               mac_addr_chars[indx++] = ':';
+                                               panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( ':' );
                                        }
                                }
                                        }
                                }
-                               /* now print the ip address */
-                               mac_addr_digit_x = (vinfo.v_width/2) + 10;
-                               if(ip_addr != 0)
-                               {
-                                       /* blit the digits for ip address */
-                                       for (count = 0; count < 4; count++ )
-                                       {
+
+                               mac_addr_chars[0] = indx;
+                               panic_dialog_info[panic_dialog_count].chars = mac_addr_chars;
+                               panic_dialog_count++;
+
+                               /*
+                                * IP ADDRESS
+                                *
+                                * do not display the ip addresses if the machine isn't attachable.
+                                * there's no sense in possibly confusing people.
+                                */
+
+                               if ( (ip_addr = (unsigned int) ntohl(kdp_get_ip_address())) != 0 ) {
+                                       int d1, d2, d3;
+
+                                       panic_dialog_info[panic_dialog_count].pixels = 0;
+
+                                       for ( indx=1, count=0; count < 4; count++ ) {
                                                nibble = (ip_addr & 0xff000000 ) >> 24;
                                
                                                nibble = (ip_addr & 0xff000000 ) >> 24;
                                
-                                               d3 = (nibble % 0xa) + '0';
-                                               nibble = nibble/0xa;
-                                               d2 = (nibble % 0xa) + '0';
-                                               nibble = nibble /0xa;
-                                               d1 = (nibble % 0xa) + '0';
+                                               d3 = (nibble % 10) ; nibble = nibble / 10;
+                                               d2 = (nibble % 10) ; nibble = nibble / 10;
+                                               d1 = (nibble % 10) ;
                                        
                                        
-                                               if( d1 != '0' ) blit_digit(d1);
-                                               blit_digit(d2);
-                                               blit_digit(d3);
-                                               if( count < 3 )
-                                                       blit_digit(dot);
+                                               if( d1 != 0 ) {
+                                                       ip_addr_chars[indx++] = d1; 
+                                                       panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( d1 );
+                                               }
+
+                                               ip_addr_chars[indx++] = d2; 
+                                               panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( d2 );
+
+                                               ip_addr_chars[indx++] = d3; 
+                                               panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( d3 );
+
+                                               if ( count < 3 ) {
+                                                       ip_addr_chars[indx++] = '.'; 
+                                                       panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( '.' );
+                                               }
                                        
                                                d1= d2 = d3 = 0;
                                                ip_addr = ip_addr << 8;
                                        }
                                        
                                                d1= d2 = d3 = 0;
                                                ip_addr = ip_addr << 8;
                                        }
+
+                                       ip_addr_chars[0] = indx;
+                                       panic_dialog_info[panic_dialog_count].chars = ip_addr_chars;
+                                       panic_dialog_count++;
                                }
                                }
-                       }
-               }
-       }
+
+
+                               /* vertical alignment for information to be displayed */
+                               panic_info_y = (int)((vinfo.v_height/2) + panic_dialog->pd_height/2 - (panic_dialog->pd_info_height));
+
+                               /* blit out all the information we gathered */
+
+                               switch ( panic_dialog_count ) {
+                                       case 1 :        /* one item is centered */
+                                                       panic_info_x = (int)((vinfo.v_width/2) - (panic_dialog_info[0].pixels/2));
+                                                       for (indx=1; indx < panic_dialog_info[0].chars[0]; indx++)
+                                                               blit_digit(panic_dialog_info[0].chars[indx]);
+
+                                                       break;
+
+                                       case 2 : /* left centered and right centered */
+                                                       x1 = ((panic_dialog->pd_width/2) - panic_dialog_info[0].pixels)/2;
+                                                       panic_info_x = (int)(((vinfo.v_width/2) - (panic_dialog->pd_width/2)) + x1);
+
+                                                       for (indx=1; indx < panic_dialog_info[0].chars[0]; indx++)
+                                                               blit_digit(panic_dialog_info[0].chars[indx]);
+
+                                                       x2 = ((panic_dialog->pd_width/2) - panic_dialog_info[1].pixels)/2;
+                                                       panic_info_x = (int)((vinfo.v_width/2) + x2);
+
+                                                       for (indx=1; indx < panic_dialog_info[1].chars[0]; indx++)
+                                                               blit_digit(panic_dialog_info[1].chars[indx]);
+
+                                                       break;
+
+                                       case 3 : /* left centered, middle and right centered */
+                                                       x1 = ((panic_dialog->pd_width/2) - panic_dialog_info[0].pixels - (panic_dialog_info[1].pixels/2))/2;
+                                                       panic_info_x = (int)(((vinfo.v_width/2) - (panic_dialog->pd_width/2)) + x1);
+
+                                                       for (indx=1; indx < panic_dialog_info[0].chars[0]; indx++)
+                                                               blit_digit(panic_dialog_info[0].chars[indx]);
+
+                                                       panic_info_x = (int)((vinfo.v_width/2) - (panic_dialog_info[1].pixels/2));
+
+                                                       for (indx=1; indx < panic_dialog_info[1].chars[0]; indx++)
+                                                               blit_digit(panic_dialog_info[1].chars[indx]);
+
+                                                       x2 = ((panic_dialog->pd_width/2) - panic_dialog_info[2].pixels - (panic_dialog_info[1].pixels/2))/2;
+                                                       panic_info_x = (int)((vinfo.v_width/2) + x2 + (panic_dialog_info[1].pixels/2));
+
+                                                       for (indx=1; indx < panic_dialog_info[2].chars[0]; indx++)
+                                                               blit_digit(panic_dialog_info[2].chars[indx]);
+
+                                                       break;
+
+                                       default :  /* nothing */
+                                                       break;
+
+                               } /* switch */
+                       } /* if panic_deugging */
+               } /* if ! logPanicDataToScreen */
+       } /* if ! panicDialogDrawn && ! panicDialogDesired */
+
        panicDialogDrawn = TRUE;
        panicDialogDesired = FALSE;
        panicDialogDrawn = TRUE;
        panicDialogDesired = FALSE;
+}
+
 
 
+/*
+ * This routine installs a new panic dialog
+ * If ptr is NULL, then the default "built-in" panic dialog will be installed.
+ * note: It is the caller that must take care of deallocating memory used for the previous panic dialog
+ */
+
+int
+panic_dialog_set_image( const unsigned char * ptr, unsigned int size )
+{
+       int error;
+       unsigned int newsize;
+       const struct panicimage * newimage;
+
+       /* if ptr is NULL, restore panic image to built-in default */
+       if ( ptr == NULL ) {
+               newimage = &panic_dialog_default;
+               newsize = (unsigned int)(sizeof(struct panicimage) + newimage->pd_dataSize);
+       }
+       else {
+               newimage = (const struct panicimage *)ptr;
+               newsize = size;
+       }
+
+       if ( (error = panic_dialog_verify( newimage, newsize )) )
+               return (error);
+
+       panic_dialog = newimage;
+       panic_dialog_data = &panic_dialog->data[0];
+       panic_dialog_clut = &panic_dialog->data[panic_dialog->pd_dataSize-CLUT_SIZE];
+
+       curr_image_ptr = ptr;
+       curr_image_size = size;
+
+       return (0);
 }
 
 }
 
+
+/*
+ * This routines returns the current address of the panic dialog
+ * If the default panic dialog is active, then *ptr will be NULL
+ */
+
+void
+panic_dialog_get_image(const unsigned char ** ptr, unsigned int * size )
+{
+       *ptr =  curr_image_ptr;
+       *size = curr_image_size;
+}
+
+
+/*
+ * This routine verifies the panic dialog image is valid.
+ */
+
+static int
+panic_dialog_verify( const struct panicimage * newimage, unsigned int size )
+{
+       unsigned int sum, i;
+
+       if ( size < (sizeof(struct panicimage) + newimage->pd_dataSize) )
+               return EINVAL;
+
+       if ( newimage->pd_tag != 0x524E4D70 /* 'RNMp' */ )
+               return EINVAL;
+
+       size = newimage->pd_dataSize-CLUT_SIZE;
+       for (sum=0,i=0; i<size; i++) {
+               sum += newimage->data[i];
+               sum <<= sum&1;
+       }
+
+       if ( sum != newimage->pd_sum )
+               return EINVAL;
+
+       return 0;
+}
+
+
+/*
+ * Service Routines for managing the panic dialog 
+ */
+
+
+static const struct rendered_num * find_rendered_digit( int digit );
+static void panic_blit_rect_8(unsigned int x, unsigned int y,
+                             unsigned int width, unsigned int height,
+                             int transparent, const unsigned char *dataPtr);
+static void panic_blit_rect_16(unsigned int x, unsigned int y,
+                              unsigned int width, unsigned int height,
+                              int transparent, const unsigned char *dataPtr);
+static void panic_blit_rect_32(unsigned int x, unsigned int y,
+                              unsigned int width, unsigned int height,
+                              int transparent, const unsigned char *dataPtr);
+static void panic_blit_rect_30(unsigned int x, unsigned int y,
+                              unsigned int width, unsigned int height,
+                              int transparent, const unsigned char *dataPtr);
+static int decode_rle(const unsigned char *dataPtr,
+                     unsigned int *quantity, unsigned int *depth,
+                     const unsigned char **value);
+
+
+/* Utilities to convert 8 bit/gray */
+static unsigned int make24bitcolor( unsigned int index, const unsigned char * clut );
+static unsigned char findIndexMatch( unsigned char index );
+static unsigned char color24togray8( unsigned int color24 );
+static unsigned char findbestgray( unsigned int color24 );
+static int isActiveClutOK( void );
+
+static int
+pixels_needed_to_blit_digit(__unused int digit )
+{
+       return FONT_WIDTH;
+}
+
+
+static const struct rendered_num *
+find_rendered_digit( int digit )
+{
+       //extern unsigned char iso_font[];
+       const struct rendered_num *digitPtr;
+
+       if ( digit < 16 ) {
+               if ( digit < 10 )
+                       digit += 0x30;
+               else
+                       digit += 0x37;
+       }
+
+       digitPtr = (const struct rendered_num *) &iso_font[digit * 16];
+       return digitPtr;
+}
+
+
 static void 
 blit_digit( int digit )
 {
 static void 
 blit_digit( int digit )
 {
-       switch( digit )
-       {
-               case '0':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_0.num_w, num_0.num_h, 255, (unsigned char*) num_0.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_0.num_w - 1;
-                       break;
-               }
-               case '1':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_1.num_w, num_1.num_h, 255, (unsigned char*) num_1.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_1.num_w ;
-                       break;
-               }
-               case '2':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_2.num_w, num_2.num_h, 255, (unsigned char*) num_2.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_2.num_w ;
-                       break;
-               }
-               case '3':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_3.num_w, num_3.num_h, 255, (unsigned char*) num_3.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_3.num_w ;
-                       break;
-               }
-               case '4':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_4.num_w, num_4.num_h, 255, (unsigned char*) num_4.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_4.num_w ;
-                       break;
-               }
-               case '5':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_5.num_w, num_5.num_h, 255, (unsigned char*) num_5.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_5.num_w ;
-                       break;
-               }
-               case '6':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_6.num_w, num_6.num_h, 255, (unsigned char*) num_6.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_6.num_w ;
-                       break;
-               }
-               case '7':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_7.num_w, num_7.num_h, 255, (unsigned char*) num_7.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_7.num_w ;
-                       break;
-               }
-               case '8':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_8.num_w, num_8.num_h, 255, (unsigned char*) num_8.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_8.num_w ;
-                       break;
-               }
-               case '9':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_9.num_w, num_9.num_h, 255, (unsigned char*) num_9.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_9.num_w ;
-                       break;
-               }
-               case 'a':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_a.num_w, num_a.num_h, 255, (unsigned char*) num_a.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_a.num_w ;
-                       break;
-               }
-               case 'b':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_b.num_w, num_b.num_h, 255, (unsigned char*) num_b.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_b.num_w ;
-                       break;
-               }
-               case 'c':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_c.num_w, num_c.num_h, 255, (unsigned char*) num_c.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_c.num_w ;
-                       break;
-               }
-               case 'd':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_d.num_w, num_d.num_h, 255, (unsigned char*) num_d.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_d.num_w ;
-                       break;
-               }
-               case 'e':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_e.num_w, num_e.num_h, 255, (unsigned char*) num_e.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_e.num_w ;
-                       break;
+       const unsigned char *raw_data =
+               (const unsigned char *)find_rendered_digit(digit);
+       unsigned width = FONT_WIDTH, height = FONT_HEIGHT;
+       int row;
+
+       for (row=0; row<FONT_HEIGHT; row++) {
+               int j;
+               unsigned char bits;
+
+               bits = raw_data[row];
+               for( j=FONT_WIDTH-1; j>=0; j--) {
+
+                       if ( bits & 0x80 )
+                               rendered_font[row][j] = OSSwapBigToHostInt16(0x0100 | panic_dialog->pd_info_color[0]);
+                       else
+                               rendered_font[row][j] = OSSwapBigToHostInt16(0x0100 | panic_dialog->pd_info_color[1]);
+                       bits <<= 1;
                }
                }
-               case 'f':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_f.num_w, num_f.num_h, 255, (unsigned char*) num_f.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_f.num_w ;
-                       break;
-               }
-               case ':':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y, num_colon.num_w, num_colon.num_h, 255, (unsigned char*) num_colon.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_colon.num_w;
-                       break;
-               }
-               case '.':  {
-                       panic_blit_rect( mac_addr_digit_x, mac_addr_digit_y + (num_colon.num_h/2), num_colon.num_w, num_colon.num_h/2, 255, (unsigned char*) num_colon.num_pixel_data);
-                       mac_addr_digit_x = mac_addr_digit_x + num_colon.num_w;
-                       break;
-               }
-               default:
-                       break;
-       
        }
        }
+       
+       panic_blit_rect( panic_info_x, panic_info_y , width, height, 255, (unsigned char *) rendered_font);
+       panic_info_x += width;
 }
 
 }
 
+
 static void 
 static void 
-panic_blit_rect(       unsigned int x, unsigned int y,
-                       unsigned int width, unsigned int height,
-                       int transparent, unsigned char * dataPtr )
+panic_blit_rect(unsigned int x, unsigned int y, unsigned int width,
+               unsigned int height, int transparent,
+               const unsigned char *dataPtr)
 {
        if(!vinfo.v_depth)
                return;
 {
        if(!vinfo.v_depth)
                return;
@@ -385,244 +564,441 @@ panic_blit_rect(        unsigned int x, unsigned int y,
        case 32:
            panic_blit_rect_32( x, y, width, height, transparent, dataPtr);
            break;
        case 32:
            panic_blit_rect_32( x, y, width, height, transparent, dataPtr);
            break;
+       case 30:
+           panic_blit_rect_30( x, y, width, height, transparent, dataPtr);
+           break;
     }
 }
 
     }
 }
 
-/*     panic_blit_rect_8 uses the built in clut for drawing.
+/*
+ *  panic_blit_rect_8 decodes the RLE encoded image data on the fly, looks up the
+ *     color by indexing into the clut, or attempts to find the best index.
+ */
 
 
-*/
 static void 
 static void 
-panic_blit_rect_8(     unsigned int x, unsigned int y,
-                       unsigned int width, unsigned int height,
-                       int transparent, unsigned char * dataPtr )
+panic_blit_rect_8(unsigned int x, unsigned int y, unsigned int width,
+                 unsigned int height, __unused int transparent,
+                 const unsigned char * dataPtr)
 {
        volatile unsigned char * dst;
 {
        volatile unsigned char * dst;
-       int line, col;
-       unsigned int data, quantity, value;
+       unsigned int line, col, i;
+       static int clutOK = -1;
+       unsigned int data, quantity, depth;
+       const unsigned char *value;
        
        
+
+       if ( clutOK == -1 )
+               clutOK = isActiveClutOK();
+
        dst = (volatile unsigned char *) (vinfo.v_baseaddr +
        dst = (volatile unsigned char *) (vinfo.v_baseaddr +
-                                         (y * vinfo.v_rowbytes) +
-                                         x);
+                                                                        (y * vinfo.v_rowbytes) +
+                                                                        x);
        
        quantity = 0;
        
        quantity = 0;
+       i = 0;
        
        for( line = 0; line < height; line++) {
                for( col = 0; col < width; col++) {
        
        for( line = 0; line < height; line++) {
                for( col = 0; col < width; col++) {
+
                        if (quantity == 0) {
                        if (quantity == 0) {
-                               dataPtr += decode_rle(dataPtr, &quantity, &value);
+                               dataPtr += decode_rle(dataPtr, &quantity, &depth, &value);
+                               i = 0;
                        }
                        
                        }
                        
-                       data = value;
+                       if ( clutOK )
+                               data = value[i++];
+                       else
+                               data = findIndexMatch( value[i++] );
+
                        *(dst + col) = data;
                        *(dst + col) = data;
-                       quantity--;
+
+                       if ( i == depth ) {
+                               i = 0;
+                               quantity--;
+                       }
                }
                
                }
                
-               dst = (volatile unsigned char *) (((int)dst) + vinfo.v_rowbytes);
+               dst = (volatile unsigned char *) (((uintptr_t)dst) + vinfo.v_rowbytes);
        }
 }
 
        }
 }
 
-/*     panic_blit_rect_16 draws using a clut.
-       
-        panic_blit_rect_16 decodes the RLE encoded image data on the fly, looks up the
-       color by indexing into the clut, uses the top 5 bits to fill in each of the three 
-       pixel values (RGB) and writes each pixel to the screen.
-*/
- static void 
- panic_blit_rect_16(   unsigned int x, unsigned int y,
-                        unsigned int width, unsigned int height,
-                        int transparent, unsigned char * dataPtr )
- {
-        volatile unsigned short * dst;
-        int line, col;
-        unsigned int  quantity, index, value, data;
+/*
+ *  panic_blit_rect_16 decodes the RLE encoded image data on the fly, looks up the
+ *     color by indexing into the clut, uses the top 5 bits to fill in each of the three 
+ *     pixel values (RGB) and writes each pixel to the screen.
+ */
 
 
-        /* If our clut has disappeared, use the standard MacOS 8-bit clut */
-        if(!clut) {
-                clut = appleClut8; 
-        }
+static void 
+panic_blit_rect_16(unsigned int x, unsigned int y, unsigned int width,
+                  unsigned int height, __unused int transparent,
+                  const unsigned char *dataPtr)
+{
 
 
-        dst = (volatile unsigned short *) (vinfo.v_baseaddr +
-                                           (y * vinfo.v_rowbytes) +
-                                           (x * 2));
+       volatile unsigned short * dst;
+       unsigned int line, col, i;
+       unsigned int  quantity, index, data, depth;
+       const unsigned char *value;
 
 
-        quantity = 0;
+       dst = (volatile unsigned short *) (vinfo.v_baseaddr +
+                                                                         (y * vinfo.v_rowbytes) +
+                                                                         (x * 2));
 
 
-        for( line = 0; line < height; line++) {
-                for( col = 0; col < width; col++) {
+       quantity = 0;
+       i = 0;
 
 
-                        if (quantity == 0) {
-                                dataPtr += decode_rle(dataPtr, &quantity, &value);
-                                index = value * 3;
-                        }
+       for( line = 0; line < height; line++) {
+               for( col = 0; col < width; col++) {
 
 
-                        data = ( (unsigned short) (0xf8 & (clut[index + 0])) << 7)
-                                | ( (unsigned short) (0xf8 & (clut[index + 1])) << 2)
-                                | ( (unsigned short) (0xf8 & (clut[index + 2])) >> 3);
+                       if (quantity == 0) {
+                               dataPtr += decode_rle(dataPtr, &quantity, &depth, &value);
+                               i = 0;
+                       }
 
 
-                        *(dst + col) = data;
-                        quantity--;
-                }
+                       index = value[i++] * 3;
+                       
+                       data = ( (unsigned short) (0xf8 & (panic_dialog_clut[index + 0])) << 7)
+                                | ( (unsigned short) (0xf8 & (panic_dialog_clut[index + 1])) << 2)
+                                | ( (unsigned short) (0xf8 & (panic_dialog_clut[index + 2])) >> 3);
 
 
-                dst = (volatile unsigned short *) (((int)dst) + vinfo.v_rowbytes);
-        }
+                       *(dst + col) = data;
 
 
+                       if ( i == depth ) {
+                               i = 0;
+                               quantity--;
+                       }
+               }
+
+               dst = (volatile unsigned short *) (((uintptr_t)dst) + vinfo.v_rowbytes);
+       }
  }
 
  }
 
- /*
       panic_blit_rect_32 decodes the RLE encoded image data on the fly, and fills
       in each of the three pixel values from the clut (RGB) for each pixel and 
       writes it to the screen.
+/*
*      panic_blit_rect_32 decodes the RLE encoded image data on the fly, and fills
*      in each of the three pixel values from the clut (RGB) for each pixel and 
*      writes it to the screen.
  */    
  */    
- static void 
- panic_blit_rect_32(   unsigned int x, unsigned int y,
-                        unsigned int width, unsigned int height,
-                        int transparent, unsigned char * dataPtr )
- {
-        volatile unsigned int * dst;
-        int line, col;
-        unsigned int value, quantity, index, data;
-
-
-       /* If our clut has disappeared, use the standard MacOS 8-bit clut */
-       if(!clut) {
-               clut = appleClut8; 
-       }
+
+static void 
+panic_blit_rect_32(unsigned int x, unsigned int y, unsigned int width,
+                  unsigned int height, __unused int transparent,
+                  const unsigned char *dataPtr)
+{
+       volatile unsigned int * dst;
+       unsigned int line, col, i;
+       unsigned int quantity, index, data, depth;
+       const unsigned char *value;
+
 
        dst = (volatile unsigned int *) (vinfo.v_baseaddr +
 
        dst = (volatile unsigned int *) (vinfo.v_baseaddr +
-                                        (y * vinfo.v_rowbytes) +
-                                        (x * 4));
+                                                                       (y * vinfo.v_rowbytes) +
+                                                                       (x * 4));
        
        quantity = 0;
        
        quantity = 0;
+       i = 0;
        
        for( line = 0; line < height; line++) {
                for( col = 0; col < width; col++) {
        
        for( line = 0; line < height; line++) {
                for( col = 0; col < width; col++) {
+
                        if (quantity == 0) {
                        if (quantity == 0) {
-                               dataPtr += decode_rle(dataPtr, &quantity, &value);
-                               index = value * 3;
+                               dataPtr += decode_rle(dataPtr, &quantity, &depth, &value);
+                               i = 0;
                        }
                        }
+
+                       index = value[i++] * 3;
                        
                        
-                       data = ( (unsigned int) clut[index + 0] << 16)
-                               | ( (unsigned int) clut[index + 1] << 8)
-                               | ( (unsigned int) clut[index + 2]);
+                       data = ( (unsigned int) panic_dialog_clut[index + 0] << 16)
+                                | ( (unsigned int) panic_dialog_clut[index + 1] << 8)
+                                | ( (unsigned int) panic_dialog_clut[index + 2]);
                        
                        *(dst + col) = data;
                        
                        *(dst + col) = data;
-                       quantity--;
+
+                       if ( i == depth ) {
+                               i = 0;
+                               quantity--;
+                       }
                }
                
                }
                
-               dst = (volatile unsigned int *) (((int)dst) + vinfo.v_rowbytes);
+               dst = (volatile unsigned int *) (((uintptr_t)dst) + vinfo.v_rowbytes);
        }
 }
 
        }
 }
 
+/*
+ *      panic_blit_rect_30 decodes the RLE encoded image data on the fly, and fills
+ *      in each of the three pixel values from the clut (RGB) for each pixel and 
+ *      writes it to the screen.
+ */    
+
+static void 
+panic_blit_rect_30(unsigned int x, unsigned int y, unsigned int width,
+                  unsigned int height, __unused int transparent,
+                  const unsigned char *dataPtr)
+{
+       volatile unsigned int * dst;
+       unsigned int line, col, i;
+       unsigned int quantity, index, data, depth;
+       const unsigned char *value;
+       unsigned int in;
+
+       dst = (volatile unsigned int *) (vinfo.v_baseaddr +
+                                                                       (y * vinfo.v_rowbytes) +
+                                                                       (x * 4));
+       
+       quantity = 0;
+       i = 0;
+       
+       for( line = 0; line < height; line++) {
+               for( col = 0; col < width; col++) {
+
+                       if (quantity == 0) {
+                               dataPtr += decode_rle(dataPtr, &quantity, &depth, &value);
+                               i = 0;
+                       }
+
+                       index = value[i++] * 3;
+                       in = panic_dialog_clut[index + 0];
+                       data = (in << 2) | (in >> 6);
+
+                       in = panic_dialog_clut[index + 1];
+                       data |= (in << (2 + 10)) | ((3 << 10) & (in << 4));
+
+                       in = panic_dialog_clut[index + 2];
+                       data |= (in << (2 + 20)) | ((3 << 20) & (in << 14));
+               
+                       *(dst + col) = data;
+
+                       if ( i == depth ) {
+                               i = 0;
+                               quantity--;
+                       }
+               }
+               
+               dst = (volatile unsigned int *) (((uintptr_t)dst) + vinfo.v_rowbytes);
+       }
+}
+
+
 /*     
 /*     
-        decode_rle decodes a single quantity/value pair of a "modified-RLE" encoded
-        image. The encoding works as follows:
-        
-        The quantity and value will be described by either two or three bytes. If the
-        most significant bit of the first byte is a 0, then the next seven bits are
-        the quantity (run-length) and the following 8 bits are the value (index into
-        a clut, in this case). If the msb of the first byte is a 1, then the next 15 bits
-        are the quantity and the following 8 are the value. Visually, the two possible
-        encodings are: (q = quantity, v = value)
-        
-          Byte 1                          Byte 2                       Byte 3
-  case 1: [ 0 q6 q5 q4 q3 q2 q1 q0 ]       [ v7 v6 v5 v4 v3 v2 v1 v0 ]  [ ]
-  case 2: [ 1 q14 q13 q12 a11 q10 q9 q8 ]  [ q7 q6 q5 q4 q3 q2 q1 q0 ]  [ v7 v6 v5 v4 v3 v2 v1 v0 ]
+    decode_rle decodes a single quantity/value run of a "modified-RLE" encoded
+    image. The encoding works as follows:
+
+       The run is described in the first byte.  If the MSB is zero, then the next seven bits
+       are the quantity of bytes that follow that make up the run of value bytes.  (see case 0)
+
+       If the MSB is set, bits 0-3 are the quantity's least significant 4 bits.  If bit 5 is set,
+       then the quantity is further described in the next byte, where an additional 7 bits (4-10)
+       worth of quantity will be found.  If the MSB of this byte is set, then an additional
+       7 bits (11-17) worth of quantity will be found in the next byte. This repeats until the MSB of
+       a quantity byte is zero, thus ending the run of quantity bytes.
+
+       Bits 5/6 of the first byte, describe the number of bytes in the value run following the quantity run.
+       These bits describe value runs of 1 to 4 bytes.  And the quantity describe the number of value runs.
+       (see cases 1-4)
+       
+       encodings are: (q = quantity, v = value, c = quantity continues)
+               
+  case 0: [ 0       q6-q0 ] [ v7-v0 ] ... [ v7-v0 ]
+  case 1: [ 1 0 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ]
+  case 2: [ 1 0 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ]
+  case 3: [ 1 1 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
+  case 4: [ 1 1 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
 */
 */
+
 static int
 static int
-decode_rle( unsigned char * dataPtr, unsigned int * quantity, unsigned int * value )
+decode_rle(const unsigned char *dataPtr, unsigned int *quantity,
+          unsigned int *depth, const unsigned char **value )
 {
 {
-       unsigned char byte1 = *dataPtr++;
-       unsigned char byte2 = *dataPtr++;
-       int num_slots = 0;
-       
-       /* if the most-significant bit is 0, then the first byte is quanity, the second is value */
-       if ((byte1 >> 7) ==  0) {
-               *quantity = (unsigned int) byte1;
-               *value = (unsigned int) byte2;
-               num_slots = 2;
+       unsigned int mask;
+       int i, runlen, runsize;
+
+       i = 0;
+       mask = dataPtr[i] & 0xF0;
+
+       if ( mask & 0x80 ) {
+               runsize = ((mask & 0x60) >> 5) + 1;
+               runlen = dataPtr[i++] & 0x0F;
+
+               if ( mask & 0x10 ) {
+                       int shift = 4;
+
+                       do {
+                               mask = dataPtr[i] & 0x80;
+                               runlen |= ((dataPtr[i++] & 0x7F) << shift);
+                               shift+=7;
+                       } while (mask);
+               }
        } else {
        } else {
-               /* clear the leading 1 */
-               byte1 ^= 0x80;
-               
-               /* the first two bytes are the quantity, the third is value */
-               *quantity = (unsigned int) byte1 << 8 | byte2;
-               *value = *dataPtr++;
-               num_slots = 3;
+               runlen = 1;
+               runsize = dataPtr[i++];
        }
        }
-       
-       return num_slots;
+
+       *depth = runsize;
+       *quantity = runlen;
+       *value = &dataPtr[i];
+
+       return i+runsize;
 }
 
 }
 
-static void 
+
+void 
 dim_screen(void)
 {
 dim_screen(void)
 {
+       unsigned int *p, *endp, *row;
+       int      col, rowline, rowlongs;
+       register unsigned int mask;
+
        if(!vinfo.v_depth)
                return;
 
        if(!vinfo.v_depth)
                return;
 
-    switch( vinfo.v_depth) {
-       case 16:
-           dim_screen_16();
-           break;
-       case 32:
-           dim_screen_32();
-           break;
-    }
+       if ( vinfo.v_depth == 32 )
+               mask = 0x007F7F7F;
+       else if ( vinfo.v_depth == 30 )
+               mask = (0x1ff<<20) | (0x1ff<<10) | 0x1ff;
+       else if ( vinfo.v_depth == 16 )
+               mask = 0x3DEF3DEF;
+       else
+               return;
+
+       rowline = (int)(vinfo.v_rowscanbytes / 4);
+       rowlongs = (int)(vinfo.v_rowbytes / 4);
+
+       p = (unsigned int*) vinfo.v_baseaddr;
+       endp = p + (rowlongs * vinfo.v_height);
+
+       for (row = p ; row < endp ; row += rowlongs) {
+               for (p = &row[0], col = 0; col < rowline; col++) {
+                       *p = (*p >> 1) & mask;
+                       ++p;
+               }
+       }
 }
 
 }
 
-static void 
-dim_screen_16(void)
+
+/* From user mode Libc - this ought to be in a library */
+static const char *
+strnstr(const char * s, const char * find, size_t slen)
 {
 {
-       unsigned long *p, *endp, *row;
-       int      col;
-       int      rowline, rowlongs;
-        unsigned long value, tmp;
+  char c, sc;
+  size_t len;
+
+  if ((c = *find++) != '\0') {
+    len = strlen(find);
+    do {
+      do {
+    if ((sc = *s++) == '\0' || slen-- < 1)
+      return (NULL);
+      } while (sc != c);
+      if (len > slen)
+    return (NULL);
+    } while (strncmp(s, find, len) != 0);
+    s--; 
+  }       
+  return s;
+} 
 
 
-       rowline = vinfo.v_rowscanbytes / 4;
-       rowlongs = vinfo.v_rowbytes / 4;
+/*
+ * these routines are for converting a color into grayscale
+ * in 8-bit mode, if the active clut is different than the
+ * clut used to create the panic dialog, then we must convert to gray
+ */
 
 
-       p = (unsigned long*) vinfo.v_baseaddr;
-       endp = (unsigned long*) vinfo.v_baseaddr;
+static unsigned int
+make24bitcolor( unsigned int index, const unsigned char * clut )
+{
+       unsigned int color24 = 0;
+       int i = index * 3;
 
 
-        endp += rowlongs * vinfo.v_height;
+       color24 |= clut[i+0] << 16;
+       color24 |= clut[i+1] << 8;
+       color24 |= clut[i+2];
+
+       return color24;
+}
 
 
-       for (row = p ; row < endp ; row += rowlongs) {
-               for (col = 0; col < rowline; col++) {
-                        value = *(row+col);
-                        tmp =  ((value & 0x7C007C00) >> 1) & 0x3C003C00;
-                        tmp |= ((value & 0x03E003E0) >> 1) & 0x01E001E0;
-                        tmp |= ((value & 0x001F001F) >> 1) & 0x000F000F;
-                        *(row+col) = tmp;              //half (dimmed)?
-                }
 
 
+static unsigned char
+findbestgray( unsigned int color24 )
+{
+       unsigned int c24, rel, bestindex=-1, bestgray = -1;
+       unsigned char gray8, c8;
+       int i;
+#define abs(v)  ((v) > 0)?(v):-(v)
+
+       gray8 = color24togray8( color24 );              /* convert the original color into grayscale */
+
+       for (i=0; i<CLUT_ENTRIES; i++) {
+               c24  = make24bitcolor( i, active_clut );
+               if ( (((c24>>16)&0xff) != ((c24>>8)&0xff)) || ((c24>>8)&0xff) != (c24 & 0xff) )
+                       continue;                               /* only match against grays */
+
+               c8 = c24 & 0xFF;                        /* isolate the gray */
+
+               /* find the gray with the smallest difference */
+               rel = abs( gray8 - c8 );
+               if ( rel < bestgray ) {
+                       bestgray = rel;
+                       bestindex = i;
+               }
+       }
+
+       /* Did we fail to find any grays ? */
+       if (ULONG_MAX == bestindex) {
+               /* someday we should look for the best color match */
+               /* but for now just return the gray as the index */
+               /* at least there might be something readble on the display */
+
+               bestindex = gray8;
        }
 
        }
 
+       return bestindex;
+#undef abs
 }
 
 }
 
-static void 
-dim_screen_32(void)
+
+static unsigned char
+color24togray8( unsigned int color24 )
+{       
+    int R, G, B;
+    int Gray;
+    unsigned char gray8;
+    
+    R = (color24 & 0xFF0000) >> 16 ;
+    G = (color24 & 0xFF00) >> 8 ;
+    B = (color24 & 0xFF);
+    
+    Gray = (R*30) + (G*59) + (B*11);
+    gray8 = (unsigned char) ((Gray + 50) / 100);
+    return gray8;
+}
+
+
+static unsigned char
+findIndexMatch( unsigned char index )
 {
 {
-       unsigned long *p, *endp, *row;
-       int      col;
-       int      rowline, rowlongs;
-        unsigned long value, tmp;
+       static unsigned int last_in_index = -1;
+       static unsigned char last_index;
+       unsigned int sc;
 
 
-       rowline = vinfo.v_rowscanbytes / 4;
-       rowlongs = vinfo.v_rowbytes / 4;
+       if ( index == last_in_index )
+               return last_index;
 
 
-       p = (unsigned long*) vinfo.v_baseaddr;
-       endp = (unsigned long*) vinfo.v_baseaddr;
+       last_in_index = index;
+       sc = make24bitcolor( index, panic_dialog_clut );
+       last_index = findbestgray( sc );                /* find the nearest matching gray in the active clut */
 
 
-        endp += rowlongs * vinfo.v_height;
+       return last_index;
+}
 
 
-       for (row = p ; row < endp ; row += rowlongs) {
-               for (col = 0; col < rowline; col++) {
-                        value = *(row+col);
-                        tmp =  ((value & 0x00FF0000) >> 1) & 0x007F0000;
-                        tmp |= ((value & 0x0000FF00) >> 1) & 0x00007F00;
-                        tmp |= (value & 0x000000FF) >> 1;
-                        *(row+col) = tmp;              //half (dimmed)?
-                }
+static int
+isActiveClutOK( void )
+{
+       int i;
+       int r = 1; /* assume OK */
 
 
+       for (i=0; i<CLUT_ENTRIES; i++) {
+               if ( panic_dialog_clut[i] == active_clut[i] ) continue;
+               r = 0;
+               break;
        }
 
        }
 
+       return r;
 }
 }