1 /* SCCS Id: @(#)txt2iff.c 3.2 95/07/28 */
2 /* Copyright (c) 1995 by Gregg Wonderly, Naperville, Illinois */
3 /* NetHack may be freely redistributed. See license for details. */
12 #include <dos/dosextens.h>
13 #include <graphics/gfx.h>
14 #include <graphics/gfxbase.h>
15 #include <graphics/view.h>
16 #include <libraries/iffparse.h>
17 #include <libraries/dos.h>
18 #include <clib/dos_protos.h>
19 #include <clib/iffparse_protos.h>
21 # include <proto/exec.h>
22 # include <proto/iffparse.h>
23 # include <proto/dos.h>
26 void panic(const char *);
27 void map_colors(void);
28 int BestMatch(int, int, int);
30 extern pixval ColorMap[3][MAXCOLORMAPSIZE];
31 extern int colorsinmap;
35 * This program carries forth the assumption that the colormaps in all
36 * of the .txt files are the same. This is a bug.
45 * We are using a hybrid form of our own design which we call a BMAP (for
46 * bitmap) form. It is an ILBM with the bitmaps already deinterleaved,
47 * completely uncompressed.
48 * This speeds the loading of the images from the games point of view because it
49 * does not have to deinterleave and uncompress them.
51 #define ID_BMAP MAKE_ID( 'B', 'M', 'A', 'P' ) /* instead of ILBM */
52 #define ID_BMHD MAKE_ID( 'B', 'M', 'H', 'D' ) /* Same as ILBM */
53 #define ID_CAMG MAKE_ID( 'C', 'A', 'M', 'G' ) /* Same as ILBM */
54 #define ID_CMAP MAKE_ID( 'C', 'M', 'A', 'P' ) /* Same as ILBM */
55 #define ID_PDAT MAKE_ID( 'P', 'D', 'A', 'T' ) /* Extra data describing plane
56 * size due to graphics.library
57 * rounding requirements.
59 #define ID_PLNE MAKE_ID( 'P', 'L', 'N', 'E' ) /* The planes of the image */
65 struct Library *IFFParseBase;
70 /* BMHD from IFF documentation */
78 UWORD transparentColor;
79 UBYTE xAspect, yAspect;
80 WORD pageWidth, pageHeight;
87 pixel pixels[TILE_Y][TILE_X];
91 int findcolor( register pixel *pix );
92 void packwritebody( pixel (*tile)[TILE_X], char **planes, int tileno );
98 fprintf( stderr, "ERROR: %s\n", str );
102 * This array maps the image colors to the amiga's first 16 colors. The colors
103 * are reordered to help with maintaining dripen settings.
105 int colrmap[] = { 0, 6, 9, 15, 4, 10, 2, 3, 5, 11, 7, 13, 8, 1, 14, 12 };
107 /* How many tiles fit across and down. */
110 #define ROWS ((tiles + COLS-1) / COLS)
112 main( int argc, char **argv )
124 long pbytes; /* Bytes of data in a plane */
127 struct IFFHandle *iff;
128 long camg = HIRES|LACE;
133 fprintf(stderr, "Usage: %s source destination\n", argv[0]);
137 #if defined(_DCC) || defined(__GNUC__)
138 IFFParseBase = OpenLibrary( "iffparse.library", 0 );
139 if( !IFFParseBase ) {
140 error( "unable to open iffparse.library" );
145 /* First, count the files in the file */
146 if( fopen_text_file( argv[1], "r" ) != TRUE )
153 i = colorsinmap-1; /*IFFScreen.Colors - 1; */
160 planes = malloc( nplanes * sizeof( char * ) );
163 error( "can not allocate planes pointer" );
167 while( read_text_tile( pixels ) == TRUE )
171 IFFScreen.Width = COLS * TILE_X;
172 IFFScreen.Height = ROWS * TILE_Y;
174 pbytes = (COLS * ROWS * TILE_X + 15) / 16 * 2 * TILE_Y;
176 for( i = 0; i < nplanes; ++i )
178 planes[ i ] = calloc( 1, pbytes );
179 if( planes[ i ] == 0 )
181 error( "can not allocate planes pointer" );
186 /* Now, process it */
187 if( fopen_text_file( argv[1], "r" ) != TRUE )
196 error( "Can not allocate IFFHandle" );
200 iff->iff_Stream = Open( argv[2], MODE_NEWFILE );
201 if( !iff->iff_Stream )
203 error( "Can not open output file" );
208 OpenIFF( iff, IFFF_WRITE );
210 PushChunk( iff, ID_BMAP, ID_FORM, IFFSIZE_UNKNOWN );
212 bmhd.w = IFFScreen.Width;
213 bmhd.h = IFFScreen.Height;
216 bmhd.nPlanes = nplanes;
218 bmhd.compression = 0;
220 bmhd.transparentColor = 0;
223 bmhd.pageWidth = TILE_X;
224 bmhd.pageHeight = TILE_Y;
226 PushChunk( iff, ID_BMAP, ID_BMHD, sizeof( bmhd ) );
227 WriteChunkBytes( iff, &bmhd, sizeof( bmhd ) );
230 PushChunk( iff, ID_BMAP, ID_CAMG, sizeof( camg ) );
231 WriteChunkBytes( iff, &camg, sizeof( camg ) );
234 /* We need to reorder the colors to get reasonable default pens but
235 * we also need to know where some of the colors are - so go find out.
239 cmap = malloc( (colors = (1L<<nplanes)) * sizeof(AmiColorMap) );
240 for( i = 0; i < colors; ++i )
242 cmap[ colrmap[ i ] ].r = ColorMap[ CM_RED ][ i ];
243 cmap[ colrmap[ i ] ].g = ColorMap[ CM_GREEN ][ i ];
244 cmap[ colrmap[ i ] ].b = ColorMap[ CM_BLUE ][ i ];
247 PushChunk( iff, ID_BMAP, ID_CMAP, IFFSIZE_UNKNOWN );
248 for (i = 0; i < colors; ++i)
249 WriteChunkBytes(iff, &cmap[i], 3);
253 while( read_text_tile( pixels ) == TRUE )
255 packwritebody( pixels, planes, cnt );
257 printf( "%d..", cnt );
262 pdat.nplanes = nplanes;
263 pdat.pbytes = pbytes;
270 PushChunk( iff, ID_BMAP, ID_PDAT, IFFSIZE_UNKNOWN );
271 WriteChunkBytes( iff, &pdat, sizeof( pdat ) );
274 PushChunk( iff, ID_BMAP, ID_PLNE, IFFSIZE_UNKNOWN );
275 for( i = 0; i < nplanes; ++i )
276 WriteChunkBytes( iff, planes[i], pbytes );
280 Close( iff->iff_Stream );
283 printf( "\n%d tiles converted\n", cnt );
285 #if defined(_DCC) || defined(__GNUC__)
286 CloseLibrary( IFFParseBase );
291 findcolor( register pixel *pix )
295 for( i = 0; i < MAXCOLORMAPSIZE; ++i )
297 if( (pix->r == ColorMap[ CM_RED ][i] ) &&
298 (pix->g == ColorMap[ CM_GREEN ][i] ) &&
299 (pix->b == ColorMap[ CM_BLUE ][i] ) )
308 packwritebody( pixel (*tile)[TILE_X], char **planes, int tileno )
310 register int i, j, k, col;
312 register int across, rowbytes, xoff, yoff;
314 /* how many tiles fit across? */
317 /* How many bytes per pixel row */
318 rowbytes = ((IFFScreen.Width + 15)/16)*2;
320 /* How many bytes to account for y distance in planes */
321 yoff = ((tileno / across) * TILE_Y) * rowbytes;
323 /* How many bytes to account for x distance in planes */
324 xoff = (tileno % across) * (TILE_X/8);
326 /* For each row... */
327 for( i = 0; i < TILE_Y; ++i )
329 /* For each bitplane... */
330 for( k = 0; k < nplanes; ++k )
332 const int mask = 1l<<k;
334 /* Go across the row */
335 for( j = 0; j < TILE_X; j++ )
337 col = findcolor( &tile[ i ][ j ] );
340 error( "can not convert pixel color to colormap index" );
343 /* Shift the colors around to have good complements and to
344 * know the dripen values.
346 col = colrmap[ col ];
348 /* To top left corner of tile */
349 buf = planes[ k ] + yoff + xoff;
351 /*To i'th row of tile and the correct byte for the j'th pixel*/
352 buf += ( i * rowbytes ) + (j/8);
354 /* Or in the bit for this color */
355 *buf |= (((col & mask)!=0)<<(7-(j%8)));
364 * The incoming colormap is in arbitrary order and has arbitrary colors in
365 * it, but we need (some) specific colors in specific places. Find the
366 * colors we need and fix the mapping table to match.
368 /* What we are aiming for: */
375 #define CX_MAGENTA 10
378 /* we don't care about the rest, at least now */
379 /* should get: black white blue red grey greyblue ltgrey */
384 int tmpmap[]={0,2,3,7,4,5,8,9,10,11,13,15,12,1,14,6};
385 /* still not right: gray green yellow lost somewhere? */
389 for(x=0;x<16;x++)tmpmap[x]=-1; /* set not assigned yet */
391 tmpmap[BestMatch(0,0,0)] = CX_BLACK;
392 tmpmap[BestMatch(255,255,255)] = CX_WHITE;
393 tmpmap[BestMatch(255,0,0)] = CX_RED;
394 tmpmap[BestMatch(0,255,0)] = CX_GREEN;
395 tmpmap[BestMatch(0,0,255)] = CX_BLUE;
397 /* clean up the rest */
400 if(tmpmap[y]==x)goto outer_cont;
406 if(y==16)panic("too many colors?");
410 if(tmpmap[y]==-1)panic("lost color?");
414 printf("final: c[%d]=%d (target: %d)\n",x,tmpmap[x],colrmap[x]);
416 colrmap[x]=tmpmap[x];
424 int bestrate=99999999L;
426 int rr = r-ColorMap[CM_RED][x];
427 int gg = g-ColorMap[CM_GREEN][x];
428 int bb = b-ColorMap[CM_BLUE][x];
429 int rate = rr*rr + gg*gg + bb*bb;
436 printf("map (%d,%d,%d) -> %d (error=%d)\n",r,g,b,bestslot,bestrate);
443 alloc( unsigned int n )
445 long *ret = malloc( n );
447 error("Can't allocate memory");
454 panic(const char *msg){
455 fprintf(stderr,"PANIC: %s\n",msg);