#include #include #include #define STB_IMAGE_WRITE_IMPLEMENTATION #include "stb_image_write.h" #define COLOR 5 #define OFFSET (256*128) #define WIDTH 256 #define HEIGHT 64//(512 - 8) #define PAGES 1 #define MAX_ENTRIES 4096 typedef struct clut_entry_t { int stp; /* transparency control bit */ float r; /* red */ float g; /* green */ float b; /* blue */ } clut_entry_t; clut_entry_t *read_clt_file (char *path) { FILE *fp; clut_entry_t *entries; fp = fopen (path, "rb"); /* read all the clut entries */ entries = (clut_entry_t *) malloc (MAX_ENTRIES * sizeof (clut_entry_t)); uint16_t clut; int i = 0; while (fread (&clut, 2, 1, fp) > 0) { int r, g, b; /* read a clut entry */ clut_entry_t *entry = &entries[i++]; r = (clut >> 0) & 0x1f; g = (clut >> 5) & 0x1f; b = (clut >> 10) & 0x1f; entry->stp = (clut >> 15) & 1; entry->r = r / 31.; entry->g = g / 31.; entry->b = b / 31.; } fclose (fp); return entries; } uint32_t lookup (int index, clut_entry_t *palette) { clut_entry_t entry = palette[index + 64 * COLOR]; uint8_t r = entry.r * 255; uint8_t g = entry.g * 255; uint8_t b = entry.b * 255; uint8_t a = (entry.r == 0 && entry.g == 0 && entry.b == 0 && entry.stp == 0) ? 0 : 255; uint32_t color = (r << 0) + (g << 8) + (b << 16) + (a << 24); return color; } void decode (FILE *fp, uint32_t *buffer, clut_entry_t *pal) { /* 2bpp, interleaved */ fseek (fp, OFFSET, SEEK_SET); int size = WIDTH * HEIGHT / PAGES; for (int i = 0; i < size;) { uint8_t byte; int a, b, c, d; fread (&byte, 1, 1, fp); a = (byte >> 0) & 0x03; /* buffer a */ b = (byte >> 2) & 0x03; /* buffer b */ c = (byte >> 4) & 0x03; /* buffer a */ d = (byte >> 6) & 0x03; /* buffer b */ buffer[i] = lookup (a, pal); //buffer[i + size] = lookup (b, pal); i++; buffer[i] = lookup (c, pal); //buffer[i + size] = lookup (d, pal); i++; } } int main (int argc, char **argv) { /* 32-bit image buffers */ uint32_t *buffer; /* palette */ clut_entry_t *palette; /* file paths */ char *pxl_path; char *clt_path; char *png_path; /* file handles */ FILE *fp; /* parse arguments */ if (argc != 4) { fprintf (stderr, "usage: %s [input.pxl] [input.clt] [output.png]\n", argv[0]); return EXIT_FAILURE; } pxl_path = argv[1]; clt_path = argv[2]; png_path = argv[3]; /* decode the palette */ palette = read_clt_file (clt_path); /* allocate buffer */ printf ("allocating 32-bit image buffers for %dx%d pixels...\n", WIDTH, HEIGHT); if ((buffer = (uint32_t *) malloc (WIDTH * HEIGHT * sizeof(uint32_t))) == NULL) { fprintf (stderr, "failure to allocate first image buffer.\n"); return EXIT_FAILURE; } /* decode input */ printf ("opening pxl file \"%s\"...\n", pxl_path); if ((fp = fopen (pxl_path, "rb")) == NULL) { fprintf (stderr, "failure to open pxl file \"%s\".\n", pxl_path); return EXIT_FAILURE; } printf ("decoding...\n"); decode (fp, buffer, palette); fclose (fp); /* write out image buffers */ printf ("writing 32-bit %dx%d data to \"%s\"...\n", WIDTH, HEIGHT, png_path); stbi_write_png (png_path, WIDTH, HEIGHT, 4, buffer, sizeof (uint32_t) * WIDTH); /* cleanup */ printf ("done.\n"); free (palette); free (buffer); return EXIT_SUCCESS; }