]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/console/panic_ui/setupdialog.c
1 /* setupdialog : converts a RAW image file into the c structure that the
2 * kernel panic ui system expects.
4 * to build: cc -o setupdialog setupdialog.c
13 void create_numbers_file( FILE *stream
, char *outfile
);
14 unsigned int encode_rle(unsigned char * fileArr
, unsigned int filePos
, unsigned int quantity
, unsigned char value
);
18 printf("\nusage: setupdialog -i <image file> -oi <image output> -n <numbers file> -on <numbers output>\n");
20 printf("\nYou can supply a panic image file, a numbers file, or both. Input files\n");
21 printf("must be in RAW format where each pixel is represented by an index into the\n");
22 printf("MacOS X system CLUT. The first %d bytes must be the width, height, and depth\n", 3 * sizeof(short));
23 printf("(in that order, %d bytes each).\n", sizeof(short));
25 printf("\nThe output files are generated C structures in the format the panic ui code\n");
26 printf("expects (default output files are panic_image.c and rendered_numbers.c).\n\n");
30 main( int argc
, char *argv
[] )
33 char *file
= NULL
, *ptr
, *out
= NULL
, *numsfile
= NULL
, *numsout
= NULL
;
34 FILE * stream
, *out_stream
;
36 short width
= 0, height
= 0, depth
= 0;
39 unsigned int i
, pixels
, filePos
;
41 unsigned char *fileArr
;
49 // pull apart the arguments
50 for( next
= 1; next
< argc
; next
++ )
52 if (strcmp(argv
[next
], "-i") == 0) // image file (RAW/PICT?)
54 else if (strcmp(argv
[next
], "-n") == 0) // numbers/chars image file (RAW)
55 numsfile
= argv
[++next
];
56 else if (strcmp(argv
[next
], "-oi") == 0) // output file for image
58 else if (strcmp(argv
[next
], "-on") == 0) // output file for numbers
59 numsout
= argv
[++next
];
61 /* perhaps we should just let the user specify the W/H rather than require the header */
63 else if (strcmp(argv[next], "-w") == 0) // image width (pixels)
64 width = strtoul(argv[++next], &ptr, 0);
65 else if (strcmp(argv[next], "-h") == 0) // image height (pixels)
66 width = strtoul(argv[++next], &ptr, 0);
70 if (!(numsfile
|| file
)) {
76 printf("\nNo numbers file to process\n");
78 stream
= fopen(numsfile
, "r");
80 printf("bad nums infile.. bailing.\n");
83 create_numbers_file( stream
, numsout
);
88 printf("\nNo image file to process\n");
92 stream
= fopen(file
, "r");
94 printf("bad infile.. bailing.\n");
98 printf("\nReading image file...\n");
100 fread((void *) &width
, sizeof(short), 1, stream
);
101 printf("got width: %d\n", width
);
102 fread((void *) &height
, sizeof(short), 1, stream
);
103 printf("got height: %d\n", height
);
104 fread((void *) &depth
, sizeof(short), 1, stream
);
105 printf("got depth: %d\n", depth
);
107 if (!(width
&& height
&& depth
)) {
108 printf("Invalid image file header (width, height, or depth is 0)\n");
112 pixels
= width
* height
;
114 if (!(fileArr
= (unsigned char *) malloc(pixels
))) {
115 printf("couldn't malloc fileArr (%d pixels)... bailing.\n", pixels
);
121 filePos
= 0; // position in the file we're writing out
123 for (i
=0; i
< pixels
; i
++) {
124 nextP
= fgetc(stream
);
126 if (nextP
== currP
) {
127 if (count
>= RUN_MAX
) {
128 filePos
+= encode_rle(fileArr
, filePos
, count
, (unsigned char) currP
);
134 filePos
+= encode_rle(fileArr
, filePos
, count
-1, (unsigned char) currP
);
136 currP
= nextP
; // start a new run
141 // write out any run that was in progress
143 filePos
+= encode_rle(fileArr
, filePos
, count
, (unsigned char) currP
);
148 // now, generate the c file
151 out
= "panic_image.c";
152 out_stream
= fopen(out
, "w");
154 if(out_stream
== NULL
) {
155 printf("couldn't open out file.. bailing\n");
161 fprintf( out_stream
, "/* generated c file */\n\n");
162 fprintf( out_stream
, "static const struct {\n");
163 fprintf( out_stream
, " unsigned int pd_width;\n");
164 fprintf( out_stream
, " unsigned int pd_height;\n");
165 fprintf( out_stream
, " unsigned int bytes_per_pixel; /* 1: CLUT, 3:RGB, 4:RGBA */\n");
166 fprintf( out_stream
, " unsigned char image_pixel_data[%#4.2x];\n", (filePos
));
168 fprintf( out_stream
, "} panic_dialog = {\n");
169 fprintf( out_stream
, "\t%d, ", width
); /* panic dialog x */
170 fprintf( out_stream
, "%d, ", height
); /* panic dialog y */
171 fprintf( out_stream
, "1,\n"); /* bytes per pixel */
173 for( i
=0; i
< filePos
;) {
174 fprintf( out_stream
, "0x%.2x,0x%.2x", fileArr
[i
], fileArr
[i
+1]);
178 // if the first byte had a leading 1, this is a 3-byte encoding
179 if ((fileArr
[i
-2] >> 7) == 1) {
180 fprintf( out_stream
, ",0x%.2x", fileArr
[i
++]);
184 if (i
>= filePos
) // this is the last element
185 fprintf( out_stream
, "\n};");
186 else fprintf( out_stream
, ", ");
188 if(pairs_this_line
> 8) {
189 fprintf( out_stream
, "\n");
195 fclose( out_stream
);
201 /* Each number/char (0-f) has its own row in the pixmap array.
202 When done, these rows each contain an RLE character.
203 The image file is read row by row, so the individual characters
204 must be constructed in the same way. The numPos array tracks the
205 current position in each character's RLE array.
208 create_numbers_file( FILE *stream
, char *outfile
)
211 short height
, depth
, totalwidth
;
213 int width
[17] = {9,7,8,6,9,7,8,7,8,7,10,7,9,10,7,6,4};
214 int numPos
[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
217 int row
, col
, item
, line
=0, currWidth
;
223 printf("\nReading numbers file...\n");
224 fread((void *) &totalwidth
, sizeof(short), 1, stream
);
225 printf("got width: %d\n", totalwidth
);
226 fread((void *) &height
, sizeof(short), 1, stream
);
227 printf("got height: %d\n", height
);
228 fread((void *) &depth
, sizeof(short), 1, stream
);
229 printf("got depth: %d\n", depth
);
231 if (!(width
&& height
&& depth
)) {
232 printf("Invalid numbers file header (width, height, or depth is 0)\n");
236 // allocate array to hold each number's RLE encoding (20 = 2xwidest width[i] value, 17 = num chars)
237 pixmap
= (int **) malloc( 17 * sizeof(int *) );
238 for( item
=0; item
<17; item
++)
239 pixmap
[item
] = (int *) malloc( 2*width
[item
]*height
*sizeof(int) );
246 for( row
=0; row
< height
; row
++) {
247 for( item
=0; item
< numbers
; item
++) {
249 currP
= -1; // start each character fresh
250 for( col
=0; col
< width
[item
]; col
++) {
251 nextP
= fgetc( stream
);
252 if( nextP
== currP
) {
253 if( count
== 127) { // probably never executed given the small widths
254 pixmap
[item
][numPos
[item
]] = count
;
255 pixmap
[item
][numPos
[item
]+1] = currP
;
259 } else count
++; // add one to the current run
262 pixmap
[item
][numPos
[item
]] = count
; // currP was the end of the run
263 pixmap
[item
][numPos
[item
]+1] = currP
;
266 currP
= nextP
; // start a new run
270 // write out any run that was in progress
272 pixmap
[item
][numPos
[item
]] = count
;
273 pixmap
[item
][numPos
[item
]+1] = currP
;
279 // now, generate the c file
281 if ( outfile
== NULL
)
282 outfile
= "rendered_numbers.c";
283 out_stream
= fopen(outfile
, "w");
285 if(out_stream
== NULL
) {
286 printf("couldn't open numbers outfile.. bailing\n");
290 fprintf( out_stream
, " /* generated c file */\n\n");
292 // iterate through all the numbers/chars
293 for( item
=0; item
<numbers
; item
++)
295 fprintf( out_stream
, "static const struct {\n");
296 fprintf( out_stream
, " unsigned int num_w;\n");
297 fprintf( out_stream
, " unsigned int num_h;\n");
298 fprintf( out_stream
, " unsigned char num_pixel_data[%#4.2x];\n", numPos
[item
]); // num elems
299 item
== 16 ? fprintf( out_stream
, "} num_colon = {\n") : fprintf( out_stream
, "} num_%x = {\n", item
);
300 fprintf( out_stream
, "/* w */ %d,\n", width
[item
]);
301 fprintf( out_stream
, "/* h */ %d,\n", height
);
302 fprintf( out_stream
, "/* pixel_data */ \n");
304 for( col
= 0; col
< numPos
[item
];)
306 fprintf( out_stream
, "0x%.2x,0x%.2x", pixmap
[item
][col
], pixmap
[item
][col
+1]);
307 if (col
== (numPos
[item
] - 2)) // this is the last element
308 fprintf( out_stream
, "\n};\n\n");
309 else fprintf( out_stream
, ", ");
311 line
+=pixmap
[item
][col
];
312 if( line
>= width
[item
]) {
313 fprintf( out_stream
, "\n");
320 fclose( out_stream
);
324 /* encode_rle applies a "modified-RLE encoding to a given image. The encoding works as follows:
326 The quantity and value will be described by either two or three bytes. If the
327 most significant bit of the first byte is a 0, then the next seven bits are
328 the quantity (run-length) and the following 8 bits are the value (index into
329 a clut, in this case). If the msb of the first byte is a 1, then the next 15 bits
330 are the quantity and the following 8 are the value. Visually, the two possible
331 encodings are: (q = quantity, v = value)
334 case 1: [ 0 q6 q5 q4 q3 q2 q1 q0 ] [ v7 v6 v5 v4 v3 v2 v1 v0 ] [ ]
335 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 ]
340 encode_rle(unsigned char * fileArr
, unsigned int filePos
, unsigned int quantity
, unsigned char value
)
342 unsigned char single_mask
= 0x00;
343 unsigned char double_mask
= 0x80;
344 unsigned char slots_used
= 0;
346 if (quantity
< 128) {
347 fileArr
[filePos
] = single_mask
| quantity
;
350 fileArr
[filePos
] = double_mask
| (quantity
>> 8); // high 7 bits (plus mask)
351 fileArr
[filePos
+1] = (unsigned char) quantity
; // low 8 bits
355 fileArr
[filePos
+slots_used
] = value
;