]> git.saurik.com Git - apple/xnu.git/blame - osfmk/console/panic_ui/setupdialog.c
xnu-1456.1.26.tar.gz
[apple/xnu.git] / osfmk / console / panic_ui / setupdialog.c
CommitLineData
91447636
A
1/* setupdialog : converts a RAW image file into the c structure that the
2 * kernel panic ui system expects.
3 *
4 * to build: cc -o setupdialog setupdialog.c
5*/
6
7#include <stdio.h>
8#include <sys/types.h>
9#include <fcntl.h>
10
11#define RUN_MAX 32767
12
13void create_numbers_file( FILE *stream, char *outfile );
14unsigned int encode_rle(unsigned char * fileArr, unsigned int filePos, unsigned int quantity, unsigned char value);
15
16void
17usage(void) {
18 printf("\nusage: setupdialog -i <image file> -oi <image output> -n <numbers file> -on <numbers output>\n");
19
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));
24
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");
27}
28
29int
30main( int argc, char *argv[] )
31{
32 int next;
33 char *file = NULL, *ptr, *out = NULL, *numsfile = NULL, *numsout = NULL;
34 FILE * stream, *out_stream;
35 int * data;
36 short width = 0, height = 0, depth = 0;
37 char word[2];
38 char byte;
39 unsigned int i, pixels, filePos;
40 int err;
41 unsigned char *fileArr;
42 unsigned char nextP;
43 unsigned int count;
44 int currP;
45 int fd;
46 int pairs_this_line;
47
48
49 // pull apart the arguments
50 for( next = 1; next < argc; next++ )
51 {
52 if (strcmp(argv[next], "-i") == 0) // image file (RAW/PICT?)
53 file = argv[++next];
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
57 out = argv[++next];
58 else if (strcmp(argv[next], "-on") == 0) // output file for numbers
59 numsout = argv[++next];
60
61 /* perhaps we should just let the user specify the W/H rather than require the header */
62 /*
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);
67 */
68 }
69
70 if (!(numsfile || file)) {
71 usage();
72 exit(1);
73 }
74
75 if (!numsfile) {
76 printf("\nNo numbers file to process\n");
77 } else {
78 stream = fopen(numsfile, "r");
79 if (!stream) {
80 printf("bad nums infile.. bailing.\n");
81 exit(1);
82 }
83 create_numbers_file( stream, numsout );
84 fclose(stream);
85 }
86
87 if( file == NULL) {
88 printf("\nNo image file to process\n");
89 exit(1);
90 }
91
92 stream = fopen(file, "r");
93 if (!stream) {
94 printf("bad infile.. bailing.\n");
95 exit(1);
96 }
97
98 printf("\nReading image file...\n");
99
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);
106
107 if (!(width && height && depth)) {
108 printf("Invalid image file header (width, height, or depth is 0)\n");
109 exit(1);
110 }
111
112 pixels = width * height;
113
114 if (!(fileArr = (unsigned char *) malloc(pixels))) {
115 printf("couldn't malloc fileArr (%d pixels)... bailing.\n", pixels);
116 exit(1);
117 }
118
119 currP = -1;
120 count = 0;
121 filePos = 0; // position in the file we're writing out
122
123 for (i=0; i < pixels; i++) {
124 nextP = fgetc(stream);
125 count++;
126 if (nextP == currP) {
127 if (count >= RUN_MAX) {
128 filePos += encode_rle(fileArr, filePos, count, (unsigned char) currP);
129 count = 0;
130 currP = -1;
131 }
132 } else {
133 if (currP != -1) {
134 filePos += encode_rle(fileArr, filePos, count-1, (unsigned char) currP);
135 }
136 currP = nextP; // start a new run
137 count = 1;
138 }
139 }
140
141 // write out any run that was in progress
142 if (count > 0) {
143 filePos += encode_rle(fileArr, filePos, count, (unsigned char) currP);
144 }
145
146 fclose( stream );
147
148 // now, generate the c file
149
150 if ( out == NULL)
151 out = "panic_image.c";
152 out_stream = fopen(out, "w");
153
154 if(out_stream == NULL) {
155 printf("couldn't open out file.. bailing\n");
156 exit(1);
157 }
158
159 pairs_this_line = 0;
160
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));
167
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 */
172
173 for( i=0; i < filePos;) {
174 fprintf( out_stream, "0x%.2x,0x%.2x", fileArr[i], fileArr[i+1]);
175 i+=2;
176 pairs_this_line++;
177
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++]);
181 pairs_this_line++;
182 }
183
184 if (i >= filePos) // this is the last element
185 fprintf( out_stream, "\n};");
186 else fprintf( out_stream, ", ");
187
188 if(pairs_this_line > 8) {
189 fprintf( out_stream, "\n");
190 pairs_this_line = 0;
191 }
192 }
193
194
195 fclose( out_stream );
196
197 return 0;
198}
199
200
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.
206 */
207void
208create_numbers_file( FILE *stream, char *outfile )
209{
210 int err;
211 short height, depth, totalwidth;
212 int numbers = 17;
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};
215
216 int **pixmap;
217 int row, col, item, line=0, currWidth;
218 int nextP, currP;
219 int count, currNum;
220
221 FILE *out_stream;
222
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);
230
231 if (!(width && height && depth)) {
232 printf("Invalid numbers file header (width, height, or depth is 0)\n");
233 return;
234 }
235
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) );
240
241 currP = -1;
242 count = 0;
243 currWidth = 0;
244 currNum = 0;
245
246 for( row=0; row < height; row++) {
247 for( item=0; item < numbers; item++) {
248 count = 0;
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;
256 numPos[item]+=2;
257 count = 0;
258 currP = -1;
259 } else count++; // add one to the current run
260 } else {
261 if( currP != -1) {
262 pixmap[item][numPos[item]] = count; // currP was the end of the run
263 pixmap[item][numPos[item]+1] = currP;
264 numPos[item]+=2;
265 }
266 currP = nextP; // start a new run
267 count = 1;
268 }
269 }
270 // write out any run that was in progress
271 if( count > 0) {
272 pixmap[item][numPos[item]] = count;
273 pixmap[item][numPos[item]+1] = currP;
274 numPos[item]+=2;
275 }
276 }
277 }
278
279 // now, generate the c file
280
281 if ( outfile == NULL)
282 outfile = "rendered_numbers.c";
283 out_stream = fopen(outfile, "w");
284
285 if(out_stream == NULL) {
286 printf("couldn't open numbers outfile.. bailing\n");
287 exit(1);
288 }
289
290 fprintf( out_stream, " /* generated c file */\n\n");
291
292 // iterate through all the numbers/chars
293 for( item=0; item<numbers; item++)
294 {
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");
303
304 for( col = 0; col < numPos[item];)
305 {
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, ", ");
310
311 line+=pixmap[item][col];
312 if( line >= width[item]) {
313 fprintf( out_stream, "\n");
314 line = 0;
315 }
316 col+=2;
317 }
318 }
319
320 fclose( out_stream );
321}
322
323
324/* encode_rle applies a "modified-RLE encoding to a given image. The encoding works as follows:
325
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)
332
333 Byte 1 Byte 2 Byte 3
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 ]
336*/
337
338
339unsigned int
340encode_rle(unsigned char * fileArr, unsigned int filePos, unsigned int quantity, unsigned char value)
341{
342 unsigned char single_mask = 0x00;
343 unsigned char double_mask = 0x80;
344 unsigned char slots_used = 0;
345
346 if (quantity < 128) {
347 fileArr[filePos] = single_mask | quantity;
348 slots_used = 1;
349 } else {
350 fileArr[filePos] = double_mask | (quantity >> 8); // high 7 bits (plus mask)
351 fileArr[filePos+1] = (unsigned char) quantity; // low 8 bits
352 slots_used = 2;
353 }
354
355 fileArr[filePos+slots_used] = value;
356 slots_used++;
357
358 return slots_used;
359}