From 0c1035bcc5a2c78640f45d0bd5f4454a51c87398 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Thu, 22 Apr 2021 11:05:41 +0200 Subject: Add support for output 1bpp packed sprites --- src/main.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 14 deletions(-) diff --git a/src/main.c b/src/main.c index 54864cd..67c5d69 100644 --- a/src/main.c +++ b/src/main.c @@ -44,22 +44,64 @@ typedef struct Image { int n_channels; } Image; +u8 +pack_1bb(u32 hex) { + u32 low_nibble = hex & 0xFFFF; + u32 high_nibble = (hex >> 16) & 0xFFFF; + u32 low = (low_nibble & 0x1); + low += 2 * ((low_nibble >> 4) & 0x1); + low += 4 * ((low_nibble >> 8) & 0x1); + low += 8 * ((low_nibble >> 12) & 0x1); + u32 high = (high_nibble & 0x1); + high += 2 * ((high_nibble >> 4) & 0x1); + high += 4 * ((high_nibble >> 8) & 0x1); + high += 8 * ((high_nibble >> 12) & 0x1); + return (high << 4) | low; +} + void -export_c_file(Tiles *tiles, Palette *palette, FILE *file) { +export_c_file(Tiles *tiles, Palette *palette, FILE *file, bool pack_1bpp) { // Output tiles. - fprintf(file, "u32 tiles[%lu][%u] = {\n", tiles->capacity, TILE_SIZE); - for (size_t i = 0; i < tiles->capacity; ++i) { - fprintf(file, " {"); - for (size_t j = 0; j < TILE_SIZE; ++j) { - fprintf(file, "0x%08x", tiles->data[i][j]); - if (j != (TILE_SIZE - 1)) { - fprintf(file, ", "); + if (pack_1bpp) { + fprintf(file, "u32 packed_tiles[] = {\n "); + size_t counter = 0; + for (size_t i = 0; i < tiles->capacity; ++i) { + for (size_t j = 0; j < TILE_SIZE; j += 4, counter++) { + if (counter == 4) { + counter = 0; + fprintf(file, "\n "); + } + u32 tile_a = tiles->data[i][j]; + u32 tile_b = tiles->data[i][j + 1]; + u32 tile_c = tiles->data[i][j + 2]; + u32 tile_d = tiles->data[i][j + 3]; + u32 packed = pack_1bb(tile_d); + packed |= pack_1bb(tile_c) << 8; + packed |= pack_1bb(tile_b) << 16; + packed |= pack_1bb(tile_a) << 24; + fprintf(file, "0x%08x,", packed); + if (counter < 3) { + fprintf(file, " "); + } } } - fprintf(file, "},\n"); + fprintf(file, "\n};\n"); + fprintf(file, "\n"); + } else { + fprintf(file, "u32 tiles[%lu][%u] = {\n", tiles->capacity, TILE_SIZE); + for (size_t i = 0; i < tiles->capacity; ++i) { + fprintf(file, " {"); + for (size_t j = 0; j < TILE_SIZE; ++j) { + fprintf(file, "0x%08x", tiles->data[i][j]); + if (j != (TILE_SIZE - 1)) { + fprintf(file, ", "); + } + } + fprintf(file, "},\n"); + } + fprintf(file, "};\n"); + fprintf(file, "\n"); } - fprintf(file, "};\n"); - fprintf(file, "\n"); // Output palette. fprintf(file, "u16 palette[%lu] = {\n", palette->capacity); @@ -153,10 +195,13 @@ print_usage(void) { printf("\t-o \tPath to the output file. If blank, stdout will be used.\n"); printf("\t-W <8>\tSelect the sprite width in pixels. Must be a multiple of the tile size.\n"); printf("\t-H <8>\tSelect the sprite height in pixels. Must be a multiple of the tile size.\n"); + printf("\t-1\tBit pack the output to 1bbp (4x size reduction).\n"); printf("\t-h\tShow help.\n"); printf("\n"); } +// TODO: Enable 1bit bit-packing (in u32 units). +// TODO: Support multiple files at once? int main(int argc, char *argv[]) { // Initialize default parameters. @@ -165,9 +210,10 @@ main(int argc, char *argv[]) { size_t sprite_width = TILE_SIZE; size_t sprite_height = TILE_SIZE; char *out_file_path = NULL; + bool pack_1bpp = false; int option; - while ((option = getopt(argc, argv, "hb:o:W:H:")) != -1) { + while ((option = getopt(argc, argv, "hb:o:W:H:1")) != -1) { switch (option) { case 'b': { // Background color. @@ -226,6 +272,10 @@ main(int argc, char *argv[]) { // Output file. out_file_path = optarg; } break; + case '1': { + // Pack output to 1bpp. + pack_1bpp = true; + } break; case 'h': { // Help. print_usage(); @@ -302,14 +352,14 @@ main(int argc, char *argv[]) { } if (out_file_path == NULL) { - export_c_file(&tiles, &palette, stdout); + export_c_file(&tiles, &palette, stdout, pack_1bpp); } else { FILE *file = fopen(out_file_path, "w"); if (!file) { fprintf(stderr, "%s: can't open output file: %s\n", BIN_NAME, out_file_path); return EXIT_FAILURE; } - export_c_file(&tiles, &palette, file); + export_c_file(&tiles, &palette, file, pack_1bpp); fclose(file); } -- cgit v1.2.1