diff --git a/tools/common.h b/tools/common.h index 3664703ea..2010e9e9d 100644 --- a/tools/common.h +++ b/tools/common.h @@ -25,6 +25,15 @@ void *malloc_verbose(size_t size) { return m; } +void *calloc_verbose(size_t size) { + errno = 0; + void *m = calloc(size, 1); + if (!m) { + error_exit("Could not allocate %zu bytes: %s\n", size, strerror(errno)); + } + return m; +} + FILE *fopen_verbose(const char *filename, char rw) { char mode[3] = {rw, 'b', '\0'}; errno = 0; @@ -100,4 +109,19 @@ uint32_t read_png_width_verbose(const char *filename) { return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; } +void read_dimensions(const char *filename, int *width) { + long filesize; + uint8_t *bytes = read_u8(filename, &filesize); + if (filesize != 1) { + error_exit("%s: invalid dimensions file\n", filename); + } + uint8_t dimensions = bytes[0]; + free(bytes); + *width = dimensions & 0xF; + int height = dimensions >> 4; + if (*width != height || (*width != 5 && *width != 6 && *width != 7)) { + error_exit("%s: invalid dimensions: %dx%d tiles\n", filename, *width, height); + } +} + #endif // GUARD_COMMON_H diff --git a/tools/png_dimensions.c b/tools/png_dimensions.c index f257d0e2e..e043097ee 100644 --- a/tools/png_dimensions.c +++ b/tools/png_dimensions.c @@ -1,10 +1,10 @@ #include "common.h" void usage() { - fputs("Usage: png_dimensions in.png out.dimensions\n", stderr); + fputs("Usage: png_dimensions front.png front.dimensions\n", stderr); } -uint8_t read_dimensions(const char *filename) { +uint8_t read_png_dimensions(const char *filename) { uint32_t width_px = read_png_width_verbose(filename); if (width_px != 40 && width_px != 48 && width_px != 56) { error_exit("Not a valid width for \"%s\": %" PRIu32 " px\n", filename, width_px); @@ -19,7 +19,7 @@ int main(int argc, char *argv[]) { exit(1); } - uint8_t output_byte = read_dimensions(argv[1]); + uint8_t output_byte = read_png_dimensions(argv[1]); write_u8(argv[2], &output_byte, 1); return 0; } diff --git a/tools/pokemon_animation.c b/tools/pokemon_animation.c index 6e330a975..a854c8b4c 100644 --- a/tools/pokemon_animation.c +++ b/tools/pokemon_animation.c @@ -1,112 +1,104 @@ -#include -#include -#include -#include -#include -#include -#include +#include "common.h" + +struct Options { + bool use_bitmasks; + bool use_frames; +}; + +void usage() { + fputs("Usage: pokemon_animation [-b|--bitmasks] [-f|--frames] front.animated.tilemap front.dimensions\n", stderr); +} + +void parse_args(int argc, char *argv[], struct Options *options) { + struct option long_options[] = { + {"bitmasks", no_argument, 0, 'b'}, + {"frames", no_argument, 0, 'f'}, + {"help", no_argument, 0, 'h'}, + {0} + }; + for (int opt; (opt = getopt_long(argc, argv, "bfh", long_options)) != -1;) { + switch (opt) { + case 'b': + options->use_bitmasks = true; + break; + case 'f': + options->use_frames = true; + break; + case 'h': + usage(); + exit(0); + break; + default: + usage(); + exit(1); + } + } +} struct Frame { - uint8_t* data; + uint8_t *data; int size; int bitmask; }; struct Frames { - struct Frame* frames; + struct Frame *frames; int num_frames; - int frame_size; }; struct Bitmask { - uint8_t* data; + uint8_t *data; int bitlength; }; struct Bitmasks { - struct Bitmask* bitmasks; + struct Bitmask *bitmasks; int num_bitmasks; }; - -void make_frames(struct Frames* frames, struct Bitmasks* bitmasks, char* tilemap_filename, char* dimensions_filename); -int bitmask_exists(struct Bitmask *bitmask, struct Bitmasks *bitmasks); -void print_frames(struct Frames* frames); - - -void make_frames(struct Frames* frames, struct Bitmasks* bitmasks, char* tilemap_filename, char* dimensions_filename) { - uint8_t* tilemap; - uint8_t* this_frame; - FILE* f; - size_t size; - int width; - int height; - uint8_t byte; - int frame_size; - int num_frames; - int i, j; - - f = fopen(tilemap_filename, "rb"); - if (f == NULL) { - fprintf(stderr, "could not open file %s\n", tilemap_filename); - exit(1); +int bitmask_exists(const struct Bitmask *bitmask, const struct Bitmasks *bitmasks) { + for (int i = 0; i < bitmasks->num_bitmasks; i++) { + struct Bitmask existing = bitmasks->bitmasks[i]; + if (bitmask->bitlength != existing.bitlength) { + continue; + } + bool match = true; + int length = (bitmask->bitlength + 7) / 8; + for (int j = 0; j < length; j++) { + if (bitmask->data[j] != existing.data[j]) { + match = false; + break; + } + } + if (match) { + return i; + } } + return -1; +} - fseek(f, 0, SEEK_END); - size = ftell(f); - if (!size) { - fprintf(stderr, "empty file %s\n", tilemap_filename); - exit(1); - } - rewind(f); +void make_frames(const uint8_t *tilemap, long tilemap_size, int width, struct Frames *frames, struct Bitmasks *bitmasks) { + int num_tiles_per_frame = width * width; + int num_frames = tilemap_size / num_tiles_per_frame - 1; - tilemap = malloc(size); - if (!tilemap) { - fprintf(stderr, "malloc failure\n"); - exit(1); - } - if (size != fread(tilemap, 1, size, f)) { - fprintf(stderr, "failed to read file %s\n", tilemap_filename); - exit(1); - } - fclose(f); + frames->frames = malloc_verbose((sizeof *frames->frames) * num_frames); + frames->num_frames = num_frames; - f = fopen(dimensions_filename, "rb"); - if (f == NULL) { - fprintf(stderr, "could not open file %s\n", dimensions_filename); - exit(1); - } - if (1 != fread(&byte, 1, 1, f)) { - fprintf(stderr, "failed to read file %s\n", dimensions_filename); - exit(1); - } - fclose(f); - - width = byte & 0xf; - height = byte >> 4; - - frame_size = width * height; - - num_frames = size / frame_size - 1; - //fprintf(stderr, "num_frames: %d\n", num_frames); - - bitmasks->bitmasks = malloc((sizeof (struct Bitmask)) * num_frames); + bitmasks->bitmasks = malloc_verbose((sizeof *bitmasks->bitmasks) * num_frames); bitmasks->num_bitmasks = 0; - frames->frames = malloc((sizeof (struct Frame)) * num_frames); - frames->frame_size = frame_size; - frames->num_frames = 0; - - uint8_t *first_frame = tilemap; - this_frame = tilemap + frame_size; - for (i = 0; i < num_frames; i++) { - struct Frame *frame = (struct Frame*)malloc(sizeof(struct Frame)); - frame->data = malloc(frame_size); + const uint8_t *first_frame = &tilemap[0]; + const uint8_t *this_frame = &tilemap[num_tiles_per_frame]; + for (int i = 0; i < num_frames; i++) { + struct Frame *frame = malloc_verbose(sizeof *frame); + frame->data = malloc_verbose(num_tiles_per_frame); frame->size = 0; - struct Bitmask *bitmask = (struct Bitmask*)malloc(sizeof(struct Bitmask)); - bitmask->data = calloc((frame_size + 7) / 8, 1); + + struct Bitmask *bitmask = malloc_verbose(sizeof *bitmask); + bitmask->data = calloc_verbose((num_tiles_per_frame + 7) / 8); bitmask->bitlength = 0; - for (j = 0; j < frame_size; j++) { + + for (int j = 0; j < num_tiles_per_frame; j++) { if (bitmask->bitlength % 8 == 0) { bitmask->data[bitmask->bitlength / 8] = 0; } @@ -133,151 +125,76 @@ void make_frames(struct Frames* frames, struct Bitmasks* bitmasks, char* tilemap free(bitmask); } frames->frames[i] = *frame; - frames->num_frames++; - this_frame += frame_size; + this_frame += num_tiles_per_frame; } - - //for (i = 0; i < frames->num_frames; i++) { - //free(frames->frames[i].data); - //free(frames->frames[i]); - //} - //free(frames->frames); - - //fprintf(stderr, "num bitmasks: %d\n", bitmasks->num_bitmasks); - //for (i = 0; i < bitmasks->num_bitmasks; i++) { - // free(bitmasks->bitmasks[i].data); - // fprintf(stderr, "freed bitmask %d\n", i); - //free(bitmasks->bitmasks[i]); - //} - //free(bitmasks->bitmasks); - //fprintf(stderr, "freed bitmasks\n"); - - free(tilemap); } -int bitmask_exists(struct Bitmask *bitmask, struct Bitmasks *bitmasks) { - int i, j; - struct Bitmask existing; - for (i = 0; i < bitmasks->num_bitmasks; i++) { - existing = bitmasks->bitmasks[i]; - if (bitmask->bitlength != existing.bitlength) { - continue; - } - bool match = true; - for (j = 0; j < (bitmask->bitlength + 7) / 8; j++) { - if (bitmask->data[j] != existing.data[j]) { - match = false; - break; - } - } - if (match) { - return i; - } - } - return -1; -} - -void print_frames(struct Frames* frames) { - int i; - int j; - for (i = 0; i < frames->num_frames; i++) { +void print_frames(struct Frames *frames) { + for (int i = 0; i < frames->num_frames; i++) { printf("\tdw .frame%d\n", i + 1); } - for (i = 0; i < frames->num_frames; i++) { - struct Frame *frame = &frames->frames[i]; + for (int i = 0; i < frames->num_frames; i++) { + const struct Frame *frame = &frames->frames[i]; printf(".frame%d\n", i + 1); printf("\tdb $%02x ; bitmask\n", frame->bitmask); if (frame->size > 0) { - for (j = 0; j < frame->size; j++) { + for (int j = 0; j < frame->size; j++) { if (j % 12 == 0) { if (j) { - printf("\n"); + putchar('\n'); } printf("\tdb $%02x", frame->data[j]); } else { printf(", $%02x", frame->data[j]); } } - printf("\n"); + putchar('\n'); } } } -void print_bitmasks(struct Bitmasks* bitmasks) { - int i, j, k; - int length; - struct Bitmask bitmask; - for (i = 0; i < bitmasks->num_bitmasks; i++) { +void print_bitmasks(const struct Bitmasks *bitmasks) { + for (int i = 0; i < bitmasks->num_bitmasks; i++) { + struct Bitmask bitmask = bitmasks->bitmasks[i]; printf("; %d\n", i); - bitmask = bitmasks->bitmasks[i]; - length = (bitmask.bitlength + 7) / 8; - for (j = 0; j < length; j++) { + int length = (bitmask.bitlength + 7) / 8; + for (int j = 0; j < length; j++) { printf("\tdb %%"); - for (k = 0; k < 8; k++) { - if ((bitmask.data[j] >> (7 - k)) & 1) { - printf("1"); - } else { - printf("0"); - }; + for (int k = 0; k < 8; k++) { + putchar(((bitmask.data[j] >> (7 - k)) & 1) ? '1' : '0'); } - printf("\n"); + putchar('\n'); } } } -// HOW ARE YOU GENTLEMEN. -char* cats (char* head, char* tail) { - char* string; - string = malloc(strlen(head) + strlen(tail) + 1); - strcpy(string, head); - strcat(string, tail); - return string; -} +int main(int argc, char *argv[]) { + struct Options options = {0}; + parse_args(argc, argv, &options); -static void usage(void) { - printf("Usage: pokemon_animation [-b] [-f] tilemap_file dimensions_file\n"); - exit(1); -} - -int main(int argc, char* argv[]) { - struct Frames frames = {0}; - struct Bitmasks bitmasks = {0}; - int ch; - bool use_bitmasks = false, use_frames = false; - char* tilemap_filename; - char* dimensions_filename; - - while ((ch = getopt(argc, argv, "bf")) != -1) { - switch (ch) { - case 'b': - use_bitmasks = true; - break; - case 'f': - use_frames = true; - break; - default: - usage(); - } - } argc -= optind; argv += optind; if (argc < 2) { usage(); + exit(1); } - tilemap_filename = argv[0]; - dimensions_filename = argv[1]; - //ext = strrchr(argv[3], '.'); - //if (!ext || ext == argv[3]) { - // fprintf(stderr, "need a file extension to determine what to write to %s\n", argv[3]); - //} + int width; + read_dimensions(argv[1], &width); + long tilemap_size; + uint8_t *tilemap = read_u8(argv[0], &tilemap_size); - make_frames(&frames, &bitmasks, tilemap_filename, dimensions_filename); - if (use_frames) { + struct Frames frames = {0}; + struct Bitmasks bitmasks = {0}; + make_frames(tilemap, tilemap_size, width, &frames, &bitmasks); + + if (options.use_frames) { print_frames(&frames); } - if (use_bitmasks) { + if (options.use_bitmasks) { print_bitmasks(&bitmasks); } + + free(tilemap); return 0; } diff --git a/tools/pokemon_animation_graphics.c b/tools/pokemon_animation_graphics.c index a49d4b7e1..27573a516 100644 --- a/tools/pokemon_animation_graphics.c +++ b/tools/pokemon_animation_graphics.c @@ -67,19 +67,8 @@ int get_tile_index(const uint8_t *tile, const uint8_t *tiles, int num_tiles, int return -1; } -uint8_t read_dimensions(const char *filename) { - long filesize; - uint8_t *bytes = read_u8(filename, &filesize); - if (filesize != 1) { - error_exit("%s: invalid dimensions file\n", filename); - } - uint8_t dimensions = bytes[0]; - free(bytes); - return dimensions; -} - -uint8_t *read_tiles(const char *filename, int width, int height, long *tiles_size) { - int frame_size = width * height * TILE_SIZE; +uint8_t *read_tiles(const char *filename, int width, long *tiles_size) { + int frame_size = width * width * TILE_SIZE; uint8_t *tiles = read_u8(filename, tiles_size); if (!*tiles_size) { @@ -87,7 +76,7 @@ uint8_t *read_tiles(const char *filename, int width, int height, long *tiles_siz } else if (*tiles_size % TILE_SIZE) { error_exit("%s: not divisible into 8x8-px 2bpp tiles\n", filename); } else if (*tiles_size % frame_size) { - error_exit("%s: not divisible into %dx%d-tile frames\n", filename, width, height); + error_exit("%s: not divisible into %dx%d-tile frames\n", filename, width, width); } int num_frames = *tiles_size / frame_size; @@ -169,18 +158,16 @@ int main(int argc, char *argv[]) { exit(1); } - uint8_t dimensions = read_dimensions(argv[1]); - int width = dimensions & 0xF; - int height = dimensions >> 4; - + int width; + read_dimensions(argv[1], &width); long tiles_size; - uint8_t *tiles = read_tiles(argv[0], width, height, &tiles_size); + uint8_t *tiles = read_tiles(argv[0], width, &tiles_size); if (options.out_filename) { - write_graphics(options.out_filename, tiles, tiles_size, width * height, options.girafarig); + write_graphics(options.out_filename, tiles, tiles_size, width * width, options.girafarig); } if (options.map_filename) { - write_tilemap(options.map_filename, tiles, tiles_size, width * height, options.girafarig); + write_tilemap(options.map_filename, tiles, tiles_size, width * width, options.girafarig); } free(tiles);