mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
gfx: Add mirrored tile check when generating tilemap
This commit is contained in:
@@ -36,6 +36,8 @@ Other contributors
|
|||||||
|
|
||||||
- The OpenBSD Project <http://www.openbsd.org>
|
- The OpenBSD Project <http://www.openbsd.org>
|
||||||
|
|
||||||
|
- Quint Guvernator <quint@guvernator.net>
|
||||||
|
|
||||||
- Sanqui <gsanky@gmail.com>
|
- Sanqui <gsanky@gmail.com>
|
||||||
|
|
||||||
- YamaArashi <shadow962@live.com>
|
- YamaArashi <shadow962@live.com>
|
||||||
|
|||||||
@@ -12,14 +12,24 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "gfx/main.h"
|
#include "gfx/main.h"
|
||||||
|
|
||||||
|
#define XFLIP 0x40
|
||||||
|
#define YFLIP 0x20
|
||||||
|
|
||||||
void raw_to_gb(const struct RawIndexedImage *raw_image, struct GBImage *gb);
|
void raw_to_gb(const struct RawIndexedImage *raw_image, struct GBImage *gb);
|
||||||
void output_file(const struct Options *opts, const struct GBImage *gb);
|
void output_file(const struct Options *opts, const struct GBImage *gb);
|
||||||
int get_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles,
|
int get_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles,
|
||||||
int tile_size);
|
int tile_size);
|
||||||
void create_tilemap(const struct Options *opts, struct GBImage *gb,
|
uint8_t reverse_bits(uint8_t b);
|
||||||
struct Tilemap *tilemap);
|
void xflip(uint8_t *tile, uint8_t *tile_xflip, int tile_size);
|
||||||
|
void yflip(uint8_t *tile, uint8_t *tile_yflip, int tile_size);
|
||||||
|
int get_mirrored_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles,
|
||||||
|
int tile_size, int *flags);
|
||||||
|
void create_mapfiles(const struct Options *opts, struct GBImage *gb,
|
||||||
|
struct Mapfile *tilemap, struct Mapfile *attrmap);
|
||||||
void output_tilemap_file(const struct Options *opts,
|
void output_tilemap_file(const struct Options *opts,
|
||||||
const struct Tilemap *tilemap);
|
const struct Mapfile *tilemap);
|
||||||
|
void output_attrmap_file(const struct Options *opts,
|
||||||
|
const struct Mapfile *attrmap);
|
||||||
void output_palette_file(const struct Options *opts,
|
void output_palette_file(const struct Options *opts,
|
||||||
const struct RawIndexedImage *raw_image);
|
const struct RawIndexedImage *raw_image);
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,13 @@ struct Options {
|
|||||||
bool hardfix;
|
bool hardfix;
|
||||||
bool fix;
|
bool fix;
|
||||||
bool horizontal;
|
bool horizontal;
|
||||||
|
bool mirror;
|
||||||
bool unique;
|
bool unique;
|
||||||
int trim;
|
int trim;
|
||||||
char *mapfile;
|
char *tilemapfile;
|
||||||
bool mapout;
|
bool tilemapout;
|
||||||
|
char *attrmapfile;
|
||||||
|
bool attrmapout;
|
||||||
char *palfile;
|
char *palfile;
|
||||||
bool palout;
|
bool palout;
|
||||||
char *outfile;
|
char *outfile;
|
||||||
@@ -40,8 +43,10 @@ struct RGBColor {
|
|||||||
struct ImageOptions {
|
struct ImageOptions {
|
||||||
bool horizontal;
|
bool horizontal;
|
||||||
int trim;
|
int trim;
|
||||||
char *mapfile;
|
char *tilemapfile;
|
||||||
bool mapout;
|
bool tilemapout;
|
||||||
|
char *attrmapfile;
|
||||||
|
bool attrmapout;
|
||||||
char *palfile;
|
char *palfile;
|
||||||
bool palout;
|
bool palout;
|
||||||
};
|
};
|
||||||
@@ -71,7 +76,7 @@ struct GBImage {
|
|||||||
int trim;
|
int trim;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Tilemap {
|
struct Mapfile {
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
int size;
|
int size;
|
||||||
};
|
};
|
||||||
|
|||||||
142
src/gfx/gb.c
142
src/gfx/gb.c
@@ -85,8 +85,87 @@ int get_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles, int tile_size)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_tilemap(const struct Options *opts, struct GBImage *gb,
|
uint8_t reverse_bits(uint8_t b)
|
||||||
struct Tilemap *tilemap)
|
{
|
||||||
|
uint8_t rev = 0;
|
||||||
|
|
||||||
|
rev |= (b & 0x80) >> 7;
|
||||||
|
rev |= (b & 0x40) >> 5;
|
||||||
|
rev |= (b & 0x20) >> 3;
|
||||||
|
rev |= (b & 0x10) >> 1;
|
||||||
|
rev |= (b & 0x08) << 1;
|
||||||
|
rev |= (b & 0x04) << 3;
|
||||||
|
rev |= (b & 0x02) << 5;
|
||||||
|
rev |= (b & 0x01) << 7;
|
||||||
|
return rev;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xflip(uint8_t *tile, uint8_t *tile_xflip, int tile_size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < tile_size; i++)
|
||||||
|
tile_xflip[i] = reverse_bits(tile[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void yflip(uint8_t *tile, uint8_t *tile_yflip, int tile_size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < tile_size; i++)
|
||||||
|
tile_yflip[i] = tile[(tile_size - i - 1) ^ (depth - 1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_mirrored_tile_index looks for `tile` in tile array `tiles`, also
|
||||||
|
* checking x-, y-, and xy-mirrored versions of `tile`. If one is found,
|
||||||
|
* `*flags` is set according to the type of mirroring and the index of the
|
||||||
|
* matched tile is returned. If no match is found, -1 is returned.
|
||||||
|
*/
|
||||||
|
int get_mirrored_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles,
|
||||||
|
int tile_size, int *flags)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
uint8_t *tile_xflip;
|
||||||
|
uint8_t *tile_yflip;
|
||||||
|
|
||||||
|
index = get_tile_index(tile, tiles, num_tiles, tile_size);
|
||||||
|
if (index >= 0) {
|
||||||
|
*flags = 0;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
tile_yflip = malloc(tile_size);
|
||||||
|
yflip(tile, tile_yflip, tile_size);
|
||||||
|
index = get_tile_index(tile_yflip, tiles, num_tiles, tile_size);
|
||||||
|
if (index >= 0) {
|
||||||
|
*flags = YFLIP;
|
||||||
|
free(tile_yflip);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
tile_xflip = malloc(tile_size);
|
||||||
|
xflip(tile, tile_xflip, tile_size);
|
||||||
|
index = get_tile_index(tile_xflip, tiles, num_tiles, tile_size);
|
||||||
|
if (index >= 0) {
|
||||||
|
*flags = XFLIP;
|
||||||
|
free(tile_yflip);
|
||||||
|
free(tile_xflip);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
yflip(tile_xflip, tile_yflip, tile_size);
|
||||||
|
index = get_tile_index(tile_yflip, tiles, num_tiles, tile_size);
|
||||||
|
if (index >= 0)
|
||||||
|
*flags = XFLIP | YFLIP;
|
||||||
|
|
||||||
|
free(tile_yflip);
|
||||||
|
free(tile_xflip);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_mapfiles(const struct Options *opts, struct GBImage *gb,
|
||||||
|
struct Mapfile *tilemap, struct Mapfile *attrmap)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
int gb_i;
|
int gb_i;
|
||||||
@@ -94,6 +173,7 @@ void create_tilemap(const struct Options *opts, struct GBImage *gb,
|
|||||||
int max_tiles;
|
int max_tiles;
|
||||||
int num_tiles;
|
int num_tiles;
|
||||||
int index;
|
int index;
|
||||||
|
int flags;
|
||||||
int gb_size;
|
int gb_size;
|
||||||
uint8_t *tile;
|
uint8_t *tile;
|
||||||
uint8_t **tiles;
|
uint8_t **tiles;
|
||||||
@@ -109,19 +189,33 @@ void create_tilemap(const struct Options *opts, struct GBImage *gb,
|
|||||||
tiles = calloc(max_tiles, sizeof(uint8_t *));
|
tiles = calloc(max_tiles, sizeof(uint8_t *));
|
||||||
num_tiles = 0;
|
num_tiles = 0;
|
||||||
|
|
||||||
tilemap->data = calloc(max_tiles, sizeof(uint8_t));
|
if (*opts->tilemapfile) {
|
||||||
tilemap->size = 0;
|
tilemap->data = calloc(max_tiles, sizeof(uint8_t));
|
||||||
|
tilemap->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*opts->attrmapfile) {
|
||||||
|
attrmap->data = calloc(max_tiles, sizeof(uint8_t));
|
||||||
|
attrmap->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_i = 0;
|
gb_i = 0;
|
||||||
while (gb_i < gb_size) {
|
while (gb_i < gb_size) {
|
||||||
|
flags = 0;
|
||||||
tile = malloc(tile_size);
|
tile = malloc(tile_size);
|
||||||
for (i = 0; i < tile_size; i++) {
|
for (i = 0; i < tile_size; i++) {
|
||||||
tile[i] = gb->data[gb_i];
|
tile[i] = gb->data[gb_i];
|
||||||
gb_i++;
|
gb_i++;
|
||||||
}
|
}
|
||||||
if (opts->unique) {
|
if (opts->unique) {
|
||||||
index = get_tile_index(tile, tiles, num_tiles,
|
if (opts->mirror) {
|
||||||
tile_size);
|
index = get_mirrored_tile_index(tile, tiles, num_tiles,
|
||||||
|
tile_size, &flags);
|
||||||
|
} else {
|
||||||
|
index = get_tile_index(tile, tiles, num_tiles,
|
||||||
|
tile_size);
|
||||||
|
}
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
index = num_tiles;
|
index = num_tiles;
|
||||||
tiles[num_tiles] = tile;
|
tiles[num_tiles] = tile;
|
||||||
@@ -132,8 +226,14 @@ void create_tilemap(const struct Options *opts, struct GBImage *gb,
|
|||||||
tiles[num_tiles] = tile;
|
tiles[num_tiles] = tile;
|
||||||
num_tiles++;
|
num_tiles++;
|
||||||
}
|
}
|
||||||
tilemap->data[tilemap->size] = index;
|
if (*opts->tilemapfile) {
|
||||||
tilemap->size++;
|
tilemap->data[tilemap->size] = index;
|
||||||
|
tilemap->size++;
|
||||||
|
}
|
||||||
|
if (*opts->attrmapfile) {
|
||||||
|
attrmap->data[attrmap->size] = flags;
|
||||||
|
attrmap->size++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->unique) {
|
if (opts->unique) {
|
||||||
@@ -154,19 +254,35 @@ void create_tilemap(const struct Options *opts, struct GBImage *gb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void output_tilemap_file(const struct Options *opts,
|
void output_tilemap_file(const struct Options *opts,
|
||||||
const struct Tilemap *tilemap)
|
const struct Mapfile *tilemap)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
f = fopen(opts->mapfile, "wb");
|
f = fopen(opts->tilemapfile, "wb");
|
||||||
if (!f)
|
if (!f)
|
||||||
err(1, "Opening tilemap file '%s' failed", opts->mapfile);
|
err(1, "Opening tilemap file '%s' failed", opts->tilemapfile);
|
||||||
|
|
||||||
fwrite(tilemap->data, 1, tilemap->size, f);
|
fwrite(tilemap->data, 1, tilemap->size, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
if (opts->mapout)
|
if (opts->tilemapout)
|
||||||
free(opts->mapfile);
|
free(opts->tilemapfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void output_attrmap_file(const struct Options *opts,
|
||||||
|
const struct Mapfile *attrmap)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
f = fopen(opts->attrmapfile, "wb");
|
||||||
|
if (!f)
|
||||||
|
err(1, "Opening attrmap file '%s' failed", opts->attrmapfile);
|
||||||
|
|
||||||
|
fwrite(attrmap->data, 1, attrmap->size, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if (opts->attrmapout)
|
||||||
|
free(opts->attrmapfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void output_palette_file(const struct Options *opts,
|
void output_palette_file(const struct Options *opts,
|
||||||
|
|||||||
106
src/gfx/main.c
106
src/gfx/main.c
@@ -18,8 +18,8 @@
|
|||||||
static void print_usage(void)
|
static void print_usage(void)
|
||||||
{
|
{
|
||||||
printf(
|
printf(
|
||||||
"usage: rgbgfx [-DFfhPTuVv] [-d #] [-o outfile] [-p palfile] [-t mapfile]\n"
|
"usage: rgbgfx [-ADFfhmPTuVv] [-o outfile] [-a attrmap] [-d #] [-p palfile]\n"
|
||||||
" [-x #] infile\n");
|
" [-t tilemap] [-x #] infile\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,21 +30,29 @@ int main(int argc, char *argv[])
|
|||||||
struct ImageOptions png_options = {0};
|
struct ImageOptions png_options = {0};
|
||||||
struct RawIndexedImage *raw_image;
|
struct RawIndexedImage *raw_image;
|
||||||
struct GBImage gb = {0};
|
struct GBImage gb = {0};
|
||||||
struct Tilemap tilemap = {0};
|
struct Mapfile tilemap = {0};
|
||||||
|
struct Mapfile attrmap = {0};
|
||||||
char *ext;
|
char *ext;
|
||||||
const char *errmsg = "Warning: The PNG's %s setting is not the same as the setting defined on the command line.";
|
const char *errmsg = "Warning: The PNG's %s setting is not the same as the setting defined on the command line.";
|
||||||
|
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
print_usage();
|
print_usage();
|
||||||
|
|
||||||
opts.mapfile = "";
|
opts.tilemapfile = "";
|
||||||
|
opts.attrmapfile = "";
|
||||||
opts.palfile = "";
|
opts.palfile = "";
|
||||||
opts.outfile = "";
|
opts.outfile = "";
|
||||||
|
|
||||||
depth = 2;
|
depth = 2;
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "Dd:Ffho:Tt:uPp:Vvx:")) != -1) {
|
while ((ch = getopt(argc, argv, "Aa:Dd:Ffhmo:Tt:uPp:Vvx:")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
|
case 'A':
|
||||||
|
opts.attrmapout = true;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
opts.attrmapfile = optarg;
|
||||||
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
opts.debug = true;
|
opts.debug = true;
|
||||||
break;
|
break;
|
||||||
@@ -60,6 +68,10 @@ int main(int argc, char *argv[])
|
|||||||
case 'h':
|
case 'h':
|
||||||
opts.horizontal = true;
|
opts.horizontal = true;
|
||||||
break;
|
break;
|
||||||
|
case 'm':
|
||||||
|
opts.mirror = true;
|
||||||
|
opts.unique = true;
|
||||||
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
opts.outfile = optarg;
|
opts.outfile = optarg;
|
||||||
break;
|
break;
|
||||||
@@ -70,10 +82,10 @@ int main(int argc, char *argv[])
|
|||||||
opts.palfile = optarg;
|
opts.palfile = optarg;
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
opts.mapout = true;
|
opts.tilemapout = true;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
opts.mapfile = optarg;
|
opts.tilemapfile = optarg;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
opts.unique = true;
|
opts.unique = true;
|
||||||
@@ -107,7 +119,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
raw_image = input_png_file(&opts, &png_options);
|
raw_image = input_png_file(&opts, &png_options);
|
||||||
|
|
||||||
png_options.mapfile = "";
|
png_options.tilemapfile = "";
|
||||||
|
png_options.attrmapfile = "";
|
||||||
png_options.palfile = "";
|
png_options.palfile = "";
|
||||||
|
|
||||||
if (png_options.horizontal != opts.horizontal) {
|
if (png_options.horizontal != opts.horizontal) {
|
||||||
@@ -148,25 +161,45 @@ int main(int argc, char *argv[])
|
|||||||
(raw_image->width / 8) * (raw_image->height / 8) - 1);
|
(raw_image->width / 8) * (raw_image->height / 8) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(png_options.mapfile, opts.mapfile) != 0) {
|
if (strcmp(png_options.tilemapfile, opts.tilemapfile) != 0) {
|
||||||
if (opts.verbose)
|
if (opts.verbose)
|
||||||
warnx(errmsg, "tilemap file");
|
warnx(errmsg, "tilemap file");
|
||||||
|
|
||||||
if (opts.hardfix)
|
if (opts.hardfix)
|
||||||
png_options.mapfile = opts.mapfile;
|
png_options.tilemapfile = opts.tilemapfile;
|
||||||
}
|
}
|
||||||
if (!*opts.mapfile)
|
if (!*opts.tilemapfile)
|
||||||
opts.mapfile = png_options.mapfile;
|
opts.tilemapfile = png_options.tilemapfile;
|
||||||
|
|
||||||
if (png_options.mapout != opts.mapout) {
|
if (png_options.tilemapout != opts.tilemapout) {
|
||||||
if (opts.verbose)
|
if (opts.verbose)
|
||||||
warnx(errmsg, "tilemap file");
|
warnx(errmsg, "tilemap file");
|
||||||
|
|
||||||
if (opts.hardfix)
|
if (opts.hardfix)
|
||||||
png_options.mapout = opts.mapout;
|
png_options.tilemapout = opts.tilemapout;
|
||||||
}
|
}
|
||||||
if (png_options.mapout)
|
if (png_options.tilemapout)
|
||||||
opts.mapout = png_options.mapout;
|
opts.tilemapout = png_options.tilemapout;
|
||||||
|
|
||||||
|
if (strcmp(png_options.attrmapfile, opts.attrmapfile) != 0) {
|
||||||
|
if (opts.verbose)
|
||||||
|
warnx(errmsg, "attrmap file");
|
||||||
|
|
||||||
|
if (opts.hardfix)
|
||||||
|
png_options.attrmapfile = opts.attrmapfile;
|
||||||
|
}
|
||||||
|
if (!*opts.attrmapfile)
|
||||||
|
opts.attrmapfile = png_options.attrmapfile;
|
||||||
|
|
||||||
|
if (png_options.attrmapout != opts.attrmapout) {
|
||||||
|
if (opts.verbose)
|
||||||
|
warnx(errmsg, "attrmap file");
|
||||||
|
|
||||||
|
if (opts.hardfix)
|
||||||
|
png_options.attrmapout = opts.attrmapout;
|
||||||
|
}
|
||||||
|
if (png_options.attrmapout)
|
||||||
|
opts.attrmapout = png_options.attrmapout;
|
||||||
|
|
||||||
if (strcmp(png_options.palfile, opts.palfile) != 0) {
|
if (strcmp(png_options.palfile, opts.palfile) != 0) {
|
||||||
if (opts.verbose)
|
if (opts.verbose)
|
||||||
@@ -189,19 +222,35 @@ int main(int argc, char *argv[])
|
|||||||
if (png_options.palout)
|
if (png_options.palout)
|
||||||
opts.palout = png_options.palout;
|
opts.palout = png_options.palout;
|
||||||
|
|
||||||
if (!*opts.mapfile && opts.mapout) {
|
if (!*opts.tilemapfile && opts.tilemapout) {
|
||||||
ext = strrchr(opts.infile, '.');
|
ext = strrchr(opts.infile, '.');
|
||||||
|
|
||||||
if (ext != NULL) {
|
if (ext != NULL) {
|
||||||
size = ext - opts.infile + 9;
|
size = ext - opts.infile + 9;
|
||||||
opts.mapfile = malloc(size);
|
opts.tilemapfile = malloc(size);
|
||||||
strncpy(opts.mapfile, opts.infile, size);
|
strncpy(opts.tilemapfile, opts.infile, size);
|
||||||
*strrchr(opts.mapfile, '.') = '\0';
|
*strrchr(opts.tilemapfile, '.') = '\0';
|
||||||
strcat(opts.mapfile, ".tilemap");
|
strcat(opts.tilemapfile, ".tilemap");
|
||||||
} else {
|
} else {
|
||||||
opts.mapfile = malloc(strlen(opts.infile) + 9);
|
opts.tilemapfile = malloc(strlen(opts.infile) + 9);
|
||||||
strcpy(opts.mapfile, opts.infile);
|
strcpy(opts.tilemapfile, opts.infile);
|
||||||
strcat(opts.mapfile, ".tilemap");
|
strcat(opts.tilemapfile, ".tilemap");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*opts.attrmapfile && opts.attrmapout) {
|
||||||
|
ext = strrchr(opts.infile, '.');
|
||||||
|
|
||||||
|
if (ext != NULL) {
|
||||||
|
size = ext - opts.infile + 9;
|
||||||
|
opts.attrmapfile = malloc(size);
|
||||||
|
strncpy(opts.attrmapfile, opts.infile, size);
|
||||||
|
*strrchr(opts.attrmapfile, '.') = '\0';
|
||||||
|
strcat(opts.attrmapfile, ".attrmap");
|
||||||
|
} else {
|
||||||
|
opts.attrmapfile = malloc(strlen(opts.infile) + 9);
|
||||||
|
strcpy(opts.attrmapfile, opts.infile);
|
||||||
|
strcat(opts.attrmapfile, ".attrmap");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,17 +275,20 @@ int main(int argc, char *argv[])
|
|||||||
gb.trim = opts.trim;
|
gb.trim = opts.trim;
|
||||||
gb.horizontal = opts.horizontal;
|
gb.horizontal = opts.horizontal;
|
||||||
|
|
||||||
if (*opts.outfile || *opts.mapfile) {
|
if (*opts.outfile || *opts.tilemapfile || *opts.attrmapfile) {
|
||||||
raw_to_gb(raw_image, &gb);
|
raw_to_gb(raw_image, &gb);
|
||||||
create_tilemap(&opts, &gb, &tilemap);
|
create_mapfiles(&opts, &gb, &tilemap, &attrmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*opts.outfile)
|
if (*opts.outfile)
|
||||||
output_file(&opts, &gb);
|
output_file(&opts, &gb);
|
||||||
|
|
||||||
if (*opts.mapfile)
|
if (*opts.tilemapfile)
|
||||||
output_tilemap_file(&opts, &tilemap);
|
output_tilemap_file(&opts, &tilemap);
|
||||||
|
|
||||||
|
if (*opts.attrmapfile)
|
||||||
|
output_attrmap_file(&opts, &attrmap);
|
||||||
|
|
||||||
if (*opts.palfile)
|
if (*opts.palfile)
|
||||||
output_palette_file(&opts, raw_image);
|
output_palette_file(&opts, raw_image);
|
||||||
|
|
||||||
|
|||||||
@@ -649,10 +649,16 @@ static void get_text(const struct PNGImage *img,
|
|||||||
png_options->trim = strtoul(text[i].text, NULL, 0);
|
png_options->trim = strtoul(text[i].text, NULL, 0);
|
||||||
png_free_data(img->png, img->info, PNG_FREE_TEXT, i);
|
png_free_data(img->png, img->info, PNG_FREE_TEXT, i);
|
||||||
} else if (strcmp(text[i].key, "t") == 0) {
|
} else if (strcmp(text[i].key, "t") == 0) {
|
||||||
png_options->mapfile = text[i].text;
|
png_options->tilemapfile = text[i].text;
|
||||||
png_free_data(img->png, img->info, PNG_FREE_TEXT, i);
|
png_free_data(img->png, img->info, PNG_FREE_TEXT, i);
|
||||||
} else if (strcmp(text[i].key, "T") == 0 && !*text[i].text) {
|
} else if (strcmp(text[i].key, "T") == 0 && !*text[i].text) {
|
||||||
png_options->mapout = true;
|
png_options->tilemapout = true;
|
||||||
|
png_free_data(img->png, img->info, PNG_FREE_TEXT, i);
|
||||||
|
} else if (strcmp(text[i].key, "a") == 0) {
|
||||||
|
png_options->attrmapfile = text[i].text;
|
||||||
|
png_free_data(img->png, img->info, PNG_FREE_TEXT, i);
|
||||||
|
} else if (strcmp(text[i].key, "A") == 0 && !*text[i].text) {
|
||||||
|
png_options->attrmapout = true;
|
||||||
png_free_data(img->png, img->info, PNG_FREE_TEXT, i);
|
png_free_data(img->png, img->info, PNG_FREE_TEXT, i);
|
||||||
} else if (strcmp(text[i].key, "p") == 0) {
|
} else if (strcmp(text[i].key, "p") == 0) {
|
||||||
png_options->palfile = text[i].text;
|
png_options->palfile = text[i].text;
|
||||||
@@ -699,18 +705,30 @@ static void set_text(const struct PNGImage *img,
|
|||||||
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||||
png_set_text(img->png, img->info, text, 1);
|
png_set_text(img->png, img->info, text, 1);
|
||||||
}
|
}
|
||||||
if (*png_options->mapfile) {
|
if (*png_options->tilemapfile) {
|
||||||
text[0].key = "t";
|
text[0].key = "t";
|
||||||
text[0].text = "";
|
text[0].text = "";
|
||||||
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||||
png_set_text(img->png, img->info, text, 1);
|
png_set_text(img->png, img->info, text, 1);
|
||||||
}
|
}
|
||||||
if (png_options->mapout) {
|
if (png_options->tilemapout) {
|
||||||
text[0].key = "T";
|
text[0].key = "T";
|
||||||
text[0].text = "";
|
text[0].text = "";
|
||||||
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||||
png_set_text(img->png, img->info, text, 1);
|
png_set_text(img->png, img->info, text, 1);
|
||||||
}
|
}
|
||||||
|
if (*png_options->attrmapfile) {
|
||||||
|
text[0].key = "a";
|
||||||
|
text[0].text = "";
|
||||||
|
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||||
|
png_set_text(img->png, img->info, text, 1);
|
||||||
|
}
|
||||||
|
if (png_options->attrmapout) {
|
||||||
|
text[0].key = "A";
|
||||||
|
text[0].text = "";
|
||||||
|
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||||
|
png_set_text(img->png, img->info, text, 1);
|
||||||
|
}
|
||||||
if (*png_options->palfile) {
|
if (*png_options->palfile) {
|
||||||
text[0].key = "p";
|
text[0].key = "p";
|
||||||
text[0].text = "";
|
text[0].text = "";
|
||||||
|
|||||||
@@ -13,11 +13,12 @@
|
|||||||
.Nd Game Boy graphics converter
|
.Nd Game Boy graphics converter
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm rgbgfx
|
.Nm rgbgfx
|
||||||
.Op Fl DfFhPTVv
|
.Op Fl ADfFhmPTuVv
|
||||||
.Op Fl o Ar outfile
|
.Op Fl o Ar outfile
|
||||||
|
.Op Fl a Ar attrmap
|
||||||
.Op Fl d Ar depth
|
.Op Fl d Ar depth
|
||||||
.Op Fl p Ar palfile
|
.Op Fl p Ar palfile
|
||||||
.Op Fl t Ar mapfile
|
.Op Fl t Ar tilemap
|
||||||
.Op Fl x Ar tiles
|
.Op Fl x Ar tiles
|
||||||
.Ar file
|
.Ar file
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
@@ -47,6 +48,19 @@ The input image may not contain more colors than the selected bit depth
|
|||||||
allows. Transparent pixels are set to palette index 0.
|
allows. Transparent pixels are set to palette index 0.
|
||||||
.Sh ARGUMENTS
|
.Sh ARGUMENTS
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
|
.It Fl a Ar attrmap
|
||||||
|
Generate a file of tile mirroring attributes for OAM or (CGB-only) background
|
||||||
|
tiles. For each tile in the input file, a byte is written representing the
|
||||||
|
dimensions that the associated tile in the output file should be mirrored.
|
||||||
|
Useful in combination with
|
||||||
|
.Fl m
|
||||||
|
to keep track the mirror direction of mirrored duplicate tiles.
|
||||||
|
.It Fl A
|
||||||
|
Same as
|
||||||
|
.Fl a ,
|
||||||
|
but the attrmap file output name is made by taking the input filename, removing
|
||||||
|
the file extension, and appending
|
||||||
|
.Pa .attrmap .
|
||||||
.It Fl D
|
.It Fl D
|
||||||
Debug features are enabled.
|
Debug features are enabled.
|
||||||
.It Fl f
|
.It Fl f
|
||||||
@@ -61,6 +75,12 @@ The bit depth of the output image (either 1 or 2).
|
|||||||
By default, the bit depth is 2 (two bits per pixel).
|
By default, the bit depth is 2 (two bits per pixel).
|
||||||
.It Fl h
|
.It Fl h
|
||||||
Lay out tiles horizontally rather than vertically.
|
Lay out tiles horizontally rather than vertically.
|
||||||
|
.It Fl m
|
||||||
|
Truncate tiles by checking for tiles that are mirrored versions of others and
|
||||||
|
omitting these from the output file. Useful with tilemaps and attrmaps together
|
||||||
|
to keep track of the duplicated tiles and the dimension mirrored. Tiles are
|
||||||
|
checked for horizontal, vertical, and horizontal-vertical mirroring. Implies
|
||||||
|
.Fl u .
|
||||||
.It Fl o Ar outfile
|
.It Fl o Ar outfile
|
||||||
The name of the output file.
|
The name of the output file.
|
||||||
.It Fl p Ar palfile
|
.It Fl p Ar palfile
|
||||||
@@ -74,17 +94,24 @@ Same as
|
|||||||
but the palette file output name is made by taking the input PNG file's
|
but the palette file output name is made by taking the input PNG file's
|
||||||
filename, removing the file extension, and appending
|
filename, removing the file extension, and appending
|
||||||
.Pa .pal .
|
.Pa .pal .
|
||||||
.It Fl t Ar mapfile
|
.It Fl t Ar tilemap
|
||||||
If any tiles are the same, don't place the repeat tiles in the output file, and
|
Generate a file of tile indices. For each tile in the input file, a byte is
|
||||||
make a tilemap file.
|
written representing the index of the associated tile in the output file.
|
||||||
|
Useful in combination with
|
||||||
|
.Fl u
|
||||||
|
or
|
||||||
|
.Fl m
|
||||||
|
to keep track of duplicate tiles.
|
||||||
.It Fl T
|
.It Fl T
|
||||||
Same as
|
Same as
|
||||||
.Fl t ,
|
.Fl t ,
|
||||||
but the tilemap file output name is made by taking the input filename,
|
but the tilemap file output name is made by taking the input filename, removing
|
||||||
removing the file extension, and appending
|
the file extension, and appending
|
||||||
.Pa .tilemap .
|
.Pa .tilemap .
|
||||||
.It Fl u
|
.It Fl u
|
||||||
Truncate repeated tiles. Useful with tilemaps.
|
Truncate tiles by checking for tiles that are exact duplicates of others and
|
||||||
|
omitting these from the output file. Useful with tilemaps to keep track of the
|
||||||
|
duplicated tiles.
|
||||||
.It Fl V
|
.It Fl V
|
||||||
Print the version of the program and exit.
|
Print the version of the program and exit.
|
||||||
.It Fl v
|
.It Fl v
|
||||||
@@ -105,6 +132,14 @@ The following creates a planar 2bpp file with only unique tiles, and its tilemap
|
|||||||
.Pp
|
.Pp
|
||||||
.D1 $ rgbgfx -T -u -o out.2bpp in.png
|
.D1 $ rgbgfx -T -u -o out.2bpp in.png
|
||||||
.Pp
|
.Pp
|
||||||
|
The following creates a planar 2bpp file with only unique tiles (accounting for
|
||||||
|
tile mirroring) and its associated tilemap
|
||||||
|
.Pa out.tilemap
|
||||||
|
and attrmap
|
||||||
|
.Pa out.attrmap :
|
||||||
|
.Pp
|
||||||
|
.D1 $ rgbgfx -A -T -m -o out.2bpp in.png
|
||||||
|
.Pp
|
||||||
The following will do nothing:
|
The following will do nothing:
|
||||||
.Pp
|
.Pp
|
||||||
.D1 $ rgbgfx in.png
|
.D1 $ rgbgfx in.png
|
||||||
|
|||||||
Reference in New Issue
Block a user