From 185a3b29e6d78b512ae371817d85fce8297926b2 Mon Sep 17 00:00:00 2001 From: Rangi42 Date: Fri, 4 Jul 2025 02:14:20 -0400 Subject: [PATCH] Implement base palette ID --- include/gfx/main.hpp | 1 + man/rgbgfx.1 | 6 ++++++ src/gfx/main.cpp | 20 ++++++++++++++++---- src/gfx/process.cpp | 8 ++++---- src/gfx/reverse.cpp | 8 ++++---- test/gfx/base_ids.flags | 3 +++ test/gfx/base_ids.out.2bpp | Bin 0 -> 32 bytes test/gfx/base_ids.out.attrmap | 1 + test/gfx/base_ids.out.pal | Bin 0 -> 32 bytes test/gfx/base_ids.out.tilemap | 1 + test/gfx/base_ids.png | Bin 0 -> 184 bytes 11 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 test/gfx/base_ids.flags create mode 100644 test/gfx/base_ids.out.2bpp create mode 100644 test/gfx/base_ids.out.attrmap create mode 100644 test/gfx/base_ids.out.pal create mode 100644 test/gfx/base_ids.out.tilemap create mode 100644 test/gfx/base_ids.png diff --git a/include/gfx/main.hpp b/include/gfx/main.hpp index 32bc4802..f1c9f26d 100644 --- a/include/gfx/main.hpp +++ b/include/gfx/main.hpp @@ -43,6 +43,7 @@ struct Options { uint32_t right() const { return left + width * 8; } uint32_t bottom() const { return top + height * 8; } } inputSlice{0, 0, 0, 0}; // -L (margins in clockwise order, like CSS) + uint8_t basePalID = 0; // -l std::array maxNbTiles{UINT16_MAX, 0}; // -N uint16_t nbPalettes = 8; // -n std::string output{}; // -o diff --git a/man/rgbgfx.1 b/man/rgbgfx.1 index 07ceb829..3c87186f 100644 --- a/man/rgbgfx.1 +++ b/man/rgbgfx.1 @@ -18,6 +18,7 @@ .Op Fl d Ar depth .Op Fl i Ar input_tiles .Op Fl L Ar slice +.Op Fl l Ar base_pal .Op Fl N Ar nb_tiles .Op Fl n Ar nb_pals .Op Fl o Ar out_file @@ -261,6 +262,11 @@ The first number pair specifies the X and Y coordinates of the top-left pixel th The second number pair specifies how many tiles to process horizontally and vertically, respectively. .Pp .Fl L Sy is ignored in reverse mode , No no padding is inserted . +.It Fl l Ar base_pal , Fl \-base-palette Ar base_pal +Set the base ID for attribute map and palette map output. +.Ar base_pal +should be a number between 0 and 255. +It defaults to 0. .It Fl m , Fl \-mirror-tiles Deduplicate tiles that are horizontally and/or vertically symmetrical mirror images of each other. Only one of each unique tile will be saved in the tile data file, with mirror images counting as duplicates. diff --git a/src/gfx/main.cpp b/src/gfx/main.cpp index 1c50c4b7..4bc41403 100644 --- a/src/gfx/main.cpp +++ b/src/gfx/main.cpp @@ -113,7 +113,7 @@ void Options::verbosePrint(uint8_t level, char const *fmt, ...) const { } // Short options -static char const *optstring = "-Aa:B:b:Cc:d:hi:L:mN:n:Oo:Pp:Qq:r:s:Tt:U:uVvXx:YZ"; +static char const *optstring = "-Aa:B:b:Cc:d:hi:L:l:mN:n:Oo:Pp:Qq:r:s:Tt:U:uVvXx:YZ"; // Equivalent long options // Please keep in the same order as short opts. @@ -133,6 +133,7 @@ static option const longopts[] = { {"help", no_argument, nullptr, 'h'}, {"input-tileset", required_argument, nullptr, 'i'}, {"slice", required_argument, nullptr, 'L'}, + {"base-palette", required_argument, nullptr, 'l'}, {"mirror-tiles", no_argument, nullptr, 'm'}, {"nb-tiles", required_argument, nullptr, 'N'}, {"nb-palettes", required_argument, nullptr, 'n'}, @@ -162,9 +163,9 @@ static void printUsage() { fputs( "Usage: rgbgfx [-r stride] [-ChmOuVXYZ] [-v [-v ...]] [-a | -A]\n" " [-b ] [-c ] [-d ] [-i ]\n" - " [-L ] [-N ] [-n ] [-o ]\n" - " [-p | -P] [-q | -Q] [-s ]\n" - " [-t | -T] [-x ] \n" + " [-L ] [-l ] [-N ] [-n ]\n" + " [-o ] [-p | -P] [-q | -Q]\n" + " [-s ] [-t | -T] [-x ] \n" "Useful options:\n" " -m, --mirror-tiles optimize out mirrored tiles\n" " -o, --output output the tile data to this path\n" @@ -481,6 +482,16 @@ static char *parseArgv(int argc, char *argv[]) { error("Unexpected extra characters after slice spec in \"%s\"", musl_optarg); } break; + case 'l': + number = parseNumber(arg, "Base palette ID", 0); + if (*arg != '\0') { + error("Base palette ID must be a valid number, not \"%s\"", musl_optarg); + } else if (number >= 256) { + error("Base palette ID must be below 256"); + } else { + options.basePalID = number; + } + break; case 'm': options.allowMirroringX = true; // Imply `-X` options.allowMirroringY = true; // Imply `-Y` @@ -876,6 +887,7 @@ int main(int argc, char *argv[]) { options.baseTileIDs[0], options.baseTileIDs[1] ); + fprintf(stderr, "\tBase palette ID: %" PRIu8 "\n", options.basePalID); fprintf( stderr, "\tMaximum %" PRIu16 " tiles in bank 0, %" PRIu16 " in bank 1\n", diff --git a/src/gfx/process.cpp b/src/gfx/process.cpp index 826d585b..1bcc7f3d 100644 --- a/src/gfx/process.cpp +++ b/src/gfx/process.cpp @@ -928,9 +928,9 @@ static void outputUnoptimizedMaps( (*tilemapOutput) ->sputc((attr.isBackgroundTile() ? 0 : tileID) + options.baseTileIDs[bank]); } - uint8_t palID = attr.getPalID(mappings); + uint8_t palID = attr.getPalID(mappings) + options.basePalID; if (attrmapOutput.has_value()) { - (*attrmapOutput)->sputc((palID & 7) | bank << 3); // The other flags are all 0 + (*attrmapOutput)->sputc((palID & 0b111) | bank << 3); // The other flags are all 0 } if (palmapOutput.has_value()) { (*palmapOutput)->sputc(palID); @@ -1112,7 +1112,7 @@ static void outputAttrmap( for (AttrmapEntry const &entry : attrmap) { uint8_t attr = entry.xFlip << 5 | entry.yFlip << 6; attr |= entry.bank << 3; - attr |= entry.getPalID(mappings) & 7; + attr |= (entry.getPalID(mappings) + options.basePalID) & 0b111; output->sputc(attr); } } @@ -1128,7 +1128,7 @@ static void outputPalmap( } for (AttrmapEntry const &entry : attrmap) { - output->sputc(entry.getPalID(mappings)); + output->sputc(entry.getPalID(mappings) + options.basePalID); } } diff --git a/src/gfx/reverse.cpp b/src/gfx/reverse.cpp index 6e3c3125..b577264e 100644 --- a/src/gfx/reverse.cpp +++ b/src/gfx/reverse.cpp @@ -289,10 +289,10 @@ void reverse() { uint8_t attr = (*attrmap)[index]; size_t tx = index % width, ty = index / width; - if ((attr & 0b111) > palettes.size()) { + if (uint8_t palID = (attr & 0b111) - options.basePalID; palID > palettes.size()) { error( "Attribute map references palette #%u at (%zu, %zu), but there are only %zu!", - attr & 0b111, + palID, tx, ty, palettes.size() @@ -356,7 +356,7 @@ void reverse() { size_t tx = index % width, ty = index / width; uint8_t tileID = (*tilemap)[index]; uint8_t attr = (*attrmap)[index]; - bool bank = attr & 0x08; + bool bank = attr & 0b1000; if (uint8_t tileOfs = tileID - options.baseTileIDs[bank]; tileOfs >= options.maxNbTiles[bank]) { @@ -511,7 +511,7 @@ void reverse() { : index; // This should have been enforced by the earlier checking. assume(tileOfs < nbTiles + options.trim); - size_t palID = palmap ? (*palmap)[index] : attribute & 0b111; + size_t palID = (palmap ? (*palmap)[index] : attribute & 0b111) - options.basePalID; assume(palID < palettes.size()); // Should be ensured on data read // We do not have data for tiles trimmed with `-x`, so assume they are "blank" diff --git a/test/gfx/base_ids.flags b/test/gfx/base_ids.flags new file mode 100644 index 00000000..a6944d16 --- /dev/null +++ b/test/gfx/base_ids.flags @@ -0,0 +1,3 @@ +-b 15 +-l 3 +-m diff --git a/test/gfx/base_ids.out.2bpp b/test/gfx/base_ids.out.2bpp new file mode 100644 index 0000000000000000000000000000000000000000..f87d96caabfff4645018b55f23aa0031bb67a6d5 GIT binary patch literal 32 UcmZQzU|{$UgdhS0jQLR^0KJR~2><{9 literal 0 HcmV?d00001 diff --git a/test/gfx/base_ids.out.attrmap b/test/gfx/base_ids.out.attrmap new file mode 100644 index 00000000..3bbc14dc --- /dev/null +++ b/test/gfx/base_ids.out.attrmap @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/gfx/base_ids.out.pal b/test/gfx/base_ids.out.pal new file mode 100644 index 0000000000000000000000000000000000000000..6baa19cf789541fac6ea724f1b9d58b36a18f41c GIT binary patch literal 32 ncmb*aIAYB*~Eu`vt3 literal 0 HcmV?d00001 diff --git a/test/gfx/base_ids.out.tilemap b/test/gfx/base_ids.out.tilemap new file mode 100644 index 00000000..0a59aad7 --- /dev/null +++ b/test/gfx/base_ids.out.tilemap @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/gfx/base_ids.png b/test/gfx/base_ids.png new file mode 100644 index 0000000000000000000000000000000000000000..257a85c3acda59c27e9c6deb9d470aab132f3ebb GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vfy;%mU%2s{hI><0@>8|%<5#&>0uFhP%dX0bHHF~1DE)$-3daBqFc%s zA8-3Vq2XInKuQ7-1Vq0%cmN0rwDYW(L11BuQ>%dji^O}r4cunN8vGl$mkCZ-euI@k X>7$6ePJjL?pw$eXu6{1-oD!MM literal 0 HcmV?d00001