724 lines
18 KiB
C
724 lines
18 KiB
C
/*
|
|
* Copyright 2002-2010 Guillaume Cottenceau.
|
|
* Copyright 2015-2018 Paul Gardner-Stephen.
|
|
*
|
|
* This software may be freely redistributed under the terms
|
|
* of the X11 license.
|
|
*
|
|
*/
|
|
|
|
/* ============================================================= */
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <strings.h>
|
|
#include <stdarg.h>
|
|
|
|
#define PNG_DEBUG 3
|
|
#include <png.h>
|
|
|
|
/* ============================================================= */
|
|
|
|
char *vhdl_prefix=
|
|
"library IEEE;\n"
|
|
"use IEEE.STD_LOGIC_1164.ALL;\n"
|
|
"use ieee.numeric_std.all;\n"
|
|
"use work.debugtools.all;\n"
|
|
"\n"
|
|
"--\n"
|
|
"entity charrom is\n"
|
|
"port (Clk : in std_logic;\n"
|
|
" address : in integer range 0 to 4095;\n"
|
|
" -- chip select, active low \n"
|
|
" cs : in std_logic;\n"
|
|
" data_o : out std_logic_vector(7 downto 0);\n"
|
|
"\n"
|
|
" writeclk : in std_logic;\n"
|
|
" -- Yes, we do have a write enable, because we allow modification of ROMs\n"
|
|
" -- in the running machine, unless purposely disabled. This gives us\n"
|
|
" -- something like the WOM that the Amiga had.\n"
|
|
" writecs : in std_logic;\n"
|
|
" we : in std_logic;\n"
|
|
" writeaddress : in unsigned(11 downto 0);\n"
|
|
" data_i : in std_logic_vector(7 downto 0)\n"
|
|
" );\n"
|
|
"end charrom;\n"
|
|
"\n"
|
|
"architecture Behavioral of charrom is\n"
|
|
"\n"
|
|
"-- 4K x 8bit pre-initialised RAM for character ROM\n"
|
|
"\n"
|
|
"type ram_t is array (0 to 4095) of std_logic_vector(7 downto 0);\n"
|
|
"signal ram : ram_t := (\n"
|
|
"\n";
|
|
|
|
char *vhdl_suffix=
|
|
");\n"
|
|
"\n"
|
|
"begin\n"
|
|
"\n"
|
|
"--process for read and write operation.\n"
|
|
"PROCESS(Clk,ram,writeclk)\n"
|
|
"BEGIN\n"
|
|
"\n"
|
|
" if(rising_edge(writeClk)) then \n"
|
|
" if writecs='1' then\n"
|
|
" if(we='1') then\n"
|
|
" ram(to_integer(writeaddress)) <= data_i;\n"
|
|
" end if;\n"
|
|
" end if;\n"
|
|
" data_o <= ram(address);\n"
|
|
" end if;\n"
|
|
"END PROCESS;\n"
|
|
"\n"
|
|
"end Behavioral;\n";
|
|
|
|
/* ============================================================= */
|
|
|
|
int x, y;
|
|
|
|
int width, height;
|
|
png_byte color_type;
|
|
png_byte bit_depth;
|
|
|
|
png_structp png_ptr;
|
|
png_infop info_ptr;
|
|
int number_of_passes;
|
|
png_bytep * row_pointers;
|
|
|
|
FILE *infile;
|
|
FILE *outfile;
|
|
|
|
/* ============================================================= */
|
|
|
|
void abort_(const char * s, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, s);
|
|
vfprintf(stderr, s, args);
|
|
fprintf(stderr, "\n");
|
|
va_end(args);
|
|
abort();
|
|
}
|
|
|
|
/* ============================================================= */
|
|
|
|
void read_png_file(char* file_name)
|
|
{
|
|
unsigned char header[8]; // 8 is the maximum size that can be checked
|
|
size_t readResult;
|
|
|
|
/* open file and test for it being a png */
|
|
infile = fopen(file_name, "rb");
|
|
if (infile == NULL)
|
|
abort_("[read_png_file] File %s could not be opened for reading", file_name);
|
|
|
|
readResult = fread(header, 1, 8, infile);
|
|
if (readResult != 8)
|
|
abort_("[read_png_file] File %s could not be read", file_name);
|
|
if (png_sig_cmp(header, 0, 8))
|
|
abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);
|
|
|
|
/* initialize stuff */
|
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
|
|
if (!png_ptr)
|
|
abort_("[read_png_file] png_create_read_struct failed");
|
|
|
|
info_ptr = png_create_info_struct(png_ptr);
|
|
if (!info_ptr)
|
|
abort_("[read_png_file] png_create_info_struct failed");
|
|
|
|
if (setjmp(png_jmpbuf(png_ptr)))
|
|
abort_("[read_png_file] Error during init_io");
|
|
|
|
png_init_io(png_ptr, infile);
|
|
png_set_sig_bytes(png_ptr, 8);
|
|
|
|
// Convert palette to RGB values
|
|
png_set_expand(png_ptr);
|
|
|
|
png_read_info(png_ptr, info_ptr);
|
|
|
|
width = png_get_image_width(png_ptr, info_ptr);
|
|
height = png_get_image_height(png_ptr, info_ptr);
|
|
color_type = png_get_color_type(png_ptr, info_ptr);
|
|
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
|
|
|
printf("Input-file is: width=%d, height=%d.\n", width, height);
|
|
|
|
number_of_passes = png_set_interlace_handling(png_ptr);
|
|
png_read_update_info(png_ptr, info_ptr);
|
|
|
|
/* read file */
|
|
if (setjmp(png_jmpbuf(png_ptr)))
|
|
abort_("[read_png_file] Error during read_image");
|
|
|
|
row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
|
|
for (y=0; y<height; y++)
|
|
row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));
|
|
|
|
png_read_image(png_ptr, row_pointers);
|
|
|
|
if (infile != NULL) {
|
|
fclose(infile);
|
|
infile = NULL;
|
|
}
|
|
|
|
printf("Input-file is read and now closed\n");
|
|
}
|
|
|
|
/* ============================================================= */
|
|
|
|
struct rgb {
|
|
int r;
|
|
int g;
|
|
int b;
|
|
};
|
|
|
|
struct rgb palette[2560];
|
|
int palette_first=16;
|
|
int palette_index=16; // only use upper half of palette
|
|
|
|
int palette_lookup(int r,int g, int b)
|
|
{
|
|
int i;
|
|
|
|
// Do we know this colour already?
|
|
for(i=palette_first;i<palette_index;i++) {
|
|
if (r==palette[i].r&&g==palette[i].g&&b==palette[i].b) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
// new colour
|
|
if (palette_index>255) {
|
|
fprintf(stderr,"Too many colours in image: Must be < 256, now up to %d\n",
|
|
palette_index);
|
|
}
|
|
if (palette_index>2559) exit(-1);
|
|
|
|
// allocate it
|
|
palette[palette_index].r=r;
|
|
palette[palette_index].g=g;
|
|
palette[palette_index].b=b;
|
|
return palette_index++;
|
|
|
|
}
|
|
|
|
unsigned char nyblswap(unsigned char in)
|
|
{
|
|
return ((in&0xf)<<4)+((in&0xf0)>>4);
|
|
}
|
|
|
|
void process_file(int mode, char *outputfilename)
|
|
{
|
|
int multiplier=-1;
|
|
if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB)
|
|
multiplier=3;
|
|
|
|
if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGBA)
|
|
multiplier=4;
|
|
|
|
if (multiplier==-1) {
|
|
fprintf(stderr,"Could not convert file to RGB or RGBA\n");
|
|
}
|
|
|
|
outfile=fopen(outputfilename,"w");
|
|
if (outfile == NULL) {
|
|
// could not open output file, so close all and exit
|
|
if (infile != NULL) {
|
|
fclose(infile);
|
|
infile = NULL;
|
|
}
|
|
abort_("[process_file] File %s could not be opened for writing", outputfilename);
|
|
}
|
|
|
|
|
|
/* ============================ */
|
|
|
|
if (mode==0) {
|
|
printf("mode=0 (logo)\n");
|
|
// Logo mode
|
|
|
|
// Pre-load in C64 palette, so that those colours can be re-used if required
|
|
|
|
palette[0]=(struct rgb){.r=0,.g=0,.b=0};
|
|
palette[1]=(struct rgb){.r=0xff,.g=0xff,.b=0xff};
|
|
palette[2]=(struct rgb){.r=0xab,.g=0x31,.b=0x26};
|
|
palette[3]=(struct rgb){.r=0x66,.g=0xda,.b=0xff};
|
|
palette[4]=(struct rgb){.r=0xbb,.g=0x3f,.b=0xb8};
|
|
palette[5]=(struct rgb){.r=0x55,.g=0xce,.b=0x58};
|
|
palette[6]=(struct rgb){.r=0x1d,.g=0x0e,.b=0x97};
|
|
palette[7]=(struct rgb){.r=0xea,.g=0xf5,.b=0x7c};
|
|
palette[8]=(struct rgb){.r=0xb9,.g=0x74,.b=0x18};
|
|
palette[9]=(struct rgb){.r=0x78,.g=0x73,.b=0x00};
|
|
palette[10]=(struct rgb){.r=0xdd,.g=0x93,.b=0x87};
|
|
palette[11]=(struct rgb){.r=0x5b,.g=0x5b,.b=0x5b};
|
|
palette[12]=(struct rgb){.r=0x8b,.g=0x8b,.b=0x8b};
|
|
palette[13]=(struct rgb){.r=0xb0,.g=0xf4,.b=0xac};
|
|
palette[14]=(struct rgb){.r=0xaa,.g=0x9d,.b=0xef};
|
|
palette[15]=(struct rgb){.r=0xb8,.g=0xb8,.b=0xb8};
|
|
|
|
|
|
for (y=0; y<height; y++) {
|
|
png_byte* row = row_pointers[y];
|
|
for (x=0; x<width; x++) {
|
|
png_byte* ptr = &(row[x*multiplier]);
|
|
int r,g,b;
|
|
if (ptr)
|
|
{ r=ptr[0]; g=ptr[1]; b=ptr[2]; // a=ptr[3];
|
|
} else { r=0; g=0; b=0; }
|
|
|
|
int c=palette_lookup(r,g,b);
|
|
|
|
if (c>255) printf("Too many colours at (%d,%d)\n",x,y);
|
|
|
|
/* work out where in logo file it must be written.
|
|
image is made of 8x8 blocks. So every 8 pixels across increases address
|
|
by 64, and every 8 pixels down increases pixel count by (64*8), and every
|
|
single pixel down increases address by 8.
|
|
*/
|
|
int address=0;
|
|
address+=0x300; // space for palettes
|
|
address+=(x&7)+(y&7)*8;
|
|
address+=(x>>3)*64;
|
|
// if (size==SIZE_LOGO)
|
|
address+=(y>>3)*64*(width/8);
|
|
// else
|
|
// address+=(y>>3)*64*40;
|
|
|
|
fseek(outfile,address,SEEK_SET);
|
|
int n=fwrite(&c,1,1,outfile);
|
|
if (n!=1) {
|
|
fprintf(stderr,"Could not write pixel (%d,%d) @ $%x\n",x,y,address);
|
|
if (outfile != NULL) {
|
|
fclose(outfile);
|
|
outfile = NULL;
|
|
}
|
|
exit(-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
fprintf(stderr,"Writing out palette of %d values\n",palette_index-palette_first);
|
|
for(int i=0;i<256;i++){
|
|
int address;
|
|
unsigned char c;
|
|
int v;
|
|
|
|
address=i+0x000;
|
|
v=palette[i].r;
|
|
c=(v>>4)|((v&0xf)<<4);
|
|
fseek(outfile,address,SEEK_SET);
|
|
fwrite(&c,1,1,outfile);
|
|
|
|
address=i+0x100;
|
|
v=palette[i].g;
|
|
c=(v>>4)|((v&0xf)<<4);
|
|
fseek(outfile,address,SEEK_SET);
|
|
fwrite(&c,1,1,outfile);
|
|
|
|
address=i+0x200;
|
|
v=palette[i].b;
|
|
c=(v>>4)|((v&0xf)<<4);
|
|
fseek(outfile,address,SEEK_SET);
|
|
fwrite(&c,1,1,outfile);
|
|
}
|
|
|
|
|
|
if (outfile != NULL) {
|
|
fclose(outfile);
|
|
outfile = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/* ============================ */
|
|
if (mode==1) {
|
|
|
|
unsigned char first_half[1024];
|
|
|
|
printf("mode=1 (charrom)\n");
|
|
// charrom mode
|
|
|
|
int vhdl_mode=1;
|
|
if (!strstr(outputfilename,".vhdl")) vhdl_mode=0;
|
|
|
|
int bytes=0;
|
|
if (vhdl_mode) fprintf(outfile,"%s",vhdl_prefix);
|
|
if (width!=8) {
|
|
fprintf(stderr,"Fonts must be 8 pixels wide\n");
|
|
}
|
|
|
|
int spots[8][8];
|
|
int charsets;
|
|
|
|
|
|
// 4KB = 2x 256 char = 2KB charsets
|
|
for(charsets = 0 ; charsets<2 ; charsets++) {
|
|
if (bytes>=4096) break;
|
|
fprintf(stdout,"yheight=%d\n",height);
|
|
for (y=0; y<height; y++) {
|
|
png_byte* row = row_pointers[y];
|
|
int byte=0;
|
|
int yy=y&7;
|
|
|
|
for (x=0; x<width; x++) {
|
|
png_byte* ptr = &(row[x*multiplier]);
|
|
int r=ptr[0],g=ptr[1],b=ptr[2]; //, a=ptr[3];
|
|
|
|
if (x<8) {
|
|
if (r>0x7f||g>0x7f||b>0x7f) {
|
|
byte|=(1<<(7-x));
|
|
spots[yy][x]=1;
|
|
} else spots[yy][x]=0;
|
|
}
|
|
}
|
|
fflush(stdout);
|
|
char comma = ',';
|
|
if (bytes<1024) {
|
|
first_half[bytes]=byte;
|
|
}
|
|
bytes++;
|
|
if (bytes>=4096) {
|
|
comma=' ';
|
|
}
|
|
if (vhdl_mode) fprintf(outfile,"x\"%02x\"%c",byte,comma);
|
|
else fputc(byte,outfile);
|
|
if (vhdl_mode) {
|
|
if ((y&7)==7) {
|
|
fprintf(outfile,"\n");
|
|
int yy;
|
|
for(yy=0;yy<8;yy++) {
|
|
fprintf(outfile,"-- [");
|
|
for(x=0;x<8;x++) {
|
|
if (spots[yy][x]) fprintf(outfile,"*"); else fprintf(outfile," ");
|
|
}
|
|
fprintf(outfile,"]\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fill in any missing bytes
|
|
if (bytes<2048) {
|
|
|
|
printf("Padding output file to 2048 after first charset\n");
|
|
|
|
if (vhdl_mode) {
|
|
fprintf(outfile,",\n");
|
|
|
|
for(;bytes<2048;bytes+=8) {
|
|
int reverse=bytes&0x400;
|
|
if (reverse) reverse=0xff;
|
|
|
|
fprintf(outfile,"x\"%02X\",x\"%02X\",x\"%02X\",x\"%02X\",x\"%02X\",x\"%02X\",x\"%02X\",x\"%02X\"%c -- 0x%03x (set %d, char 0x%02x)\n",
|
|
first_half[(bytes+0)&0x3ff]^reverse,
|
|
first_half[(bytes+1)&0x3ff]^reverse,
|
|
first_half[(bytes+2)&0x3ff]^reverse,
|
|
first_half[(bytes+3)&0x3ff]^reverse,
|
|
first_half[(bytes+4)&0x3ff]^reverse,
|
|
first_half[(bytes+5)&0x3ff]^reverse,
|
|
first_half[(bytes+6)&0x3ff]^reverse,
|
|
first_half[(bytes+7)&0x3ff]^reverse,
|
|
',',
|
|
bytes,bytes/2048,(bytes/8)&0xff);
|
|
|
|
fprintf(outfile,"\n");
|
|
int yy;
|
|
for(yy=0;yy<8;yy++) {
|
|
fprintf(outfile,"-- [");
|
|
for(x=0;x<8;x++) {
|
|
if ((first_half[(bytes+yy)&0x3ff]^reverse)&(1<<(7-x))) fprintf(outfile,"*"); else fprintf(outfile," ");
|
|
}
|
|
fprintf(outfile,"]\n");
|
|
}
|
|
}
|
|
} else {
|
|
// In raw mode, don't pad, or write charset twice
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
// Fill in any missing bytes
|
|
if (bytes<4096) {
|
|
|
|
printf("Padding output file to 4096\n");
|
|
|
|
if (vhdl_mode) {
|
|
fprintf(outfile,",\n");
|
|
for(;bytes<4096;bytes+=8) {
|
|
int reverse=bytes&0x400;
|
|
if (reverse) reverse=0xff;
|
|
|
|
fprintf(outfile,"x\"%02X\",x\"%02X\",x\"%02X\",x\"%02X\",x\"%02X\",x\"%02X\",x\"%02X\",x\"%02X\"%c -- 0x%03x (set %d, char %d)\n",
|
|
first_half[(bytes+0)&0x3ff]^reverse,
|
|
first_half[(bytes+1)&0x3ff]^reverse,
|
|
first_half[(bytes+2)&0x3ff]^reverse,
|
|
first_half[(bytes+3)&0x3ff]^reverse,
|
|
first_half[(bytes+4)&0x3ff]^reverse,
|
|
first_half[(bytes+5)&0x3ff]^reverse,
|
|
first_half[(bytes+6)&0x3ff]^reverse,
|
|
first_half[(bytes+7)&0x3ff]^reverse,
|
|
bytes<(4096-8)?',':' ',
|
|
bytes,bytes/2048,(bytes/8)&0xff);
|
|
}
|
|
} else {
|
|
// In raw mode, don't pad
|
|
}
|
|
}
|
|
if (vhdl_mode) fprintf(outfile,"%s",vhdl_suffix);
|
|
|
|
if (outfile != NULL) {
|
|
fclose(outfile);
|
|
outfile = NULL;
|
|
}
|
|
}
|
|
|
|
/* ============================ */
|
|
if (mode==2) {
|
|
printf("mode=2 (hi-res prep)\n");
|
|
// hi-res image preparation mode
|
|
|
|
// int bytes=0;
|
|
if (width%8||height%8) {
|
|
fprintf(stderr,"Image must be multiple of 8 pixels wide and high\n");
|
|
}
|
|
int problems=0;
|
|
int total=0;
|
|
int threes=0;
|
|
int fours=0;
|
|
int ones=0;
|
|
|
|
int tiles[8000][8][8];
|
|
int tile_count=0;
|
|
|
|
int this_tile[8][8];
|
|
|
|
for (y=0; y<height; y+=8) {
|
|
for (x=0; x<width; x+=8) {
|
|
int yy,xx;
|
|
int i;
|
|
int colour_count=0;
|
|
int colours[64];
|
|
|
|
printf("[%d,%d]\n",x,y);
|
|
|
|
total++;
|
|
|
|
for(yy=y;yy<y+8;yy++) {
|
|
png_byte* row = row_pointers[yy];
|
|
for(xx=x;xx<x+8;xx++) {
|
|
png_byte* ptr = &(row[xx*multiplier]);
|
|
int r,g,b;
|
|
if (ptr&&(yy<height)&&(xx<width)) {
|
|
r=ptr[0]; g=ptr[1]; b=ptr[2];
|
|
} else {
|
|
r=0; g=0; b=0;
|
|
}
|
|
int c=r+256*g+65536*b;
|
|
this_tile[yy-y][xx-x]=c;
|
|
for(i=0;i<colour_count;i++) if (c==colours[i]) break;
|
|
if (i==colour_count) {
|
|
colours[colour_count++]=c;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(i=0;i<tile_count;i++) {
|
|
int dud=0;
|
|
int xx,yy;
|
|
for(xx=0;xx<8;xx++)
|
|
for(yy=0;yy<8;yy++) {
|
|
if (this_tile[yy][xx]!=tiles[i][yy][xx]) dud=1;
|
|
}
|
|
if (!dud) break;
|
|
}
|
|
if (i==tile_count) {
|
|
int xx,yy;
|
|
for(xx=0;xx<8;xx++)
|
|
for(yy=0;yy<8;yy++) {
|
|
tiles[tile_count][yy][xx]=this_tile[yy][xx];
|
|
}
|
|
printf(".[%d]",tile_count); fflush(stdout);
|
|
tile_count++;
|
|
if (tile_count>=8000) {
|
|
fprintf(stderr,"Too many tiles\n");
|
|
if (outfile != NULL) {
|
|
fclose(outfile);
|
|
outfile = NULL;
|
|
}
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
if (colour_count==1) ones++;
|
|
if (colour_count==3) threes++;
|
|
if (colour_count==4) fours++;
|
|
if (colour_count>2) {
|
|
printf("%d colours in card\n",colour_count);
|
|
problems++;
|
|
}
|
|
}
|
|
}
|
|
printf("%d problem tiles out of %d total tiles\n",problems,total);
|
|
printf("%d with 3, %d with 4, %d with only one colour\n",threes,fours,ones);
|
|
printf("%d unique tiles\n",tile_count);
|
|
}
|
|
|
|
if (mode==3) {
|
|
// Output set of 16-colour sprites
|
|
int colour_count=0;
|
|
int colours[16];
|
|
fprintf(stderr,"Scanning colour palette...\n");
|
|
for (y=0; y<height; y++) {
|
|
for (x=0; x<width; x++) {
|
|
int i;
|
|
|
|
png_byte* row = row_pointers[y];
|
|
png_byte* ptr = &(row[x*multiplier]);
|
|
int r=ptr[0], g=ptr[1],b=ptr[2]; // , a=ptr[3];
|
|
int c=r+256*g+65536*b;
|
|
for(i=0;i<colour_count;i++) if (c==colours[i]) break;
|
|
if (i==colour_count) {
|
|
if (colour_count>=16) {
|
|
fprintf(stderr,"Too many colours. Image must be 16-colours or less.\n");
|
|
exit(-1);
|
|
}
|
|
colours[colour_count++]=c;
|
|
}
|
|
}
|
|
}
|
|
fprintf(stderr,"%d unique colours found.\n",colour_count);
|
|
|
|
// Avoid colour 0 if we can, to keep it for transparency
|
|
int colour_offset=0;
|
|
// if (colour_count<16) colour_offset=1;
|
|
|
|
|
|
int bytes_per_sprite=8*(height>>1);
|
|
while (bytes_per_sprite%64) bytes_per_sprite++;
|
|
fprintf(stderr,"Sprites are %d ($%02X) pixels high, and will occupy %d bytes (%d VIC-II sprite slots) each.\n",
|
|
height/2,height/2,bytes_per_sprite,bytes_per_sprite/64);
|
|
|
|
|
|
// Output palette
|
|
unsigned char red[16];
|
|
unsigned char green[16];
|
|
unsigned char blue[16];
|
|
int i;
|
|
|
|
for(i=0;i<16;i++)
|
|
{
|
|
int idx=i;
|
|
if (colour_offset) idx+=colour_offset;
|
|
if (idx>=16) idx-=16;
|
|
|
|
red[idx]=nyblswap(colours[i]&0xff);
|
|
green[idx]=nyblswap((colours[i]>>8)&0xff);
|
|
blue[idx]=nyblswap((colours[i]>>16)&0xff);
|
|
}
|
|
// Write magic string, height of sprites in pixels,
|
|
// and the number of sprites, and how many slots per
|
|
// sprite
|
|
fwrite("M65SPRITE16",12,1,outfile);
|
|
fputc(height/2,outfile);
|
|
fputc(width/32,outfile);
|
|
fputc(bytes_per_sprite&0xff,outfile);
|
|
fputc(bytes_per_sprite>>8,outfile);
|
|
fwrite(red,16,1,outfile);
|
|
fwrite(green,16,1,outfile);
|
|
fwrite(blue,16,1,outfile);
|
|
|
|
|
|
// Output pixels
|
|
for (x=0; x<width; x+=32) {
|
|
int bytes_written=0;
|
|
int xx;
|
|
fprintf(stderr,"Writing sprite %d\n",x/32);
|
|
for (y=0; y<height; y+=2) {
|
|
for(xx=x;xx<(x+32);xx+=4) {
|
|
unsigned char byte;
|
|
unsigned char p1,p2;
|
|
int i;
|
|
|
|
png_byte* row = row_pointers[y];
|
|
png_byte* ptr = &(row[(xx+0)*multiplier]);
|
|
int r=ptr[0], g=ptr[1],b=ptr[2]; // , a=ptr[3];
|
|
int c=r+256*g+65536*b;
|
|
for(i=0;i<colour_count;i++) if (c==colours[i]) break;
|
|
p1=i;
|
|
ptr = &(row[(xx+2)*multiplier]);
|
|
r=ptr[0]; g=ptr[1]; b=ptr[2]; // , a=ptr[3];
|
|
c=r+256*g+65536*b;
|
|
for(i=0;i<colour_count;i++) if (c==colours[i]) break;
|
|
p2=i;
|
|
byte=(p1<<4)+p2;
|
|
fputc(byte,outfile);
|
|
bytes_written++;
|
|
}
|
|
}
|
|
while(bytes_written<bytes_per_sprite) {
|
|
fputc(0x00,outfile);
|
|
bytes_written++;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* ============================================================= */
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc != 4) {
|
|
fprintf(stderr,"Usage: program_name <logo|charrom|hires|sprite16> <file_in> <file_out>\n");
|
|
exit(-1);
|
|
}
|
|
|
|
int mode=-1;
|
|
|
|
if (!strcasecmp("logo",argv[1])) mode=0;
|
|
if (!strcasecmp("charrom",argv[1])) mode=1;
|
|
if (!strcasecmp("hires",argv[1])) mode=2;
|
|
if (!strcasecmp("sprite16",argv[1])) mode=3;
|
|
if (mode==-1) {
|
|
fprintf(stderr,"Usage: program_name <logo|charrom|hires|sprite16> <file_in> <file_out>\n");
|
|
exit(-1);
|
|
}
|
|
|
|
printf("argv[0]=%s\n", argv[0]);
|
|
printf("argv[1]=%s\n", argv[1]);
|
|
printf("argv[2]=%s\n", argv[2]);
|
|
printf("argv[3]=%s\n", argv[3]);
|
|
|
|
printf("Reading %s\n",argv[2]);
|
|
read_png_file(argv[2]);
|
|
|
|
printf("Processing with mode=%d and output=%s\n", mode, argv[3]);
|
|
process_file(mode,argv[3]);
|
|
|
|
printf("done\n");
|
|
|
|
if (infile != NULL) {
|
|
fclose(infile);
|
|
infile = NULL;
|
|
}
|
|
|
|
if (outfile != NULL) {
|
|
fclose(outfile);
|
|
outfile = NULL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* ============================================================= */
|