diff options
author | Bad Diode <bd@badd10de.dev> | 2021-04-22 11:05:41 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-04-22 11:05:41 +0200 |
commit | 0c1035bcc5a2c78640f45d0bd5f4454a51c87398 (patch) | |
tree | 915ed12a0ff963a0d22e4abcf0dfd3e699040e42 | |
parent | 0e95d86056bd310f0684ce6764113a3a41b3e211 (diff) | |
download | gba-dev-tools-0c1035bcc5a2c78640f45d0bd5f4454a51c87398.tar.gz gba-dev-tools-0c1035bcc5a2c78640f45d0bd5f4454a51c87398.zip |
Add support for output 1bpp packed sprites
-rw-r--r-- | src/main.c | 78 |
1 files changed, 64 insertions, 14 deletions
@@ -44,22 +44,64 @@ typedef struct Image { | |||
44 | int n_channels; | 44 | int n_channels; |
45 | } Image; | 45 | } Image; |
46 | 46 | ||
47 | u8 | ||
48 | pack_1bb(u32 hex) { | ||
49 | u32 low_nibble = hex & 0xFFFF; | ||
50 | u32 high_nibble = (hex >> 16) & 0xFFFF; | ||
51 | u32 low = (low_nibble & 0x1); | ||
52 | low += 2 * ((low_nibble >> 4) & 0x1); | ||
53 | low += 4 * ((low_nibble >> 8) & 0x1); | ||
54 | low += 8 * ((low_nibble >> 12) & 0x1); | ||
55 | u32 high = (high_nibble & 0x1); | ||
56 | high += 2 * ((high_nibble >> 4) & 0x1); | ||
57 | high += 4 * ((high_nibble >> 8) & 0x1); | ||
58 | high += 8 * ((high_nibble >> 12) & 0x1); | ||
59 | return (high << 4) | low; | ||
60 | } | ||
61 | |||
47 | void | 62 | void |
48 | export_c_file(Tiles *tiles, Palette *palette, FILE *file) { | 63 | export_c_file(Tiles *tiles, Palette *palette, FILE *file, bool pack_1bpp) { |
49 | // Output tiles. | 64 | // Output tiles. |
50 | fprintf(file, "u32 tiles[%lu][%u] = {\n", tiles->capacity, TILE_SIZE); | 65 | if (pack_1bpp) { |
51 | for (size_t i = 0; i < tiles->capacity; ++i) { | 66 | fprintf(file, "u32 packed_tiles[] = {\n "); |
52 | fprintf(file, " {"); | 67 | size_t counter = 0; |
53 | for (size_t j = 0; j < TILE_SIZE; ++j) { | 68 | for (size_t i = 0; i < tiles->capacity; ++i) { |
54 | fprintf(file, "0x%08x", tiles->data[i][j]); | 69 | for (size_t j = 0; j < TILE_SIZE; j += 4, counter++) { |
55 | if (j != (TILE_SIZE - 1)) { | 70 | if (counter == 4) { |
56 | fprintf(file, ", "); | 71 | counter = 0; |
72 | fprintf(file, "\n "); | ||
73 | } | ||
74 | u32 tile_a = tiles->data[i][j]; | ||
75 | u32 tile_b = tiles->data[i][j + 1]; | ||
76 | u32 tile_c = tiles->data[i][j + 2]; | ||
77 | u32 tile_d = tiles->data[i][j + 3]; | ||
78 | u32 packed = pack_1bb(tile_d); | ||
79 | packed |= pack_1bb(tile_c) << 8; | ||
80 | packed |= pack_1bb(tile_b) << 16; | ||
81 | packed |= pack_1bb(tile_a) << 24; | ||
82 | fprintf(file, "0x%08x,", packed); | ||
83 | if (counter < 3) { | ||
84 | fprintf(file, " "); | ||
85 | } | ||
57 | } | 86 | } |
58 | } | 87 | } |
59 | fprintf(file, "},\n"); | 88 | fprintf(file, "\n};\n"); |
89 | fprintf(file, "\n"); | ||
90 | } else { | ||
91 | fprintf(file, "u32 tiles[%lu][%u] = {\n", tiles->capacity, TILE_SIZE); | ||
92 | for (size_t i = 0; i < tiles->capacity; ++i) { | ||
93 | fprintf(file, " {"); | ||
94 | for (size_t j = 0; j < TILE_SIZE; ++j) { | ||
95 | fprintf(file, "0x%08x", tiles->data[i][j]); | ||
96 | if (j != (TILE_SIZE - 1)) { | ||
97 | fprintf(file, ", "); | ||
98 | } | ||
99 | } | ||
100 | fprintf(file, "},\n"); | ||
101 | } | ||
102 | fprintf(file, "};\n"); | ||
103 | fprintf(file, "\n"); | ||
60 | } | 104 | } |
61 | fprintf(file, "};\n"); | ||
62 | fprintf(file, "\n"); | ||
63 | 105 | ||
64 | // Output palette. | 106 | // Output palette. |
65 | fprintf(file, "u16 palette[%lu] = {\n", palette->capacity); | 107 | fprintf(file, "u16 palette[%lu] = {\n", palette->capacity); |
@@ -153,10 +195,13 @@ print_usage(void) { | |||
153 | printf("\t-o <out_file.c>\tPath to the output file. If blank, stdout will be used.\n"); | 195 | printf("\t-o <out_file.c>\tPath to the output file. If blank, stdout will be used.\n"); |
154 | printf("\t-W <8>\tSelect the sprite width in pixels. Must be a multiple of the tile size.\n"); | 196 | printf("\t-W <8>\tSelect the sprite width in pixels. Must be a multiple of the tile size.\n"); |
155 | printf("\t-H <8>\tSelect the sprite height in pixels. Must be a multiple of the tile size.\n"); | 197 | printf("\t-H <8>\tSelect the sprite height in pixels. Must be a multiple of the tile size.\n"); |
198 | printf("\t-1\tBit pack the output to 1bbp (4x size reduction).\n"); | ||
156 | printf("\t-h\tShow help.\n"); | 199 | printf("\t-h\tShow help.\n"); |
157 | printf("\n"); | 200 | printf("\n"); |
158 | } | 201 | } |
159 | 202 | ||
203 | // TODO: Enable 1bit bit-packing (in u32 units). | ||
204 | // TODO: Support multiple files at once? | ||
160 | int | 205 | int |
161 | main(int argc, char *argv[]) { | 206 | main(int argc, char *argv[]) { |
162 | // Initialize default parameters. | 207 | // Initialize default parameters. |
@@ -165,9 +210,10 @@ main(int argc, char *argv[]) { | |||
165 | size_t sprite_width = TILE_SIZE; | 210 | size_t sprite_width = TILE_SIZE; |
166 | size_t sprite_height = TILE_SIZE; | 211 | size_t sprite_height = TILE_SIZE; |
167 | char *out_file_path = NULL; | 212 | char *out_file_path = NULL; |
213 | bool pack_1bpp = false; | ||
168 | 214 | ||
169 | int option; | 215 | int option; |
170 | while ((option = getopt(argc, argv, "hb:o:W:H:")) != -1) { | 216 | while ((option = getopt(argc, argv, "hb:o:W:H:1")) != -1) { |
171 | switch (option) { | 217 | switch (option) { |
172 | case 'b': { | 218 | case 'b': { |
173 | // Background color. | 219 | // Background color. |
@@ -226,6 +272,10 @@ main(int argc, char *argv[]) { | |||
226 | // Output file. | 272 | // Output file. |
227 | out_file_path = optarg; | 273 | out_file_path = optarg; |
228 | } break; | 274 | } break; |
275 | case '1': { | ||
276 | // Pack output to 1bpp. | ||
277 | pack_1bpp = true; | ||
278 | } break; | ||
229 | case 'h': { | 279 | case 'h': { |
230 | // Help. | 280 | // Help. |
231 | print_usage(); | 281 | print_usage(); |
@@ -302,14 +352,14 @@ main(int argc, char *argv[]) { | |||
302 | } | 352 | } |
303 | 353 | ||
304 | if (out_file_path == NULL) { | 354 | if (out_file_path == NULL) { |
305 | export_c_file(&tiles, &palette, stdout); | 355 | export_c_file(&tiles, &palette, stdout, pack_1bpp); |
306 | } else { | 356 | } else { |
307 | FILE *file = fopen(out_file_path, "w"); | 357 | FILE *file = fopen(out_file_path, "w"); |
308 | if (!file) { | 358 | if (!file) { |
309 | fprintf(stderr, "%s: can't open output file: %s\n", BIN_NAME, out_file_path); | 359 | fprintf(stderr, "%s: can't open output file: %s\n", BIN_NAME, out_file_path); |
310 | return EXIT_FAILURE; | 360 | return EXIT_FAILURE; |
311 | } | 361 | } |
312 | export_c_file(&tiles, &palette, file); | 362 | export_c_file(&tiles, &palette, file, pack_1bpp); |
313 | fclose(file); | 363 | fclose(file); |
314 | } | 364 | } |
315 | 365 | ||