/*
- * 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,
- * 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 <console/video_console.h>
+#include <libkern/OSByteOrder.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;
-/* 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 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 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)
{
- 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 )
{
- 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 */
- 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++ )
- {
- 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;
- 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;
}
+
+ 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;
+}
+
+/*
+ * 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 )
{
- 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
-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;
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
-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;
- 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 +
- (y * vinfo.v_rowbytes) +
- x);
+ (y * vinfo.v_rowbytes) +
+ x);
quantity = 0;
+ i = 0;
for( line = 0; line < height; line++) {
for( col = 0; col < width; col++) {
+
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;
- 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 +
- (y * vinfo.v_rowbytes) +
- (x * 4));
+ (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, &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;
- 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
-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 {
- /* 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)
{
+ unsigned int *p, *endp, *row;
+ int col, rowline, rowlongs;
+ register unsigned int mask;
+
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;
}