]> git.saurik.com Git - apple/xnu.git/blob - osfmk/console/panic_dialog.c
xnu-517.12.7.tar.gz
[apple/xnu.git] / osfmk / console / panic_dialog.c
1 /*
2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 #include <vc.h>
24
25 #include <console/video_console.h>
26 #include <kdp/kdp_udp.h>
27 #include <kern/debug.h>
28
29 #include "panic_image.c"
30 #include "rendered_numbers.c"
31
32 extern struct vc_info vinfo;
33 extern boolean_t panicDialogDesired;
34
35 /* panic image clut */
36 static const unsigned char *clut = NULL;
37 extern void panic_ui_initialize(const unsigned char * system_clut);
38
39 /* We use this standard MacOS clut as a fallback */
40 static const unsigned char appleClut8[ 256 * 3 ] = {
41 // 00
42 0xFF,0xFF,0xFF, 0xFF,0xFF,0xCC, 0xFF,0xFF,0x99, 0xFF,0xFF,0x66,
43 0xFF,0xFF,0x33, 0xFF,0xFF,0x00, 0xFF,0xCC,0xFF, 0xFF,0xCC,0xCC,
44 0xFF,0xCC,0x99, 0xFF,0xCC,0x66, 0xFF,0xCC,0x33, 0xFF,0xCC,0x00,
45 0xFF,0x99,0xFF, 0xFF,0x99,0xCC, 0xFF,0x99,0x99, 0xFF,0x99,0x66,
46 // 10
47 0xFF,0x99,0x33, 0xFF,0x99,0x00, 0xFF,0x66,0xFF, 0xFF,0x66,0xCC,
48 0xFF,0x66,0x99, 0xFF,0x66,0x66, 0xFF,0x66,0x33, 0xFF,0x66,0x00,
49 0xFF,0x33,0xFF, 0xFF,0x33,0xCC, 0xFF,0x33,0x99, 0xFF,0x33,0x66,
50 0xFF,0x33,0x33, 0xFF,0x33,0x00, 0xFF,0x00,0xFF, 0xFF,0x00,0xCC,
51 // 20
52 0xFF,0x00,0x99, 0xFF,0x00,0x66, 0xFF,0x00,0x33, 0xFF,0x00,0x00,
53 0xCC,0xFF,0xFF, 0xCC,0xFF,0xCC, 0xCC,0xFF,0x99, 0xCC,0xFF,0x66,
54 0xCC,0xFF,0x33, 0xCC,0xFF,0x00, 0xCC,0xCC,0xFF, 0xCC,0xCC,0xCC,
55 0xCC,0xCC,0x99, 0xCC,0xCC,0x66, 0xCC,0xCC,0x33, 0xCC,0xCC,0x00,
56 // 30
57 0xCC,0x99,0xFF, 0xCC,0x99,0xCC, 0xCC,0x99,0x99, 0xCC,0x99,0x66,
58 0xCC,0x99,0x33, 0xCC,0x99,0x00, 0xCC,0x66,0xFF, 0xCC,0x66,0xCC,
59 0xCC,0x66,0x99, 0xCC,0x66,0x66, 0xCC,0x66,0x33, 0xCC,0x66,0x00,
60 0xCC,0x33,0xFF, 0xCC,0x33,0xCC, 0xCC,0x33,0x99, 0xCC,0x33,0x66,
61 // 40
62 0xCC,0x33,0x33, 0xCC,0x33,0x00, 0xCC,0x00,0xFF, 0xCC,0x00,0xCC,
63 0xCC,0x00,0x99, 0xCC,0x00,0x66, 0xCC,0x00,0x33, 0xCC,0x00,0x00,
64 0x99,0xFF,0xFF, 0x99,0xFF,0xCC, 0x99,0xFF,0x99, 0x99,0xFF,0x66,
65 0x99,0xFF,0x33, 0x99,0xFF,0x00, 0x99,0xCC,0xFF, 0x99,0xCC,0xCC,
66 // 50
67 0x99,0xCC,0x99, 0x99,0xCC,0x66, 0x99,0xCC,0x33, 0x99,0xCC,0x00,
68 0x99,0x99,0xFF, 0x99,0x99,0xCC, 0x99,0x99,0x99, 0x99,0x99,0x66,
69 0x99,0x99,0x33, 0x99,0x99,0x00, 0x99,0x66,0xFF, 0x99,0x66,0xCC,
70 0x99,0x66,0x99, 0x99,0x66,0x66, 0x99,0x66,0x33, 0x99,0x66,0x00,
71 // 60
72 0x99,0x33,0xFF, 0x99,0x33,0xCC, 0x99,0x33,0x99, 0x99,0x33,0x66,
73 0x99,0x33,0x33, 0x99,0x33,0x00, 0x99,0x00,0xFF, 0x99,0x00,0xCC,
74 0x99,0x00,0x99, 0x99,0x00,0x66, 0x99,0x00,0x33, 0x99,0x00,0x00,
75 0x66,0xFF,0xFF, 0x66,0xFF,0xCC, 0x66,0xFF,0x99, 0x66,0xFF,0x66,
76 // 70
77 0x66,0xFF,0x33, 0x66,0xFF,0x00, 0x66,0xCC,0xFF, 0x66,0xCC,0xCC,
78 0x66,0xCC,0x99, 0x66,0xCC,0x66, 0x66,0xCC,0x33, 0x66,0xCC,0x00,
79 0x66,0x99,0xFF, 0x66,0x99,0xCC, 0x66,0x99,0x99, 0x66,0x99,0x66,
80 0x66,0x99,0x33, 0x66,0x99,0x00, 0x66,0x66,0xFF, 0x66,0x66,0xCC,
81 // 80
82 0x66,0x66,0x99, 0x66,0x66,0x66, 0x66,0x66,0x33, 0x66,0x66,0x00,
83 0x66,0x33,0xFF, 0x66,0x33,0xCC, 0x66,0x33,0x99, 0x66,0x33,0x66,
84 0x66,0x33,0x33, 0x66,0x33,0x00, 0x66,0x00,0xFF, 0x66,0x00,0xCC,
85 0x66,0x00,0x99, 0x66,0x00,0x66, 0x66,0x00,0x33, 0x66,0x00,0x00,
86 // 90
87 0x33,0xFF,0xFF, 0x33,0xFF,0xCC, 0x33,0xFF,0x99, 0x33,0xFF,0x66,
88 0x33,0xFF,0x33, 0x33,0xFF,0x00, 0x33,0xCC,0xFF, 0x33,0xCC,0xCC,
89 0x33,0xCC,0x99, 0x33,0xCC,0x66, 0x33,0xCC,0x33, 0x33,0xCC,0x00,
90 0x33,0x99,0xFF, 0x33,0x99,0xCC, 0x33,0x99,0x99, 0x33,0x99,0x66,
91 // a0
92 0x33,0x99,0x33, 0x33,0x99,0x00, 0x33,0x66,0xFF, 0x33,0x66,0xCC,
93 0x33,0x66,0x99, 0x33,0x66,0x66, 0x33,0x66,0x33, 0x33,0x66,0x00,
94 0x33,0x33,0xFF, 0x33,0x33,0xCC, 0x33,0x33,0x99, 0x33,0x33,0x66,
95 0x33,0x33,0x33, 0x33,0x33,0x00, 0x33,0x00,0xFF, 0x33,0x00,0xCC,
96 // b0
97 0x33,0x00,0x99, 0x33,0x00,0x66, 0x33,0x00,0x33, 0x33,0x00,0x00,
98 0x00,0xFF,0xFF, 0x00,0xFF,0xCC, 0x00,0xFF,0x99, 0x00,0xFF,0x66,
99 0x00,0xFF,0x33, 0x00,0xFF,0x00, 0x00,0xCC,0xFF, 0x00,0xCC,0xCC,
100 0x00,0xCC,0x99, 0x00,0xCC,0x66, 0x00,0xCC,0x33, 0x00,0xCC,0x00,
101 // c0
102 0x00,0x99,0xFF, 0x00,0x99,0xCC, 0x00,0x99,0x99, 0x00,0x99,0x66,
103 0x00,0x99,0x33, 0x00,0x99,0x00, 0x00,0x66,0xFF, 0x00,0x66,0xCC,
104 0x00,0x66,0x99, 0x00,0x66,0x66, 0x00,0x66,0x33, 0x00,0x66,0x00,
105 0x00,0x33,0xFF, 0x00,0x33,0xCC, 0x00,0x33,0x99, 0x00,0x33,0x66,
106 // d0
107 0x00,0x33,0x33, 0x00,0x33,0x00, 0x00,0x00,0xFF, 0x00,0x00,0xCC,
108 0x00,0x00,0x99, 0x00,0x00,0x66, 0x00,0x00,0x33, 0xEE,0x00,0x00,
109 0xDD,0x00,0x00, 0xBB,0x00,0x00, 0xAA,0x00,0x00, 0x88,0x00,0x00,
110 0x77,0x00,0x00, 0x55,0x00,0x00, 0x44,0x00,0x00, 0x22,0x00,0x00,
111 // e0
112 0x11,0x00,0x00, 0x00,0xEE,0x00, 0x00,0xDD,0x00, 0x00,0xBB,0x00,
113 0x00,0xAA,0x00, 0x00,0x88,0x00, 0x00,0x77,0x00, 0x00,0x55,0x00,
114 0x00,0x44,0x00, 0x00,0x22,0x00, 0x00,0x11,0x00, 0x00,0x00,0xEE,
115 0x00,0x00,0xDD, 0x00,0x00,0xBB, 0x00,0x00,0xAA, 0x00,0x00,0x88,
116 // f0
117 0x00,0x00,0x77, 0x00,0x00,0x55, 0x00,0x00,0x44, 0x00,0x00,0x22,
118 0x00,0x00,0x11, 0xEE,0xEE,0xEE, 0xDD,0xDD,0xDD, 0xBB,0xBB,0xBB,
119 0xAA,0xAA,0xAA, 0x88,0x88,0x88, 0x77,0x77,0x77, 0x55,0x55,0x55,
120 0x44,0x44,0x44, 0x22,0x22,0x22, 0x11,0x11,0x11, 0x00,0x00,0x00
121 };
122
123
124 /* panic dialog and info saving */
125 static int mac_addr_digit_x;
126 static int mac_addr_digit_y;
127 static void blit_digit( int digit );
128 static boolean_t panicDialogDrawn = FALSE;
129
130 static void
131 panic_blit_rect( unsigned int x, unsigned int y,
132 unsigned int width, unsigned int height,
133 int transparent, unsigned char * dataPtr );
134
135 static void
136 panic_blit_rect_8( unsigned int x, unsigned int y,
137 unsigned int width, unsigned int height,
138 int transparent, unsigned char * dataPtr );
139
140 static void
141 panic_blit_rect_16( unsigned int x, unsigned int y,
142 unsigned int width, unsigned int height,
143 int transparent, unsigned char * dataPtr );
144
145 static void
146 panic_blit_rect_32( unsigned int x, unsigned int y,
147 unsigned int width, unsigned int height,
148 int transparent, unsigned char * dataPtr );
149
150 static void
151 dim_screen(void);
152
153 static void
154 dim_screen_16(void);
155
156 static void
157 dim_screen_32(void);
158
159 static int
160 decode_rle( unsigned char * dataPtr, unsigned int * quantity, unsigned int * value );
161
162 void
163 panic_ui_initialize(const unsigned char * system_clut)
164 {
165 clut = system_clut;
166 }
167
168 void
169 draw_panic_dialog( void )
170 {
171 int pd_x,pd_y, iconx, icony, tx_line, tx_col;
172 int line_width = 1;
173 int f1, f2, d1, d2, d3, rem;
174 char *pair = "ff";
175 int count = 0;
176 char digit;
177 int nibble;
178 char colon = ':';
179 char dot = '.';
180 struct ether_addr kdp_mac_addr = kdp_get_mac_addr();
181 unsigned int ip_addr = (unsigned int) ntohl(kdp_get_ip_address());
182
183 if (!panicDialogDrawn && panicDialogDesired)
184 {
185 if ( !logPanicDataToScreen )
186 {
187
188 /* dim the screen 50% before putting up panic dialog */
189 dim_screen();
190
191 /* set up to draw background box */
192 pd_x = (vinfo.v_width/2) - panic_dialog.pd_width/2;
193 pd_y = (vinfo.v_height/2) - panic_dialog.pd_height/2;
194
195 /* draw image */
196 panic_blit_rect( pd_x, pd_y, panic_dialog.pd_width, panic_dialog.pd_height, 0, (unsigned char*) panic_dialog.image_pixel_data);
197
198 /* do not display the mac and ip addresses if the machine isn't attachable. */
199 /* there's no sense in possibly confusing people. */
200 if (panicDebugging)
201 {
202
203 /* offset for mac address text */
204 mac_addr_digit_x = (vinfo.v_width/2) - 130; /* use 62 if no ip */
205 mac_addr_digit_y = (vinfo.v_height/2) + panic_dialog.pd_height/2 - 20;
206
207 if(kdp_mac_addr.ether_addr_octet[0] || kdp_mac_addr.ether_addr_octet[1]|| kdp_mac_addr.ether_addr_octet[2]
208 || kdp_mac_addr.ether_addr_octet[3] || kdp_mac_addr.ether_addr_octet[4] || kdp_mac_addr.ether_addr_octet[5])
209 {
210 /* blit the digits for mac address */
211 for (count = 0; count < 6; count++ )
212 {
213 nibble = (kdp_mac_addr.ether_addr_octet[count] & 0xf0) >> 4;
214 digit = nibble < 10 ? nibble + '0':nibble - 10 + 'a';
215 blit_digit(digit);
216
217 nibble = kdp_mac_addr.ether_addr_octet[count] & 0xf;
218 digit = nibble < 10 ? nibble + '0':nibble - 10 + 'a';
219 blit_digit(digit);
220 if( count < 5 )
221 blit_digit( colon );
222 }
223 }
224 else /* blit the ff's */
225 {
226 for( count = 0; count < 6; count++ )
227 {
228 digit = pair[0];
229 blit_digit(digit);
230 digit = pair[1];
231 blit_digit(digit);
232 if( count < 5 )
233 blit_digit( colon );
234 }
235 }
236 /* now print the ip address */
237 mac_addr_digit_x = (vinfo.v_width/2) + 10;
238 if(ip_addr != 0)
239 {
240 /* blit the digits for ip address */
241 for (count = 0; count < 4; count++ )
242 {
243 nibble = (ip_addr & 0xff000000 ) >> 24;
244
245 d3 = (nibble % 0xa) + '0';
246 nibble = nibble/0xa;
247 d2 = (nibble % 0xa) + '0';
248 nibble = nibble /0xa;
249 d1 = (nibble % 0xa) + '0';
250
251 if( d1 != '0' ) blit_digit(d1);
252 blit_digit(d2);
253 blit_digit(d3);
254 if( count < 3 )
255 blit_digit(dot);
256
257 d1= d2 = d3 = 0;
258 ip_addr = ip_addr << 8;
259 }
260 }
261 }
262 }
263 }
264 panicDialogDrawn = TRUE;
265 panicDialogDesired = FALSE;
266
267 }
268
269 static void
270 blit_digit( int digit )
271 {
272 switch( digit )
273 {
274 case '0': {
275 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);
276 mac_addr_digit_x = mac_addr_digit_x + num_0.num_w - 1;
277 break;
278 }
279 case '1': {
280 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);
281 mac_addr_digit_x = mac_addr_digit_x + num_1.num_w ;
282 break;
283 }
284 case '2': {
285 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);
286 mac_addr_digit_x = mac_addr_digit_x + num_2.num_w ;
287 break;
288 }
289 case '3': {
290 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);
291 mac_addr_digit_x = mac_addr_digit_x + num_3.num_w ;
292 break;
293 }
294 case '4': {
295 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);
296 mac_addr_digit_x = mac_addr_digit_x + num_4.num_w ;
297 break;
298 }
299 case '5': {
300 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);
301 mac_addr_digit_x = mac_addr_digit_x + num_5.num_w ;
302 break;
303 }
304 case '6': {
305 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);
306 mac_addr_digit_x = mac_addr_digit_x + num_6.num_w ;
307 break;
308 }
309 case '7': {
310 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);
311 mac_addr_digit_x = mac_addr_digit_x + num_7.num_w ;
312 break;
313 }
314 case '8': {
315 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);
316 mac_addr_digit_x = mac_addr_digit_x + num_8.num_w ;
317 break;
318 }
319 case '9': {
320 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);
321 mac_addr_digit_x = mac_addr_digit_x + num_9.num_w ;
322 break;
323 }
324 case 'a': {
325 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);
326 mac_addr_digit_x = mac_addr_digit_x + num_a.num_w ;
327 break;
328 }
329 case 'b': {
330 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);
331 mac_addr_digit_x = mac_addr_digit_x + num_b.num_w ;
332 break;
333 }
334 case 'c': {
335 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);
336 mac_addr_digit_x = mac_addr_digit_x + num_c.num_w ;
337 break;
338 }
339 case 'd': {
340 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);
341 mac_addr_digit_x = mac_addr_digit_x + num_d.num_w ;
342 break;
343 }
344 case 'e': {
345 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);
346 mac_addr_digit_x = mac_addr_digit_x + num_e.num_w ;
347 break;
348 }
349 case 'f': {
350 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);
351 mac_addr_digit_x = mac_addr_digit_x + num_f.num_w ;
352 break;
353 }
354 case ':': {
355 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);
356 mac_addr_digit_x = mac_addr_digit_x + num_colon.num_w;
357 break;
358 }
359 case '.': {
360 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);
361 mac_addr_digit_x = mac_addr_digit_x + num_colon.num_w;
362 break;
363 }
364 default:
365 break;
366
367 }
368 }
369
370 static void
371 panic_blit_rect( unsigned int x, unsigned int y,
372 unsigned int width, unsigned int height,
373 int transparent, unsigned char * dataPtr )
374 {
375 if(!vinfo.v_depth)
376 return;
377
378 switch( vinfo.v_depth) {
379 case 8:
380 panic_blit_rect_8( x, y, width, height, transparent, dataPtr);
381 break;
382 case 16:
383 panic_blit_rect_16( x, y, width, height, transparent, dataPtr);
384 break;
385 case 32:
386 panic_blit_rect_32( x, y, width, height, transparent, dataPtr);
387 break;
388 }
389 }
390
391 /* panic_blit_rect_8 uses the built in clut for drawing.
392
393 */
394 static void
395 panic_blit_rect_8( unsigned int x, unsigned int y,
396 unsigned int width, unsigned int height,
397 int transparent, unsigned char * dataPtr )
398 {
399 volatile unsigned char * dst;
400 int line, col;
401 unsigned int data, quantity, value;
402
403 dst = (volatile unsigned char *) (vinfo.v_baseaddr +
404 (y * vinfo.v_rowbytes) +
405 x);
406
407 quantity = 0;
408
409 for( line = 0; line < height; line++) {
410 for( col = 0; col < width; col++) {
411 if (quantity == 0) {
412 dataPtr += decode_rle(dataPtr, &quantity, &value);
413 }
414
415 data = value;
416 *(dst + col) = data;
417 quantity--;
418 }
419
420 dst = (volatile unsigned char *) (((int)dst) + vinfo.v_rowbytes);
421 }
422 }
423
424 /* panic_blit_rect_16 draws using a clut.
425
426 panic_blit_rect_16 decodes the RLE encoded image data on the fly, looks up the
427 color by indexing into the clut, uses the top 5 bits to fill in each of the three
428 pixel values (RGB) and writes each pixel to the screen.
429 */
430 static void
431 panic_blit_rect_16( unsigned int x, unsigned int y,
432 unsigned int width, unsigned int height,
433 int transparent, unsigned char * dataPtr )
434 {
435 volatile unsigned short * dst;
436 int line, col;
437 unsigned int quantity, index, value, data;
438
439 /* If our clut has disappeared, use the standard MacOS 8-bit clut */
440 if(!clut) {
441 clut = appleClut8;
442 }
443
444 dst = (volatile unsigned short *) (vinfo.v_baseaddr +
445 (y * vinfo.v_rowbytes) +
446 (x * 2));
447
448 quantity = 0;
449
450 for( line = 0; line < height; line++) {
451 for( col = 0; col < width; col++) {
452
453 if (quantity == 0) {
454 dataPtr += decode_rle(dataPtr, &quantity, &value);
455 index = value * 3;
456 }
457
458 data = ( (unsigned short) (0xf8 & (clut[index + 0])) << 7)
459 | ( (unsigned short) (0xf8 & (clut[index + 1])) << 2)
460 | ( (unsigned short) (0xf8 & (clut[index + 2])) >> 3);
461
462 *(dst + col) = data;
463 quantity--;
464 }
465
466 dst = (volatile unsigned short *) (((int)dst) + vinfo.v_rowbytes);
467 }
468
469 }
470
471 /*
472 panic_blit_rect_32 decodes the RLE encoded image data on the fly, and fills
473 in each of the three pixel values from the clut (RGB) for each pixel and
474 writes it to the screen.
475 */
476 static void
477 panic_blit_rect_32( unsigned int x, unsigned int y,
478 unsigned int width, unsigned int height,
479 int transparent, unsigned char * dataPtr )
480 {
481 volatile unsigned int * dst;
482 int line, col;
483 unsigned int value, quantity, index, data;
484
485
486 /* If our clut has disappeared, use the standard MacOS 8-bit clut */
487 if(!clut) {
488 clut = appleClut8;
489 }
490
491 dst = (volatile unsigned int *) (vinfo.v_baseaddr +
492 (y * vinfo.v_rowbytes) +
493 (x * 4));
494
495 quantity = 0;
496
497 for( line = 0; line < height; line++) {
498 for( col = 0; col < width; col++) {
499 if (quantity == 0) {
500 dataPtr += decode_rle(dataPtr, &quantity, &value);
501 index = value * 3;
502 }
503
504 data = ( (unsigned int) clut[index + 0] << 16)
505 | ( (unsigned int) clut[index + 1] << 8)
506 | ( (unsigned int) clut[index + 2]);
507
508 *(dst + col) = data;
509 quantity--;
510 }
511
512 dst = (volatile unsigned int *) (((int)dst) + vinfo.v_rowbytes);
513 }
514 }
515
516 /*
517 decode_rle decodes a single quantity/value pair of a "modified-RLE" encoded
518 image. The encoding works as follows:
519
520 The quantity and value will be described by either two or three bytes. If the
521 most significant bit of the first byte is a 0, then the next seven bits are
522 the quantity (run-length) and the following 8 bits are the value (index into
523 a clut, in this case). If the msb of the first byte is a 1, then the next 15 bits
524 are the quantity and the following 8 are the value. Visually, the two possible
525 encodings are: (q = quantity, v = value)
526
527 Byte 1 Byte 2 Byte 3
528 case 1: [ 0 q6 q5 q4 q3 q2 q1 q0 ] [ v7 v6 v5 v4 v3 v2 v1 v0 ] [ ]
529 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 ]
530 */
531 static int
532 decode_rle( unsigned char * dataPtr, unsigned int * quantity, unsigned int * value )
533 {
534 unsigned char byte1 = *dataPtr++;
535 unsigned char byte2 = *dataPtr++;
536 int num_slots = 0;
537
538 /* if the most-significant bit is 0, then the first byte is quanity, the second is value */
539 if ((byte1 >> 7) == 0) {
540 *quantity = (unsigned int) byte1;
541 *value = (unsigned int) byte2;
542 num_slots = 2;
543 } else {
544 /* clear the leading 1 */
545 byte1 ^= 0x80;
546
547 /* the first two bytes are the quantity, the third is value */
548 *quantity = (unsigned int) byte1 << 8 | byte2;
549 *value = *dataPtr++;
550 num_slots = 3;
551 }
552
553 return num_slots;
554 }
555
556 static void
557 dim_screen(void)
558 {
559 if(!vinfo.v_depth)
560 return;
561
562 switch( vinfo.v_depth) {
563 case 16:
564 dim_screen_16();
565 break;
566 case 32:
567 dim_screen_32();
568 break;
569 }
570 }
571
572 static void
573 dim_screen_16(void)
574 {
575 unsigned long *p, *endp, *row;
576 int col;
577 int rowline, rowlongs;
578 unsigned long value, tmp;
579
580 rowline = vinfo.v_rowscanbytes / 4;
581 rowlongs = vinfo.v_rowbytes / 4;
582
583 p = (unsigned long*) vinfo.v_baseaddr;
584 endp = (unsigned long*) vinfo.v_baseaddr;
585
586 endp += rowlongs * vinfo.v_height;
587
588 for (row = p ; row < endp ; row += rowlongs) {
589 for (col = 0; col < rowline; col++) {
590 value = *(row+col);
591 tmp = ((value & 0x7C007C00) >> 1) & 0x3C003C00;
592 tmp |= ((value & 0x03E003E0) >> 1) & 0x01E001E0;
593 tmp |= ((value & 0x001F001F) >> 1) & 0x000F000F;
594 *(row+col) = tmp; //half (dimmed)?
595 }
596
597 }
598
599 }
600
601 static void
602 dim_screen_32(void)
603 {
604 unsigned long *p, *endp, *row;
605 int col;
606 int rowline, rowlongs;
607 unsigned long value, tmp;
608
609 rowline = vinfo.v_rowscanbytes / 4;
610 rowlongs = vinfo.v_rowbytes / 4;
611
612 p = (unsigned long*) vinfo.v_baseaddr;
613 endp = (unsigned long*) vinfo.v_baseaddr;
614
615 endp += rowlongs * vinfo.v_height;
616
617 for (row = p ; row < endp ; row += rowlongs) {
618 for (col = 0; col < rowline; col++) {
619 value = *(row+col);
620 tmp = ((value & 0x00FF0000) >> 1) & 0x007F0000;
621 tmp |= ((value & 0x0000FF00) >> 1) & 0x00007F00;
622 tmp |= (value & 0x000000FF) >> 1;
623 *(row+col) = tmp; //half (dimmed)?
624 }
625
626 }
627
628 }