shithub: rgbds

Download patch

ref: 6e406b22bbe3e5f66193a94364114aafacc8b8da
parent: d30e507270ab476011b69706ee60a550d55974a0
author: ISSOtm <[email protected]>
date: Tue Mar 1 14:41:27 EST 2022

Implement more features and fix bugs

--- a/include/gfx/convert.hpp
+++ b/include/gfx/convert.hpp
@@ -23,9 +23,14 @@
 	Rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : red(r), green(g), blue(b), alpha(a) {}
 	Rgba(uint32_t rgba) : red(rgba), green(rgba >> 8), blue(rgba >> 16), alpha(rgba >> 24) {}
 
-	operator uint32_t() const {
+	operator uint32_t() const { return toCSS(); }
+	/**
+	 * Returns this RGBA as a 32-bit number that can be printed in hex (`%08x`) to yield its CSS
+	 * representation
+	 */
+	uint32_t toCSS() const {
 		auto shl = [](uint8_t val, unsigned shift) { return static_cast<uint32_t>(val) << shift; };
-		return shl(red, 0) | shl(green, 8) | shl(blue, 16) | shl(alpha, 24);
+		return shl(red, 24) | shl(green, 16) | shl(blue, 8) | shl(alpha, 0);
 	}
 	bool operator!=(Rgba const &other) const {
 		return static_cast<uint32_t>(*this) != static_cast<uint32_t>(other);
@@ -39,12 +44,15 @@
 	 */
 	static constexpr uint16_t transparent = 0b1'00000'00000'00000;
 
-	static constexpr uint8_t transparency_threshold = 5; // TODO: adjust this
 	/**
+	 * All alpha values strictly below this will be considered transparent
+	 */
+	static constexpr uint8_t opacity_threshold = 0xF0; // TODO: adjust this
+	/**
 	 * Computes the equivalent CGB color, respects the color curve depending on options
 	 */
 	uint16_t cgbColor() const {
-		if (alpha > 0xFF - transparency_threshold)
+		if (alpha < opacity_threshold)
 			return transparent;
 		if (options.useColorCurve) {
 			assert(!"TODO");
--- a/include/gfx/main.hpp
+++ b/include/gfx/main.hpp
@@ -11,6 +11,7 @@
 
 #include <array>
 #include <filesystem>
+#include <limits.h>
 #include <stdint.h>
 
 #include "helpers.h"
@@ -27,7 +28,7 @@
 	uint8_t nbPalettes = 8; // TODO
 	uint8_t nbColorsPerPal = 0; // TODO; 0 means "auto" = 1 << bitDepth;
 	std::array<uint8_t, 2> baseTileIDs{0, 0}; // TODO
-	std::array<uint16_t, 2> maxNbTiles{384, 0}; // TODO
+	std::array<uint16_t, 2> maxNbTiles{UINT16_MAX, 0}; // TODO
 	std::filesystem::path tilemap{}; // -t, -T
 	std::filesystem::path attrmap{}; // -a, -A
 	std::filesystem::path palettes{}; // -p, -P
@@ -35,6 +36,9 @@
 	std::filesystem::path input{}; // positional arg
 
 	format_(printf, 2, 3) void verbosePrint(char const *fmt, ...) const;
+	uint8_t maxPalSize() const {
+		return nbColorsPerPal;
+	} // TODO: minus 1 when transparency is active
 };
 
 extern Options options;
--- a/src/gfx/convert.cpp
+++ b/src/gfx/convert.cpp
@@ -44,7 +44,8 @@
 		if (!slot.has_value()) {
 			slot.emplace(rgba);
 		} else if (*slot != rgba) {
-			warning("Different colors melded together"); // TODO: indicate position
+			warning("Different colors melded together (#%08x into #%08x as %04x)", rgba.toCSS(),
+			        slot->toCSS(), rgba.cgbColor()); // TODO: indicate position
 		}
 	}
 
@@ -363,7 +364,7 @@
 	public:
 		iterator begin() const { return {*this, _width, 0, 0}; }
 		iterator end() const {
-			iterator it{*this, _width, _width - 8, _height - 8}; // Last valid one
+			iterator it{*this, _limit, _width - 8, _height - 8}; // Last valid one
 			return ++it; // Now one-past-last
 		}
 	};
@@ -443,7 +444,9 @@
 				}
 			}
 			output.sputc(row & 0xFF);
-			output.sputc(row >> 8);
+			if (options.bitDepth == 2) {
+				output.sputc(row >> 8);
+			}
 		}
 		++iter;
 	}
@@ -505,6 +508,7 @@
 	mutable size_t tileID;
 
 	TileData(Png::TilesVisitor::Tile const &tile, Palette const &palette) : _hash(0) {
+		size_t writeIndex = 0;
 		for (uint32_t y = 0; y < 8; ++y) {
 			uint16_t bitplanes = 0;
 			for (uint32_t x = 0; x < 8; ++x) {
@@ -517,8 +521,10 @@
 					bitplanes |= 0x100;
 				}
 			}
-			_data[y * 2] = bitplanes & 0xFF;
-			_data[y * 2 + 1] = bitplanes >> 8;
+			_data[writeIndex++] = bitplanes & 0xFF;
+			if (options.bitDepth == 2) {
+				_data[writeIndex++] = bitplanes >> 8;
+			}
 
 			// Update the hash
 			_hash ^= bitplanes;
@@ -632,7 +638,7 @@
 	for (TileData const *tile : tiles) {
 		assert(tile->tileID == tileID);
 		++tileID;
-		output.sputn(reinterpret_cast<char const *>(tile->data().data()), tile->data().size());
+		output.sputn(reinterpret_cast<char const *>(tile->data().data()), options.bitDepth * 8);
 	}
 }
 
--- a/src/gfx/pal_packing.cpp
+++ b/src/gfx/pal_packing.cpp
@@ -203,10 +203,8 @@
 	size_t volume() const { return uniqueColors().size(); }
 	bool canFit(ProtoPalette const &protoPal) const {
 		auto &colors = uniqueColors();
-		for (uint16_t color : protoPal) {
-			colors.insert(color);
-		}
-		return colors.size() <= 4;
+		colors.insert(protoPal.begin(), protoPal.end());
+		return colors.size() <= options.maxPalSize();
 	}
 };
 
@@ -274,9 +272,9 @@
 			bestPal.assign(std::move(attrs));
 
 			// If this overloads the palette, get it back to normal (if possible)
-			while (bestPal.volume() > 4) {
-				options.verbosePrint("Palette %zu is overloaded! (%zu > 4)\n", bestPalIndex,
-				                     bestPal.volume());
+			while (bestPal.volume() > options.maxPalSize()) {
+				options.verbosePrint("Palette %zu is overloaded! (%zu > %" PRIu8 ")\n",
+				                     bestPalIndex, bestPal.volume(), options.maxPalSize());
 
 				// Look for a proto-pal minimizing "efficiency" (size / rel_size)
 				auto efficiency = [&bestPal](ProtoPalette const &pal) {
@@ -309,7 +307,7 @@
 
 	// Deal with palettes still overloaded, by emptying them
 	for (AssignedProtos &pal : assignments) {
-		if (pal.volume() > 4) {
+		if (pal.volume() > options.maxPalSize()) {
 			for (ProtoPalAttrs &attrs : pal) {
 				queue.emplace(std::move(attrs));
 			}