diff --git a/Makefile b/Makefile index fb9e75a42..ed74afe5c 100644 --- a/Makefile +++ b/Makefile @@ -130,6 +130,11 @@ gfx/title/logo.2bpp: rgbgfx += -x 4 gfx/trade/ball.2bpp: tools/gfx += --remove-whitespace +gfx/slots_2.2bpp: tools/gfx += --interleave --width=16 +gfx/slots_3.2bpp: tools/gfx += --interleave --width=24 --remove-duplicates --keep-whitespace --remove-xflip +gfx/slots_3a.2bpp: tools/gfx += --interleave --width=16 +gfx/slots_3b.2bpp: tools/gfx += --interleave --width=24 --remove-duplicates --keep-whitespace --remove-xflip + %.bin: ; %.blk: ; diff --git a/gfx/pc.2bpp.lz b/gfx/pc.2bpp.lz.2201c1aa similarity index 100% rename from gfx/pc.2bpp.lz rename to gfx/pc.2bpp.lz.2201c1aa diff --git a/gfx/pc.png b/gfx/pc.png new file mode 100644 index 000000000..ce8fed73b Binary files /dev/null and b/gfx/pc.png differ diff --git a/gfx/pc_mail.2bpp b/gfx/pc_mail.2bpp deleted file mode 100644 index 9a6d66ab9..000000000 Binary files a/gfx/pc_mail.2bpp and /dev/null differ diff --git a/gfx/pc_mail.png b/gfx/pc_mail.png new file mode 100644 index 000000000..fd4b2892f Binary files /dev/null and b/gfx/pc_mail.png differ diff --git a/gfx/shrink1.2bpp.lz b/gfx/shrink1.2bpp.lz.d4443930 similarity index 100% rename from gfx/shrink1.2bpp.lz rename to gfx/shrink1.2bpp.lz.d4443930 diff --git a/gfx/shrink1.png b/gfx/shrink1.png new file mode 100644 index 000000000..6cf5b8077 Binary files /dev/null and b/gfx/shrink1.png differ diff --git a/gfx/shrink2.2bpp.lz b/gfx/shrink2.2bpp.lz.3f58480a similarity index 100% rename from gfx/shrink2.2bpp.lz rename to gfx/shrink2.2bpp.lz.3f58480a diff --git a/gfx/shrink2.png b/gfx/shrink2.png new file mode 100644 index 000000000..276b4e7c7 Binary files /dev/null and b/gfx/shrink2.png differ diff --git a/gfx/slots_1.2bpp.lz b/gfx/slots_1.2bpp.lz.b22ddc13 similarity index 100% rename from gfx/slots_1.2bpp.lz rename to gfx/slots_1.2bpp.lz.b22ddc13 diff --git a/gfx/slots_1.png b/gfx/slots_1.png new file mode 100644 index 000000000..a10340844 Binary files /dev/null and b/gfx/slots_1.png differ diff --git a/gfx/slots_2.2bpp.lz b/gfx/slots_2.2bpp.lz.b28f76e3 similarity index 100% rename from gfx/slots_2.2bpp.lz rename to gfx/slots_2.2bpp.lz.b28f76e3 diff --git a/gfx/slots_2.png b/gfx/slots_2.png new file mode 100644 index 000000000..aa1292ccb Binary files /dev/null and b/gfx/slots_2.png differ diff --git a/gfx/slots_3.2bpp.lz b/gfx/slots_3.2bpp.lz.70c2984c similarity index 100% rename from gfx/slots_3.2bpp.lz rename to gfx/slots_3.2bpp.lz.70c2984c diff --git a/gfx/slots_3.png b/gfx/slots_3.png new file mode 100755 index 000000000..456e9b6bf Binary files /dev/null and b/gfx/slots_3.png differ diff --git a/tools/gfx.c b/tools/gfx.c index bfad43c0e..8283d9e73 100644 --- a/tools/gfx.c +++ b/tools/gfx.c @@ -7,7 +7,7 @@ #include "common.h" static void usage(void) { - fprintf(stderr, "Usage: gfx [--trim-whitespace] [--remove-whitespace] [--interleave] [-w width] [-d depth] [-h] [-o outfile] infile\n"); + fprintf(stderr, "Usage: gfx [--trim-whitespace] [--remove-whitespace] [--interleave] [--remove-duplicates [--keep-whitespace]] [--remove-xflip] [-w width] [-d depth] [-h] [-o outfile] infile\n"); } static void error(char *message) { @@ -23,6 +23,9 @@ struct Options { int depth; int interleave; int width; + int remove_duplicates; + int keep_whitespace; + int remove_xflip; }; struct Options Options = { @@ -34,6 +37,9 @@ void get_args(int argc, char *argv[]) { {"remove-whitespace", no_argument, &Options.remove_whitespace, 1}, {"trim-whitespace", no_argument, &Options.trim_whitespace, 1}, {"interleave", no_argument, &Options.interleave, 1}, + {"remove-duplicates", no_argument, &Options.remove_duplicates, 1}, + {"keep-whitespace", no_argument, &Options.keep_whitespace, 1}, + {"remove-xflip", no_argument, &Options.remove_xflip, 1}, {"width", required_argument, 0, 'w'}, {"depth", required_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, @@ -92,11 +98,15 @@ void trim_whitespace(struct Graphic *graphic) { void remove_whitespace(struct Graphic *graphic) { int tile_size = Options.depth * 8; + if (Options.interleave) tile_size *= 2; int i = 0; for (int j = 0; i < graphic->size && j < graphic->size; i += tile_size, j += tile_size) { while (is_whitespace(&graphic->data[j], tile_size)) { j += tile_size; } + if (j >= graphic->size) { + break; + } if (j > i) { memcpy(&graphic->data[i], &graphic->data[j], tile_size); } @@ -104,6 +114,94 @@ void remove_whitespace(struct Graphic *graphic) { graphic->size = i; } +bool tile_exists(uint8_t *tile, uint8_t *tiles, int tile_size, int num_tiles) { + for (int i = 0; i < num_tiles; i++) { + bool match = true; + for (int j = 0; j < tile_size; j++) { + if (tile[j] != tiles[i * tile_size + j]) { + match = false; + } + } + if (match) { + return true; + } + } + return false; +} + +void remove_duplicates(struct Graphic *graphic) { + int tile_size = Options.depth * 8; + if (Options.interleave) tile_size *= 2; + int num_tiles = 0; + for (int i = 0, j = 0; i < graphic->size && j < graphic->size; i += tile_size, j += tile_size) { + while (tile_exists(&graphic->data[j], graphic->data, tile_size, num_tiles)) { + if (Options.keep_whitespace && is_whitespace(&graphic->data[j], tile_size)) { + break; + } + j += tile_size; + } + if (j >= graphic->size) { + break; + } + if (j > i) { + memcpy(&graphic->data[i], &graphic->data[j], tile_size); + } + num_tiles++; + } + graphic->size = num_tiles * tile_size; +} + +bool flip_exists(uint8_t *tile, uint8_t *tiles, int tile_size, int num_tiles, bool xflip, bool yflip) { + uint8_t *flip = calloc(tile_size, 1); + int half_size = tile_size / 2; + for (int i = 0; i < tile_size; i++) { + int byte = i; + if (yflip) { + byte = tile_size - 1 - i; + if (Options.interleave && i < half_size) { + byte = half_size - 1 - i; + } + } + if (flip) { + for (int bit = 0; bit < 8; bit++) { + flip[byte] |= ((tile[i] >> bit) & 1) << (7 - bit); + } + } else { + flip[byte] = tile[i]; + } + } + if (tile_exists(flip, tiles, tile_size, num_tiles)) { + return true; + } + return false; +} + +bool xflip_exists(uint8_t *tile, uint8_t *tiles, int tile_size, int num_tiles) { + return flip_exists(tile, tiles, tile_size, num_tiles, true, false); +} + +void remove_xflip(struct Graphic *graphic) { + int tile_size = Options.depth * 8; + if (Options.interleave) tile_size *= 2; + int num_tiles = 0; + for (int i = 0, j = 0; i < graphic->size && j < graphic->size; i += tile_size, j += tile_size) { + while (xflip_exists(&graphic->data[j], graphic->data, tile_size, num_tiles)) { + if (Options.keep_whitespace && is_whitespace(&graphic->data[j], tile_size)) { + break; + } + j += tile_size; + } + if (j >= graphic->size) { + break; + } + if (j > i) { + memcpy(&graphic->data[i], &graphic->data[j], tile_size); + } + num_tiles++; + } + graphic->size = num_tiles * tile_size; +} + void interleave(struct Graphic *graphic, int width) { int tile_size = Options.depth * 8; int width_tiles = width / 8; @@ -119,6 +217,7 @@ void interleave(struct Graphic *graphic, int width) { } memcpy(&interleaved[tile * tile_size], &graphic->data[i * tile_size], tile_size); } + graphic->size = num_tiles * tile_size; memcpy(graphic->data, interleaved, graphic->size); free(interleaved); } @@ -139,9 +238,6 @@ int main(int argc, char *argv[]) { char *infile = argv[0]; struct Graphic graphic; graphic.data = read_u8(infile, &graphic.size); - if (Options.remove_whitespace) { - remove_whitespace(&graphic); - } if (Options.trim_whitespace) { trim_whitespace(&graphic); } @@ -153,6 +249,15 @@ int main(int argc, char *argv[]) { } interleave(&graphic, Options.width); } + if (Options.remove_duplicates) { + remove_duplicates(&graphic); + } + if (Options.remove_xflip) { + remove_xflip(&graphic); + } + if (Options.remove_whitespace) { + remove_whitespace(&graphic); + } if (Options.outfile) { write_u8(Options.outfile, graphic.data, graphic.size); }