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