changes from Alessandro Scotti from 20060129
[xboard.git] / zic2xpm.c
1 /*
2         zic2xpm.c
3
4         Program to convert pieces from ZIICS format to XPM & XIM format.
5         (C version)  By Frank McIngvale <frankm@hiwaay.net>.
6
7         Copyright (C) 1996 Free Software Foundation, Inc.
8
9         NOTICE: The piece images distributed with ZIICS are
10             copyrighted works of their original creators.  Images 
11             converted with zic2xpm may not be redistributed without
12             the permission of the copyright holders.  Do not contact
13             the authors of zic2xpm or of ZIICS itself to request
14             permission. 
15
16         NOTICE:  The format of the ZIICS piece file was gleaned from
17             SHOWSETS.PAS, a part of ZIICS.  Thanks to Andy McFarland
18             (Zek on ICC) for making this source available!  ZIICS is a 
19             completely separate and copyrighted work of Andy
20             McFarland.  Use and distribution of ZIICS falls under the
21             ZIICS license, NOT the GNU General Public License.
22
23         NOTICE: The format of the VGA imageblocks was determined
24             by experimentation, and without access to any
25             of Borland Inc.'s BGI library source code.
26
27         This program is free software; you can redistribute it and/or modify
28         it under the terms of the GNU General Public License as published by
29         the Free Software Foundation; either version 2 of the License, or
30         (at your option) any later version.  However, the above notices
31         MUST BE RETAINED in any copy that you redistribute or modify.
32
33         This program is distributed in the hope that it will be useful,
34         but WITHOUT ANY WARRANTY; without even the implied warranty of
35         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36         GNU General Public License for more details.
37
38         You should have received a copy of the GNU General Public License
39         along with this program; if not, write to the Free Software
40         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
41
42         ** If you find a bug in zic2xpm.c, please report it to me,
43            Frank McIngvale (frankm@hiwaay.net) so that I may fix it. **
44 */
45
46 /*
47         Usage: zic2xpm file1 [file2 ...]
48
49         We split the ZIICS file(s) into 24 XPM & 24 XIM files with names:
50
51         <piece><type><size>.(xpm|xim).
52
53         Where:
54                 piece = p, n, b, r, q, k
55                 type = ll, ld, dl, dd
56                 size = Piece size.
57
58         Plus 4 files for the light & dark squares.
59         
60         This means that you can extract multiple SIZES in one directory
61         without name clashes. Extracting two sets of the SAME
62         size in a directory will cause the second to overwrite
63         the first.
64 */
65
66 /*
67    Technical note: Yes, this file is huge. I made it by cramming
68                    `zic2xpm' and `zic2xim' together. This should
69                    be less confusing to use, though.
70 */
71
72 #include "config.h"
73 #include <stdio.h>
74 #if STDC_HEADERS
75 #include <stdlib.h>
76 #endif
77
78 #ifndef SEEK_SET
79 #define SEEK_SET 0
80 #endif
81
82 /*
83    XIM file format:
84
85    width        byte
86    height       byte
87
88    Data (1 byte per pixel, row major)
89 */
90
91 /*
92    Map colors from ZIICS -> XIM :
93
94    0    0       Dark piece
95    2    1       Dark square
96    15   2       Light piece
97    14   3       Light square
98 */
99
100 typedef struct {
101   int zval;             /* ZIICS value */
102   int xval;             /* XIM value */
103 } z2xim;
104
105 /* Associate VGA color with XPM color/sym */
106
107 typedef struct {
108   int cval;             /* VGA pixel value */
109   char xchar;   /* XPM character for this color */
110   char *csym;   /* Symbolic name */
111   char *cdefault; /* Default color */
112 } z2xpm;
113
114 #define NR_ZIICS_COLORS 4
115
116 /* SHOWSETS.PAS (from ZIICS) states that images may only
117    use color numbers 0, 2, 14, and 15 */
118
119 z2xim z2xim_tab[NR_ZIICS_COLORS] = {
120   { 0, 0 },
121   { 2, 1 },
122   { 15, 2 },
123   { 14, 3 } };
124
125 z2xpm z2xpm_tab[NR_ZIICS_COLORS] = {
126   { 15, 'X', "light_piece", "white" },
127   { 0, ' ', "dark_piece", "black" },
128   { 14, '*', "light_square", "gray" },
129   { 2, '.', "dark_square", "green" } };
130
131 void fatal( str )
132          char *str;
133 {
134   printf("Fatal error: %s\n", str );
135   exit(1);
136 }
137
138 z2xim *lookup_xim_color( color )
139          int color;
140 {
141   int i;
142
143   for( i=0; i<NR_ZIICS_COLORS; ++i )
144         {
145           if ( z2xim_tab[i].zval == color )
146                 return (z2xim_tab + i);
147         }
148
149   fatal("Illegal color in image.");
150
151   /* NOT REACHED */
152   return NULL;                                  /* Make compiler happy */
153 }
154
155 z2xpm *lookup_xpm_color( color )
156          int color;
157 {
158   int i;
159
160   for( i=0; i<NR_ZIICS_COLORS; ++i )
161         {
162           if ( z2xpm_tab[i].cval == color )
163                 return (z2xpm_tab + i);
164         }
165
166   fatal("Illegal color in image.");
167
168   /* NOT REACHED */
169   return NULL;                                  /* Make compiler happy */
170 }
171
172 char *src_name;
173
174 int up8( i )
175          int i;
176 {
177   int r;
178
179   r = i % 8;
180   if ( r == 0 )
181         return i;
182
183   return i + 8 - r;
184 }
185
186 unsigned int vga_imagesize( w, h )
187          int w, h;
188 {
189   int w8;
190   unsigned int s;
191
192   w8 = up8( w );
193
194   s = 4 + w8/2 * h + 2;
195
196   return s;
197 }
198
199 unsigned char *decode_byte( dest, b, w )
200          unsigned char *dest, *b;
201          int w;
202 {
203   int i, j;
204   unsigned char byte, bit;
205
206   for( i=7; w > 0; --i, --w )
207         {
208           byte = 0;
209
210           /* 1 bit from each plane */
211           for( j=0; j<4; ++j )
212                 {
213                   bit = b[j];
214                   bit &= (1 << i);
215                   bit >>= i;
216                   bit <<= 3-j;
217                   byte |= bit;
218                 }
219
220           *(dest++) = byte;
221         }
222
223   return dest;
224 }
225
226 /*
227    W is width of image in PIXELS.
228    SRC is in packed pixel format.
229    DEST is filled with 1 BYTE per PIXEL.
230 */
231 unsigned char *decode_line( dest, src, w )
232          unsigned char *dest, *src;
233          int w;
234 {
235   unsigned int w8;
236   unsigned int bpp;
237   unsigned char b[4];
238   int i;
239   unsigned char *p;
240
241   p = src;
242   w8 = up8( w );
243
244   /* 4 planes, bpp BYTES per plane */
245   /* Planes are MSB -> LSB */
246   bpp = w8 >> 3;
247
248   while( w > 0 )
249         {
250           for( i=0; i<4; ++i )
251                 b[i] = p[i*bpp];
252
253           if ( w > 8 )
254                 dest = decode_byte( dest, b, 8 );
255           else
256                 dest = decode_byte( dest, b, w );
257
258           w -= 8;
259           ++p;
260         }
261
262   return (src + bpp * 4);
263 }
264
265 int write_xim_header( fp, w, h )
266          FILE *fp;
267          int w, h;
268 {
269   fputc( w, fp );
270   fputc( h, fp );
271   
272   return 0;
273 }
274
275 int write_xpm_header( fp, w, h )
276          FILE *fp;
277          int w, h;
278 {
279   int i;
280   z2xpm *cv;
281
282   fprintf(fp, "/* XPM */\n");
283   fprintf(fp, "/* This file was automatically generated from the file %s\n",
284           src_name );
285   fprintf(fp, "using the program ``zic2xpm''.\n");
286   fprintf(fp, "\n    %s\n    %s\n    %s\n    %s\n    %s\n    %s */\n",
287           "NOTICE: The piece images distributed with ZIICS are",
288           "    copyrighted works of their original creators.  Images",
289           "    converted with zic2xpm may not be redistributed without",
290           "    the permission of the copyright holders.  Do not contact",
291           "    the authors of zic2xpm or of ZIICS itself to request",
292           "    permission.");
293   fprintf( fp, "static char * image_name[] = {\n" );
294   fprintf( fp, "\"%d %d %d 1\",\n", h, w, NR_ZIICS_COLORS );
295
296   cv = z2xpm_tab;
297
298   for( i=0; i<NR_ZIICS_COLORS; ++i, ++cv )
299         {
300           fprintf( fp, "\"%c\tc %s s %s\",\n", cv->xchar,
301                           cv->cdefault, cv->csym );
302         }
303
304   return 0;
305 }
306
307 void create_piece_xim( outname, fpin, W, H )
308          char *outname;
309          FILE *fpin;
310          int W, H;
311 {
312   FILE *fpout;
313   int w, h, i, j, c;
314   unsigned char *lump, *p, *line;
315   long size;
316   z2xim *ent;
317   
318   fpout = fopen( outname, "wb" );
319   if ( !fpout )
320         fatal( "Can't create output file.");
321
322   /* Header is two ints -- Width then Height, x86 format */
323   c = fgetc( fpin );
324   w = (fgetc(fpin) << 8) | c;
325
326   c = fgetc( fpin );
327   h = (fgetc(fpin) << 8) | c;
328   
329   ++w; ++h;
330
331   if ( w != W || h != H )
332         fatal( "Bad header." );   
333
334   size = vga_imagesize( w, h ) - 4;
335   lump = (unsigned char*)malloc( size );
336   line = (unsigned char*)malloc( w );
337
338   if ( !lump || !line )
339         fatal( "Out of memory." );
340
341   fread( lump, 1, size, fpin );
342
343   /* Write XIM header */
344   write_xim_header( fpout, w, h );
345
346   p = lump;
347   
348   /* Write XIM data */
349   for( i=0; i<h; ++i )
350         {
351           p = decode_line( line, p, w );
352           
353           for( j=0; j<w; ++j )
354                 {
355                   ent = lookup_xim_color( line[j] );
356                   fputc( ent->xval, fpout );
357                 }
358         }
359   
360   free( lump );
361   free( line );
362   fclose( fpout );
363 }
364
365 void create_piece_xpm( outname, fpin, W, H )
366          char *outname;
367          FILE *fpin;
368          int W, H;
369 {
370   FILE *fpout;
371   int w, h, i, j, c;
372   unsigned char *lump, *p, *line;
373   long size;
374   z2xpm *cv;
375   
376   fpout = fopen( outname, "wb" );
377   if ( !fpout )
378         fatal( "Can't create output file.");
379
380   /* Header is two ints -- Width then Height, x86 format */
381   c = fgetc( fpin );
382   w = (fgetc(fpin) << 8) | c;
383
384   c = fgetc( fpin );
385   h = (fgetc(fpin) << 8) | c;
386   
387   ++w; ++h;
388
389   if ( w != W || h != H )
390         fatal( "Bad header." );   
391
392   size = vga_imagesize( w, h ) - 4;
393   lump = (unsigned char*)malloc( size );
394   line = (unsigned char*)malloc( w );
395
396   if ( !lump || !line )
397         fatal( "Out of memory." );
398
399   fread( lump, 1, size, fpin );
400
401   /* Write XPM header */
402   write_xpm_header( fpout, w, h );
403
404   p = lump;
405   
406   /* Write XPM data */
407   for( i=0; i<h; ++i )
408         {
409           p = decode_line( line, p, w );
410           
411           fprintf( fpout, "\"" );
412           for( j=0; j<w; ++j )
413                 {
414                   cv = lookup_xpm_color( line[j] );
415                   fprintf( fpout, "%c", cv->xchar );
416                 }
417           fprintf( fpout, "\",\n" );
418         }
419
420   fprintf( fpout, "};\n" );
421   
422   free( lump );
423   free( line );
424   fclose( fpout );
425 }
426
427 /* The order of the pieces in the ZIICS piece file (from SHOWSETS.PAS) */
428 char *pieces = "prkqbn";
429 char *pname[] = { "Pawn", "Rook", "King", "Queen", "Bishop", "Knight" };
430
431 /* The suborder - Light/Light, Light/Dark, etc. */
432 char *prefixes[] = { "ll", "ld", "dl", "dd" };
433
434 int process_file_xim( filename )
435          char *filename;
436 {
437   int w, h, piece, kind, c;
438   int nr_pieces = 6;
439   int nr_kinds = 4;
440   FILE *fp;
441   char buf[100];
442
443   src_name = filename;
444   
445   fp = fopen( filename, "rb" );
446   if ( !fp )
447         fatal( "Can't open input file." );
448   
449   /* Header is two ints -- Width then Height, x86 format */
450   c = fgetc( fp );
451   w = (fgetc(fp) << 8) | c;
452
453   c = fgetc( fp );
454   h = (fgetc(fp) << 8) | c;
455   
456   ++w; ++h;
457
458   if ( w != h )
459         {
460           printf("ERROR: Can only convert square pieces.\n");
461           printf("       (This set is %dx%d)\n", w, h );
462           exit(1);
463         }
464
465   printf("Creating XIM files...\n");
466   printf("File: %s, W=%d, H=%d\n", filename, w, h );
467   fseek( fp, 0, SEEK_SET );
468   
469   /* Write .XIM files */
470   for( piece = 0; piece < nr_pieces; ++piece )
471         {
472           printf("%s ", pname[piece] );
473           
474           for( kind = 0; kind < nr_kinds; ++kind )
475                 {
476                   printf( "." );
477                   /* Form output filename -- <piece><kind><size>.xim */
478                   sprintf(buf, "%c%s%d.xim", pieces[piece], prefixes[kind], w);
479                   create_piece_xim( buf, fp, w, h );
480                 }
481           printf("\n");
482         }
483
484   /* Write the light & dark squares */
485   sprintf( buf, "lsq%d.xim", w );
486   printf("Light Square" );
487   create_piece_xim( buf, fp, w, h );
488
489   sprintf( buf, "dsq%d.xim", w );
490   printf("\nDark Square" );
491   create_piece_xim( buf, fp, w, h );  
492   printf("\n");
493   
494   printf("Successfully converted!!\n" );
495
496   fclose( fp );
497   
498   return 0;
499 }
500
501 int process_file_xpm( filename )
502          char *filename;
503 {
504   int w, h, piece, kind, c;
505   int nr_pieces = 6;
506   int nr_kinds = 4;
507   FILE *fp;
508   char buf[100];
509
510   src_name = filename;
511   
512   fp = fopen( filename, "rb" );
513   if ( !fp )
514         fatal( "Can't open input file." );
515   
516   /* Header is two ints -- Width then Height, x86 format */
517   c = fgetc( fp );
518   w = (fgetc(fp) << 8) | c;
519
520   c = fgetc( fp );
521   h = (fgetc(fp) << 8) | c;
522   
523   ++w; ++h;
524
525   if ( w != h )
526         {
527           printf("ERROR: Can only convert square pieces.\n");
528           printf("       (This set is %dx%d)\n", w, h );
529           exit(1);
530         }
531   
532   printf("Creating XPM files...\n");
533   printf("File: %s, W=%d, H=%d\n", filename, w, h );
534   fseek( fp, 0, SEEK_SET );
535   
536   /* Write .XPM files */
537   for( piece = 0; piece < nr_pieces; ++piece )
538         {
539           printf("%s ", pname[piece] );
540           
541           for( kind = 0; kind < nr_kinds; ++kind )
542                 {
543                   printf( "." );
544                   /* Form output filename -- <piece><kind><size>.xpm */
545                   sprintf(buf, "%c%s%d.xpm", pieces[piece], prefixes[kind], w);
546                   create_piece_xpm( buf, fp, w, h );
547                 }
548           printf("\n");
549         }
550
551   /* Write the light & dark squares */
552   sprintf( buf, "lsq%d.xpm", w );
553   printf("Light Square" );
554   create_piece_xpm( buf, fp, w, h );
555
556   sprintf( buf, "dsq%d.xpm", w );
557   printf("\nDark Square" );
558   create_piece_xpm( buf, fp, w, h );  
559   printf("\n");
560   
561   printf("Successfully converted!!\n" );
562
563   fclose( fp );
564   
565   return 0;
566 }
567
568 int main( argc, argv )
569          int argc;
570          char *argv[];
571 {
572   int i;
573   
574   if ( argc < 2 )
575         {
576           printf("ZIC2XPM 2.01 - by Frank McIngvale (frankm@hiwaay.net)\n");
577           printf("Copyright (C) 1996 Free Software Foundation, Inc.\n\n");
578           printf("Usage: zic2xpm file1 [file2 ...]\n\n");
579           printf("  Splits each file (ZIICS piece files) into 26 XPM & XIM files\n");
580           printf("  suitable for use in XBoard 3.5 or later.\n");
581           printf("\n* ZIICS is a copyrighted work of Andy McFarland (Zek on ICC) *\n");
582           return 1;
583         }
584
585
586   setbuf( stdout, NULL );
587   
588   for( i=1; i<argc; ++i )
589         {
590           process_file_xpm( argv[i] );
591           process_file_xim( argv[i] );
592         }
593   
594   fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n",
595           "NOTICE: The piece images distributed with ZIICS are",
596           "    copyrighted works of their original creators.  Images",
597           "    converted with zic2xpm may not be redistributed without",
598           "    the permission of the copyright holders.  Do not contact",
599           "    the authors of zic2xpm or of ZIICS itself to request",
600           "    permission.");
601   return 0;
602 }