diff --git a/src/gfx/main.cpp b/src/gfx/main.cpp index 9e9014d0..9e38cdb7 100644 --- a/src/gfx/main.cpp +++ b/src/gfx/main.cpp @@ -736,6 +736,9 @@ void Palette::addColor(uint16_t color) { } } +/** + * Returns the ID of the color in the palette, or `size()` if the color is not in + */ uint8_t Palette::indexOf(uint16_t color) const { return std::find(colors.begin(), colors.end(), color) - colors.begin(); } diff --git a/src/gfx/pal_packing.cpp b/src/gfx/pal_packing.cpp index 92c451ee..21af352f 100644 --- a/src/gfx/pal_packing.cpp +++ b/src/gfx/pal_packing.cpp @@ -8,9 +8,11 @@ #include "gfx/pal_packing.hpp" +#include #include #include #include +#include #include #include #include @@ -19,6 +21,8 @@ #include #include +#include "defaultinitalloc.hpp" + #include "gfx/main.hpp" #include "gfx/proto_palette.hpp" @@ -356,32 +360,16 @@ std::tuple, size_t> options.verbosePrint(Options::VERB_LOG_ACT, "Paginating palettes using \"overload-and-remove\" strategy...\n"); - struct Iota { - using value_type = size_t; - using difference_type = size_t; - using pointer = value_type const *; - using reference = value_type const &; - using iterator_category = std::input_iterator_tag; - - // Use aggregate init etc. - value_type i; - - bool operator!=(Iota const &other) { return i != other.i; } - reference operator*() const { return i; } - pointer operator->() const { return &i; } - Iota operator++() { - ++i; - return *this; - } - Iota operator++(int) { - Iota copy = *this; - ++i; - return copy; - } - }; - + // Sort the proto-palettes by size, which improves the packing algorithm's efficiency + DefaultInitVec sortedProtoPalIDs(protoPalettes.size()); + sortedProtoPalIDs.clear(); + for (size_t i = 0; i < protoPalettes.size(); ++i) { + sortedProtoPalIDs.insert( + std::lower_bound(sortedProtoPalIDs.begin(), sortedProtoPalIDs.end(), i), i); + } // Begin with all proto-palettes queued up for insertion - std::queue queue(std::deque(Iota{0}, Iota{protoPalettes.size()})); + std::queue queue( + std::deque(sortedProtoPalIDs.begin(), sortedProtoPalIDs.end())); // Begin with no pages std::vector assignments{}; diff --git a/src/gfx/process.cpp b/src/gfx/process.cpp index d023c511..87ba5905 100644 --- a/src/gfx/process.cpp +++ b/src/gfx/process.cpp @@ -574,6 +574,7 @@ public: for (uint32_t x = 0; x < 8; ++x) { row <<= 1; uint8_t index = palette.indexOf(tile.pixel(x, y).cgbColor()); + assert(index < palette.size()); // The color should be in the palette if (index & 1) { row |= 1; } @@ -948,12 +949,6 @@ contained:; } } - // Sort the proto-palettes by size, which improves the packing algorithm's efficiency - // We sort after all insertions to avoid moving items: https://stackoverflow.com/a/2710332 - std::sort( - protoPalettes.begin(), protoPalettes.end(), - [](ProtoPalette const &lhs, ProtoPalette const &rhs) { return lhs.size() < rhs.size(); }); - auto [mappings, palettes] = options.palSpecType == Options::NO_SPEC ? generatePalettes(protoPalettes, png) : makePalsAsSpecified(protoPalettes, png);