*** empty log message ***
This commit is contained in:
353
sys/amiga/xpm2iff.c
Normal file
353
sys/amiga/xpm2iff.c
Normal file
@@ -0,0 +1,353 @@
|
||||
/* SCCS Id: @(#)xpm2iff.c 3.2 95/08/04 */
|
||||
/* Copyright (c) 1995 by Gregg Wonderly, Naperville, Illinois */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "tile.h"
|
||||
|
||||
#include <dos/dos.h>
|
||||
#include <dos/dos.h>
|
||||
#include <dos/dosextens.h>
|
||||
#include <graphics/gfx.h>
|
||||
#include <graphics/gfxbase.h>
|
||||
#include <graphics/view.h>
|
||||
#include <libraries/iffparse.h>
|
||||
#include <libraries/dos.h>
|
||||
#ifndef _DCC
|
||||
# include <proto/iffparse.h>
|
||||
# include <proto/dos.h>
|
||||
# include <proto/exec.h>
|
||||
#endif
|
||||
|
||||
struct xpmscreen {
|
||||
int Width;
|
||||
int Height;
|
||||
int Colors;
|
||||
int ColorResolution;
|
||||
int Background;
|
||||
int AspectRatio;
|
||||
int Interlace;
|
||||
int BytesPerRow;
|
||||
} XpmScreen;
|
||||
|
||||
/* translation table from xpm characters to RGB and colormap slots */
|
||||
struct Ttable {
|
||||
char flag;
|
||||
char r,g,b;
|
||||
int slot; /* output colortable index */
|
||||
}ttable[256];
|
||||
|
||||
pixval ColorMap[3][MAXCOLORMAPSIZE];
|
||||
int colorsinmap;
|
||||
|
||||
/*
|
||||
* We are using a hybrid form of our own design which we call a BMAP (for
|
||||
* bitmap) form. It is an ILBM with the bitmaps already deinterleaved,
|
||||
* completely uncompressed.
|
||||
* This speeds the loading of the images from the games point of view because it
|
||||
* does not have to deinterleave and uncompress them.
|
||||
*/
|
||||
#define ID_BMAP MAKE_ID( 'B', 'M', 'A', 'P' ) /* instead of ILBM */
|
||||
#define ID_BMHD MAKE_ID( 'B', 'M', 'H', 'D' ) /* Same as ILBM */
|
||||
#define ID_CAMG MAKE_ID( 'C', 'A', 'M', 'G' ) /* Same as ILBM */
|
||||
#define ID_CMAP MAKE_ID( 'C', 'M', 'A', 'P' ) /* Same as ILBM */
|
||||
#define ID_PDAT MAKE_ID( 'P', 'D', 'A', 'T' ) /* Extra data describing plane
|
||||
* size due to graphics.library
|
||||
* rounding requirements.
|
||||
*/
|
||||
#define ID_PLNE MAKE_ID( 'P', 'L', 'N', 'E' ) /* The planes of the image */
|
||||
|
||||
int nplanes;
|
||||
|
||||
/* BMHD from IFF documentation */
|
||||
typedef struct {
|
||||
UWORD w, h;
|
||||
WORD x, y;
|
||||
UBYTE nPlanes;
|
||||
UBYTE masking;
|
||||
UBYTE compression;
|
||||
UBYTE reserved1;
|
||||
UWORD transparentColor;
|
||||
UBYTE xAspect, yAspect;
|
||||
WORD pageWidth, pageHeight;
|
||||
} BitMapHeader;
|
||||
|
||||
typedef struct {
|
||||
UBYTE r, g, b;
|
||||
} AmiColorMap;
|
||||
|
||||
pixel pixels[TILE_Y][TILE_X];
|
||||
AmiColorMap *cmap;
|
||||
|
||||
void
|
||||
error( char *str )
|
||||
{
|
||||
fprintf( stderr, "ERROR: %s\n", str );
|
||||
}
|
||||
|
||||
char **planes;
|
||||
|
||||
main( int argc, char **argv )
|
||||
{
|
||||
int colors;
|
||||
struct {
|
||||
long nplanes;
|
||||
long pbytes;
|
||||
long across;
|
||||
long down;
|
||||
long npics;
|
||||
long xsize;
|
||||
long ysize;
|
||||
} pdat;
|
||||
long pbytes; /* Bytes of data in a plane */
|
||||
int i, cnt;
|
||||
BitMapHeader bmhd;
|
||||
struct IFFHandle *iff;
|
||||
long camg = HIRES|LACE;
|
||||
int tiles=0;
|
||||
int index;
|
||||
|
||||
#if defined(_DCC) || defined (__GNUC__)
|
||||
IFFParseBase = OpenLibrary( "iffparse.library", 0 );
|
||||
if( !IFFParseBase ) {
|
||||
error( "unable to open iffparse.library" );
|
||||
exit( 1 );
|
||||
}
|
||||
#endif
|
||||
|
||||
if( fopen_xpm_file( argv[1], "r" ) != TRUE )
|
||||
{
|
||||
perror( argv[1] );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
nplanes = 0;
|
||||
i = XpmScreen.Colors - 1;
|
||||
while( i != 0 )
|
||||
{
|
||||
nplanes++;
|
||||
i >>= 1;
|
||||
}
|
||||
|
||||
planes = malloc( nplanes * sizeof( char * ) );
|
||||
if( planes == 0 )
|
||||
{
|
||||
error( "can not allocate planes pointer" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
XpmScreen.BytesPerRow = ((XpmScreen.Width + 15)/16)*2;
|
||||
pbytes = XpmScreen.BytesPerRow * XpmScreen.Height;
|
||||
for( i = 0; i < nplanes; ++i )
|
||||
{
|
||||
planes[ i ] = malloc( pbytes );
|
||||
if( planes[ i ] == 0 )
|
||||
{
|
||||
error( "can not allocate planes pointer" );
|
||||
exit( 1 );
|
||||
}
|
||||
memset( planes[i], 0, pbytes );
|
||||
}
|
||||
|
||||
iff = AllocIFF();
|
||||
if( !iff )
|
||||
{
|
||||
error( "Can not allocate IFFHandle" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
iff->iff_Stream = Open( argv[2], MODE_NEWFILE );
|
||||
if( !iff->iff_Stream )
|
||||
{
|
||||
error( "Can not open output file" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
InitIFFasDOS( iff );
|
||||
OpenIFF( iff, IFFF_WRITE );
|
||||
|
||||
PushChunk( iff, ID_BMAP, ID_FORM, IFFSIZE_UNKNOWN );
|
||||
|
||||
bmhd.w = XpmScreen.Width;
|
||||
bmhd.h = XpmScreen.Height;
|
||||
bmhd.x = 0;
|
||||
bmhd.y = 0;
|
||||
bmhd.nPlanes = nplanes;
|
||||
bmhd.masking = 0;
|
||||
bmhd.compression = 0;
|
||||
bmhd.reserved1 = 0;
|
||||
bmhd.transparentColor = 0;
|
||||
bmhd.xAspect = 100;
|
||||
bmhd.yAspect = 100;
|
||||
bmhd.pageWidth = 0; /* not needed for this program */
|
||||
bmhd.pageHeight = 0; /* not needed for this program */
|
||||
|
||||
PushChunk( iff, ID_BMAP, ID_BMHD, sizeof( bmhd ) );
|
||||
WriteChunkBytes( iff, &bmhd, sizeof( bmhd ) );
|
||||
PopChunk( iff );
|
||||
|
||||
PushChunk( iff, ID_BMAP, ID_CAMG, sizeof( camg ) );
|
||||
WriteChunkBytes( iff, &camg, sizeof( camg ) );
|
||||
PopChunk( iff );
|
||||
|
||||
#define SCALE(x) (x)
|
||||
cmap = malloc( (colors = (1L<<nplanes)) * sizeof(AmiColorMap) );
|
||||
if(cmap == 0){
|
||||
error("Can't allocate color map");
|
||||
exit(1);
|
||||
}
|
||||
for(index = 0; index<256; index++){
|
||||
if(ttable[index].flag){
|
||||
cmap[ttable[index].slot].r = SCALE(ttable[index].r);
|
||||
cmap[ttable[index].slot].g = SCALE(ttable[index].g);
|
||||
cmap[ttable[index].slot].b = SCALE(ttable[index].b);
|
||||
}
|
||||
}
|
||||
#undef SCALE
|
||||
|
||||
PushChunk( iff, ID_BMAP, ID_CMAP, IFFSIZE_UNKNOWN );
|
||||
WriteChunkBytes( iff, cmap, colors*sizeof(*cmap) );
|
||||
PopChunk( iff );
|
||||
|
||||
conv_image();
|
||||
|
||||
pdat.nplanes = nplanes;
|
||||
pdat.pbytes = pbytes;
|
||||
pdat.xsize = XpmScreen.Width;
|
||||
pdat.ysize = XpmScreen.Height;
|
||||
pdat.across = 0;
|
||||
pdat.down = 0;
|
||||
pdat.npics = 1;
|
||||
|
||||
PushChunk( iff, ID_BMAP, ID_PDAT, IFFSIZE_UNKNOWN );
|
||||
WriteChunkBytes( iff, &pdat, sizeof( pdat ) );
|
||||
PopChunk( iff );
|
||||
|
||||
PushChunk( iff, ID_BMAP, ID_PLNE, IFFSIZE_UNKNOWN );
|
||||
for( i = 0; i < nplanes; ++i )
|
||||
WriteChunkBytes( iff, planes[i], pbytes );
|
||||
PopChunk( iff );
|
||||
|
||||
CloseIFF( iff );
|
||||
Close( iff->iff_Stream );
|
||||
FreeIFF( iff );
|
||||
|
||||
#if defined(_DCC) || defined (__GNUC__)
|
||||
CloseLibrary( IFFParseBase );
|
||||
#endif
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
#define SETBIT(Plane, Plane_offset, Col, Value) \
|
||||
if(Value){ \
|
||||
planes[Plane][Plane_offset + (Col/8)] |= 1<<(7-(Col & 7)); \
|
||||
}
|
||||
|
||||
conv_image(){
|
||||
int row, col, planeno;
|
||||
|
||||
for(row = 0;row<XpmScreen.Height;row++){
|
||||
char *xb = xpmgetline();
|
||||
int plane_offset;
|
||||
if(xb==0)return;
|
||||
plane_offset = row*XpmScreen.BytesPerRow;
|
||||
for(col = 0;col<XpmScreen.Width;col++){
|
||||
int slot;
|
||||
int color = xb[col];
|
||||
if(!ttable[color].flag){
|
||||
fprintf(stderr, "Bad image data\n");
|
||||
}
|
||||
slot = ttable[color].slot;
|
||||
for(planeno = 0; planeno<nplanes; planeno++){
|
||||
SETBIT(planeno, plane_offset, col, slot & (1<<planeno));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long *
|
||||
alloc( unsigned int n )
|
||||
{
|
||||
long *ret = malloc( n );
|
||||
if(!ret){
|
||||
error("Can't allocate memory");
|
||||
exit(1);
|
||||
}
|
||||
return( ret );
|
||||
}
|
||||
|
||||
FILE *xpmfh = 0;
|
||||
char initbuf[200];
|
||||
char *xpmbuf = initbuf;
|
||||
|
||||
/* version 1. Reads the raw xpm file, NOT the compiled version. This is
|
||||
* not a particularly good idea but I don't have time to do the right thing
|
||||
* at this point, even if I was absolutely sure what that was. */
|
||||
fopen_xpm_file(const char *fn, const char *mode){
|
||||
int temp;
|
||||
char *xb;
|
||||
if(strcmp(mode, "r"))return FALSE; /* no choice now */
|
||||
if(xpmfh)return FALSE; /* one file at a time */
|
||||
xpmfh = fopen(fn, mode);
|
||||
if(!xpmfh)return FALSE; /* I'm hard to please */
|
||||
|
||||
/* read the header */
|
||||
xb = xpmgetline();
|
||||
if(xb == 0)return FALSE;
|
||||
if(4 != sscanf(xb,"%d %d %d %d",
|
||||
&XpmScreen.Width, &XpmScreen.Height,
|
||||
&XpmScreen.Colors, &temp))return FALSE; /* bad header */
|
||||
/* replace the original buffer with one big enough for
|
||||
* the real data
|
||||
*/
|
||||
/* XXX */
|
||||
xpmbuf = malloc(XpmScreen.Width * 2);
|
||||
if(!xpmbuf){
|
||||
error("Can't allocate line buffer");
|
||||
exit(1);
|
||||
}
|
||||
if(temp != 1)return FALSE; /* limitation of this code */
|
||||
|
||||
{
|
||||
/* read the colormap and translation table */
|
||||
int ccount = -1;
|
||||
while(ccount++ < (XpmScreen.Colors-1)){
|
||||
char index;
|
||||
int r, g, b;
|
||||
xb = xpmgetline();
|
||||
if(xb==0)return FALSE;
|
||||
if(4 != sscanf(xb,"%c c #%2x%2x%2x",&index,&r,&g,&b)){
|
||||
fprintf(stderr,"Bad color entry: %s\n",xb);
|
||||
return FALSE;
|
||||
}
|
||||
ttable[index].flag = 1; /* this color is valid */
|
||||
ttable[index].r = r;
|
||||
ttable[index].g = g;
|
||||
ttable[index].b = b;
|
||||
ttable[index].slot = ccount;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* This deserves better. Don't read it too closely - you'll get ill. */
|
||||
#define bufsz 2048
|
||||
char buf[bufsz];
|
||||
xpmgetline(){
|
||||
char *bp;
|
||||
do {
|
||||
if(fgets(buf, bufsz, xpmfh) == 0)return 0;
|
||||
} while(buf[0] != '"');
|
||||
/* strip off the trailing <",> if any */
|
||||
for(bp = buf;*bp;bp++);
|
||||
bp--;
|
||||
while(isspace(*bp))bp--;
|
||||
if(*bp==',')bp--;
|
||||
if(*bp=='"')bp--;
|
||||
bp++;
|
||||
*bp = '\0';
|
||||
|
||||
return &buf[1];
|
||||
}
|
||||
Reference in New Issue
Block a user