diff options
-rw-r--r-- | img2gba/Makefile (renamed from sprite2gba/Makefile) | 2 | ||||
-rw-r--r-- | img2gba/src/main.c (renamed from sprite2gba/src/main.c) | 130 | ||||
-rw-r--r-- | img2gba/src/shorthand.h (renamed from sprite2gba/src/shorthand.h) | 0 | ||||
-rw-r--r-- | img2gba/src/stb_image.h (renamed from sprite2gba/src/stb_image.h) | 4 |
4 files changed, 97 insertions, 39 deletions
diff --git a/sprite2gba/Makefile b/img2gba/Makefile index 0d6dc07..f374ea9 100644 --- a/sprite2gba/Makefile +++ b/img2gba/Makefile | |||
@@ -9,7 +9,7 @@ WATCH_SRC := $(wildcard $(SRC_DIR)/*.c) | |||
9 | WATCH_SRC += $(wildcard $(SRC_DIR)/*.h) | 9 | WATCH_SRC += $(wildcard $(SRC_DIR)/*.h) |
10 | 10 | ||
11 | # Output library names and executables. | 11 | # Output library names and executables. |
12 | BIN_NAME := sprite2gba | 12 | BIN_NAME := img2gba |
13 | BUILD_DIR := build | 13 | BUILD_DIR := build |
14 | BIN := $(BUILD_DIR)/$(BIN_NAME) | 14 | BIN := $(BUILD_DIR)/$(BIN_NAME) |
15 | 15 | ||
diff --git a/sprite2gba/src/main.c b/img2gba/src/main.c index f91ecd0..8a5edfc 100644 --- a/sprite2gba/src/main.c +++ b/img2gba/src/main.c | |||
@@ -6,8 +6,9 @@ | |||
6 | #include "stb_image.h" | 6 | #include "stb_image.h" |
7 | 7 | ||
8 | #define TILE_SIZE 8 | 8 | #define TILE_SIZE 8 |
9 | #define DEFAULT_PALETTE_SIZE 16 | 9 | #define PALETTE_SIZE 16 |
10 | #define DEFAULT_BG_COLOR 0x0000 | 10 | #define DEFAULT_BG_COLOR 0x0000 |
11 | #define MAX_FILE_NAME 1024 | ||
11 | 12 | ||
12 | typedef u16 Color; | 13 | typedef u16 Color; |
13 | 14 | ||
@@ -32,7 +33,7 @@ typedef struct Tiles { | |||
32 | } Tiles; | 33 | } Tiles; |
33 | 34 | ||
34 | typedef struct Palette { | 35 | typedef struct Palette { |
35 | Color *data; | 36 | Color data[PALETTE_SIZE]; |
36 | size_t size; | 37 | size_t size; |
37 | size_t capacity; | 38 | size_t capacity; |
38 | } Palette; | 39 | } Palette; |
@@ -48,22 +49,22 @@ u8 | |||
48 | pack_1bb(u32 hex) { | 49 | pack_1bb(u32 hex) { |
49 | u32 low_nibble = hex & 0xFFFF; | 50 | u32 low_nibble = hex & 0xFFFF; |
50 | u32 high_nibble = (hex >> 16) & 0xFFFF; | 51 | u32 high_nibble = (hex >> 16) & 0xFFFF; |
51 | u32 low = (low_nibble & 0x1); | 52 | u32 low = ((low_nibble >> 12) & 0x1); |
52 | low += 2 * ((low_nibble >> 4) & 0x1); | 53 | low += 2 * ((low_nibble >> 8) & 0x1); |
53 | low += 4 * ((low_nibble >> 8) & 0x1); | 54 | low += 4 * ((low_nibble >> 4) & 0x1); |
54 | low += 8 * ((low_nibble >> 12) & 0x1); | 55 | low += 8 * ((low_nibble >> 0) & 0x1); |
55 | u32 high = (high_nibble & 0x1); | 56 | u32 high = ((high_nibble >> 12) & 0x1); |
56 | high += 2 * ((high_nibble >> 4) & 0x1); | 57 | high += 2 * ((high_nibble >> 8) & 0x1); |
57 | high += 4 * ((high_nibble >> 8) & 0x1); | 58 | high += 4 * ((high_nibble >> 4) & 0x1); |
58 | high += 8 * ((high_nibble >> 12) & 0x1); | 59 | high += 8 * ((high_nibble >> 0) & 0x1); |
59 | return (high << 4) | low; | 60 | return (low << 4) | high; |
60 | } | 61 | } |
61 | 62 | ||
62 | void | 63 | void |
63 | export_c_file(Tiles *tiles, Palette *palette, FILE *file, bool pack_1bpp) { | 64 | export_c_file(Tiles *tiles, Palette *palette, FILE *file, bool pack_1bpp) { |
64 | // Output tiles. | 65 | // Output tiles. |
65 | if (pack_1bpp) { | 66 | if (pack_1bpp) { |
66 | fprintf(file, "u32 packed_tiles[] = {\n "); | 67 | fprintf(file, "static const u32 packed_tiles[] = {\n "); |
67 | size_t counter = 0; | 68 | size_t counter = 0; |
68 | for (size_t i = 0; i < tiles->capacity; ++i) { | 69 | for (size_t i = 0; i < tiles->capacity; ++i) { |
69 | for (size_t j = 0; j < TILE_SIZE; j += 4, counter++) { | 70 | for (size_t j = 0; j < TILE_SIZE; j += 4, counter++) { |
@@ -75,10 +76,10 @@ export_c_file(Tiles *tiles, Palette *palette, FILE *file, bool pack_1bpp) { | |||
75 | u32 tile_b = tiles->data[i][j + 1]; | 76 | u32 tile_b = tiles->data[i][j + 1]; |
76 | u32 tile_c = tiles->data[i][j + 2]; | 77 | u32 tile_c = tiles->data[i][j + 2]; |
77 | u32 tile_d = tiles->data[i][j + 3]; | 78 | u32 tile_d = tiles->data[i][j + 3]; |
78 | u32 packed = pack_1bb(tile_d); | 79 | u32 packed = pack_1bb(tile_d) << 0; |
79 | packed |= pack_1bb(tile_c) << 8; | 80 | packed |= pack_1bb(tile_c) << 8; |
80 | packed |= pack_1bb(tile_b) << 16; | 81 | packed |= pack_1bb(tile_b) << 16; |
81 | packed |= pack_1bb(tile_a) << 24; | 82 | packed |= pack_1bb(tile_a) << 24; |
82 | fprintf(file, "0x%08x,", packed); | 83 | fprintf(file, "0x%08x,", packed); |
83 | if (counter < 3) { | 84 | if (counter < 3) { |
84 | fprintf(file, " "); | 85 | fprintf(file, " "); |
@@ -88,7 +89,7 @@ export_c_file(Tiles *tiles, Palette *palette, FILE *file, bool pack_1bpp) { | |||
88 | fprintf(file, "\n};\n"); | 89 | fprintf(file, "\n};\n"); |
89 | fprintf(file, "\n"); | 90 | fprintf(file, "\n"); |
90 | } else { | 91 | } else { |
91 | fprintf(file, "u32 tiles[%lu][%u] = {\n", tiles->capacity, TILE_SIZE); | 92 | fprintf(file, "static const u32 tiles[%lu][%u] = {\n", tiles->capacity, TILE_SIZE); |
92 | for (size_t i = 0; i < tiles->capacity; ++i) { | 93 | for (size_t i = 0; i < tiles->capacity; ++i) { |
93 | fprintf(file, " {"); | 94 | fprintf(file, " {"); |
94 | for (size_t j = 0; j < TILE_SIZE; ++j) { | 95 | for (size_t j = 0; j < TILE_SIZE; ++j) { |
@@ -122,6 +123,36 @@ export_c_file(Tiles *tiles, Palette *palette, FILE *file, bool pack_1bpp) { | |||
122 | } | 123 | } |
123 | 124 | ||
124 | void | 125 | void |
126 | export_bin_file(Tiles *tiles, Palette *palette, FILE *file, FILE *filepal, bool pack_1bpp) { | ||
127 | if (pack_1bpp) { | ||
128 | u64 counter = 0; | ||
129 | for (size_t i = 0; i < tiles->capacity; ++i) { | ||
130 | for (size_t j = 0; j < TILE_SIZE; j += 4, counter++) { | ||
131 | u32 tile_a = tiles->data[i][j]; | ||
132 | u32 tile_b = tiles->data[i][j + 1]; | ||
133 | u32 tile_c = tiles->data[i][j + 2]; | ||
134 | u32 tile_d = tiles->data[i][j + 3]; | ||
135 | u32 packed = pack_1bb(tile_a) << 0; | ||
136 | packed |= pack_1bb(tile_b) << 8; | ||
137 | packed |= pack_1bb(tile_c) << 16; | ||
138 | packed |= pack_1bb(tile_d) << 24; | ||
139 | fwrite(&packed, sizeof(u32), 1, file); | ||
140 | } | ||
141 | } | ||
142 | // Pad with zeros to avoid alignment issues. | ||
143 | if (counter) { | ||
144 | u32 zero = 0; | ||
145 | fwrite(&zero, sizeof(u32), counter % 8, file); | ||
146 | } | ||
147 | } else { | ||
148 | for (size_t i = 0; i < tiles->capacity; ++i) { | ||
149 | fwrite(&tiles->data[i][0], sizeof(u32), TILE_SIZE, file); | ||
150 | } | ||
151 | fwrite(palette->data, sizeof(u16), PALETTE_SIZE, filepal); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | void | ||
125 | extract_tile(Tiles *tiles, Palette *palette, Image *img, | 156 | extract_tile(Tiles *tiles, Palette *palette, Image *img, |
126 | size_t offset_x, size_t offset_y) { | 157 | size_t offset_x, size_t offset_y) { |
127 | for (size_t j = 0; j < TILE_SIZE; ++j) { | 158 | for (size_t j = 0; j < TILE_SIZE; ++j) { |
@@ -191,24 +222,24 @@ void | |||
191 | print_usage(void) { | 222 | print_usage(void) { |
192 | printf("Usage: %s [options] <filename>\n", BIN_NAME); | 223 | printf("Usage: %s [options] <filename>\n", BIN_NAME); |
193 | printf("\n"); | 224 | printf("\n"); |
194 | printf("\t-b <RRGGBB>\tSelects the background color used for transparency.\n"); | 225 | printf("\t-b <RRGGBB> Selects the background color used for transparency.\n"); |
195 | printf("\t-o <out_file.c>\tPath to the output file. If blank, stdout will be used.\n"); | 226 | printf("\t-o <out_file> Path to the output file. If blank, stdout will be used with C array export.\n"); |
196 | printf("\t-x <0>\tStart x position (in pixels).\n"); | 227 | printf("\t-x <0> Start x position (in pixels).\n"); |
197 | printf("\t-y <0>\tStart y position (in pixels).\n"); | 228 | printf("\t-y <0> Start y position (in pixels).\n"); |
198 | printf("\t-W <8>\tSelect the sprite width in pixels. Must be a multiple of the tile size.\n"); | 229 | printf("\t-W <8> Select the sprite width in pixels. Must be a multiple of the tile size.\n"); |
199 | printf("\t-H <8>\tSelect the sprite height in pixels. Must be a multiple of the tile size.\n"); | 230 | printf("\t-H <8> Select the sprite height in pixels. Must be a multiple of the tile size.\n"); |
200 | printf("\t-1\tBit pack the output to 1bbp (4x size reduction).\n"); | 231 | printf("\t-1 Bit pack the output to 1bbp (4x size reduction).\n"); |
201 | printf("\t-w <0>\tWidth of region to extract from (x0,y0). Defaults to image width.\n"); | 232 | printf("\t-w <0> Width of region to extract from (x0,y0). Defaults to image width.\n"); |
202 | printf("\t-h <0>\tHeight of region to extract from (x0,y0). Defaults to image height.\n"); | 233 | printf("\t-h <0> Height of region to extract from (x0,y0). Defaults to image height.\n"); |
234 | printf("\t-v Verbose mode\n"); | ||
203 | printf("\n"); | 235 | printf("\n"); |
204 | } | 236 | } |
205 | 237 | ||
206 | // TODO: Support multiple files at once? | ||
207 | int | 238 | int |
208 | main(int argc, char *argv[]) { | 239 | main(int argc, char *argv[]) { |
209 | // Initialize default parameters. | 240 | // Initialize default parameters. |
210 | u16 background_color = DEFAULT_BG_COLOR; | 241 | u16 background_color = DEFAULT_BG_COLOR; |
211 | u16 palette_size = DEFAULT_PALETTE_SIZE; | 242 | u16 palette_size = PALETTE_SIZE; |
212 | size_t sprite_width = TILE_SIZE; | 243 | size_t sprite_width = TILE_SIZE; |
213 | size_t sprite_height = TILE_SIZE; | 244 | size_t sprite_height = TILE_SIZE; |
214 | char *out_file_path = NULL; | 245 | char *out_file_path = NULL; |
@@ -217,9 +248,10 @@ main(int argc, char *argv[]) { | |||
217 | size_t start_y = 0; | 248 | size_t start_y = 0; |
218 | size_t width = 0; | 249 | size_t width = 0; |
219 | size_t height = 0; | 250 | size_t height = 0; |
251 | bool verbose = false; | ||
220 | 252 | ||
221 | int option; | 253 | int option; |
222 | while ((option = getopt(argc, argv, "b:o:W:H:1x:y:w:h:")) != -1) { | 254 | while ((option = getopt(argc, argv, "b:o:W:H:1x:y:w:h:v")) != -1) { |
223 | switch (option) { | 255 | switch (option) { |
224 | case 'b': { | 256 | case 'b': { |
225 | // Background color. | 257 | // Background color. |
@@ -298,6 +330,9 @@ main(int argc, char *argv[]) { | |||
298 | // Height of region to extract from (x0,y0). | 330 | // Height of region to extract from (x0,y0). |
299 | height = atoi(optarg); | 331 | height = atoi(optarg); |
300 | } break; | 332 | } break; |
333 | case 'v': { | ||
334 | verbose = true; | ||
335 | } break; | ||
301 | default: { | 336 | default: { |
302 | print_usage(); | 337 | print_usage(); |
303 | return EXIT_FAILURE; | 338 | return EXIT_FAILURE; |
@@ -315,7 +350,6 @@ main(int argc, char *argv[]) { | |||
315 | 350 | ||
316 | // Fill the palette with the background color if one was given. | 351 | // Fill the palette with the background color if one was given. |
317 | Palette palette = { | 352 | Palette palette = { |
318 | .data = malloc(palette_size * sizeof(Color)), | ||
319 | .size = 1, | 353 | .size = 1, |
320 | .capacity = palette_size, | 354 | .capacity = palette_size, |
321 | }; | 355 | }; |
@@ -357,8 +391,6 @@ main(int argc, char *argv[]) { | |||
357 | .capacity = n_tiles, | 391 | .capacity = n_tiles, |
358 | }; | 392 | }; |
359 | 393 | ||
360 | int offset_x = start_x; | ||
361 | int offset_y = start_y; | ||
362 | size_t n_sprites_x = width / sprite_width; | 394 | size_t n_sprites_x = width / sprite_width; |
363 | size_t n_sprites_y = height / sprite_height; | 395 | size_t n_sprites_y = height / sprite_height; |
364 | size_t n_sprite_tiles_x = sprite_width / TILE_SIZE; | 396 | size_t n_sprite_tiles_x = sprite_width / TILE_SIZE; |
@@ -379,18 +411,42 @@ main(int argc, char *argv[]) { | |||
379 | if (out_file_path == NULL) { | 411 | if (out_file_path == NULL) { |
380 | export_c_file(&tiles, &palette, stdout, pack_1bpp); | 412 | export_c_file(&tiles, &palette, stdout, pack_1bpp); |
381 | } else { | 413 | } else { |
382 | FILE *file = fopen(out_file_path, "w"); | 414 | char file_name[MAX_FILE_NAME] = {0}; |
415 | char file_name_pal[MAX_FILE_NAME] = {0}; | ||
416 | strncpy(file_name, out_file_path, MAX_FILE_NAME - 1); | ||
417 | strncpy(file_name_pal, out_file_path, MAX_FILE_NAME - 1); | ||
418 | FILE *file = fopen(strcat(file_name, ".img.bin"), "w"); | ||
383 | if (!file) { | 419 | if (!file) { |
384 | fprintf(stderr, "%s: can't open output file: %s\n", BIN_NAME, out_file_path); | 420 | fprintf(stderr, "%s: can't open output file: %s\n", BIN_NAME, file_name); |
385 | return EXIT_FAILURE; | 421 | return EXIT_FAILURE; |
386 | } | 422 | } |
387 | export_c_file(&tiles, &palette, file, pack_1bpp); | 423 | if (pack_1bpp) { |
388 | fclose(file); | 424 | export_bin_file(&tiles, &palette, file, NULL, pack_1bpp); |
425 | fclose(file); | ||
426 | if (verbose) { | ||
427 | printf("Exporting binary file (1bpp packed)\n"); | ||
428 | printf("FILE IMG: %s\n", file_name); | ||
429 | } | ||
430 | } else { | ||
431 | FILE *file_pal = fopen(strcat(file_name_pal, ".pal.bin"), "w"); | ||
432 | if (!file_pal) { | ||
433 | fprintf(stderr, "%s: can't open output file: %s\n", BIN_NAME, file_name_pal); | ||
434 | fclose(file); | ||
435 | return EXIT_FAILURE; | ||
436 | } | ||
437 | if (verbose) { | ||
438 | printf("Exporting binary file\n"); | ||
439 | printf("FILE IMG: %s\n", file_name); | ||
440 | printf("FILE PAL: %s\n", file_name_pal); | ||
441 | } | ||
442 | export_bin_file(&tiles, &palette, file, file_pal, pack_1bpp); | ||
443 | fclose(file); | ||
444 | fclose(file_pal); | ||
445 | } | ||
389 | } | 446 | } |
390 | 447 | ||
391 | // Cleanup resources and exit. | 448 | // Cleanup resources and exit. |
392 | free(tiles.data); | 449 | free(tiles.data); |
393 | free(palette.data); | ||
394 | stbi_image_free(img.data); | 450 | stbi_image_free(img.data); |
395 | return EXIT_SUCCESS; | 451 | return EXIT_SUCCESS; |
396 | } | 452 | } |
diff --git a/sprite2gba/src/shorthand.h b/img2gba/src/shorthand.h index 9c2e2f0..9c2e2f0 100644 --- a/sprite2gba/src/shorthand.h +++ b/img2gba/src/shorthand.h | |||
diff --git a/sprite2gba/src/stb_image.h b/img2gba/src/stb_image.h index accef48..3448d5f 100644 --- a/sprite2gba/src/stb_image.h +++ b/img2gba/src/stb_image.h | |||
@@ -4120,7 +4120,7 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) | |||
4120 | if (s >= 16) return -1; // invalid code! | 4120 | if (s >= 16) return -1; // invalid code! |
4121 | // code size is s, so: | 4121 | // code size is s, so: |
4122 | b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; | 4122 | b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; |
4123 | if (b >= sizeof (z->size)) return -1; // some data was corrupt somewhere! | 4123 | if ((size_t)b >= sizeof (z->size)) return -1; // some data was corrupt somewhere! |
4124 | if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. | 4124 | if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. |
4125 | a->code_buffer >>= s; | 4125 | a->code_buffer >>= s; |
4126 | a->num_bits -= s; | 4126 | a->num_bits -= s; |
@@ -6777,6 +6777,8 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, | |||
6777 | int stride; | 6777 | int stride; |
6778 | int out_size = 0; | 6778 | int out_size = 0; |
6779 | int delays_size = 0; | 6779 | int delays_size = 0; |
6780 | (void)out_size; | ||
6781 | (void)delays_size; | ||
6780 | memset(&g, 0, sizeof(g)); | 6782 | memset(&g, 0, sizeof(g)); |
6781 | if (delays) { | 6783 | if (delays) { |
6782 | *delays = 0; | 6784 | *delays = 0; |