/* Converts a 24-bit PCX file to SNES background tiles */ /* It is "compressed", that is it detects identical tiles */ /* instead of using just a plain linear tilemap */ #include /* For FILE I/O */ #include /* For strncmp */ #include /* for open() */ #include /* for lseek() */ #include /* for file modes */ #include /* exit() */ /* Horizontally flip the bits in a byte */ static unsigned int hflip_byte(unsigned int byte) { int new_byte=0,i; for(i=0;i<8;i++) { new_byte<<=1; if (byte&(1<>3)&0x1f; g2=(g>>3)&0x1f; b2=(b>>3)&0x1f; bgr=(b2<<10)|(g2<<5)|r2; return bgr; } static char symbol_name[BUFSIZ]="temp"; #define MAX_TILE_X 64 #define MAX_TILE_Y 64 #define MAX_PLANES_DIV2 4 #define Y_SIZE 8 static unsigned short tilemap[MAX_TILE_X*MAX_TILE_Y]; /* 2k */ static unsigned short tiledata[MAX_TILE_X*MAX_TILE_Y][Y_SIZE][MAX_PLANES_DIV2]; static unsigned short tiledata_hflip[MAX_TILE_X*MAX_TILE_Y][Y_SIZE][MAX_PLANES_DIV2]; static unsigned short temp_tile[Y_SIZE][MAX_PLANES_DIV2]; static int total_tiles=0; static int compressed_tiles=0; static int max_planes=8; static int palette=0; /* File already open */ static int vmwLoadPCX(int pcx_fd) { int debug=1,bpp; int x,y; int i,numacross,planes=0; int xsize,ysize,plane; int xmin,ymin,xmax,ymax,version; unsigned char pcx_header[128]; unsigned char temp_byte; /*************** DECODE THE HEADER *************************/ read(pcx_fd,&pcx_header,128); xmin=(pcx_header[5]<<8)+pcx_header[4]; ymin=(pcx_header[7]<<8)+pcx_header[6]; xmax=(pcx_header[9]<<8)+pcx_header[8]; ymax=(pcx_header[11]<<8)+pcx_header[10]; version=pcx_header[1]; bpp=pcx_header[3]; if (debug) { fprintf(stderr,"Manufacturer: "); if (pcx_header[0]==10) fprintf(stderr,"Zsoft\n"); else fprintf(stderr,"Unknown %i\n",pcx_header[0]); fprintf(stderr,"Version: "); switch(version) { case 0: fprintf(stderr,"2.5\n"); break; case 2: fprintf(stderr,"2.8 w palette\n"); break; case 3: fprintf(stderr,"2.8 w/o palette\n"); break; case 4: fprintf(stderr,"Paintbrush for Windows\n"); break; case 5: fprintf(stderr,"3.0+\n"); break; default: fprintf(stderr,"Unknown %i\n",version); } fprintf(stderr,"Encoding: "); if (pcx_header[2]==1) fprintf(stderr,"RLE\n"); else fprintf(stderr,"Unknown %i\n",pcx_header[2]); fprintf(stderr,"BitsPerPixelPerPlane: %i\n",bpp); fprintf(stderr,"File goes from %i,%i to %i,%i\n",xmin,ymin,xmax,ymax); fprintf(stderr,"Horizontal DPI: %i\n",(pcx_header[13]<<8)+pcx_header[12]); fprintf(stderr,"Vertical DPI: %i\n",(pcx_header[15]<<8)+pcx_header[14]); fprintf(stderr,"Number of colored planes: %i\n",pcx_header[65]); fprintf(stderr,"Bytes per line: %i\n",(pcx_header[67]<<8)+pcx_header[66]); fprintf(stderr,"Palette Type: %i\n",(pcx_header[69]<<8)+pcx_header[68]); fprintf(stderr,"Hscreen Size: %i\n",(pcx_header[71]<<8)+pcx_header[70]); fprintf(stderr,"Vscreen Size: %i\n",(pcx_header[73]<<8)+pcx_header[72]); } planes=pcx_header[65]; xsize=((xmax-xmin)+1); ysize=((ymax-ymin)+1); char *output; output=calloc((xsize*ysize),sizeof(unsigned int)); if (output==NULL) return -1; x=0; y=0; while(y> plane); plane1|=(((output[offset])&(1<<(plane+1)) )>>(plane+1)); } temp_tile[y][i]=(plane1<<8)|plane0; } } int v=0,h=0,o=0,pal=palette,found_tile=0,found=0,match; /* see if the new tile matches an existing one */ for(i=0;i>8)&0xff)<<8) | hflip_byte( temp_tile[y][plane]&0xff); } } compressed_tiles++; } else { } tilemap[total_tiles]= ( ((v&1)<<15) | ((h&1)<<14) | ((o&1)<<13) | ((pal&7)<<10) | (found_tile&0x3ff)); total_tiles++; } } fprintf(stderr,"Total tiles: %d Compressed tiles %d\n", total_tiles,compressed_tiles); fprintf(stderr,"Original size\t= %d bytes\n",total_tiles*2*8*4); fprintf(stderr,"Compressed size\t= %d bytes\n", (compressed_tiles*2*8*4)+(total_tiles*2)); printf("%s_tilemap:\n",symbol_name); for(x=0;x>15)&1, (tilemap[x]>>14)&1, (tilemap[x]>>13)&1, (tilemap[x]>>10)&7, (tilemap[x])&0x3ff); } printf("%s_palette:\n",symbol_name); /* read in palette */ read(pcx_fd,&temp_byte,1); if (temp_byte!=12) { fprintf(stderr,"Error! No palette found!\n"); } else { int r,g,b; for(i=0;i<(1<1) { strncpy(symbol_name,argv[1],BUFSIZ); } if (argc>2) { max_planes=atoi(argv[2]); } if (argc>3) { palette=atoi(argv[3]); } /* read from stdin */ result=vmwLoadPCX(fileno(stdin)); if (result<0) { fprintf(stderr,"Error reading PCX from stdin\n"); exit(1); } return 0; }