Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / x68k / stand / bootlogo / xpm2bootimg.c
blobf67953b84b5036652fca545024114987db8b29d7
1 /* $NetBSD: xpm2bootimg.c,v 1.3 2009/03/14 21:04:17 dsl Exp $ */
3 /*
4 * convert XPM format image to boot title format
6 * written by Yasha (ITOH Yasufumi), public domain
7 */
9 #include <stdio.h>
10 #include <string.h>
12 static int opt_ascii;
14 #define IMGWIDTH 56
15 #define IMGHEIGHT 52
17 /* if you change this, you must also make changes to the extraction code */
18 #define VALBIT 2
19 #define LENBIT 3
20 #define LENMAX (1<<LENBIT)
22 #if VALBIT + LENBIT > 8
23 #error too long encoding --- not portable between architectures in this code
24 #endif
26 /* this program may run on cross host, and should be portable */
27 #ifdef __STDC__
28 # define PROTO(x) x
29 #else
30 # define PROTO(x) ()
31 #endif
33 static void putbyte PROTO((int c));
34 static void initdot PROTO((void));
35 static void putrun PROTO((int val, int len));
36 static void adddot PROTO((int val));
37 static void flushdot PROTO((void));
39 static unsigned rgb16b PROTO((int rgb));
40 static char *destring PROTO((char *str));
41 static char *getline PROTO((void));
42 static void error PROTO((char *msg));
43 int main PROTO((int argc, char *argv[]));
45 static int outbuf;
46 static int bufbits;
47 static int curval;
48 static int curlen;
50 static int obytes;
52 static void
53 putbyte(int c)
55 static unsigned char wbuf;
57 if (c == -1) {
58 if (obytes % 16 && opt_ascii)
59 printf("\n");
60 if (obytes & 1) {
61 if (opt_ascii)
62 printf("\t.byte\t0x%02x\n", wbuf);
63 else
64 putchar(wbuf);
66 if (opt_ascii)
67 printf("| compressed image %d bytes\n", obytes);
68 return;
70 if (obytes % 16 == 0 && opt_ascii)
71 printf("\t.word\t");
73 obytes++;
74 if (obytes & 1)
75 wbuf = c;
76 else {
77 if (opt_ascii) {
78 if ((obytes >> 1) % 8 != 1)
79 printf(",");
80 printf("0x%04x", (wbuf << 8) | c);
81 } else
82 printf("%c%c", wbuf, c);
85 if (obytes % 16 == 0 && opt_ascii)
86 printf("\n");
89 static void
90 initdot(void)
93 outbuf = bufbits = curval = curlen = obytes = 0;
96 static int put;
98 static void
99 putrun(int val, int len)
102 /* fprintf(stderr, "val %d, len %d\n", val, len);*/
103 outbuf <<= VALBIT;
104 outbuf |= val;
105 outbuf <<= LENBIT;
106 outbuf |= len - 1;
107 bufbits += VALBIT + LENBIT;
109 if (bufbits >= 8) {
110 putbyte((unsigned char) (outbuf >> (bufbits - 8)));
111 bufbits -= 8;
112 put = 1;
116 static void
117 adddot(int val)
120 if (curval != val) {
121 if (curlen)
122 putrun(curval, curlen);
123 curlen = 0;
124 curval = val;
126 curlen++;
127 if (curlen == LENMAX) {
128 putrun(val, LENMAX);
129 curlen = 0;
133 static void
134 flushdot(void)
137 if (curlen) {
138 putrun(curval, curlen);
139 curlen = 0;
142 if (bufbits) {
143 /* make sure data drain */
144 put = 0;
145 while (put == 0)
146 putrun(curval, LENMAX);
148 putbyte(-1);
152 * convert r8g8b8 to g5r5b5i1
154 static unsigned
155 rgb16b(int rgb)
157 unsigned r = rgb >> 16, g = (rgb >> 8) & 0xff, b = rgb & 0xff;
158 unsigned rgb16;
160 rgb16 = (g << 8 & 0xf800) | (r << 3 & 0x7c0) | (b >> 2 & 0x3e);
163 * v v v v v i i i
164 * valid bits used for I bit
166 if ((r & 7) + (g & 7) + (b & 7) >= 11)
167 rgb16 |= 1;
169 return rgb16;
172 static char *
173 destring(char *str)
174 /* str: must be writable */
176 size_t len;
177 char *p;
179 if (*str != '"' || (len = strlen(str)) < 2)
180 return NULL;
181 p = str + len - 1;
182 if (*p == ',') {
183 if (len < 3)
184 return NULL;
185 p--;
188 if (*p != '"')
189 return NULL;
191 *p = '\0';
192 return str + 1;
195 static char *filename;
196 static FILE *infp;
197 static unsigned lineno;
199 static char *
200 getline(void)
202 static char buf[256];
203 char *p;
205 if (!fgets(buf, sizeof buf, infp)) {
206 if (ferror(infp)) {
207 perror(filename);
208 exit(1);
209 } else
210 return NULL; /* end of input */
212 lineno++;
213 if (!(p = strchr(buf, '\n'))) {
214 fprintf(stderr, "%s:%d: too long line\n", filename, lineno);
215 exit(1);
217 *p = '\0';
219 return buf;
222 static void
223 error(char *msg)
225 if (!msg)
226 msg = "format error";
228 fprintf(stderr, "%s:%d: %s\n", filename, lineno, msg);
229 exit(1);
232 static struct color {
233 int ch;
234 enum col {
235 COL_BLACK, COL_1, COL_2, COL_WHITE
236 } val;
237 } coltbl[32];
239 unsigned col1, col2;
241 enum col bitmap[IMGHEIGHT][IMGWIDTH];
244 main(int argc, char *argv[])
246 char *p;
247 unsigned u, colors, xcol, x;
248 char buf[256];
249 int in_oc;
250 char *progname = argv[0];
253 * parse arg
255 if (argc > 1 && !strcmp(argv[1], "-s")) {
257 * -s option: output assembler source
258 * (output binary otherwise)
260 opt_ascii = 1;
261 argc--;
262 argv++;
264 if (argc == 1) {
265 infp = stdin;
266 filename = "stdin";
267 } else if (argc == 2) {
268 if ((infp = fopen(argv[1], "r")) == NULL) {
269 perror(argv[1]);
270 return 1;
272 filename = argv[1];
273 } else {
274 fprintf(stderr, "usage: %s [file.xpm]\n", progname);
275 return 1;
279 * check XPM magic
281 if (!(p = getline()))
282 error("short file");
284 if (strcmp(p, "/* XPM */"))
285 error((char *) NULL);
287 while ((p = getline()) && !(p = destring(p)))
289 if (!p)
290 error((char *) NULL);
293 * the first string must be
294 * "56 52 5 1 XPMEXT",
297 unsigned w, h, cpp;
299 if (sscanf(p, "%u %u %u %u %s",
300 &w, &h, &colors, &cpp, buf) != 5)
301 error("must be \"56 52 * 1 XPMEXT\"");
303 if (w != IMGWIDTH)
304 error("image width must be 56");
305 if (h != IMGHEIGHT)
306 error("image height must be 52");
307 if (cpp != 1)
308 error("chars-per-pixel must be 1");
309 if (strcmp(buf, "XPMEXT"))
310 error("XPMEXT is required");
312 if (colors > sizeof coltbl / sizeof coltbl[0])
313 error("too many colors");
316 * read colors
317 * ". c #ffffff",
319 xcol = 0;
320 for (u = 0; u < colors; u++) {
321 while ((p = getline()) && !(p = destring(p)))
323 if (!p)
324 error((char *) NULL);
325 if (sscanf(p, "%c %c %s", buf, buf+1, buf+2) != 3)
326 error((char *) NULL);
328 coltbl[u].ch = buf[0];
329 if (buf[2] == '#') {
330 int v;
331 if (sscanf(buf+3, "%x", &v) != 1)
332 error((char *) NULL);
333 if (v == 0)
334 coltbl[u].val = COL_BLACK;
335 else if (v == 0xffffff)
336 coltbl[u].val = COL_WHITE;
337 else if (xcol == 0) {
338 coltbl[u].val = COL_1;
339 col1 = rgb16b(v);
340 xcol++;
341 } else if (xcol == 1) {
342 coltbl[u].val = COL_2;
343 col2 = rgb16b(v);
344 xcol++;
345 } else
346 error("too many colors");
347 } else if (!strcmp(buf+2, "None")) {
349 * transparent color is treated as black
351 coltbl[u].val = COL_BLACK;
352 } else
353 error("unknown color (symbolic name is not supported)");
357 * read bitmaps
359 for (u = 0; u < IMGHEIGHT; u++) {
361 while ((p = getline()) && !(p = destring(p)))
363 if (!p)
364 error((char *) NULL);
366 if (strlen(p) != IMGWIDTH)
367 error((char *) NULL);
369 for (x = 0; x < IMGWIDTH; x++, p++) {
370 unsigned i;
372 for (i = 0; i < colors; i++)
373 if (coltbl[i].ch == *p)
374 goto found_ch;
375 error("unknown character");
377 found_ch:
378 bitmap[u][x] = coltbl[i].val;
383 * read XPMEXTs and output copyright string
385 in_oc = 0;
386 while ((p = getline()) && *p == '\"') {
387 if (!(p = destring(p)))
388 error((char *) NULL);
389 if (!strcmp(p, "XPMEXT copyright"))
390 in_oc = 1;
391 else if (!strncmp(p, "XPMENDEXT", 3))
392 break;
393 else if (!strncmp(p, "XPM", 3))
394 in_oc = 0;
395 else {
396 if (in_oc) {
397 if (opt_ascii)
398 printf("\t.ascii\t\"\\n%s\"\n", p);
399 else
400 printf("\n%s", p);
405 /* terminate string */
406 if (opt_ascii)
407 printf("\t.byte\t0\n");
408 else
409 putchar('\0');
411 /* output color palette */
412 if (opt_ascii)
413 printf("\t.word\t0x%x,0x%x\n", col1, col2);
414 else
415 printf("%c%c%c%c", col1 >> 8, col1, col2 >> 8, col2);
418 * scan bitmap and output
420 initdot();
422 for (u = 0; u < IMGHEIGHT; u++)
423 for (x = 0; x < IMGWIDTH; x++)
424 adddot(bitmap[u][x]);
426 flushdot();
428 if (opt_ascii)
429 printf("\t.even\n");
431 return ferror(stdout);