summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-04-22 11:05:41 +0200
committerBad Diode <bd@badd10de.dev>2021-04-22 11:05:41 +0200
commit0c1035bcc5a2c78640f45d0bd5f4454a51c87398 (patch)
tree915ed12a0ff963a0d22e4abcf0dfd3e699040e42
parent0e95d86056bd310f0684ce6764113a3a41b3e211 (diff)
downloadgba-dev-tools-0c1035bcc5a2c78640f45d0bd5f4454a51c87398.tar.gz
gba-dev-tools-0c1035bcc5a2c78640f45d0bd5f4454a51c87398.zip
Add support for output 1bpp packed sprites
-rw-r--r--src/main.c78
1 files 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 {
44 int n_channels; 44 int n_channels;
45} Image; 45} Image;
46 46
47u8
48pack_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
47void 62void
48export_c_file(Tiles *tiles, Palette *palette, FILE *file) { 63export_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?
160int 205int
161main(int argc, char *argv[]) { 206main(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