From 3f5983358cc8f791d80912d928a4d65cb4c62212 Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Sat, 21 May 2022 15:34:44 +0200 Subject: [PATCH] Add proper error message for bad manual palettes --- include/gfx/main.hpp | 13 +++++++++++++ src/gfx/main.cpp | 16 ++++++++-------- src/gfx/process.cpp | 33 ++++++++++++++++++++++++++++----- test/gfx/bad_manual_pals.err | 6 ++++++ test/gfx/bad_manual_pals.flags | 1 + test/gfx/bad_manual_pals.png | Bin 0 -> 712 bytes 6 files changed, 56 insertions(+), 13 deletions(-) create mode 100644 test/gfx/bad_manual_pals.err create mode 100644 test/gfx/bad_manual_pals.flags create mode 100644 test/gfx/bad_manual_pals.png diff --git a/include/gfx/main.hpp b/include/gfx/main.hpp index a85b929f..7a030917 100644 --- a/include/gfx/main.hpp +++ b/include/gfx/main.hpp @@ -67,8 +67,21 @@ struct Options { extern Options options; +/** + * Prints the error count, and exits with failure + */ +[[noreturn]] void giveUp(); +/** + * Prints a warning, and does not change the error count + */ void warning(char const *fmt, ...); +/** + * Prints an error, and increments the error count + */ void error(char const *fmt, ...); +/** + * Prints a fatal error, increments the error count, and gives up + */ [[noreturn]] void fatal(char const *fmt, ...); struct Palette { diff --git a/src/gfx/main.cpp b/src/gfx/main.cpp index 092282df..cacb8553 100644 --- a/src/gfx/main.cpp +++ b/src/gfx/main.cpp @@ -37,6 +37,11 @@ Options options; char const *externalPalSpec = nullptr; static uintmax_t nbErrors; +[[noreturn]] void giveUp() { + fprintf(stderr, "Conversion aborted after %ju error%s\n", nbErrors, nbErrors == 1 ? "" : "s"); + exit(1); +} + void warning(char const *fmt, ...) { va_list ap; @@ -72,8 +77,7 @@ void error(char const *fmt, ...) { if (nbErrors != std::numeric_limits::max()) nbErrors++; - fprintf(stderr, "Conversion aborted after %ju error%s\n", nbErrors, nbErrors == 1 ? "" : "s"); - exit(1); + giveUp(); } void Options::verbosePrint(uint8_t level, char const *fmt, ...) const { @@ -718,9 +722,7 @@ int main(int argc, char *argv[]) { // Do not do anything if option parsing went wrong if (nbErrors) { - fprintf(stderr, "Conversion aborted after %ju error%s\n", nbErrors, - nbErrors == 1 ? "" : "s"); - return 1; + giveUp(); } if (options.reverse()) { @@ -730,9 +732,7 @@ int main(int argc, char *argv[]) { } if (nbErrors) { - fprintf(stderr, "Conversion aborted after %ju error%s\n", nbErrors, - nbErrors == 1 ? "" : "s"); - return 1; + giveUp(); } return 0; } diff --git a/src/gfx/process.cpp b/src/gfx/process.cpp index a857c688..07a7e6f3 100644 --- a/src/gfx/process.cpp +++ b/src/gfx/process.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -557,8 +558,6 @@ static std::tuple, std::vector> // Fill in the palette spec options.palSpec.emplace_back(); // A single palette, with `#00000000`s (transparent) assert(options.palSpec.size() == 1); - // TODO: abort if ignored colors are being used; do it now for a friendlier error - // message if (embPalSize > options.maxOpaqueColors()) { // Ignore extraneous colors if they are unused embPalSize = options.maxOpaqueColors(); } @@ -571,13 +570,24 @@ static std::tuple, std::vector> // Convert the palette spec to actual palettes std::vector palettes(options.palSpec.size()); for (auto [spec, pal] : zip(options.palSpec, palettes)) { - for (size_t i = 0; i < options.nbColorsPerPal; ++i) { + for (size_t i = 0; i < options.nbColorsPerPal && spec[i].isOpaque(); ++i) { pal[i] = spec[i].cgbColor(); } } + auto listColors = [](auto const &list) { + static char buf[sizeof(", $XXXX, $XXXX, $XXXX, $XXXX")]; + char *ptr = buf; + for (uint16_t cgbColor : list) { + sprintf(ptr, ", $%04x", cgbColor); + ptr += 7; + } + return &buf[2]; + }; + // Iterate through proto-palettes, and try mapping them to the specified palettes DefaultInitVec mappings(protoPalettes.size()); + bool bad = false; for (size_t i = 0; i < protoPalettes.size(); ++i) { ProtoPalette const &protoPal = protoPalettes[i]; // Find the palette... @@ -587,8 +597,21 @@ static std::tuple, std::vector> return std::find(pal.begin(), pal.end(), color) != pal.end(); }); }); - assert(iter != palettes.end()); // TODO: produce a proper error message - mappings[i] = iter - palettes.begin(); + + if (iter == palettes.end()) { + assert(!protoPal.empty()); + error("Could not fit tile colors [%s] in specified palettes", listColors(protoPal)); + bad = true; + } + mappings[i] = iter - palettes.begin(); // Bogus value, but whatever + } + if (bad) { + fprintf(stderr, "note: The following palette%s specified:\n", + palettes.size() == 1 ? " was" : "s were"); + for (Palette const &pal : palettes) { + fprintf(stderr, " [%s]\n", listColors(pal)); + } + giveUp(); } return {mappings, palettes}; diff --git a/test/gfx/bad_manual_pals.err b/test/gfx/bad_manual_pals.err new file mode 100644 index 00000000..100436c6 --- /dev/null +++ b/test/gfx/bad_manual_pals.err @@ -0,0 +1,6 @@ +error: Could not fit tile colors [$6c8a, $7f55, $7fff] in specified palettes +error: Could not fit tile colors [$6c8a, $7f55] in specified palettes +note: The following palettes were specified: + [$7fff, $7f55] + [$7fff, $6c8a] +Conversion aborted after 2 errors diff --git a/test/gfx/bad_manual_pals.flags b/test/gfx/bad_manual_pals.flags new file mode 100644 index 00000000..e50cdf66 --- /dev/null +++ b/test/gfx/bad_manual_pals.flags @@ -0,0 +1 @@ +-c #fff,#a9d4fe:#fff,#5721d9 diff --git a/test/gfx/bad_manual_pals.png b/test/gfx/bad_manual_pals.png new file mode 100644 index 0000000000000000000000000000000000000000..57fdd36f50ceea06ff1b3c6d58a745fd05c30f13 GIT binary patch literal 712 zcmV;(0yq7MP)EX>4Tx04R}tkv&MmKp2MKrk09SMA|{bAwzYtAS&XhRVYG*P%E_RU~=gnG%+M8 zE{=k0!NH%!s)LKOt`4q(Aov5~=;Wm6A|-y86k5c1$8itueecWNcYx5SGR^8512o+> zGpVGQ%dd#xSA-BnKh3zzEMr!Z((oN$_XzO)F2S?>>;4?QYQbVaKqQ`FhG`S86Hjg0 z2Iqa^7%R&v@j3CRNf#u3)BVfh)c3-)I2SpQP8@ zTKov;+XgPK+nTZmT zjFc#Q&F9_SoqhYarq#b6S`%`eYNz2J00009a7bBm001r{001r{0eGc9b^rhX>PbXF zR7l6oRxu94APfX6FR7F+eM^=MRi9XOV98s$G*Z7phDeo*iERvt;w{0tGv_nlV~p-U zUhnkJR@`r1%mFjHG8tT5h#X)pUm4(bjs^t$zPoyYFw6mcKEGGI>ak6gJqW|hCtwaJ z^|gq8w2QhTt*czbmv2MgWeyS-L0fSWbQOUfeVlr#b2Ev?skijN+}jKRow9oL!%tJZ zi6-S|cCd1^LeER2Ir2__qtSun&CZ0U?;;$J%O{JTGzl*y3JU~34rT4Me=