summaryrefslogtreecommitdiff
path: root/src/factories/TextureFactory.cpp
diff options
context:
space:
mode:
authorKiritoDv <kiritodev01@gmail.com>2024-02-21 12:51:47 -0600
committerLywx <kiritodev01@gmail.com>2024-02-21 20:38:05 -0600
commit70a6bb7cf1a93609bcb92f14673c064d98ff9cf5 (patch)
tree6d30a15ac7ce377343422798b2c9b9bcffca4b5b /src/factories/TextureFactory.cpp
parent3845d02cf603dbba49b44a160b4e1958c86c738e (diff)
Added asset mods support
Diffstat (limited to 'src/factories/TextureFactory.cpp')
-rw-r--r--src/factories/TextureFactory.cpp176
1 files changed, 157 insertions, 19 deletions
diff --git a/src/factories/TextureFactory.cpp b/src/factories/TextureFactory.cpp
index 5a0caad..6f1de04 100644
--- a/src/factories/TextureFactory.cpp
+++ b/src/factories/TextureFactory.cpp
@@ -4,18 +4,22 @@
#include "Companion.h"
#include <iomanip>
-static const std::unordered_map <std::string, TextureType> gTextureTypes = {
- { "RGBA16", TextureType::RGBA16bpp },
- { "RGBA32", TextureType::RGBA32bpp },
- { "CI4", TextureType::Palette4bpp },
- { "CI8", TextureType::Palette8bpp },
- { "I4", TextureType::Grayscale4bpp },
- { "I8", TextureType::Grayscale8bpp },
- { "IA1", TextureType::GrayscaleAlpha1bpp },
- { "IA4", TextureType::GrayscaleAlpha4bpp },
- { "IA8", TextureType::GrayscaleAlpha8bpp },
- { "IA16", TextureType::GrayscaleAlpha16bpp },
- { "TLUT", TextureType::TLUT },
+extern "C" {
+#include "n64graphics/n64graphics.h"
+}
+
+static const std::unordered_map <std::string, TextureFormat> gTextureTypes = {
+ { "RGBA16", { TextureType::RGBA16bpp, 16 } },
+ { "RGBA32", { TextureType::RGBA32bpp, 32 } },
+ { "CI4", { TextureType::Palette4bpp, 4 } },
+ { "CI8", { TextureType::Palette8bpp, 8 } },
+ { "I4", { TextureType::Grayscale4bpp, 4 } },
+ { "I8", { TextureType::Grayscale8bpp, 8 } },
+ { "IA1", { TextureType::GrayscaleAlpha1bpp, 1 } },
+ { "IA4", { TextureType::GrayscaleAlpha4bpp, 4 } },
+ { "IA8", { TextureType::GrayscaleAlpha8bpp, 8 } },
+ { "IA16", { TextureType::GrayscaleAlpha16bpp, 16 } },
+ { "TLUT", { TextureType::TLUT, 0 } },
};
size_t CalculateTextureSize(TextureType type, uint32_t width, uint32_t height) {
@@ -134,7 +138,7 @@ void TextureBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedD
WriteHeader(writer, LUS::ResourceType::Texture, 0);
- writer.Write((uint32_t) texture->mType);
+ writer.Write((uint32_t) texture->mType.type);
writer.Write(texture->mWidth);
writer.Write(texture->mHeight);
@@ -143,6 +147,53 @@ void TextureBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedD
writer.Finish(write);
}
+void TextureModdingExporter::Export(std::ostream&write, std::shared_ptr<IParsedData> data, std::string&entryName, YAML::Node&node, std::string* replacement) {
+ auto texture = std::static_pointer_cast<TextureData>(data);
+ auto format = texture->mType;
+ uint8_t* raw = new uint8_t[CalculateTextureSize(format.type, texture->mWidth, texture->mHeight) * 2];
+ int size = 0;
+
+ auto ext = GetSafeNode<std::string>(node, "format");
+
+ std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
+ (*replacement) += "." + ext + ".png";
+
+ switch (format.type) {
+ case TextureType::RGBA16bpp:
+ case TextureType::RGBA32bpp: {
+ rgba* imgr = raw2rgba(texture->mBuffer.data(), texture->mWidth, texture->mHeight, format.depth);
+ if(rgba2png(&raw, &size, imgr, texture->mWidth, texture->mHeight)) {
+ throw std::runtime_error("Failed to convert texture to PNG");
+ }
+ break;
+ }
+ case TextureType::GrayscaleAlpha16bpp:
+ case TextureType::GrayscaleAlpha8bpp:
+ case TextureType::GrayscaleAlpha4bpp:
+ case TextureType::GrayscaleAlpha1bpp: {
+ ia* imgia = raw2ia(texture->mBuffer.data(), texture->mWidth, texture->mHeight, format.depth);
+ if(ia2png(&raw, &size, imgia, texture->mWidth, texture->mHeight)) {
+ throw std::runtime_error("Failed to convert texture to PNG");
+ }
+ break;
+ }
+ case TextureType::Grayscale8bpp:
+ case TextureType::Grayscale4bpp: {
+ ia* imgi = raw2i(texture->mBuffer.data(), texture->mWidth, texture->mHeight, format.depth);
+ if(ia2png(&raw, &size, imgi, texture->mWidth, texture->mHeight)) {
+ throw std::runtime_error("Failed to convert texture to PNG");
+ }
+ break;
+ }
+ default: {
+ SPDLOG_ERROR("Unsupported texture format for modding: {}", ext);
+ }
+ }
+
+ write.write(reinterpret_cast<char*>(raw), size);
+}
+
+
std::optional<std::shared_ptr<IParsedData>> TextureFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
auto format = GetSafeNode<std::string>(node, "format");
uint32_t width;
@@ -161,9 +212,9 @@ std::optional<std::shared_ptr<IParsedData>> TextureFactory::parse(std::vector<ui
return std::nullopt;
}
- TextureType type = gTextureTypes.at(format);
+ TextureFormat fmt = gTextureTypes.at(format);
- if(type == TextureType::TLUT){
+ if(fmt.type == TextureType::TLUT){
width = GetSafeNode<uint32_t>(node, "colors");
height = 1;
} else {
@@ -171,18 +222,105 @@ std::optional<std::shared_ptr<IParsedData>> TextureFactory::parse(std::vector<ui
height = GetSafeNode<uint32_t>(node, "height");
}
- size = GetSafeNode<uint32_t>(node, "size", CalculateTextureSize(gTextureTypes.at(format), width, height));
+ size = GetSafeNode<uint32_t>(node, "size", CalculateTextureSize(gTextureTypes.at(format).type, width, height));
auto [_, segment] = Decompressor::AutoDecode(node, buffer, size);
std::vector<uint8_t> result;
- if(type == TextureType::GrayscaleAlpha1bpp){
+ if(fmt.type == TextureType::GrayscaleAlpha1bpp){
result = alloc_ia8_text_from_i1(reinterpret_cast<uint16_t*>(segment.data), 8, 16);
} else {
result = std::vector(segment.data, segment.data + segment.size);
}
SPDLOG_INFO("Texture: {}", format);
- if(type == TextureType::TLUT){
+ if(fmt.type == TextureType::TLUT){
+ SPDLOG_INFO("Colors: {}", width);
+ } else {
+ SPDLOG_INFO("Width: {}", width);
+ SPDLOG_INFO("Height: {}", height);
+ }
+ SPDLOG_INFO("Size: {}", size);
+ SPDLOG_INFO("Offset: 0x{:X}", offset);
+ SPDLOG_INFO("Is Compressed: {}", Decompressor::IsCompressed(node) ? "true" : "false");
+
+ if(result.size() == 0){
+ return std::nullopt;
+ }
+
+ return std::make_shared<TextureData>(fmt, width, height, result);
+}
+
+std::optional<std::shared_ptr<IParsedData>> TextureFactory::parse_modding(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ auto format = GetSafeNode<std::string>(node, "format");
+ int width;
+ int height;
+ uint32_t size;
+ auto offset = GetSafeNode<uint32_t>(node, "offset");
+
+ if (format.empty()) {
+ SPDLOG_ERROR("Texture entry at {:X} in yaml missing format node\n\
+ Please add one of the following formats\n\
+ rgba16, rgba32, ia16, ia8, ia4, i8, i4, ci8, ci4, 1bpp, tlut", offset);
+ return std::nullopt;
+ }
+
+ if(!gTextureTypes.contains(format)) {
+ return std::nullopt;
+ }
+
+ TextureFormat fmt = gTextureTypes.at(format);
+ if(fmt.type == TextureType::TLUT){
+ width = GetSafeNode<uint32_t>(node, "colors");
+ height = 1;
+ } else {
+ width = GetSafeNode<uint32_t>(node, "width");
+ height = GetSafeNode<uint32_t>(node, "height");
+ }
+
+ uint8_t* raw;
+ switch (fmt.type) {
+ case TextureType::RGBA16bpp:
+ case TextureType::RGBA32bpp: {
+ const auto imgr = png2rgba(buffer.data(), buffer.size(), &width, &height);
+ size = width * height * fmt.depth / 8;
+ raw = new uint8_t[size];
+ if(rgba2raw(raw, imgr, width, height, fmt.depth) <= 0){
+ throw std::runtime_error("Failed to convert PNG to texture");
+ }
+ break;
+ }
+ case TextureType::GrayscaleAlpha16bpp:
+ case TextureType::GrayscaleAlpha8bpp:
+ case TextureType::GrayscaleAlpha4bpp:
+ case TextureType::GrayscaleAlpha1bpp: {
+ const auto imgia = png2ia(buffer.data(), buffer.size(), &width, &height);
+ size = width * height * fmt.depth / 8;
+ raw = new uint8_t[size];
+ if(ia2raw(raw, imgia, width, height, fmt.depth) <= 0){
+ throw std::runtime_error("Failed to convert PNG to texture");
+ }
+ break;
+ }
+ case TextureType::Grayscale8bpp:
+ case TextureType::Grayscale4bpp: {
+ const auto imgi = png2ia(buffer.data(), buffer.size(), &width, &height);
+ size = width * height * fmt.depth / 8;
+ raw = new uint8_t[size];
+ if(i2raw(raw, imgi, width, height, fmt.depth) <= 0){
+ throw std::runtime_error("Failed to convert PNG to texture");
+ }
+ break;
+ }
+ default: {
+ SPDLOG_ERROR("Unsupported texture format for modding: {}", format);
+ return std::nullopt;
+ }
+ }
+
+ auto result = std::vector(raw, raw + size);
+
+ SPDLOG_INFO("Texture: {}", format);
+ if(fmt.type == TextureType::TLUT){
SPDLOG_INFO("Colors: {}", width);
} else {
SPDLOG_INFO("Width: {}", width);
@@ -196,5 +334,5 @@ std::optional<std::shared_ptr<IParsedData>> TextureFactory::parse(std::vector<ui
return std::nullopt;
}
- return std::make_shared<TextureData>(type, width, height, result);
+ return std::make_shared<TextureData>(fmt, width, height, result);
}