Add support for GBC palette dumps to `-c`
Fixes
@@ -191,6 +191,15 @@ static T readBE(U const *bytes) {
return val;
}
+template<typename T, typename U>
+static T readLE(U const *bytes) {
+ T val = 0;
+ for (size_t i = 0; i < sizeof(val); ++i) {
+ val |= static_cast<uint8_t>(bytes[i]) << (i * 8);
+ }
+ return val;
+}
+
/*
* **Appends** the first line read from `file` to the end of the provided `buffer`.
*/
@@ -295,7 +304,7 @@ static void parsePSPFile(std::filebuf &file) {
}
}
-void parseACTFile(std::filebuf &file) {
+static void parseACTFile(std::filebuf &file) {
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577411_pgfId-1070626
std::array<char, 772> buf;
@@ -344,8 +353,8 @@ void parseACTFile(std::filebuf &file) {
}
}
-void parseACOFile(std::filebuf &file) {
- // rhttps://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577411_pgfId-1055819
+static void parseACOFile(std::filebuf &file) {
+ // https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577411_pgfId-1055819
// http://www.nomodes.com/aco.html
char buf[10];
@@ -412,6 +421,29 @@ void parseACOFile(std::filebuf &file) {
// `codecvt` can be used to convert from UTF-16 to UTF-8
}
+static void parseGBCFile(std::filebuf &file) {
+ // This only needs to be able to read back files generated by `rgbgfx -p`
+ options.palSpec.clear();
+
+ for (;;) {
+ char buf[2 * 4];
+ auto len = file.sgetn(buf, sizeof(buf));
+ if (len == 0) {
+ break;
+ } else if (len != sizeof(buf)) {
+ error("GBC palette dump contains %zu 8-byte palette%s, plus %zu byte%s",
+ options.palSpec.size(), options.palSpec.size() == 1 ? "" : "s",
+ len, len == 1 ? "" : "s");
+ break;
+ }
+
+ options.palSpec.push_back({Rgba::fromCGBColor(readLE<uint16_t>(&buf[0])),
+ Rgba::fromCGBColor(readLE<uint16_t>(&buf[2])),
+ Rgba::fromCGBColor(readLE<uint16_t>(&buf[4])),
+ Rgba::fromCGBColor(readLE<uint16_t>(&buf[6]))});
+ }
+}
+
void parseExternalPalSpec(char const *arg) {
// `fmt:path`, parse the file according to the given format
@@ -427,6 +459,7 @@ void parseExternalPalSpec(char const *arg) {
std::tuple{"PSP", &parsePSPFile, std::ios::in },
std::tuple{"ACT", &parseACTFile, std::ios::binary},
std::tuple{"ACO", &parseACOFile, std::ios::binary},
+ std::tuple{"GBC", &parseGBCFile, std::ios::binary},
};
auto iter = std::find_if(parsers.begin(), parsers.end(),
