diff options
| author | Anghelo Carvajal <angheloalf95@gmail.com> | 2021-05-07 17:35:00 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-07 17:35:00 -0400 |
| commit | 547c9b200d1dff745dee694c20a9f9e8e409a11d (patch) | |
| tree | 4eb2ec3fe46fb5709a43d268a2de74668839f2f1 /ZAPD | |
| parent | 5a721d58d4b28f4797d6fdf29d9926e5e968a939 (diff) | |
Change image library to `libpng` and improve how palettized textures are extracted (#133)
* trying to change to libpng
* It works again!
* move the libpng abstraction to another file
* GetBytesPerPixel
* I'm dumb
* fix warnings and remove dead code
* Fix CRC being called multiples times and clean up code
* textureDataRaw
* code clean
* Optimizations and removal of redundant data moves
* ups
* run format
* use fs::path more
* i'm dumb again
* Add a Readme
* remove texDeclarations
* handle tluts better
* vtx change and set segment file
* small changes
* Fix ZAPD ignoring textures declared in a scene in the XML
* small cleanup before tluts
* paletted images are broken
* kinda works for automatic textures
* fix automatic ci
* TEXTURE_DEBUG
* Remove extra `-j`
* Fix extraction of ci4
* Finally palettes OK
* ups
* Move textures map to ZFile
* Fix intersection warnings
* Add `TlutOffset` attribute
* Move Tlut declaration to a later step
* Hopefully the last cleanup of this branch
* Run format
* Always calc hash
* run format
* Delete stb
* fix merge issues
* run format
Diffstat (limited to 'ZAPD')
32 files changed, 1477 insertions, 1114 deletions
diff --git a/ZAPD/Globals.cpp b/ZAPD/Globals.cpp index 93e7fdf..060c59f 100644 --- a/ZAPD/Globals.cpp +++ b/ZAPD/Globals.cpp @@ -47,14 +47,12 @@ string Globals::FindSymbolSegRef(int32_t segNumber, uint32_t symbolAddress) if (root == nullptr) return "ERROR"; - // vector<ZFile*> files = vector<ZFile*>(); - for (XMLElement* child = root->FirstChildElement(); child != NULL; child = child->NextSiblingElement()) { if (string(child->Name()) == "File") { - ZFile* file = new ZFile(fileMode, child, "", "", "", "", true); + ZFile* file = new ZFile(fileMode, child, "", "", "", filePath, true); file->GeneratePlaceholderDeclarations(); segmentRefFiles[segNumber] = file; break; @@ -175,10 +173,13 @@ void Globals::GenSymbolMap(const std::string& symbolMapPath) } } -void Globals::AddSegment(int32_t segment) +void Globals::AddSegment(int32_t segment, ZFile* file) { if (std::find(segments.begin(), segments.end(), segment) == segments.end()) segments.push_back(segment); + + segmentRefs[segment] = file->GetXmlFilePath(); + segmentRefFiles[segment] = file; } bool Globals::HasSegment(int32_t segment) diff --git a/ZAPD/Globals.h b/ZAPD/Globals.h index 5186947..c830b9f 100644 --- a/ZAPD/Globals.h +++ b/ZAPD/Globals.h @@ -42,7 +42,8 @@ public: bool genSourceFile; // Used for extraction bool useExternalResources; - bool testMode; // Enables certain experimental features + bool testMode; // Enables certain experimental features + bool outputCrc = false; bool profile; // Measure performance of certain operations bool includeFilePrefix; // Include the file prefix in symbols bool useLegacyZDList; @@ -66,7 +67,7 @@ public: void ReadConfigFile(const std::string& configFilePath); void ReadTexturePool(const std::string& texturePoolXmlPath); void GenSymbolMap(const std::string& symbolMapPath); - void AddSegment(int32_t segment); + void AddSegment(int32_t segment, ZFile* file); bool HasSegment(int32_t segment); }; diff --git a/ZAPD/HighLevel/HLModelIntermediette.cpp b/ZAPD/HighLevel/HLModelIntermediette.cpp index b4eae32..1c0cd2f 100644 --- a/ZAPD/HighLevel/HLModelIntermediette.cpp +++ b/ZAPD/HighLevel/HLModelIntermediette.cpp @@ -66,16 +66,16 @@ void HLModelIntermediette::FromZDisplayList(HLModelIntermediette* model, ZDispla limb->name = zDisplayList->GetName(); // Go through verts - vector<Vertex> finalVerts = vector<Vertex>(); + vector<ZVtx> finalVerts; int32_t vStart = -1; - for (pair<int32_t, vector<Vertex>> pair : zDisplayList->vertices) + for (auto& pair : zDisplayList->vertices) { if (vStart == -1) // TODO: Find a better way to do this vStart = pair.first; - for (Vertex v : pair.second) + for (auto& v : pair.second) finalVerts.push_back(v); } @@ -85,14 +85,17 @@ void HLModelIntermediette::FromZDisplayList(HLModelIntermediette* model, ZDispla model->blocks.push_back(vertIntr); // Go through textures + // TODO: Textures are now stored directly in ZFile + /* for (pair<uint32_t, ZTexture*> pair : zDisplayList->textures) { - HLTextureIntermediette* texIntr = new HLTextureIntermediette(); - texIntr->tex = pair.second; - texIntr->name = texIntr->tex->GetName(); + HLTextureIntermediette* texIntr = new HLTextureIntermediette(); + texIntr->tex = pair.second; + texIntr->name = texIntr->tex->GetName(); - model->blocks.push_back(texIntr); + model->blocks.push_back(texIntr); } + */ // Analyze display lists to determine components HLDisplayListIntermediette* dList = new HLDisplayListIntermediette(); @@ -173,9 +176,10 @@ void HLModelIntermediette::FromZDisplayList(HLModelIntermediette* model, ZDispla lastMat->clrM = lastClrM; // Bit of a hack here... - int32_t lastData = (int32_t)(zDisplayList->instructions[i - 1]); - string texName = zDisplayList->textures[lastData & 0x00FFFFFF]->GetName(); - lastMat->textureName = texName; + // int32_t lastData = (int32_t)(zDisplayList->instructions[i - 1]); + // TODO + // string texName = zDisplayList->textures[lastData & 0x00FFFFFF]->GetName(); + // lastMat->textureName = texName; // -------------------------- model->blocks.push_back(mesh); @@ -189,10 +193,11 @@ void HLModelIntermediette::FromZDisplayList(HLModelIntermediette* model, ZDispla } else if (opcode == F3DZEXOpcode::G_SETTIMG) { - int32_t texAddress = data & 0x00FFFFFF; + // int32_t texAddress = data & 0x00FFFFFF; - string texName = zDisplayList->textures[texAddress]->GetName(); - lastMat->textureName = texName; + // TODO + // string texName = zDisplayList->textures[texAddress]->GetName(); + // lastMat->textureName = texName; } else if (opcode == F3DZEXOpcode::G_VTX) { @@ -449,25 +454,27 @@ void HLMeshCommand::OutputXML(tinyxml2::XMLElement* parent) HLVerticesIntermediette::HLVerticesIntermediette() : HLIntermediette() { - vertices = vector<Vertex>(); + vertices = vector<ZVtx>(); } void HLVerticesIntermediette::InitFromXML(XMLElement* verticesElement) { name = verticesElement->Attribute("Name"); + /* for (XMLElement* child = verticesElement->FirstChildElement(); child != NULL; child = child->NextSiblingElement()) - vertices.push_back(Vertex(child->IntAttribute("X"), child->IntAttribute("Y"), - child->IntAttribute("Z"), child->IntAttribute("Flags"), - child->IntAttribute("S"), child->IntAttribute("T"), - child->IntAttribute("R"), child->IntAttribute("G"), - child->IntAttribute("B"), child->IntAttribute("A"))); + vertices.push_back(ZVtx(child->IntAttribute("X"), child->IntAttribute("Y"), + child->IntAttribute("Z"), child->IntAttribute("Flags"), + child->IntAttribute("S"), child->IntAttribute("T"), + child->IntAttribute("R"), child->IntAttribute("G"), + child->IntAttribute("B"), child->IntAttribute("A"))); + */ } -void HLVerticesIntermediette::InitFromVertices(vector<Vertex> dispListVertices) +void HLVerticesIntermediette::InitFromVertices(vector<ZVtx> dispListVertices) { - for (Vertex v : dispListVertices) + for (auto v : dispListVertices) vertices.push_back(v); } @@ -477,7 +484,7 @@ string HLVerticesIntermediette::OutputCode(HLModelIntermediette* parent) output += StringHelper::Sprintf("Vtx %s_verts[] = \n{\n", name.c_str()); - for (Vertex v : vertices) + for (auto v : vertices) { output += StringHelper::Sprintf(" { %i, %i, %i, %i, %i, %i, %i, %i, %i, %i },\n", v.x, v.y, v.z, v.flag, v.s, v.t, v.r, v.g, v.b, v.a); @@ -492,7 +499,7 @@ std::string HLVerticesIntermediette::OutputOBJ() { string output = ""; - for (Vertex v : vertices) + for (auto& v : vertices) { output += StringHelper::Sprintf("v %f %f %f %i %i %i %i\n", (float)v.x * 0.1f, (float)v.y * 0.1f, (float)v.z * 0.1f, v.r, v.g, v.b, v.a); @@ -517,7 +524,7 @@ void HLVerticesIntermediette::OutputXML(tinyxml2::XMLDocument* doc, tinyxml2::XM element->SetAttribute("Name", name.c_str()); - for (Vertex v : vertices) + for (auto& v : vertices) { XMLElement* vElem = doc->NewElement("Vertex"); vElem->SetAttribute("X", v.x); @@ -875,9 +882,10 @@ void HLTextureIntermediette::InitFromXML(tinyxml2::XMLElement* xmlElement) // tex = HLTexture::FromPNG(fileName, // (HLTextureType)ZTexture::GetTextureTypeFromString(format)); - tex = ZTexture::FromPNG(Path::GetDirectoryName(Globals::Instance->inputPath.string()) + "/" + - fileName, - ZTexture::GetTextureTypeFromString(format)); + tex = new ZTexture(nullptr); + tex->ZTexture::FromPNG(Path::GetDirectoryName(Globals::Instance->inputPath.string()) + "/" + + fileName, + ZTexture::GetTextureTypeFromString(format)); } std::string HLTextureIntermediette::OutputCode() diff --git a/ZAPD/HighLevel/HLModelIntermediette.h b/ZAPD/HighLevel/HLModelIntermediette.h index 5fda096..474b641 100644 --- a/ZAPD/HighLevel/HLModelIntermediette.h +++ b/ZAPD/HighLevel/HLModelIntermediette.h @@ -156,12 +156,12 @@ public: class HLVerticesIntermediette : public HLIntermediette { public: - std::vector<Vertex> vertices; + std::vector<ZVtx> vertices; HLVerticesIntermediette(); virtual void InitFromXML(tinyxml2::XMLElement* verticesElement); - void InitFromVertices(std::vector<Vertex> dispListVertices); + void InitFromVertices(std::vector<ZVtx> dispListVertices); virtual std::string OutputCode(HLModelIntermediette* parent); virtual std::string OutputOBJ(); virtual void OutputAssimp(aiScene* scene, std::vector<aiVector3D>* verts); diff --git a/ZAPD/HighLevel/HLTexture.cpp b/ZAPD/HighLevel/HLTexture.cpp index 0bf6b36..15abec9 100644 --- a/ZAPD/HighLevel/HLTexture.cpp +++ b/ZAPD/HighLevel/HLTexture.cpp @@ -1,16 +1,15 @@ #include "HLTexture.h" -#include <stb_image.h> #include "../StringHelper.h" using namespace std; HLTexture* HLTexture::FromPNG(std::string pngFilePath, HLTextureType texType) { - int32_t comp; + // int32_t comp; HLTexture* tex = new HLTexture(); tex->type = texType; - tex->bmpRgba = (uint8_t*)stbi_load((pngFilePath).c_str(), (int32_t*)&tex->width, - (int32_t*)&tex->height, &comp, STBI_rgb_alpha); + // tex->bmpRgba = (uint8_t*)stbi_load((pngFilePath).c_str(), (int32_t*)&tex->width, + // (int32_t*)&tex->height, &comp, STBI_rgb_alpha); return tex; } diff --git a/ZAPD/ImageBackend.cpp b/ZAPD/ImageBackend.cpp new file mode 100644 index 0000000..0b4bce3 --- /dev/null +++ b/ZAPD/ImageBackend.cpp @@ -0,0 +1,473 @@ +#include "ImageBackend.h" + +#include <cassert> +#include <cstdlib> +#include <png.h> +#include <stdexcept> + +#include "StringHelper.h" + +/* ImageBackend */ + +ImageBackend::~ImageBackend() +{ + FreeImageData(); +} + +void ImageBackend::ReadPng(const char* filename) +{ + FreeImageData(); + + FILE* fp = fopen(filename, "rb"); + if (fp == nullptr) + throw std::runtime_error(StringHelper::Sprintf( + "ImageBackend::ReadPng: Error.\n\t Couldn't open file '%s'.", filename)); + + png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + if (!png) + throw std::runtime_error("ImageBackend::ReadPng: Error.\n\t Couldn't create png struct."); + + png_infop info = png_create_info_struct(png); + if (!info) + throw std::runtime_error("ImageBackend::ReadPng: Error.\n\t Couldn't create png info."); + + if (setjmp(png_jmpbuf(png))) + throw std::runtime_error("ImageBackend::ReadPng: Error.\n\t setjmp(png_jmpbuf(png))."); + + png_init_io(png, fp); + + png_read_info(png, info); + + width = png_get_image_width(png, info); + height = png_get_image_height(png, info); + colorType = png_get_color_type(png, info); + bitDepth = png_get_bit_depth(png, info); + +#ifdef TEXTURE_DEBUG + printf("Width: %u\n", width); + printf("Height: %u\n", height); + printf("ColorType: "); + switch (colorType) + { + case PNG_COLOR_TYPE_RGBA: + printf("PNG_COLOR_TYPE_RGBA\n"); + break; + + case PNG_COLOR_TYPE_RGB: + printf("PNG_COLOR_TYPE_RGB\n"); + break; + + case PNG_COLOR_TYPE_PALETTE: + printf("PNG_COLOR_TYPE_PALETTE\n"); + break; + + default: + printf("%u\n", colorType); + break; + } + printf("BitDepth: %u\n", bitDepth); + printf("\n"); +#endif + + // Read any color_type into 8bit depth, RGBA format. + // See http://www.libpng.org/pub/png/libpng-manual.txt + + if (bitDepth == 16) + png_set_strip_16(png); + + if (colorType == PNG_COLOR_TYPE_PALETTE) + { + // png_set_palette_to_rgb(png); + isColorIndexed = true; + } + + // PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth. + if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) + png_set_expand_gray_1_2_4_to_8(png); + + /*if (png_get_valid(png, info, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png);*/ + + // These color_type don't have an alpha channel then fill it with 0xff. + /*if(*color_type == PNG_COLOR_TYPE_RGB || + *color_type == PNG_COLOR_TYPE_GRAY || + *color_type == PNG_COLOR_TYPE_PALETTE) + png_set_filler(png, 0xFF, PNG_FILLER_AFTER);*/ + + if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png); + + png_read_update_info(png, info); + + size_t rowBytes = png_get_rowbytes(png, info); + pixelMatrix = (uint8_t**)malloc(sizeof(uint8_t*) * height); + for (size_t y = 0; y < height; y++) + { + pixelMatrix[y] = (uint8_t*)malloc(rowBytes); + } + + png_read_image(png, pixelMatrix); + +#ifdef TEXTURE_DEBUG + printf("rowBytes: %zu\n", rowBytes); + + size_t bytePerPixel = GetBytesPerPixel(); + printf("imgData\n"); + for (size_t y = 0; y < height; y++) + { + for (size_t x = 0; x < width; x++) + { + for (size_t z = 0; z < bytePerPixel; z++) + { + printf("%02X ", pixelMatrix[y][x * bytePerPixel + z]); + } + printf(" "); + } + printf("\n"); + } + printf("\n"); +#endif + + fclose(fp); + + png_destroy_read_struct(&png, &info, nullptr); + + hasImageData = true; +} + +void ImageBackend::ReadPng(const fs::path& filename) +{ + ReadPng(filename.c_str()); +} + +void ImageBackend::WritePng(const char* filename) +{ + assert(hasImageData); + + FILE* fp = fopen(filename, "wb"); + if (!fp) + throw std::runtime_error(StringHelper::Sprintf( + "ImageBackend::WritePng: Error.\n\t Couldn't open file '%s' in write mode.", filename)); + + png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + if (!png) + throw std::runtime_error("ImageBackend::WritePng: Error.\n\t Couldn't create png struct."); + + png_infop info = png_create_info_struct(png); + if (!info) + throw std::runtime_error("ImageBackend::WritePng: Error.\n\t Couldn't create png info."); + + if (setjmp(png_jmpbuf(png))) + throw std::runtime_error("ImageBackend::WritePng: Error.\n\t setjmp(png_jmpbuf(png))."); + + png_init_io(png, fp); + + png_set_IHDR(png, info, width, height, + bitDepth, // 8, + colorType, // PNG_COLOR_TYPE_RGBA, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + if (isColorIndexed) + { + png_set_PLTE(png, info, static_cast<png_color*>(colorPalette), paletteSize); + +#ifdef TEXTURE_DEBUG + printf("palette\n"); + png_color* aux = (png_color*)colorPalette; + for (size_t y = 0; y < paletteSize; y++) + { + printf("#%02X%02X%02X ", aux[y].red, aux[y].green, aux[y].blue); + if ((y + 1) % 8 == 0) + printf("\n"); + } + printf("\n"); +#endif + + png_set_tRNS(png, info, alphaPalette, paletteSize, nullptr); + } + + png_write_info(png, info); + + // To remove the alpha channel for PNG_COLOR_TYPE_RGB format, + // Use png_set_filler(). + // png_set_filler(png, 0, PNG_FILLER_AFTER); + +#ifdef TEXTURE_DEBUG + size_t bytePerPixel = GetBytesPerPixel(); + printf("imgData\n"); + for (size_t y = 0; y < height; y++) + { + for (size_t x = 0; x < width * bytePerPixel; x++) + { + printf("%02X ", pixelMatrix[y][x]); + } + printf("\n"); + } + printf("\n"); +#endif + + png_write_image(png, pixelMatrix); + png_write_end(png, nullptr); + + fclose(fp); + + png_destroy_write_struct(&png, &info); +} + +void ImageBackend::WritePng(const fs::path& filename) +{ + WritePng(filename.c_str()); +} + +void ImageBackend::SetTextureData(const std::vector<std::vector<RGBAPixel>>& texData, + uint32_t nWidth, uint32_t nHeight, uint8_t nColorType, + uint8_t nBitDepth) +{ + FreeImageData(); + + width = nWidth; + height = nHeight; + colorType = nColorType; + bitDepth = nBitDepth; + + size_t bytePerPixel = GetBytesPerPixel(); + + pixelMatrix = static_cast<uint8_t**>(malloc(sizeof(uint8_t*) * height)); + for (size_t y = 0; y < height; y++) + { + pixelMatrix[y] = static_cast<uint8_t*>(malloc(sizeof(uint8_t*) * width * bytePerPixel)); + for (size_t x = 0; x < width; x++) + { + pixelMatrix[y][x * bytePerPixel + 0] = texData.at(y).at(x).r; + pixelMatrix[y][x * bytePerPixel + 1] = texData.at(y).at(x).g; + pixelMatrix[y][x * bytePerPixel + 2] = texData.at(y).at(x).b; + + if (colorType == PNG_COLOR_TYPE_RGBA) + pixelMatrix[y][x * bytePerPixel + 3] = texData.at(y).at(x).a; + } + } + hasImageData = true; +} + +void ImageBackend::InitEmptyRGBImage(uint32_t nWidth, uint32_t nHeight, bool alpha) +{ + FreeImageData(); + + width = nWidth; + height = nHeight; + colorType = PNG_COLOR_TYPE_RGB; + if (alpha) + colorType = PNG_COLOR_TYPE_RGBA; + bitDepth = 8; // nBitDepth; + + size_t bytePerPixel = GetBytesPerPixel(); + + pixelMatrix = static_cast<uint8_t**>(malloc(sizeof(uint8_t*) * height)); + for (size_t y = 0; y < height; y++) + { + pixelMatrix[y] = static_cast<uint8_t*>(calloc(width * bytePerPixel, sizeof(uint8_t*))); + } + + hasImageData = true; +} + +void ImageBackend::InitEmptyPaletteImage(uint32_t nWidth, uint32_t nHeight) +{ + FreeImageData(); + + width = nWidth; + height = nHeight; + colorType = PNG_COLOR_TYPE_PALETTE; + bitDepth = 8; + + size_t bytePerPixel = GetBytesPerPixel(); + + pixelMatrix = (uint8_t**)malloc(sizeof(uint8_t*) * height); + for (size_t y = 0; y < height; y++) + { + pixelMatrix[y] = static_cast<uint8_t*>(calloc(width * bytePerPixel, sizeof(uint8_t*))); + } + colorPalette = calloc(paletteSize, sizeof(png_color)); + alphaPalette = static_cast<uint8_t*>(calloc(paletteSize, sizeof(uint8_t))); + + hasImageData = true; + isColorIndexed = true; +} + +RGBAPixel ImageBackend::GetPixel(size_t y, size_t x) const +{ + assert(y < height); + assert(x < width); + assert(!isColorIndexed); + + RGBAPixel pixel; + size_t bytePerPixel = GetBytesPerPixel(); + pixel.r = pixelMatrix[y][x * bytePerPixel + 0]; + pixel.g = pixelMatrix[y][x * bytePerPixel + 1]; + pixel.b = pixelMatrix[y][x * bytePerPixel + 2]; + if (colorType == PNG_COLOR_TYPE_RGBA) + pixel.a = pixelMatrix[y][x * bytePerPixel + 3]; + return pixel; +} + +uint8_t ImageBackend::GetIndexedPixel(size_t y, size_t x) const +{ + assert(y < height); + assert(x < width); + assert(isColorIndexed); + + return pixelMatrix[y][x]; +} + +void ImageBackend::SetRGBPixel(size_t y, size_t x, uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA) +{ + assert(hasImageData); + assert(y < height); + assert(x < width); + + size_t bytePerPixel = GetBytesPerPixel(); + pixelMatrix[y][x * bytePerPixel + 0] = nR; + pixelMatrix[y][x * bytePerPixel + 1] = nG; + pixelMatrix[y][x * bytePerPixel + 2] = nB; + if (colorType == PNG_COLOR_TYPE_RGBA) + pixelMatrix[y][x * bytePerPixel + 3] = nA; +} + +void ImageBackend::SetGrayscalePixel(size_t y, size_t x, uint8_t grayscale, uint8_t alpha) +{ + assert(hasImageData); + assert(y < height); + assert(x < width); + + size_t bytePerPixel = GetBytesPerPixel(); + pixelMatrix[y][x * bytePerPixel + 0] = grayscale; + pixelMatrix[y][x * bytePerPixel + 1] = grayscale; + pixelMatrix[y][x * bytePerPixel + 2] = grayscale; + if (colorType == PNG_COLOR_TYPE_RGBA) + pixelMatrix[y][x * bytePerPixel + 3] = alpha; +} + +void ImageBackend::SetIndexedPixel(size_t y, size_t x, uint8_t index, uint8_t grayscale) +{ + assert(hasImageData); + assert(y < height); + assert(x < width); + + size_t bytePerPixel = GetBytesPerPixel(); + pixelMatrix[y][x * bytePerPixel + 0] = index; + + assert(index < paletteSize); + png_color* pal = static_cast<png_color*>(colorPalette); + pal[index].red = grayscale; + pal[index].green = grayscale; + pal[index].blue = grayscale; + alphaPalette[index] = 255; +} + +void ImageBackend::SetPaletteIndex(size_t index, uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA) +{ + assert(isColorIndexed); + assert(index < paletteSize); + + png_color* pal = static_cast<png_color*>(colorPalette); + pal[index].red = nR; + pal[index].green = nG; + pal[index].blue = nB; + alphaPalette[index] = nA; +} + +void ImageBackend::SetPalette(const ImageBackend& pal) +{ + assert(isColorIndexed); + size_t bytePerPixel = pal.GetBytesPerPixel(); + + for (size_t y = 0; y < pal.height; y++) + { + for (size_t x = 0; x < pal.width; x++) + { + uint8_t r = pal.pixelMatrix[y][x * bytePerPixel + 0]; + uint8_t g = pal.pixelMatrix[y][x * bytePerPixel + 1]; + uint8_t b = pal.pixelMatrix[y][x * bytePerPixel + 2]; + uint8_t a = pal.pixelMatrix[y][x * bytePerPixel + 3]; + SetPaletteIndex(y * pal.width + x, r, g, b, a); + } + } +} + +uint32_t ImageBackend::GetWidth() const +{ + return width; +} + +uint32_t ImageBackend::GetHeight() const +{ + return height; +} + +uint8_t ImageBackend::GetColorType() const +{ + return colorType; +} + +uint8_t ImageBackend::GetBitDepth() const +{ + return bitDepth; +} + +double ImageBackend::GetBytesPerPixel() const +{ + switch (colorType) + { + case PNG_COLOR_TYPE_RGBA: + return 4 * bitDepth / 8; + + case PNG_COLOR_TYPE_RGB: + return 3 * bitDepth / 8; + + case PNG_COLOR_TYPE_PALETTE: + return 1 * bitDepth / 8; + + default: + throw std::invalid_argument("ImageBackend::GetBytesPerPixel():\n\t Invalid color type."); + } +} + +void ImageBackend::FreeImageData() +{ + if (hasImageData) + { + for (size_t y = 0; y < height; y++) + free(pixelMatrix[y]); + free(pixelMatrix); + pixelMatrix = nullptr; + } + + if (isColorIndexed) + { + free(colorPalette); + free(alphaPalette); + colorPalette = nullptr; + alphaPalette = nullptr; + isColorIndexed = false; + } + + hasImageData = false; +} + +/* RGBAPixel */ + +void RGBAPixel::SetRGBA(uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA) +{ + r = nR; + g = nG; + b = nB; + a = nA; +} + +void RGBAPixel::SetGrayscale(uint8_t grayscale, uint8_t alpha) +{ + r = grayscale; + g = grayscale; + b = grayscale; + a = alpha; +} diff --git a/ZAPD/ImageBackend.h b/ZAPD/ImageBackend.h new file mode 100644 index 0000000..25ab832 --- /dev/null +++ b/ZAPD/ImageBackend.h @@ -0,0 +1,71 @@ +#pragma once + +#include <cstdint> +#include <vector> + +#include "Directory.h" + +class RGBAPixel +{ +public: + RGBAPixel() = default; + + void SetRGBA(uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA); + void SetGrayscale(uint8_t grayscale, uint8_t alpha = 0); + + uint8_t r = 0; + uint8_t g = 0; + uint8_t b = 0; + uint8_t a = 0; +}; + +class ImageBackend +{ +public: + ImageBackend() = default; + ~ImageBackend(); + + void ReadPng(const char* filename); + void ReadPng(const fs::path& filename); + void WritePng(const char* filename); + void WritePng(const fs::path& filename); + + void SetTextureData(const std::vector<std::vector<RGBAPixel>>& texData, uint32_t nWidth, + uint32_t nHeight, uint8_t nColorType, uint8_t nBitDepth); + void InitEmptyRGBImage(uint32_t nWidth, uint32_t nHeight, bool alpha); + void InitEmptyPaletteImage(uint32_t nWidth, uint32_t nHeight); + + RGBAPixel GetPixel(size_t y, size_t x) const; + uint8_t GetIndexedPixel(size_t y, size_t x) const; + + void SetRGBPixel(size_t y, size_t x, uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA = 0); + void SetGrayscalePixel(size_t y, size_t x, uint8_t grayscale, uint8_t alpha = 0); + + void SetIndexedPixel(size_t y, size_t x, uint8_t index, uint8_t grayscale); + void SetPaletteIndex(size_t index, uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA); + void SetPalette(const ImageBackend& pal); + + uint32_t GetWidth() const; + uint32_t GetHeight() const; + uint8_t GetColorType() const; + uint8_t GetBitDepth() const; + +protected: + uint8_t** pixelMatrix = nullptr; // height * [width * bytePerPixel] + + void* colorPalette = nullptr; + uint8_t* alphaPalette = nullptr; + size_t paletteSize = 16 * 16; + + uint32_t width = 0; + uint32_t height = 0; + uint8_t colorType = 0; + uint8_t bitDepth = 0; + + bool hasImageData = false; + bool isColorIndexed = false; + + double GetBytesPerPixel() const; + + void FreeImageData(); +}; diff --git a/ZAPD/Main.cpp b/ZAPD/Main.cpp index 16e5960..51af8a6 100644 --- a/ZAPD/Main.cpp +++ b/ZAPD/Main.cpp @@ -43,9 +43,15 @@ void ErrorHandler(int sig) size_t size = backtrace(array, nMaxFrames); char** symbols = backtrace_symbols(array, nMaxFrames); - // To prevent unused parameter warning - (void)sig; + fprintf(stderr, "\nZAPD crashed. (Signal: %i)\n", sig); + fprintf(stderr, "\n\t\tYou've met with a terrible fate, haven't you?\n\n"); + /** + * Other possible options: + * - SEA BEARS FOAM. SLEEP BEARS DREAMS. \n BOTH END IN THE SAME WAY: CRASSSH! + */ + + fprintf(stderr, "Traceback:\n"); for (size_t i = 1; i < size; i++) { Dl_info info; @@ -71,7 +77,8 @@ void ErrorHandler(int sig) fprintf(stderr, "%-3zd %s\n", i, functionName.c_str()); } - // backtrace_symbols_fd(array, size, STDERR_FILENO); + fprintf(stderr, "\n"); + free(symbols); exit(1); } @@ -160,6 +167,11 @@ int main(int argc, char* argv[]) Globals::Instance->testMode = string(argv[i + 1]) == "1"; i++; } + else if (arg == "-crc" || + arg == "--output-crc") // Outputs a CRC file for each extracted texture. + { + Globals::Instance->outputCrc = true; + } else if (arg == "-ulzdl") // Use Legacy ZDisplay List { Globals::Instance->useLegacyZDList = string(argv[i + 1]) == "1"; @@ -200,7 +212,8 @@ int main(int argc, char* argv[]) signal(SIGSEGV, ErrorHandler); signal(SIGABRT, ErrorHandler); #else - printf("Warning: Tried to set error handler, but this build lacks support for one.\n"); + fprintf(stderr, + "Warning: Tried to set error handler, but this build lacks support for one.\n"); #endif } else if (arg == "-v") // Verbose @@ -216,55 +229,47 @@ int main(int argc, char* argv[]) if (Globals::Instance->verbosity >= VERBOSITY_INFO) printf("ZAPD: Zelda Asset Processor For Decomp: %s\n", gBuildHash); - try + if (fileMode == ZFileMode::Extract || fileMode == ZFileMode::BuildSourceFile) { - if (fileMode == ZFileMode::Extract || fileMode == ZFileMode::BuildSourceFile) - { - bool parseSuccessful = - Parse(Globals::Instance->inputPath, Globals::Instance->baseRomPath, - Globals::Instance->outputPath, fileMode); + bool parseSuccessful = Parse(Globals::Instance->inputPath, Globals::Instance->baseRomPath, + Globals::Instance->outputPath, fileMode); - if (!parseSuccessful) - return 1; - } - else if (fileMode == ZFileMode::BuildTexture) - { - TextureType texType = Globals::Instance->texType; - - BuildAssetTexture(Globals::Instance->inputPath, texType, Globals::Instance->outputPath); - } - else if (fileMode == ZFileMode::BuildBackground) - { - BuildAssetBackground(Globals::Instance->inputPath, Globals::Instance->outputPath); - } - else if (fileMode == ZFileMode::BuildBlob) - { - BuildAssetBlob(Globals::Instance->inputPath, Globals::Instance->outputPath); - } - else if (fileMode == ZFileMode::BuildModelIntermediette) - { - BuildAssetModelIntermediette(Globals::Instance->outputPath); - } - else if (fileMode == ZFileMode::BuildAnimationIntermediette) - { - BuildAssetAnimationIntermediette(Globals::Instance->inputPath, - Globals::Instance->outputPath); - } - else if (fileMode == ZFileMode::BuildOverlay) - { - ZOverlay* overlay = - ZOverlay::FromBuild(Path::GetDirectoryName(Globals::Instance->inputPath.string()), - Path::GetDirectoryName(Globals::Instance->cfgPath.string())); - - if (overlay) - File::WriteAllText(Globals::Instance->outputPath.string(), - overlay->GetSourceOutputCode("")); - } + if (!parseSuccessful) + return 1; + } + else if (fileMode == ZFileMode::BuildTexture) + { + TextureType texType = Globals::Instance->texType; + BuildAssetTexture(Globals::Instance->inputPath, texType, Globals::Instance->outputPath); + } + else if (fileMode == ZFileMode::BuildBackground) + { + BuildAssetBackground(Globals::Instance->inputPath, Globals::Instance->outputPath); + } + else if (fileMode == ZFileMode::BuildBlob) + { + BuildAssetBlob(Globals::Instance->inputPath, Globals::Instance->outputPath); + } + else if (fileMode == ZFileMode::BuildModelIntermediette) + { + BuildAssetModelIntermediette(Globals::Instance->outputPath); + } + else if (fileMode == ZFileMode::BuildAnimationIntermediette) + { + BuildAssetAnimationIntermediette(Globals::Instance->inputPath, + Globals::Instance->outputPath); } - catch (std::runtime_error& e) + else if (fileMode == ZFileMode::BuildOverlay) { - printf("Exception occurred: %s\n", e.what()); + ZOverlay* overlay = + ZOverlay::FromBuild(Path::GetDirectoryName(Globals::Instance->inputPath), + Path::GetDirectoryName(Globals::Instance->cfgPath)); + + if (overlay) + File::WriteAllText(Globals::Instance->outputPath.string(), + overlay->GetSourceOutputCode("")); } + delete g; return 0; } @@ -327,17 +332,16 @@ void BuildAssetTexture(const fs::path& pngFilePath, TextureType texType, const f { string name = outPath.stem().string(); - ZTexture* tex = ZTexture::FromPNG(pngFilePath.string(), texType); + ZTexture tex(nullptr); + tex.FromPNG(pngFilePath, texType); string cfgPath = StringHelper::Split(pngFilePath.string(), ".")[0] + ".cfg"; if (File::Exists(cfgPath)) name = File::ReadAllText(cfgPath); - string src = tex->GetSourceOutputCode(name); + string src = tex.GetBodySourceCode(); File::WriteAllText(outPath.string(), src); - - delete tex; } void BuildAssetBackground(const fs::path& imageFilePath, const fs::path& outPath) diff --git a/ZAPD/Path.h b/ZAPD/Path.h index a5c073c..68cfaea 100644 --- a/ZAPD/Path.h +++ b/ZAPD/Path.h @@ -46,8 +46,8 @@ public: return output; }; - static std::string GetDirectoryName(const std::string& path) + static std::string GetDirectoryName(const fs::path& path) { - return fs::path(path).parent_path().u8string(); + return path.parent_path().u8string(); }; }; diff --git a/ZAPD/StringHelper.h b/ZAPD/StringHelper.h index 3d63a74..e04bc08 100644 --- a/ZAPD/StringHelper.h +++ b/ZAPD/StringHelper.h @@ -92,4 +92,9 @@ public: return ss.empty() ? s : ss + separator + s; }); } + + static int64_t StrToL(const std::string& str, int32_t base = 10) + { + return std::strtoull(str.c_str(), nullptr, base); + } }; diff --git a/ZAPD/ZAnimation.cpp b/ZAPD/ZAnimation.cpp index e111dc5..3274cb3 100644 --- a/ZAPD/ZAnimation.cpp +++ b/ZAPD/ZAnimation.cpp @@ -26,13 +26,13 @@ void ZAnimation::ParseRawData() frameCount = BitConverter::ToInt16BE(data, rawDataIndex + 0); } -void ZAnimation::Save(const std::string& outFolder) +void ZAnimation::Save(const fs::path& outFolder) { if (Globals::Instance->testMode) { HLAnimationIntermediette* anim = HLAnimationIntermediette::FromZAnimation(this); string xml = anim->OutputXML(); - File::WriteAllText(outFolder + "/" + name + ".anmi", xml); + File::WriteAllText(outFolder / (name + ".anmi"), xml); delete anim; } diff --git a/ZAPD/ZAnimation.h b/ZAPD/ZAnimation.h index de57bca..b79d780 100644 --- a/ZAPD/ZAnimation.h +++ b/ZAPD/ZAnimation.h @@ -33,7 +33,7 @@ public: protected: void ParseRawData() override; - void Save(const std::string& outFolder) override; + void Save(const fs::path& outFolder) override; void ParseXML(tinyxml2::XMLElement* reader) override; }; diff --git a/ZAPD/ZBackground.cpp b/ZAPD/ZBackground.cpp index a877c70..a3c9a1b 100644 --- a/ZAPD/ZBackground.cpp +++ b/ZAPD/ZBackground.cpp @@ -156,10 +156,9 @@ std::string ZBackground::GetExternalExtension() return "jpg"; } -void ZBackground::Save(const std::string& outFolder) +void ZBackground::Save(const fs::path& outFolder) { - fs::path folder(outFolder); - fs::path filepath = folder / (outName + "." + GetExternalExtension()); + fs::path filepath = outFolder / (outName + "." + GetExternalExtension()); File::WriteAllBytes(filepath.string(), data); } diff --git a/ZAPD/ZBackground.h b/ZAPD/ZBackground.h index 000a2a1..4b4897f 100644 --- a/ZAPD/ZBackground.h +++ b/ZAPD/ZBackground.h @@ -26,7 +26,7 @@ public: bool IsExternalResource() override; std::string GetExternalExtension() override; - void Save(const std::string& outFolder) override; + void Save(const fs::path& outFolder) override; std::string GetBodySourceCode(); std::string GetSourceOutputCode(const std::string& prefix) override; diff --git a/ZAPD/ZBlob.cpp b/ZAPD/ZBlob.cpp index 171433e..3b060f4 100644 --- a/ZAPD/ZBlob.cpp +++ b/ZAPD/ZBlob.cpp @@ -85,9 +85,9 @@ string ZBlob::GetSourceOutputHeader(const std::string& prefix) return StringHelper::Sprintf("extern u8 %s[];\n", name.c_str()); } -void ZBlob::Save(const std::string& outFolder) +void ZBlob::Save(const fs::path& outFolder) { - File::WriteAllBytes(outFolder + "/" + name + ".bin", rawData); + File::WriteAllBytes(outFolder / (name + ".bin"), rawData); } bool ZBlob::IsExternalResource() diff --git a/ZAPD/ZBlob.h b/ZAPD/ZBlob.h index bfc8a30..e17327e 100644 --- a/ZAPD/ZBlob.h +++ b/ZAPD/ZBlob.h @@ -18,7 +18,7 @@ public: static ZBlob* FromFile(const std::string& filePath); std::string GetSourceOutputCode(const std::string& prefix) override; std::string GetSourceOutputHeader(const std::string& prefix) override; - void Save(const std::string& outFolder) override; + void Save(const fs::path& outFolder) override; bool IsExternalResource() override; std::string GetExternalExtension() override; std::string GetSourceTypeName() override; diff --git a/ZAPD/ZDisplayList.cpp b/ZAPD/ZDisplayList.cpp index fafdd99..9d71bff 100644 --- a/ZAPD/ZDisplayList.cpp +++ b/ZAPD/ZDisplayList.cpp @@ -34,20 +34,12 @@ ZDisplayList::ZDisplayList(ZFile* nParent) : ZResource(nParent) fileData = vector<uint8_t>(); instructions = vector<uint64_t>(); - vertices = map<uint32_t, vector<Vertex>>(); vtxDeclarations = map<uint32_t, string>(); otherDLists = vector<ZDisplayList*>(); - textures = map<uint32_t, ZTexture*>(); - texDeclarations = map<uint32_t, std::string>(); } ZDisplayList::~ZDisplayList() { - for (auto t : textures) - { - delete t.second; - } - for (auto o : otherDLists) { delete o; @@ -62,7 +54,6 @@ void ZDisplayList::ExtractFromXML(tinyxml2::XMLElement* reader, rawDataIndex = nRawDataIndex; ParseXML(reader); - // name = reader->Attribute("Name"); fileData = nRawData; int32_t rawDataSize = ZDisplayList::GetDListLength( nRawData, rawDataIndex, @@ -511,36 +502,19 @@ int32_t ZDisplayList::OptimizationCheck_LoadTextureBlock(int32_t startIndex, str texAddr = Seg2Filespace(data, parent->baseAddress); int32_t segmentNumber = GETSEGNUM(data); - lastTexSeg = (data & 0xFF000000); - - Declaration* texDecl = nullptr; + lastTexSeg = segmentNumber; - if (parent != nullptr && - segmentNumber != 2) // HACK: Until we have declarations use segment addresses, - // we'll exclude scene references... - { - texDecl = parent->GetDeclaration(texAddr); - - if (texDecl == nullptr) - texDecl = parent->GetDeclaration(data); - } + ZFile* auxParent = parent; + if (parent->segment != segmentNumber && Globals::Instance->HasSegment(segmentNumber)) + auxParent = Globals::Instance->segmentRefFiles.at(segmentNumber); - if (texAddr != 0) - { - if (texDecl != nullptr) - texStr = StringHelper::Sprintf("%s", texDecl->varName.c_str()); - else if (segmentNumber == 2) - texStr = StringHelper::Sprintf("%sTex_%06X", scene->GetName().c_str(), texAddr); - else if (!Globals::Instance->HasSegment( - segmentNumber)) // Probably an external asset we are unable to track - texStr = StringHelper::Sprintf("0x%06X", data); - else - texStr = StringHelper::Sprintf("%sTex_%06X", prefix.c_str(), texAddr); - } - else if (segmentNumber != 3) - texStr = StringHelper::Sprintf("0x%06X", data); + Declaration* decl = auxParent->GetDeclaration(texAddr); + if (Globals::Instance->HasSegment(segmentNumber) && decl != nullptr) + texStr = decl->varName; + else if (lastTexture != nullptr) + texStr = lastTexture->GetName(); else - texStr = StringHelper::Sprintf("0"); + texStr = auxParent->GetDeclarationPtrName(data & 0xFFFFFFFF); } // gsDPSetTile @@ -879,12 +853,15 @@ void ZDisplayList::Opcode_G_VTX(uint64_t data, char* line) if (nn > 0) { - vector<Vertex> vtxList = vector<Vertex>(); + std::vector<ZVtx> vtxList; vtxList.reserve(nn); for (int32_t i = 0; i < nn; i++) { - Vertex vtx = Vertex(fileData, currentPtr); + ZVtx vtx(parent); + vtx.SetRawData(fileData); + vtx.SetRawDataIndex(currentPtr); + vtx.ParseRawData(); vtxList.push_back(vtx); currentPtr += 16; @@ -955,9 +932,7 @@ void ZDisplayList::Opcode_G_SETTIMG(uint64_t data, std::string prefix, char* lin sprintf(texStr, "%sTex_%06X", prefix.c_str(), texAddress); else { - { - sprintf(texStr, "0x%08lX", data & 0xFFFFFFFF); - } + sprintf(texStr, "0x%08lX", data & 0xFFFFFFFF); } sprintf(line, "gsDPSetTextureImage(%s, %s, %i, %s),", fmtTbl[fmt].c_str(), @@ -1559,12 +1534,42 @@ string ZDisplayList::GetSourceOutputHeader(const std::string& prefix) static int32_t GfxdCallback_FormatSingleEntry(void) { + ZDisplayList* self = static_cast<ZDisplayList*>(gfxd_udata_get()); gfxd_puts("\t"); gfxd_macro_dflt(); gfxd_puts(","); + auto macroId = gfxd_macro_id(); + + switch (macroId) + { + case gfxd_SP1Triangle: + case gfxd_SP2Triangles: + if (self->lastTexture != nullptr && self->lastTexture->IsColorIndexed() && + !self->lastTexture->HasTlut()) + { + auto tex = self->lastTexture; + auto tlut = self->lastTlut; + + if (Globals::Instance->verbosity >= VERBOSITY_DEBUG) + { + if (tlut != nullptr) + printf("CI texture '%s' (0x%X), TLUT: '%s' (0x%X)\n", tex->GetName().c_str(), + tex->GetRawDataIndex(), tlut->GetName().c_str(), + tlut->GetRawDataIndex()); + else + printf("CI texture '%s' (0x%X), TLUT: null\n", tex->GetName().c_str(), + tex->GetRawDataIndex()); + } + + if (tlut != nullptr && !tex->HasTlut()) + tex->SetTlut(tlut); + } + break; + } + // dont print a new line after the last command - if (gfxd_macro_id() != gfxd_SPEndDisplayList) + if (macroId != gfxd_SPEndDisplayList) { gfxd_puts("\n"); } @@ -1578,8 +1583,8 @@ static int32_t GfxdCallback_Vtx(uint32_t seg, int32_t count) uint32_t vtxOffset = Seg2Filespace(seg, self->parent->baseAddress); string vtxName = ""; - if (!Globals::Instance->HasSegment( - GETSEGNUM(seg))) // Probably an external asset we are unable to track + // Probably an external asset we are unable to track + if (!Globals::Instance->HasSegment(GETSEGNUM(seg))) { vtxName = StringHelper::Sprintf("0x%08X", seg); } @@ -1615,13 +1620,17 @@ static int32_t GfxdCallback_Vtx(uint32_t seg, int32_t count) if (count > 0) { - vector<Vertex> vtxList = vector<Vertex>(); + std::vector<ZVtx> vtxList; vtxList.reserve(count); uint32_t currentPtr = vtxOffset; for (int32_t i = 0; i < count; i++) { - Vertex vtx = Vertex(self->fileData, currentPtr); + ZVtx vtx(self->parent); + vtx.SetRawData(self->fileData); + vtx.SetRawDataIndex(currentPtr); + vtx.ParseRawData(); + vtxList.push_back(vtx); currentPtr += 16; } @@ -1641,29 +1650,7 @@ static int32_t GfxdCallback_Texture(segptr_t seg, int32_t fmt, int32_t siz, int3 { ZDisplayList* self = static_cast<ZDisplayList*>(gfxd_udata_get()); uint32_t texOffset = Seg2Filespace(seg, self->parent->baseAddress); - uint32_t texSegNum = GETSEGNUM(seg); - Declaration* texDecl = nullptr; - string texName = ""; - - if (self->parent != nullptr && - texSegNum != SEGMENT_SCENE) // HACK: Until we have declarations use segment addresses, - // we'll exclude scene references... - { - texDecl = self->parent->GetDeclaration(texOffset); - - if (texDecl == nullptr) - texDecl = self->parent->GetDeclaration(seg); - } - - if (!Globals::Instance->HasSegment( - texSegNum)) // Probably an external asset we are unable to track - texName = StringHelper::Sprintf("0x%08X", seg); - else if (texDecl != nullptr) - texName = StringHelper::Sprintf("%s", texDecl->varName.c_str()); - else if (texSegNum == 2) - texName = StringHelper::Sprintf("%sTex_%06X", self->scene->GetName().c_str(), texOffset); - else - texName = StringHelper::Sprintf("%sTex_%06X", self->curPrefix.c_str(), texOffset); + int32_t texSegNum = GETSEGNUM(seg); self->lastTexWidth = width; self->lastTexHeight = height; @@ -1676,6 +1663,20 @@ static int32_t GfxdCallback_Texture(segptr_t seg, int32_t fmt, int32_t siz, int3 self->TextureGenCheck(self->curPrefix); + std::string texName = ""; + + ZFile* auxParent = self->parent; + if (self->parent->segment != texSegNum && Globals::Instance->HasSegment(texSegNum)) + auxParent = Globals::Instance->segmentRefFiles.at(texSegNum); + + Declaration* decl = auxParent->GetDeclaration(texOffset); + if (Globals::Instance->HasSegment(texSegNum) && decl != nullptr) + texName = decl->varName; + else if (self->lastTexture != nullptr) + texName = self->lastTexture->GetName(); + else + texName = auxParent->GetDeclarationPtrName(seg); + gfxd_puts(texName.c_str()); return 1; @@ -1685,28 +1686,7 @@ static int32_t GfxdCallback_Palette(uint32_t seg, int32_t idx, int32_t count) { ZDisplayList* self = static_cast<ZDisplayList*>(gfxd_udata_get()); uint32_t palOffset = Seg2Filespace(seg, self->parent->baseAddress); - uint32_t palSegNum = GETSEGNUM(seg); - Declaration* palDecl = nullptr; - string palName = ""; - - if (self->parent != nullptr && palSegNum != 2) // HACK: Until we have declarations use segment - // addresses, we'll exclude scene references... - { - palDecl = self->parent->GetDeclaration(palOffset); - - if (palDecl == nullptr) - palDecl = self->parent->GetDeclaration(seg); - } - - if (!Globals::Instance->HasSegment( - palSegNum)) // Probably an external asset we are unable to track - palName = StringHelper::Sprintf("0x%08X", seg); - else if (palDecl != nullptr) - palName = StringHelper::Sprintf("%s", palDecl->varName.c_str()); - else if (palSegNum == 2) - palName = StringHelper::Sprintf("%sTex_%06X", self->scene->GetName().c_str(), palOffset); - else - palName = StringHelper::Sprintf("%sTex_%06X", self->curPrefix.c_str(), palOffset); + int32_t palSegNum = GETSEGNUM(seg); self->lastTexWidth = sqrt(count); self->lastTexHeight = sqrt(count); @@ -1718,6 +1698,21 @@ static int32_t GfxdCallback_Palette(uint32_t seg, int32_t idx, int32_t count) self->lastTexIsPalette = true; self->TextureGenCheck(self->curPrefix); + + std::string palName = ""; + + ZFile* auxParent = self->parent; + if (self->parent->segment != palSegNum && Globals::Instance->HasSegment(palSegNum)) + auxParent = Globals::Instance->segmentRefFiles.at(palSegNum); + + Declaration* decl = auxParent->GetDeclaration(palOffset); + if (Globals::Instance->HasSegment(palSegNum) && decl != nullptr) + palName = decl->varName; + else if (self->lastTlut != nullptr) + palName = self->lastTlut->GetName(); + else + palName = auxParent->GetDeclarationPtrName(seg); + gfxd_puts(palName.c_str()); return 1; @@ -1727,20 +1722,7 @@ static int32_t GfxdCallback_DisplayList(uint32_t seg) { ZDisplayList* self = static_cast<ZDisplayList*>(gfxd_udata_get()); uint32_t dListOffset = GETSEGOFFSET(seg); - uint32_t dListSegNum = GETSEGNUM(seg); - Declaration* dListDecl = nullptr; - string dListName = ""; - - if (self->parent != nullptr) - dListDecl = self->parent->GetDeclaration(dListOffset); - - if (!Globals::Instance->HasSegment( - dListSegNum)) // Probably an external asset we are unable to track - dListName = StringHelper::Sprintf("0x%08X", seg); - else if (dListDecl != nullptr) - dListName = StringHelper::Sprintf("%s", dListDecl->varName.c_str()); - else - dListName = StringHelper::Sprintf("%sDL_%06X", self->curPrefix.c_str(), dListOffset); + int32_t dListSegNum = GETSEGNUM(seg); if ((dListSegNum <= 6) && Globals::Instance->HasSegment(dListSegNum)) { @@ -1752,6 +1734,12 @@ static int32_t GfxdCallback_DisplayList(uint32_t seg) self->otherDLists.push_back(newDList); } + ZFile* auxParent = self->parent; + if (self->parent->segment != dListSegNum && Globals::Instance->HasSegment(dListSegNum)) + auxParent = Globals::Instance->segmentRefFiles.at(dListSegNum); + + std::string dListName = auxParent->GetDeclarationPtrName(seg); + gfxd_puts(dListName.c_str()); return 1; @@ -1802,10 +1790,7 @@ string ZDisplayList::GetSourceOutputCode(const std::string& prefix) // Iterate through our vertex lists, connect intersecting lists. if (vertices.size() > 0) { - vector<pair<int32_t, vector<Vertex>>> verticesSorted(vertices.begin(), vertices.end()); - - sort(verticesSorted.begin(), verticesSorted.end(), - [](const auto& lhs, const auto& rhs) { return lhs.first < rhs.first; }); + vector<pair<int32_t, vector<ZVtx>>> verticesSorted(vertices.begin(), vertices.end()); for (size_t i = 0; i < verticesSorted.size() - 1; i++) { @@ -1840,20 +1825,18 @@ string ZDisplayList::GetSourceOutputCode(const std::string& prefix) parent->defines += defines; // Generate Vertex Declarations - for (pair<int32_t, vector<Vertex>> item : vertices) + for (auto& item : vertices) { string declaration = ""; - int32_t curAddr = item.first; + uint32_t curAddr = item.first; - for (Vertex vtx : item.second) + for (auto vtx : item.second) { if (curAddr != item.first) declaration += "\n"; - declaration += - StringHelper::Sprintf(" VTX(%i, %i, %i, %i, %i, %i, %i, %i, %i),", vtx.x, - vtx.y, vtx.z, vtx.s, vtx.t, vtx.r, vtx.g, vtx.b, vtx.a); + declaration += vtx.GetBodySourceCode(); curAddr += 16; } @@ -1873,116 +1856,9 @@ string ZDisplayList::GetSourceOutputCode(const std::string& prefix) // Check for texture intersections { - if (scene != nullptr && scene->textures.size() != 0) + if (scene != nullptr) { - vector<pair<uint32_t, ZTexture*>> texturesSorted(scene->textures.begin(), - scene->textures.end()); - - sort(texturesSorted.begin(), texturesSorted.end(), - [](const auto& lhs, const auto& rhs) { return lhs.first < rhs.first; }); - - for (size_t i = 0; i < texturesSorted.size() - 1; i++) - { - int32_t texSize = scene->textures[texturesSorted[i].first]->GetRawDataSize(); - - if ((texturesSorted[i].first + texSize) > texturesSorted[i + 1].first) - { - defines += StringHelper::Sprintf( - "#define %sTex_%06X ((u32)%sTex_%06X + 0x%06X)\n", scene->GetName().c_str(), - texturesSorted[i + 1].first, scene->GetName().c_str(), - texturesSorted[i].first, - texturesSorted[i + 1].first - texturesSorted[i].first); - - scene->parent->declarations.erase(texturesSorted[i + 1].first); - scene->textures.erase(texturesSorted[i + 1].first); - texturesSorted.erase(texturesSorted.begin() + i + 1); - - i--; - } - } - - scene->extDefines += defines; - } - - { - vector<pair<uint32_t, ZTexture*>> texturesSorted(textures.begin(), textures.end()); - - sort(texturesSorted.begin(), texturesSorted.end(), - [](const auto& lhs, const auto& rhs) { return lhs.first < rhs.first; }); - - for (size_t i = 0; i < texturesSorted.size() - 1; i++) - { - if (texturesSorted.size() == 0) // ????? - break; - - int32_t texSize = textures[texturesSorted[i].first]->GetRawDataSize(); - - if ((texturesSorted[i].first + texSize) > texturesSorted[i + 1].first) - { - // int32_t intersectAmt = (texturesSorted[i].first + texSize) - texturesSorted[i - // + 1].first; - - // If we're working with a palette, resize it to its "real" dimensions - if (texturesSorted[i].second->isPalette) - { - texturesSorted[i].second->SetWidth( - (texturesSorted[i + 1].first - texturesSorted[i].first) / 2); - texturesSorted[i].second->SetHeight(1); - } - else - { - defines += StringHelper::Sprintf( - "#define %sTex_%06X ((u32)%sTex_%06X + 0x%06X)\n", prefix.c_str(), - texturesSorted[i + 1].first, prefix.c_str(), texturesSorted[i].first, - texturesSorted[i + 1].first - texturesSorted[i].first); - - textures.erase(texturesSorted[i + 1].first); - texturesSorted.erase(texturesSorted.begin() + i + 1); - - i--; - } - } - } - } - - // Generate Texture Declarations - for (pair<int32_t, ZTexture*> item : textures) - { - string declaration = ""; - - declaration += item.second->GetSourceOutputCode(prefix); - texDeclarations[item.first] = declaration; - - if (parent != nullptr) - { - if (parent->GetDeclaration(item.first) == nullptr) - { - // TEXTURE POOL CHECK - std::string texOutPath = - item.second->GetPoolOutPath(Globals::Instance->outputPath.string()); - std::string texOutName = item.second->GetName(); - - auto start = chrono::steady_clock::now(); - item.second->Save(texOutPath); - auto end = chrono::steady_clock::now(); - auto diff = chrono::duration_cast<chrono::milliseconds>(end - start).count(); - - if (Globals::Instance->verbosity >= VERBOSITY_DEBUG) - printf("SAVED IMAGE TO %s in %ims\n", Globals::Instance->outputPath.c_str(), - (int32_t)diff); - - auto filepath = Globals::Instance->outputPath / - Path::GetFileNameWithoutExtension(item.second->GetName()); - std::string incStr = - StringHelper::Sprintf("%s.%s.inc.c", filepath.c_str(), - item.second->GetExternalExtension().c_str()); - std::string texName = - StringHelper::Sprintf("%sTex_%06X", prefix.c_str(), item.first); - - parent->AddDeclarationIncludeArray( - item.first, incStr, item.second->GetRawDataSize(), "u64", texName, 0); - } - } + defines += scene->extDefines; } } @@ -1999,10 +1875,7 @@ string ZDisplayList::GetSourceOutputCode(const std::string& prefix) // Iterate through our vertex lists, connect intersecting lists. if (vertices.size() > 0) { - vector<pair<uint32_t, vector<Vertex>>> verticesSorted(vertices.begin(), vertices.end()); - - sort(verticesSorted.begin(), verticesSorted.end(), - [](const auto& lhs, const auto& rhs) { return lhs.first < rhs.first; }); + vector<pair<uint32_t, vector<ZVtx>>> verticesSorted(vertices.begin(), vertices.end()); for (size_t i = 0; i < verticesSorted.size() - 1; i++) { @@ -2031,19 +1904,19 @@ string ZDisplayList::GetSourceOutputCode(const std::string& prefix) // Generate Vertex Declarations vector<int32_t> vtxKeys; - for (pair<int32_t, vector<Vertex>> item : vertices) + for (auto& item : vertices) vtxKeys.push_back(item.first); // for (pair<int32_t, vector<Vertex>> item : vertices) for (size_t i = 0; i < vtxKeys.size(); i++) { - vector<Vertex> item = vertices[vtxKeys[i]]; + auto& item = vertices[vtxKeys[i]]; string declaration = ""; int32_t curAddr = vtxKeys[i]; - for (Vertex vtx : item) + for (auto& vtx : item) { if (curAddr != vtxKeys[i]) declaration += "\n"; @@ -2167,9 +2040,8 @@ std::string ZDisplayList::ProcessGfxDis(const std::string& prefix) void ZDisplayList::TextureGenCheck(string prefix) { - if (TextureGenCheck(fileData, textures, scene, parent, prefix, lastTexWidth, lastTexHeight, - lastTexAddr, lastTexSeg, lastTexFmt, lastTexSiz, lastTexLoaded, - lastTexIsPalette)) + if (TextureGenCheck(fileData, scene, parent, prefix, lastTexWidth, lastTexHeight, lastTexAddr, + lastTexSeg, lastTexFmt, lastTexSiz, lastTexLoaded, lastTexIsPalette, this)) { lastTexAddr = 0; lastTexLoaded = false; @@ -2177,14 +2049,19 @@ void ZDisplayList::TextureGenCheck(string prefix) } } -bool ZDisplayList::TextureGenCheck(vector<uint8_t> fileData, map<uint32_t, ZTexture*>& textures, - ZRoom* scene, ZFile* parent, string prefix, int32_t texWidth, - int32_t texHeight, uint32_t texAddr, uint32_t texSeg, - F3DZEXTexFormats texFmt, F3DZEXTexSizes texSiz, bool texLoaded, - bool texIsPalette) +bool ZDisplayList::TextureGenCheck(vector<uint8_t> fileData, ZRoom* scene, ZFile* parent, + string prefix, int32_t texWidth, int32_t texHeight, + uint32_t texAddr, uint32_t texSeg, F3DZEXTexFormats texFmt, + F3DZEXTexSizes texSiz, bool texLoaded, bool texIsPalette, + ZDisplayList* self) { int32_t segmentNumber = GETSEGNUM(texSeg); + if (!texIsPalette) + self->lastTexture = nullptr; + else + self->lastTlut = nullptr; + if (Globals::Instance->verbosity >= VERBOSITY_DEBUG) printf("TextureGenCheck seg=%i width=%i height=%i ispal=%i addr=0x%06X\n", segmentNumber, texWidth, texHeight, texIsPalette, texAddr); @@ -2194,36 +2071,55 @@ bool ZDisplayList::TextureGenCheck(vector<uint8_t> fileData, map<uint32_t, ZText { if (segmentNumber != SEGMENT_SCENE) { - ZTexture* tex = - ZTexture::FromBinary(TexFormatToTexType(texFmt, texSiz), fileData, texAddr, - StringHelper::Sprintf("%sTex_%06X", prefix.c_str(), texAddr), - texWidth, texHeight, parent); - tex->isPalette = texIsPalette; - textures[texAddr] = tex; - return true; + if (texAddr < parent->GetRawData().size()) + { + ZTexture* tex = parent->GetTextureResource(texAddr); + if (tex != nullptr) + tex->isPalette = texIsPalette; + else + { + tex = new ZTexture(parent); + tex->FromBinary(fileData, texAddr, texWidth, texHeight, + TexFormatToTexType(texFmt, texSiz), texIsPalette); + parent->AddTextureResource(texAddr, tex); + } + + if (!texIsPalette) + self->lastTexture = tex; + else + self->lastTlut = tex; + + return true; + } } - else + else if (scene != nullptr) { - ZTexture* tex = ZTexture::FromBinary( - TexFormatToTexType(texFmt, texSiz), scene->GetRawData(), texAddr, - StringHelper::Sprintf("%sTex_%06X", Globals::Instance->lastScene->GetName().c_str(), - texAddr), - texWidth, texHeight, parent); - - if (scene != nullptr) + if (scene->parent->GetDeclaration(texAddr) == nullptr) { - scene->textures[texAddr] = tex; + ZTexture* tex = scene->parent->GetTextureResource(texAddr); + if (tex != nullptr) + tex->isPalette = texIsPalette; + else + { + tex = new ZTexture(scene->parent); + tex->FromBinary(scene->GetRawData(), texAddr, texWidth, texHeight, + TexFormatToTexType(texFmt, texSiz), texIsPalette); + + scene->parent->AddTextureResource(texAddr, tex); + } + + if (!texIsPalette) + self->lastTexture = tex; + else + self->lastTlut = tex; auto filepath = Globals::Instance->outputPath / Path::GetFileNameWithoutExtension(tex->GetName()); - scene->parent->AddDeclarationIncludeArray( - texAddr, - StringHelper::Sprintf("%s.%s.inc.c", filepath.c_str(), - tex->GetExternalExtension().c_str()), - tex->GetRawDataSize(), "u64", - StringHelper::Sprintf("%sTex_%06X", - Globals::Instance->lastScene->GetName().c_str(), texAddr), - 0); + auto filename = StringHelper::Sprintf("%s.%s.inc.c", filepath.c_str(), + tex->GetExternalExtension().c_str()); + scene->parent->AddDeclarationIncludeArray(texAddr, filename, tex->GetRawDataSize(), + tex->GetSourceTypeName(), tex->GetName(), + 0); } return true; } @@ -2275,10 +2171,6 @@ TextureType ZDisplayList::TexFormatToTexType(F3DZEXTexFormats fmt, F3DZEXTexSize return TextureType::RGBA16bpp; } -void ZDisplayList::Save(const std::string& outFolder) -{ -} - void ZDisplayList::GenerateHLIntermediette(HLFileIntermediette& hlFile) { HLModelIntermediette* mdl = (HLModelIntermediette*)&hlFile; @@ -2310,48 +2202,3 @@ size_t ZDisplayList::GetRawDataSize() { return instructions.size() * 8; } - -Vertex::Vertex() -{ - x = 0; - y = 0; - z = 0; - flag = 0; - s = 0; - t = 0; - r = 0; - g = 0; - b = 0; - a = 0; -} - -Vertex::Vertex(int16_t nX, int16_t nY, int16_t nZ, uint16_t nFlag, int16_t nS, int16_t nT, - uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA) -{ - x = nX; - y = nY; - z = nZ; - flag = nFlag; - s = nS; - t = nT; - r = nR; - g = nG; - b = nB; - a = nA; -} - -Vertex::Vertex(std::vector<uint8_t> rawData, uint32_t rawDataIndex) -{ - const uint8_t* data = rawData.data(); - - x = BitConverter::ToInt16BE(data, rawDataIndex + 0); - y = BitConverter::ToInt16BE(data, rawDataIndex + 2); - z = BitConverter::ToInt16BE(data, rawDataIndex + 4); - flag = BitConverter::ToInt16BE(data, rawDataIndex + 6); - s = BitConverter::ToInt16BE(data, rawDataIndex + 8); - t = BitConverter::ToInt16BE(data, rawDataIndex + 10); - r = data[rawDataIndex + 12]; - g = data[rawDataIndex + 13]; - b = data[rawDataIndex + 14]; - a = data[rawDataIndex + 15]; -} diff --git a/ZAPD/ZDisplayList.h b/ZAPD/ZDisplayList.h index 41166ba..d53626e 100644 --- a/ZAPD/ZDisplayList.h +++ b/ZAPD/ZDisplayList.h @@ -4,6 +4,7 @@ #include "ZResource.h" #include "ZRoom/ZRoom.h" #include "ZTexture.h" +#include "ZVtx.h" #include "tinyxml2.h" #include <map> @@ -282,20 +283,6 @@ enum class OoTSegments #define FORCE_BL 0x4000 #define TEX_EDGE 0x0000 -class Vertex -{ -public: - int16_t x, y, z; - uint16_t flag; - int16_t s, t; - uint8_t r, g, b, a; - - Vertex(); - Vertex(int16_t nX, int16_t nY, int16_t nZ, uint16_t nFlag, int16_t nS, int16_t nT, uint8_t nR, - uint8_t nG, uint8_t nB, uint8_t nA); - Vertex(std::vector<uint8_t> rawData, uint32_t rawDataIndex); -}; - class ZDisplayList : public ZResource { protected: @@ -350,14 +337,12 @@ public: DListType dListType; - // int32_t dListAddress; - - std::map<uint32_t, std::vector<Vertex>> vertices; + std::map<uint32_t, std::vector<ZVtx>> vertices; std::map<uint32_t, std::string> vtxDeclarations; std::vector<ZDisplayList*> otherDLists; - std::map<uint32_t, ZTexture*> textures; - std::map<uint32_t, std::string> texDeclarations; + ZTexture* lastTexture = nullptr; + ZTexture* lastTlut = nullptr; std::vector<uint32_t> references; @@ -372,16 +357,13 @@ public: void ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<uint8_t>& nRawData, const uint32_t nRawDataIndex) override; - // static ZDisplayList* BuildFromXML(tinyxml2::XMLElement* reader, std::string inFolder, bool - // readFile, ZFile* nParent); void TextureGenCheck(std::string prefix); - static bool TextureGenCheck(std::vector<uint8_t> fileData, - std::map<uint32_t, ZTexture*>& textures, ZRoom* scene, - ZFile* parent, std::string prefix, int32_t texWidth, - int32_t texHeight, uint32_t texAddr, uint32_t texSeg, - F3DZEXTexFormats texFmt, F3DZEXTexSizes texSiz, bool texLoaded, - bool texIsPalette); + static bool TextureGenCheck(std::vector<uint8_t> fileData, ZRoom* scene, ZFile* parent, + std::string prefix, int32_t texWidth, int32_t texHeight, + uint32_t texAddr, uint32_t texSeg, F3DZEXTexFormats texFmt, + F3DZEXTexSizes texSiz, bool texLoaded, bool texIsPalette, + ZDisplayList* self); static int32_t GetDListLength(std::vector<uint8_t> rawData, uint32_t rawDataIndex, DListType dListType); @@ -391,7 +373,6 @@ public: std::string ProcessLegacy(const std::string& prefix); std::string ProcessGfxDis(const std::string& prefix); - void Save(const std::string& outFolder) override; virtual void GenerateHLIntermediette(HLFileIntermediette& hlFile) override; bool IsExternalResource() override; virtual std::string GetExternalExtension() override; diff --git a/ZAPD/ZFile.cpp b/ZAPD/ZFile.cpp index b2a3996..bfb76eb 100644 --- a/ZAPD/ZFile.cpp +++ b/ZAPD/ZFile.cpp @@ -63,6 +63,7 @@ ZFile::ZFile(ZFileMode mode, tinyxml2::XMLElement* reader, const fs::path& nBase outputPath = nOutPath; ParseXML(mode, reader, filename, placeholderMode); + DeclareResourceSubReferences(); } ZFile::~ZFile() @@ -85,8 +86,6 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b else name = filename; - int32_t segment = -1; - // TODO: This should be a variable on the ZFile, but it is a large change in order to force all // ZResource types to have a parent ZFile. const char* gameStr = reader->Attribute("Game"); @@ -103,24 +102,28 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b StringHelper::Sprintf("Error: Game type %s not supported.", gameStr)); } - if (reader->Attribute("BaseAddress") != NULL) - baseAddress = (uint32_t)strtoul( - StringHelper::Split(reader->Attribute("BaseAddress"), "0x")[1].c_str(), NULL, 16); + if (reader->Attribute("BaseAddress") != nullptr) + baseAddress = StringHelper::StrToL(reader->Attribute("BaseAddress"), 16); - if (reader->Attribute("RangeStart") != NULL) - rangeStart = (uint32_t)strtoul( - StringHelper::Split(reader->Attribute("RangeStart"), "0x")[1].c_str(), NULL, 16); + if (reader->Attribute("RangeStart") != nullptr) + rangeStart = StringHelper::StrToL(reader->Attribute("RangeStart"), 16); - if (reader->Attribute("RangeEnd") != NULL) - rangeEnd = (uint32_t)strtoul( - StringHelper::Split(reader->Attribute("RangeEnd"), "0x")[1].c_str(), NULL, 16); + if (reader->Attribute("RangeEnd") != nullptr) + rangeEnd = StringHelper::StrToL(reader->Attribute("RangeEnd"), 16); - if (reader->Attribute("Segment") != NULL) - segment = strtol(reader->Attribute("Segment"), NULL, 10); + // Commented until ZArray doesn't use a ZFile to parse it's contents anymore. + /* + if (reader->Attribute("Segment") == nullptr) + throw std::runtime_error(StringHelper::Sprintf( + "ZFile::ParseXML: Error in '%s'.\n" + "\t Missing 'Segment' attribute in File node. \n", + name.c_str())); + */ - if (segment != -1) + if (reader->Attribute("Segment") != nullptr) { - Globals::Instance->AddSegment(segment); + segment = StringHelper::StrToL(reader->Attribute("Segment"), 10); + Globals::Instance->AddSegment(segment, this); } string folderName = (basePath / Path::GetFileNameWithoutExtension(name)).string(); @@ -151,7 +154,8 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b if (Globals::Instance->verbosity >= VERBOSITY_INFO) printf("%s: 0x%06X\n", nameXml, rawDataIndex); - if (offsetXml != NULL) + // Check for repeated attributes. + if (offsetXml != nullptr) { rawDataIndex = strtol(StringHelper::Split(offsetXml, "0x")[1].c_str(), NULL, 16); @@ -163,7 +167,7 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b } offsetSet.insert(offsetXml); } - if (outNameXml != NULL) + if (outNameXml != nullptr) { if (outNameSet.find(outNameXml) != outNameSet.end()) { @@ -173,7 +177,7 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b } outNameSet.insert(outNameXml); } - if (nameXml != NULL) + if (nameXml != nullptr) { if (nameSet.find(nameXml) != nameSet.end()) { @@ -194,27 +198,12 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b if (mode == ZFileMode::Extract) nRes->ExtractFromXML(child, rawData, rawDataIndex); - // TODO: See if we can make this part of the ZRoom code... - if (nRes->GetResourceType() == ZResourceType::Room) - { - if (nodeName == "Scene") - { - Globals::Instance->lastScene = (ZRoom*)nRes; - - if (segment == -1) - segment = SEGMENT_SCENE; - } - else - { - if (segment == -1) - segment = SEGMENT_ROOM; - } - - if (segment != -1) - Globals::Instance->AddSegment(segment); - } + auto resType = nRes->GetResourceType(); + if (resType == ZResourceType::Texture) + AddTextureResource(rawDataIndex, static_cast<ZTexture*>(nRes)); + else + resources.push_back(nRes); - resources.push_back(nRes); rawDataIndex += nRes->GetRawDataSize(); } else if (string(child->Name()) == "File") @@ -233,6 +222,14 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b } } +void ZFile::DeclareResourceSubReferences() +{ + for (size_t i = 0; i < resources.size(); i++) + { + resources.at(i)->DeclareReferences(name); + } +} + void ZFile::BuildSourceFile(fs::path outputDir) { string folderName = Path::GetFileNameWithoutExtension(outputPath.string()); @@ -259,6 +256,16 @@ std::string ZFile::GetName() return name; } +const fs::path& ZFile::GetXmlFilePath() const +{ + return xmlFilePath; +} + +const std::vector<uint8_t>& ZFile::GetRawData() const +{ + return rawData; +} + void ZFile::ExtractResources(fs::path outputDir) { string folderName = Path::GetFileNameWithoutExtension(outputPath.string()); @@ -280,8 +287,7 @@ void ZFile::ExtractResources(fs::path outputDir) if (Globals::Instance->verbosity >= VERBOSITY_INFO) printf("Saving resource %s\n", res->GetName().c_str()); - res->CalcHash(); - res->Save(outputPath.string()); + res->Save(outputPath); } if (Globals::Instance->testMode) @@ -460,30 +466,46 @@ void ZFile::AddDeclarationDebugChecks(uint32_t address) #endif } -std::string ZFile::GetDeclarationName(uint32_t address) +std::string ZFile::GetDeclarationName(uint32_t address) const { return GetDeclarationName(address, "ERROR_COULD_NOT_FIND_DECLARATION"); // Note: For now that default // message is just for testing } -std::string ZFile::GetDeclarationName(uint32_t address, std::string defaultResult) +std::string ZFile::GetDeclarationName(uint32_t address, std::string defaultResult) const { if (declarations.find(address) != declarations.end()) - return declarations[address]->varName; + return declarations.at(address)->varName; return defaultResult; } -Declaration* ZFile::GetDeclaration(uint32_t address) +std::string ZFile::GetDeclarationPtrName(segptr_t segAddress) const +{ + if (segAddress == 0) + return "NULL"; + + Declaration* decl = GetDeclaration(Seg2Filespace(segAddress, baseAddress)); + + if (!Globals::Instance->HasSegment(GETSEGNUM(segAddress)) || decl == nullptr) + return StringHelper::Sprintf("0x%08X", segAddress); + + if (!decl->isArray) + return "&" + decl->varName; + + return decl->varName; +} + +Declaration* ZFile::GetDeclaration(uint32_t address) const { if (declarations.find(address) != declarations.end()) - return declarations[address]; + return declarations.at(address); return nullptr; } -Declaration* ZFile::GetDeclarationRanged(uint32_t address) +Declaration* ZFile::GetDeclarationRanged(uint32_t address) const { for (const auto decl : declarations) { @@ -494,7 +516,7 @@ Declaration* ZFile::GetDeclarationRanged(uint32_t address) return nullptr; } -uint32_t ZFile::GetDeclarationRangedAddress(uint32_t address) +uint32_t ZFile::GetDeclarationRangedAddress(uint32_t address) const { for (const auto decl : declarations) { @@ -522,8 +544,9 @@ void ZFile::GenerateSourceFiles(fs::path outputDir) GeneratePlaceholderDeclarations(); // Generate Code - for (ZResource* res : resources) + for (size_t i = 0; i < resources.size(); i++) { + ZResource* res = resources.at(i); string resSrc = res->GetSourceOutputCode(name); if (res->IsExternalResource()) @@ -539,16 +562,19 @@ void ZFile::GenerateSourceFiles(fs::path outputDir) if (res->GetResourceType() == ZResourceType::Texture) { - ZTexture* tex = (ZTexture*)res; - - tex->CalcHash(); + ZTexture* tex = static_cast<ZTexture*>(res); - // TEXTURE POOL CHECK - if (Globals::Instance->cfg.texturePool.find(tex->hash) != - Globals::Instance->cfg.texturePool.end()) + if (!Globals::Instance->cfg.texturePool.empty()) { - incStr = Globals::Instance->cfg.texturePool[tex->hash].path.string() + "." + - res->GetExternalExtension() + ".inc"; + tex->CalcHash(); + + // TEXTURE POOL CHECK + if (Globals::Instance->cfg.texturePool.find(tex->hash) != + Globals::Instance->cfg.texturePool.end()) + { + incStr = Globals::Instance->cfg.texturePool[tex->hash].path.string() + "." + + res->GetExternalExtension() + ".inc"; + } } incStr += ".c"; @@ -639,6 +665,24 @@ void ZFile::GeneratePlaceholderDeclarations() } } +void ZFile::AddTextureResource(uint32_t offset, ZTexture* tex) +{ + for (auto res : resources) + assert(res->GetRawDataIndex() != offset); + + resources.push_back(tex); + texturesResources[offset] = tex; +} + +ZTexture* ZFile::GetTextureResource(uint32_t offset) const +{ + auto tex = texturesResources.find(offset); + if (tex != texturesResources.end()) + return tex->second; + + return nullptr; +} + std::map<std::string, ZResourceFactoryFunc*>* ZFile::GetNodeMap() { static std::map<std::string, ZResourceFactoryFunc*> nodeMap; @@ -658,6 +702,8 @@ string ZFile::ProcessDeclarations() if (declarations.size() == 0) return output; + defines += ProcessTextureIntersections(name); + // Account for padding/alignment uint32_t lastAddr = 0; uint32_t lastSize = 0; @@ -665,12 +711,10 @@ string ZFile::ProcessDeclarations() // printf("RANGE START: 0x%06X - RANGE END: 0x%06X\n", rangeStart, rangeEnd); // Optimization: See if there are any arrays side by side that can be merged... - auto declarationKeys = - vector<pair<int32_t, Declaration*>>(declarations.begin(), declarations.end()); - sort(declarationKeys.begin(), declarationKeys.end(), - [](const auto& lhs, const auto& rhs) { return lhs.first < rhs.first; }); + std::vector<pair<int32_t, Declaration*>> declarationKeys(declarations.begin(), + declarations.end()); - pair<int32_t, Declaration*> lastItem = declarationKeys[0]; + pair<int32_t, Declaration*> lastItem = declarationKeys.at(0); for (size_t i = 1; i < declarationKeys.size(); i++) { @@ -1153,4 +1197,61 @@ string ZFile::ProcessExterns() output += defines; return output; -}
\ No newline at end of file +} + +std::string ZFile::ProcessTextureIntersections(std::string prefix) +{ + if (texturesResources.empty()) + return ""; + + std::string defines = ""; + vector<pair<uint32_t, ZTexture*>> texturesSorted(texturesResources.begin(), + texturesResources.end()); + + for (size_t i = 0; i < texturesSorted.size() - 1; i++) + { + uint32_t currentOffset = texturesSorted[i].first; + uint32_t nextOffset = texturesSorted[i + 1].first; + auto& currentTex = texturesResources.at(currentOffset); + int texSize = currentTex->GetRawDataSize(); + + if (currentTex->WasDeclaredInXml()) + { + // We believe the user is right. + continue; + } + + if ((currentOffset + texSize) > nextOffset) + { + uint32_t offsetDiff = nextOffset - currentOffset; + if (currentTex->isPalette) + { + // Shrink palette so it doesn't overlap + currentTex->SetDimensions(offsetDiff / currentTex->GetPixelMultiplyer(), 1); + declarations.at(currentOffset)->size = currentTex->GetRawDataSize(); + } + else + { + std::string texName = GetDeclarationPtrName(currentOffset); + std::string texNextName; + + Declaration* nextDecl = GetDeclaration(nextOffset); + if (nextDecl == nullptr) + texNextName = texturesResources.at(nextOffset)->GetName(); + else + texNextName = nextDecl->varName; + + defines += StringHelper::Sprintf("#define %s ((u32)%s + 0x%06X)\n", + texNextName.c_str(), texName.c_str(), offsetDiff); + + declarations.erase(nextOffset); + texturesResources.erase(nextOffset); + texturesSorted.erase(texturesSorted.begin() + i + 1); + + i--; + } + } + } + + return defines; +} diff --git a/ZAPD/ZFile.h b/ZAPD/ZFile.h index 365bf43..278c80c 100644 --- a/ZAPD/ZFile.h +++ b/ZAPD/ZFile.h @@ -4,6 +4,7 @@ #include <vector> #include "Directory.h" #include "ZResource.h" +#include "ZTexture.h" #include "tinyxml2.h" enum class ZFileMode @@ -32,6 +33,7 @@ public: std::map<uint32_t, Declaration*> declarations; std::string defines; std::vector<ZResource*> resources; + int32_t segment; uint32_t baseAddress, rangeStart, rangeEnd; ZFile(const fs::path& nOutPath, std::string nName); @@ -42,6 +44,8 @@ public: std::string GetVarName(uint32_t address); std::string GetName(); + const fs::path& GetXmlFilePath() const; + const std::vector<uint8_t>& GetRawData() const; void ExtractResources(fs::path outputDir); void BuildSourceFile(fs::path outputDir); void AddResource(ZResource* res); @@ -72,15 +76,19 @@ public: Declaration* AddDeclarationIncludeArray(uint32_t address, std::string includePath, size_t size, std::string varType, std::string varName, size_t arrayItemCnt); - std::string GetDeclarationName(uint32_t address); - std::string GetDeclarationName(uint32_t address, std::string defaultResult); - Declaration* GetDeclaration(uint32_t address); - Declaration* GetDeclarationRanged(uint32_t address); - uint32_t GetDeclarationRangedAddress(uint32_t address); + std::string GetDeclarationName(uint32_t address) const; + std::string GetDeclarationName(uint32_t address, std::string defaultResult) const; + std::string GetDeclarationPtrName(segptr_t segAddress) const; + Declaration* GetDeclaration(uint32_t address) const; + Declaration* GetDeclarationRanged(uint32_t address) const; + uint32_t GetDeclarationRangedAddress(uint32_t address) const; bool HasDeclaration(uint32_t address); std::string GetHeaderInclude(); void GeneratePlaceholderDeclarations(); + void AddTextureResource(uint32_t offset, ZTexture* tex); + ZTexture* GetTextureResource(uint32_t offset) const; + static std::map<std::string, ZResourceFactoryFunc*>* GetNodeMap(); static void RegisterNode(std::string nodeName, ZResourceFactoryFunc* nodeFunc); @@ -90,10 +98,15 @@ protected: fs::path basePath; fs::path outputPath; fs::path xmlFilePath; + // Keep track of every texture of this ZFile. + // The pointers declared here are "borrowed" (somebody else is the owner), + // so ZFile shouldn't delete/free those textures. + std::map<uint32_t, ZTexture*> texturesResources; ZFile(); void ParseXML(ZFileMode mode, tinyxml2::XMLElement* reader, std::string filename, bool placeholderMode); + void DeclareResourceSubReferences(); void GenerateSourceFiles(fs::path outputDir); void GenerateSourceHeaderFiles(); void GenerateHLIntermediette(); @@ -101,4 +114,6 @@ protected: std::string ProcessDeclarations(); void ProcessDeclarationText(Declaration* decl); std::string ProcessExterns(); -};
\ No newline at end of file + + std::string ProcessTextureIntersections(std::string prefix); +}; diff --git a/ZAPD/ZResource.cpp b/ZAPD/ZResource.cpp index 466b3ab..fb76605 100644 --- a/ZAPD/ZResource.cpp +++ b/ZAPD/ZResource.cpp @@ -26,6 +26,7 @@ void ZResource::ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<u ParseXML(reader); ParseRawData(); + CalcHash(); } void ZResource::ExtractFromFile(const std::vector<uint8_t>& nRawData, uint32_t nRawDataIndex) @@ -34,6 +35,7 @@ void ZResource::ExtractFromFile(const std::vector<uint8_t>& nRawData, uint32_t n rawDataIndex = nRawDataIndex; ParseRawData(); + CalcHash(); } void ZResource::ParseXML(tinyxml2::XMLElement* reader) @@ -74,10 +76,12 @@ void ZResource::ParseXML(tinyxml2::XMLElement* reader) "with inner element/child detected.\n", name.c_str(), reader->Name())); } + + declaredInXml = true; } } -void ZResource::Save(const std::string& outFolder) +void ZResource::Save(const fs::path& outFolder) { } @@ -85,12 +89,12 @@ void ZResource::PreGenSourceFiles() { } -string ZResource::GetName() +const std::string& ZResource::GetName() const { return name; } -std::string ZResource::GetOutName() +const std::string& ZResource::GetOutName() const { return outName; } @@ -120,16 +124,21 @@ std::string ZResource::GetExternalExtension() return ""; } -vector<uint8_t> ZResource::GetRawData() +const std::vector<uint8_t>& ZResource::GetRawData() const { return rawData; } -void ZResource::SetRawData(std::vector<uint8_t> nData) +void ZResource::SetRawData(const std::vector<uint8_t>& nData) { rawData = nData; } +bool ZResource::WasDeclaredInXml() const +{ + return declaredInXml; +} + uint32_t ZResource::GetRawDataIndex() { return rawDataIndex; @@ -159,6 +168,10 @@ void ZResource::ParseRawData() { } +void ZResource::DeclareReferences(const std::string& prefix) +{ +} + void ZResource::GenerateHLIntermediette(HLFileIntermediette& hlFile) { } diff --git a/ZAPD/ZResource.h b/ZAPD/ZResource.h index 5b411d2..984974b 100644 --- a/ZAPD/ZResource.h +++ b/ZAPD/ZResource.h @@ -7,6 +7,8 @@ #include <vector> #include "tinyxml2.h" +#include "Directory.h" + #define SEGMENT_SCENE 2 #define SEGMENT_ROOM 3 #define SEGMENT_KEEP 4 @@ -50,26 +52,28 @@ class ZResource { public: ZFile* parent; - bool outputDeclaration; - uint32_t hash; + bool outputDeclaration = true; + uint32_t hash = 0; ZResource(ZFile* nParent); virtual ~ZResource(); // Parsing from File virtual void ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<uint8_t>& nRawData, - const uint32_t nRawDataIndex); // Extract Mode + const uint32_t nRawDataIndex); + // Extract Mode virtual void ExtractFromFile(const std::vector<uint8_t>& nRawData, uint32_t nRawDataIndex); // Misc virtual void ParseXML(tinyxml2::XMLElement* reader); virtual void ParseRawData(); + virtual void DeclareReferences(const std::string& prefix); virtual std::string GetSourceOutputCode(const std::string& prefix); virtual std::string GetSourceOutputHeader(const std::string& prefix); virtual void PreGenSourceFiles(); virtual void GenerateHLIntermediette(HLFileIntermediette& hlFile); virtual void CalcHash(); - virtual void Save(const std::string& outFolder); + virtual void Save(const fs::path& outFolder); // Properties virtual bool IsExternalResource(); @@ -79,15 +83,16 @@ public: virtual std::string GetExternalExtension(); // Getters/Setters - std::string GetName(); + const std::string& GetName() const; void SetName(std::string nName); - std::string GetOutName(); + const std::string& GetOutName() const; void SetOutName(std::string nName); virtual uint32_t GetRawDataIndex(); virtual void SetRawDataIndex(uint32_t value); virtual size_t GetRawDataSize(); - virtual std::vector<uint8_t> GetRawData(); - virtual void SetRawData(std::vector<uint8_t> nData); + virtual const std::vector<uint8_t>& GetRawData() const; + virtual void SetRawData(const std::vector<uint8_t>& nData); + bool WasDeclaredInXml() const; protected: std::string name; @@ -98,6 +103,7 @@ protected: bool canHaveInner = false; // Can this type have an inner node? bool isCustomAsset; // If set to true, create a reference for the asset in the file, but don't // actually try to extract it from the file + bool declaredInXml = false; }; enum class DeclarationAlignment @@ -178,4 +184,4 @@ typedef ZResource*(ZResourceFactoryFunc)(); ZFile::RegisterNode(#nodeName, &ZResourceFactory_##zResClass_##nodeName); \ } \ }; \ - static ZRes_##nodeName inst_ZRes_##nodeName; + static ZRes_##nodeName inst_ZRes_##nodeName diff --git a/ZAPD/ZRoom/Commands/SetCutscenes.cpp b/ZAPD/ZRoom/Commands/SetCutscenes.cpp index 345dca1..02b59bc 100644 --- a/ZAPD/ZRoom/Commands/SetCutscenes.cpp +++ b/ZAPD/ZRoom/Commands/SetCutscenes.cpp @@ -47,8 +47,9 @@ SetCutscenes::SetCutscenes(ZRoom* nZRoom, std::vector<uint8_t> rawData, uint32_t declaration += "\n"; ZCutsceneMM* cutscene = new ZCutsceneMM(nZRoom->parent); - cutscene->ExtractFromXML( - nullptr, rawData, entry->segmentOffset); // TODO: Use ExtractFromFile() here when that gets implemented + + // TODO: Use ExtractFromFile() here when that gets implemented + cutscene->ExtractFromXML(nullptr, rawData, entry->segmentOffset); cutscenes.push_back(cutscene); } diff --git a/ZAPD/ZRoom/Commands/SetMesh.cpp b/ZAPD/ZRoom/Commands/SetMesh.cpp index 62e1b1b..d875529 100644 --- a/ZAPD/ZRoom/Commands/SetMesh.cpp +++ b/ZAPD/ZRoom/Commands/SetMesh.cpp @@ -256,11 +256,6 @@ void SetMesh::GenDListDeclarations(std::vector<uint8_t> rawData, ZDisplayList* d StringHelper::Sprintf("%sVtx_%06X", zRoom->GetName().c_str(), vtxEntry.first), dList->vertices[vtxEntry.first].size(), vtxEntry.second); } - - for (pair<uint32_t, string> texEntry : dList->texDeclarations) - { - zRoom->textures[texEntry.first] = dList->textures[texEntry.first]; - } } std::string SetMesh::GenDListExterns(ZDisplayList* dList) @@ -276,10 +271,6 @@ std::string SetMesh::GenDListExterns(ZDisplayList* dList) for (ZDisplayList* otherDList : dList->otherDLists) sourceOutput += GenDListExterns(otherDList); - for (pair<uint32_t, string> texEntry : dList->texDeclarations) - sourceOutput += StringHelper::Sprintf("extern u64 %sTex_%06X[];\n", - zRoom->GetName().c_str(), texEntry.first); - sourceOutput += dList->defines; return sourceOutput; diff --git a/ZAPD/ZRoom/ZRoom.cpp b/ZAPD/ZRoom/ZRoom.cpp index de73b97..09cda02 100644 --- a/ZAPD/ZRoom/ZRoom.cpp +++ b/ZAPD/ZRoom/ZRoom.cpp @@ -50,9 +50,6 @@ REGISTER_ZFILENODE(Scene, ZRoom); ZRoom::ZRoom(ZFile* nParent) : ZResource(nParent) { - textures = map<int32_t, ZTexture*>(); - commands = vector<ZRoomCommand*>(); - commandSets = vector<CommandSet>(); extDefines = ""; scene = nullptr; roomCount = -1; @@ -63,9 +60,6 @@ ZRoom::~ZRoom() { for (ZRoomCommand* cmd : commands) delete cmd; - - for (auto t : textures) - delete t.second; } void ZRoom::ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<uint8_t>& nRawData, @@ -82,9 +76,6 @@ void ZRoom::ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<uint8 Globals::Instance->lastScene = this; } - Globals::Instance->AddSegment(SEGMENT_ROOM); - Globals::Instance->AddSegment(SEGMENT_SCENE); - uint32_t cmdCount = UINT32_MAX; if (name == "syotes_room_0") @@ -158,12 +149,14 @@ void ZRoom::ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<uint8 delete pathway; } +#ifndef DEPRECATION_OFF fprintf(stderr, "ZRoom::ExtractFromXML: Deprecation warning in '%s'.\n" "\t The resource '%s' is currently deprecated, and will be removed in a future " "version.\n" "\t Use the non-hint version instead.\n", name.c_str(), child->Name()); +#endif } // ParseCommands(rawDataIndex); @@ -487,65 +480,6 @@ string ZRoom::GetSourceOutputCode(const std::string& prefix) ProcessCommandSets(); - // Check for texture intersections - { - string defines = ""; - if (textures.size() != 0) - { - vector<pair<uint32_t, ZTexture*>> texturesSorted(textures.begin(), textures.end()); - - sort(texturesSorted.begin(), texturesSorted.end(), - [](const auto& lhs, const auto& rhs) { return lhs.first < rhs.first; }); - - for (size_t i = 0; i < texturesSorted.size() - 1; i++) - { - int32_t texSize = textures[texturesSorted[i].first]->GetRawDataSize(); - - if ((texturesSorted[i].first + texSize) > texturesSorted[i + 1].first) - { - // int32_t intersectAmt = (texturesSorted[i].first + texSize) - texturesSorted[i - // + 1].first; - - defines += StringHelper::Sprintf( - "#define %sTex_%06X ((u32)%sTex_%06X + 0x%06X)\n", prefix.c_str(), - texturesSorted[i + 1].first, prefix.c_str(), texturesSorted[i].first, - texturesSorted[i + 1].first - texturesSorted[i].first); - - parent->declarations.erase(texturesSorted[i + 1].first); - textures.erase(texturesSorted[i + 1].first); - texturesSorted.erase(texturesSorted.begin() + i + 1); - - i--; - } - } - } - - parent->defines += defines; - } - - for (pair<int32_t, ZTexture*> item : textures) - { - string declaration = ""; - - declaration += item.second->GetSourceOutputCode(prefix); - - std::string outPath = item.second->GetPoolOutPath(Globals::Instance->outputPath.string()); - - if (Globals::Instance->verbosity >= VERBOSITY_DEBUG) - printf("SAVING IMAGE TO %s\n", outPath.c_str()); - - item.second->Save(outPath); - - auto filepath = Globals::Instance->outputPath / - Path::GetFileNameWithoutExtension(item.second->GetName()); - parent->AddDeclarationIncludeArray( - item.first, - StringHelper::Sprintf("%s.%s.inc.c", filepath.c_str(), - item.second->GetExternalExtension().c_str()), - item.second->GetRawDataSize(), "u64", - StringHelper::Sprintf("%sTex_%06X", prefix.c_str(), item.first), 0); - } - return sourceOutput; } @@ -564,7 +498,7 @@ ZResourceType ZRoom::GetResourceType() return ZResourceType::Room; } -void ZRoom::Save(const std::string& outFolder) +void ZRoom::Save(const fs::path& outFolder) { for (ZRoomCommand* cmd : commands) cmd->Save(); diff --git a/ZAPD/ZRoom/ZRoom.h b/ZAPD/ZRoom/ZRoom.h index 1068ee2..7bb1241 100644 --- a/ZAPD/ZRoom/ZRoom.h +++ b/ZAPD/ZRoom/ZRoom.h @@ -21,7 +21,6 @@ protected: public: ZRoom* scene; - std::map<int32_t, ZTexture*> textures; std::vector<CommandSet> commandSets; int32_t roomCount; // Only valid for scenes @@ -38,7 +37,7 @@ public: ZRoomCommand* FindCommandOfType(RoomCommand cmdType); size_t GetRawDataSize() override; virtual ZResourceType GetResourceType() override; - virtual void Save(const std::string& outFolder) override; + virtual void Save(const fs::path& outFolder) override; virtual void PreGenSourceFiles() override; }; diff --git a/ZAPD/ZSkeleton.cpp b/ZAPD/ZSkeleton.cpp index 3838450..f610ca5 100644 --- a/ZAPD/ZSkeleton.cpp +++ b/ZAPD/ZSkeleton.cpp @@ -150,10 +150,6 @@ void ZSkeleton::ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<u } } -void ZSkeleton::Save(const std::string& outFolder) -{ -} - void ZSkeleton::GenerateHLIntermediette(HLFileIntermediette& hlFile) { HLModelIntermediette* mdl = (HLModelIntermediette*)&hlFile; diff --git a/ZAPD/ZSkeleton.h b/ZAPD/ZSkeleton.h index 400d6c1..9ca6b4e 100644 --- a/ZAPD/ZSkeleton.h +++ b/ZAPD/ZSkeleton.h @@ -32,7 +32,6 @@ public: void ParseRawData() override; void ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<uint8_t>& nRawData, const uint32_t nRawDataIndex) override; - void Save(const std::string& outFolder) override; void GenerateHLIntermediette(HLFileIntermediette& hlFile) override; size_t GetRawDataSize() override; diff --git a/ZAPD/ZTexture.cpp b/ZAPD/ZTexture.cpp index ebd7c55..cb3eaaa 100644 --- a/ZAPD/ZTexture.cpp +++ b/ZAPD/ZTexture.cpp @@ -1,164 +1,67 @@ -#define STB_IMAGE_IMPLEMENTATION -#define STB_IMAGE_WRITE_IMPLEMENTATION -#define TINYGLTF_IMPLEMENTATION - #include "ZTexture.h" + +#include <cassert> #include "BitConverter.h" #include "CRC32.h" +#include "Directory.h" #include "File.h" #include "Globals.h" #include "Path.h" -#include <Directory.h> -#include "stb_image.h" -#include "stb_image_write.h" - -using namespace std; -using namespace tinyxml2; - REGISTER_ZFILENODE(Texture, ZTexture); ZTexture::ZTexture(ZFile* nParent) : ZResource(nParent) { - bmpRgb = nullptr; - bmpRgba = nullptr; width = 0; height = 0; - type = TextureType::Error; - isPalette = false; - isRawDataFixed = false; -} - -ZTexture::~ZTexture() -{ - if (bmpRgb != nullptr) - { - stbi_image_free(bmpRgb); - bmpRgb = nullptr; - } - - if (bmpRgba != nullptr) - { - stbi_image_free(bmpRgba); - bmpRgba = nullptr; - } - - width = 0; - height = 0; - type = TextureType::Error; } void ZTexture::ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<uint8_t>& nRawData, const uint32_t nRawDataIndex) { - ParseXML(reader); - rawDataIndex = nRawDataIndex; - rawData = vector<uint8_t>(nRawData.data() + rawDataIndex, - nRawData.data() + rawDataIndex + GetRawDataSize()); - - FixRawData(); - PrepareBitmap(); -} - -ZTexture* ZTexture::FromBinary(TextureType nType, std::vector<uint8_t> nRawData, - uint32_t nRawDataIndex, std::string nName, int32_t nWidth, - int32_t nHeight, ZFile* nParent) -{ - ZTexture* tex = new ZTexture(nParent); + ZResource::ExtractFromXML(reader, nRawData, nRawDataIndex); - tex->width = nWidth; - tex->height = nHeight; - tex->type = nType; - tex->name = nName; - tex->outName = nName; - tex->rawDataIndex = nRawDataIndex; + auto filepath = Globals::Instance->outputPath / fs::path(name).stem(); - size_t dataEnd = tex->rawDataIndex + tex->GetRawDataSize(); - tex->rawData = vector<uint8_t>(nRawData.data() + tex->rawDataIndex, nRawData.data() + dataEnd); + std::string incStr = + StringHelper::Sprintf("%s.%s.inc.c", filepath.c_str(), GetExternalExtension().c_str()); - tex->FixRawData(); - tex->CalcHash(); - tex->PrepareBitmap(); - - return tex; + parent->AddDeclarationIncludeArray(rawDataIndex, incStr, GetRawDataSize(), GetSourceTypeName(), + name, 0); } -// Build Source File Mode -ZTexture* ZTexture::BuildFromXML(XMLElement* reader, string inFolder, bool readFile) +void ZTexture::FromBinary(const std::vector<uint8_t>& nRawData, uint32_t nRawDataIndex, + int32_t nWidth, int32_t nHeight, TextureType nType, bool nIsPalette) { - ZTexture* tex = new ZTexture(nullptr); - - tex->ParseXML(reader); + width = nWidth; + height = nHeight; + format = nType; + rawDataIndex = nRawDataIndex; + isPalette = nIsPalette; + name = GetDefaultName(parent->GetName()); + outName = name; - if (readFile) - tex->PrepareRawData(inFolder); + rawData.assign(nRawData.begin(), nRawData.end()); - return tex; + ParseRawData(); + CalcHash(); } -ZTexture* ZTexture::FromPNG(string pngFilePath, TextureType texType) +void ZTexture::FromPNG(const fs::path& pngFilePath, TextureType texType) { - int32_t comp; - ZTexture* tex = new ZTexture(nullptr); - tex->type = texType; - tex->name = StringHelper::Split(Path::GetFileNameWithoutExtension(pngFilePath), ".")[0]; - - tex->bmpRgb = (uint8_t*)stbi_load((pngFilePath).c_str(), (int*)&tex->width, (int*)&tex->height, - &comp, STBI_rgb); - stbi_image_free(tex->bmpRgb); - tex->bmpRgb = nullptr; - tex->rawData = vector<uint8_t>(tex->GetRawDataSize()); - - switch (texType) - { - case TextureType::RGBA16bpp: - tex->PrepareRawDataRGBA16(pngFilePath); - break; - case TextureType::RGBA32bpp: - tex->PrepareRawDataRGBA32(pngFilePath); - break; - case TextureType::Grayscale4bpp: - tex->PrepareRawDataGrayscale4(pngFilePath); - break; - case TextureType::Grayscale8bpp: - tex->PrepareRawDataGrayscale8(pngFilePath); - break; - case TextureType::GrayscaleAlpha4bpp: - tex->PrepareRawDataGrayscaleAlpha4(pngFilePath); - break; - case TextureType::GrayscaleAlpha8bpp: - tex->PrepareRawDataGrayscaleAlpha8(pngFilePath); - break; - case TextureType::GrayscaleAlpha16bpp: - tex->PrepareRawDataGrayscaleAlpha16(pngFilePath); - break; - case TextureType::Palette4bpp: - tex->PrepareRawDataPalette4(pngFilePath); - break; - case TextureType::Palette8bpp: - tex->PrepareRawDataPalette8(pngFilePath); - break; - default: - throw std::runtime_error("Format is not supported!"); - } - - tex->FixRawData(); - - return tex; + format = texType; + name = StringHelper::Split(Path::GetFileNameWithoutExtension(pngFilePath), ".")[0]; + PrepareRawDataFromFile(pngFilePath); } -ZTexture* ZTexture::FromHLTexture(HLTexture* hlTex) +void ZTexture::FromHLTexture(HLTexture* hlTex) { - ZTexture* tex = new ZTexture(nullptr); - - tex->width = hlTex->width; - tex->height = hlTex->height; - tex->type = (TextureType)hlTex->type; - - return tex; + width = hlTex->width; + height = hlTex->height; + format = static_cast<TextureType>(hlTex->type); } -void ZTexture::ParseXML(XMLElement* reader) +void ZTexture::ParseXML(tinyxml2::XMLElement* reader) { ZResource::ParseXML(reader); @@ -168,7 +71,8 @@ void ZTexture::ParseXML(XMLElement* reader) } else { - throw std::runtime_error("Width == nullptr for asset " + (string)reader->Attribute("Name")); + throw std::runtime_error("Width == nullptr for asset " + + std::string(reader->Attribute("Name"))); } if (reader->Attribute("Height") != nullptr) @@ -178,58 +82,39 @@ void ZTexture::ParseXML(XMLElement* reader) else { throw std::runtime_error("Height == nullptr for asset " + - (string)reader->Attribute("Name")); + std::string(reader->Attribute("Name"))); } - string formatStr = reader->Attribute("Format"); + std::string formatStr = reader->Attribute("Format"); - type = GetTextureTypeFromString(formatStr); + format = GetTextureTypeFromString(formatStr); - if (type == TextureType::Error) + if (format == TextureType::Error) throw std::runtime_error("Format " + formatStr + " is not supported!"); -} -void ZTexture::FixRawData() -{ - if (type == TextureType::RGBA32bpp) + auto tlutOffsetXml = reader->Attribute("TlutOffset"); + if (tlutOffsetXml != nullptr) { - for (size_t i = 0; i < rawData.size(); i += 4) + switch (format) { - uint8_t tmp = rawData[i]; - rawData[i] = rawData[i + 2]; - rawData[i + 2] = tmp; + case TextureType::Palette4bpp: + case TextureType::Palette8bpp: + tlutOffset = StringHelper::StrToL(std::string(tlutOffsetXml), 16); + break; + + default: + throw std::runtime_error(StringHelper::Sprintf( + "ZTexture::ParseXML: Error in %s\n" + "\t 'TlutOffset' declared in non color-indexed (ci4 or ci8) texture.\n", + name.c_str())); + break; } } - else if (type == TextureType::RGBA16bpp) // || type == TextureType::GrayscaleAlpha16bpp) - { - for (size_t i = 0; i < rawData.size(); i += 2) - { - uint8_t tmp = rawData[i]; - rawData[i] = rawData[i + 1]; - rawData[i + 1] = tmp; - } - } - - isRawDataFixed = !isRawDataFixed; } -void ZTexture::PrepareBitmap() +void ZTexture::ParseRawData() { - switch (type) - { - case TextureType::RGBA16bpp: - case TextureType::RGBA32bpp: - case TextureType::GrayscaleAlpha4bpp: - case TextureType::GrayscaleAlpha8bpp: - case TextureType::GrayscaleAlpha16bpp: - bmpRgba = new uint8_t[width * height * 4]; - break; - default: - bmpRgb = new uint8_t[width * height * 3]; - break; - } - - switch (type) + switch (format) { case TextureType::RGBA16bpp: PrepareBitmapRGBA16(); @@ -265,60 +150,62 @@ void ZTexture::PrepareBitmap() void ZTexture::PrepareBitmapRGBA16() { - for (int32_t y = 0; y < height; y++) + textureData.InitEmptyRGBImage(width, height, true); + auto parentRawData = parent->GetRawData(); + for (size_t y = 0; y < height; y++) { - for (int32_t x = 0; x < width; x++) + for (size_t x = 0; x < width; x++) { - int32_t pos = ((y * width) + x) * 2; - short data = (short)((rawData[pos + 1] << 8) + rawData[pos]); - uint8_t r = (uint8_t)((data & 0xF800) >> 11); - uint8_t g = (uint8_t)((data & 0x07C0) >> 6); - uint8_t b = (uint8_t)((data & 0x003E) >> 1); - uint8_t alpha = (uint8_t)(data & 0x01); - - bmpRgba[(((y * width) + x) * 4) + 0] = r * 8; - bmpRgba[(((y * width) + x) * 4) + 1] = g * 8; - bmpRgba[(((y * width) + x) * 4) + 2] = b * 8; - bmpRgba[(((y * width) + x) * 4) + 3] = alpha * 255; + int32_t pos = rawDataIndex + ((y * width) + x) * 2; + uint16_t data = parentRawData.at(pos + 1) | (parentRawData.at(pos) << 8); + uint8_t r = (data & 0xF800) >> 11; + uint8_t g = (data & 0x07C0) >> 6; + uint8_t b = (data & 0x003E) >> 1; + uint8_t alpha = data & 0x01; + + textureData.SetRGBPixel(y, x, r * 8, g * 8, b * 8, alpha * 255); } } } void ZTexture::PrepareBitmapRGBA32() { - for (uint16_t y = 0; y < height; y++) + textureData.InitEmptyRGBImage(width, height, true); + auto parentRawData = parent->GetRawData(); + for (size_t y = 0; y < height; y++) { - for (uint16_t x = 0; x < width; x++) + for (size_t x = 0; x < width; x++) { - uint16_t pos = ((y * width) + x) * 4; + size_t pos = rawDataIndex + ((y * width) + x) * 4; + uint8_t r = parentRawData.at(pos + 0); + uint8_t g = parentRawData.at(pos + 1); + uint8_t b = parentRawData.at(pos + 2); + uint8_t alpha = parentRawData.at(pos + 3); - bmpRgba[(((y * width) + x) * 4) + 0] = rawData[pos + 2]; - bmpRgba[(((y * width) + x) * 4) + 1] = rawData[pos + 1]; - bmpRgba[(((y * width) + x) * 4) + 2] = rawData[pos + 0]; - bmpRgba[(((y * width) + x) * 4) + 3] = rawData[pos + 3]; + textureData.SetRGBPixel(y, x, r, g, b, alpha); } } } void ZTexture::PrepareBitmapGrayscale4() { - for (uint16_t y = 0; y < height; y++) + textureData.InitEmptyRGBImage(width, height, false); + auto parentRawData = parent->GetRawData(); + for (size_t y = 0; y < height; y++) { - for (uint16_t x = 0; x < width; x += 2) + for (size_t x = 0; x < width; x += 2) { for (uint8_t i = 0; i < 2; i++) { - uint16_t pos = ((y * width) + x) / 2; + size_t pos = rawDataIndex + ((y * width) + x) / 2; uint8_t grayscale = 0; if (i == 0) - grayscale = rawData[pos] & 0xF0; + grayscale = parentRawData.at(pos) & 0xF0; else - grayscale = (rawData[pos] & 0x0F) << 4; + grayscale = (parentRawData.at(pos) & 0x0F) << 4; - bmpRgb[(((y * width) + x + i) * 3) + 0] = grayscale; - bmpRgb[(((y * width) + x + i) * 3) + 1] = grayscale; - bmpRgb[(((y * width) + x + i) * 3) + 2] = grayscale; + textureData.SetGrayscalePixel(y, x + i, grayscale); } } } @@ -326,42 +213,41 @@ void ZTexture::PrepareBitmapGrayscale4() void ZTexture::PrepareBitmapGrayscale8() { - for (uint16_t y = 0; y < height; y++) + textureData.InitEmptyRGBImage(width, height, false); + auto parentRawData = parent->GetRawData(); + for (size_t y = 0; y < height; y++) { - for (uint16_t x = 0; x < width; x++) + for (size_t x = 0; x < width; x++) { - uint16_t pos = ((y * width) + x) * 1; + size_t pos = rawDataIndex + ((y * width) + x) * 1; - bmpRgb[(((y * width) + x) * 3) + 0] = rawData[pos]; - bmpRgb[(((y * width) + x) * 3) + 1] = rawData[pos]; - bmpRgb[(((y * width) + x) * 3) + 2] = rawData[pos]; + textureData.SetGrayscalePixel(y, x, parentRawData.at(pos)); } } } void ZTexture::PrepareBitmapGrayscaleAlpha4() { - for (uint16_t y = 0; y < height; y++) + textureData.InitEmptyRGBImage(width, height, true); + auto parentRawData = parent->GetRawData(); + for (size_t y = 0; y < height; y++) { - for (uint16_t x = 0; x < width; x += 2) + for (size_t x = 0; x < width; x += 2) { for (uint16_t i = 0; i < 2; i++) { - uint16_t pos = ((y * width) + x) / 2; + size_t pos = rawDataIndex + ((y * width) + x) / 2; uint8_t data = 0; if (i == 0) - data = (rawData[pos] & 0xF0) >> 4; + data = (parentRawData.at(pos) & 0xF0) >> 4; else - data = rawData[pos] & 0x0F; + data = parentRawData.at(pos) & 0x0F; uint8_t grayscale = ((data & 0x0E) >> 1) * 32; uint8_t alpha = (data & 0x01) * 255; - bmpRgba[(((y * width) + x + i) * 4) + 0] = grayscale; - bmpRgba[(((y * width) + x + i) * 4) + 1] = grayscale; - bmpRgba[(((y * width) + x + i) * 4) + 2] = grayscale; - bmpRgba[(((y * width) + x + i) * 4) + 3] = alpha; + textureData.SetGrayscalePixel(y, x + i, grayscale, alpha); } } } @@ -369,59 +255,57 @@ void ZTexture::PrepareBitmapGrayscaleAlpha4() void ZTexture::PrepareBitmapGrayscaleAlpha8() { - for (uint16_t y = 0; y < height; y++) + textureData.InitEmptyRGBImage(width, height, true); + auto parentRawData = parent->GetRawData(); + for (size_t y = 0; y < height; y++) { - for (uint16_t x = 0; x < width; x++) + for (size_t x = 0; x < width; x++) { - uint16_t pos = ((y * width) + x) * 1; - uint8_t grayscale = rawData[pos] & 0xF0; - uint8_t alpha = (rawData[pos] & 0x0F) << 4; - - bmpRgba[(((y * width) + x) * 4) + 0] = grayscale; - bmpRgba[(((y * width) + x) * 4) + 1] = grayscale; - bmpRgba[(((y * width) + x) * 4) + 2] = grayscale; - bmpRgba[(((y * width) + x) * 4) + 3] = alpha; + size_t pos = rawDataIndex + ((y * width) + x) * 1; + uint8_t grayscale = parentRawData.at(pos) & 0xF0; + uint8_t alpha = (parentRawData.at(pos) & 0x0F) << 4; + + textureData.SetGrayscalePixel(y, x, grayscale, alpha); } } } void ZTexture::PrepareBitmapGrayscaleAlpha16() { - for (uint16_t y = 0; y < height; y++) + textureData.InitEmptyRGBImage(width, height, true); + auto parentRawData = parent->GetRawData(); + for (size_t y = 0; y < height; y++) { - for (uint16_t x = 0; x < width; x++) + for (size_t x = 0; x < width; x++) { - uint16_t pos = ((y * width) + x) * 2; - uint8_t grayscale = rawData[pos + 0]; - uint8_t alpha = rawData[pos + 1]; - - bmpRgba[(((y * width) + x) * 4) + 0] = grayscale; - bmpRgba[(((y * width) + x) * 4) + 1] = grayscale; - bmpRgba[(((y * width) + x) * 4) + 2] = grayscale; - bmpRgba[(((y * width) + x) * 4) + 3] = alpha; + size_t pos = rawDataIndex + ((y * width) + x) * 2; + uint8_t grayscale = parentRawData.at(pos + 0); + uint8_t alpha = parentRawData.at(pos + 1); + + textureData.SetGrayscalePixel(y, x, grayscale, alpha); } } } void ZTexture::PrepareBitmapPalette4() { - for (uint16_t y = 0; y < height; y++) + textureData.InitEmptyPaletteImage(width, height); + auto parentRawData = parent->GetRawData(); + for (size_t y = 0; y < height; y++) { - for (uint16_t x = 0; x < width; x += 2) + for (size_t x = 0; x < width; x += 2) { for (uint16_t i = 0; i < 2; i++) { - uint16_t pos = ((y * width) + x) / 2; + size_t pos = rawDataIndex + ((y * width) + x) / 2; uint8_t paletteIndex = 0; if (i == 0) - paletteIndex = (rawData[pos] & 0xF0) >> 4; + paletteIndex = (parentRawData.at(pos) & 0xF0) >> 4; else - paletteIndex = (rawData[pos] & 0x0F); + paletteIndex = (parentRawData.at(pos) & 0x0F); - bmpRgb[(((y * width) + x + i) * 3) + 0] = paletteIndex * 16; - bmpRgb[(((y * width) + x + i) * 3) + 1] = paletteIndex * 16; - bmpRgb[(((y * width) + x + i) * 3) + 2] = paletteIndex * 16; + textureData.SetIndexedPixel(y, x + i, paletteIndex, paletteIndex * 16); } } } @@ -429,267 +313,310 @@ void ZTexture::PrepareBitmapPalette4() void ZTexture::PrepareBitmapPalette8() { - for (uint16_t y = 0; y < height; y++) + textureData.InitEmptyPaletteImage(width, height); + auto parentRawData = parent->GetRawData(); + for (size_t y = 0; y < height; y++) { - for (uint16_t x = 0; x < width; x++) + for (size_t x = 0; x < width; x++) { - uint16_t pos = ((y * width) + x) * 1; + size_t pos = rawDataIndex + ((y * width) + x) * 1; + uint8_t grayscale = parentRawData.at(pos); - bmpRgb[(((y * width) + x) * 3) + 0] = rawData[pos]; - bmpRgb[(((y * width) + x) * 3) + 1] = rawData[pos]; - bmpRgb[(((y * width) + x) * 3) + 2] = rawData[pos]; + textureData.SetIndexedPixel(y, x, grayscale, grayscale); } } } -void ZTexture::PrepareRawData(string inFolder) +void ZTexture::DeclareReferences(const std::string& prefix) { - rawData = vector<uint8_t>(GetRawDataSize()); + if (tlutOffset != static_cast<uint32_t>(-1)) + { + tlut = parent->GetTextureResource(tlutOffset); + if (tlut == nullptr) + { + int32_t tlutDim = 16; + if (format == TextureType::Palette4bpp) + tlutDim = 4; + + auto filepath = Globals::Instance->outputPath / fs::path(name).stem(); + std::string incStr = StringHelper::Sprintf("%s.%s.inc.c", filepath.c_str(), + GetExternalExtension().c_str()); + + tlut = new ZTexture(parent); + tlut->FromBinary(rawData, tlutOffset, tlutDim, tlutDim, TextureType::RGBA16bpp, true); + parent->AddTextureResource(tlutOffset, tlut); + parent->AddDeclarationIncludeArray(tlutOffset, incStr, tlut->GetRawDataSize(), + tlut->GetSourceTypeName(), tlut->GetName(), 0); + } + else + { + tlut->isPalette = true; + } + SetTlut(tlut); + } +} - switch (type) +void ZTexture::PrepareRawDataFromFile(const fs::path& pngFilePath) +{ + switch (format) { case TextureType::RGBA16bpp: - PrepareRawDataRGBA16(inFolder + "/" + outName + ".rgba5a1.png"); + PrepareRawDataRGBA16(pngFilePath); break; case TextureType::RGBA32bpp: - PrepareRawDataRGBA32(inFolder + "/" + outName + ".rgba32.png"); + PrepareRawDataRGBA32(pngFilePath); break; case TextureType::Grayscale4bpp: - PrepareRawDataGrayscale4(inFolder + "/" + outName + ".i4.png"); + PrepareRawDataGrayscale4(pngFilePath); break; case TextureType::Grayscale8bpp: - PrepareRawDataGrayscale8(inFolder + "/" + outName + ".i8.png"); + PrepareRawDataGrayscale8(pngFilePath); break; case TextureType::GrayscaleAlpha4bpp: - PrepareRawDataGrayscaleAlpha4(inFolder + "/" + outName + ".ia4.png"); + PrepareRawDataGrayscaleAlpha4(pngFilePath); break; case TextureType::GrayscaleAlpha8bpp: - PrepareRawDataGrayscaleAlpha8(inFolder + "/" + outName + ".ia8.png"); + PrepareRawDataGrayscaleAlpha8(pngFilePath); break; case TextureType::GrayscaleAlpha16bpp: - PrepareRawDataGrayscaleAlpha16(inFolder + "/" + outName + ".ia16.png"); + PrepareRawDataGrayscaleAlpha16(pngFilePath); break; case TextureType::Palette4bpp: - PrepareRawDataPalette4(inFolder + "/" + outName + ".ci4.png"); + PrepareRawDataPalette4(pngFilePath); break; case TextureType::Palette8bpp: - PrepareRawDataPalette8(inFolder + "/" + outName + ".ci8.png"); + PrepareRawDataPalette8(pngFilePath); break; default: - throw std::runtime_error("Build Mode: Format is not supported!"); + throw std::runtime_error("Format is not supported!"); } } -void ZTexture::PrepareRawDataRGBA16(string rgbaPath) +void ZTexture::PrepareRawDataRGBA16(const fs::path& rgbaPath) { - int32_t width; - int32_t height; - int32_t comp; + textureData.ReadPng(rgbaPath); - bmpRgba = (uint8_t*)stbi_load(rgbaPath.c_str(), &width, &height, &comp, STBI_rgb_alpha); + width = textureData.GetWidth(); + height = textureData.GetHeight(); + textureDataRaw.clear(); + textureDataRaw.resize(GetRawDataSize()); for (uint16_t y = 0; y < height; y++) { for (uint16_t x = 0; x < width; x++) { - uint16_t pos = ((y * width) + x) * 2; + size_t pos = ((y * width) + x) * 2; + RGBAPixel pixel = textureData.GetPixel(y, x); - uint8_t r = bmpRgba[(((y * width) + x) * 4) + 0] / 8; - uint8_t g = bmpRgba[(((y * width) + x) * 4) + 1] / 8; - uint8_t b = bmpRgba[(((y * width) + x) * 4) + 2] / 8; + uint8_t r = pixel.r / 8; + uint8_t g = pixel.g / 8; + uint8_t b = pixel.b / 8; - uint8_t alphaBit = bmpRgba[(((y * width) + x) * 4) + 3] != 0; + uint8_t alphaBit = pixel.a != 0; uint16_t data = (r << 11) + (g << 6) + (b << 1) + alphaBit; - rawData[pos + 0] = (data & 0xFF00) >> 8; - rawData[pos + 1] = (data & 0x00FF); + textureDataRaw[pos + 0] = (data & 0xFF00) >> 8; + textureDataRaw[pos + 1] = (data & 0x00FF); } } } -void ZTexture::PrepareRawDataRGBA32(string rgbaPath) +void ZTexture::PrepareRawDataRGBA32(const fs::path& rgbaPath) { - int32_t width; - int32_t height; - int32_t comp; + textureData.ReadPng(rgbaPath); - bmpRgba = (uint8_t*)stbi_load(rgbaPath.c_str(), &width, &height, &comp, STBI_rgb_alpha); + width = textureData.GetWidth(); + height = textureData.GetHeight(); + textureDataRaw.clear(); + textureDataRaw.resize(GetRawDataSize()); for (uint16_t y = 0; y < height; y++) { for (uint16_t x = 0; x < width; x++) { - uint16_t pos = ((y * width) + x) * 4; + size_t pos = ((y * width) + x) * 4; + RGBAPixel pixel = textureData.GetPixel(y, x); - rawData[pos + 0] = bmpRgba[(((y * width) + x) * 4) + 0]; - rawData[pos + 1] = bmpRgba[(((y * width) + x) * 4) + 1]; - rawData[pos + 2] = bmpRgba[(((y * width) + x) * 4) + 2]; - rawData[pos + 3] = bmpRgba[(((y * width) + x) * 4) + 3]; + textureDataRaw[pos + 0] = pixel.r; + textureDataRaw[pos + 1] = pixel.g; + textureDataRaw[pos + 2] = pixel.b; + textureDataRaw[pos + 3] = pixel.a; } } } -void ZTexture::PrepareRawDataGrayscale4(string grayPath) +void ZTexture::PrepareRawDataGrayscale4(const fs::path& grayPath) { - int32_t width; - int32_t height; - int32_t comp; + textureData.ReadPng(grayPath); - bmpRgb = (uint8_t*)stbi_load(grayPath.c_str(), &width, &height, &comp, STBI_rgb); + width = textureData.GetWidth(); + height = textureData.GetHeight(); + textureDataRaw.clear(); + textureDataRaw.resize(GetRawDataSize()); for (uint16_t y = 0; y < height; y++) { for (uint16_t x = 0; x < width; x += 2) { - uint16_t pos = ((y * width) + x) / 2; - uint8_t r1 = bmpRgb[(((y * width) + x) * 3) + 0]; - uint8_t r2 = bmpRgb[(((y * width) + x + 1) * 3) + 0]; + size_t pos = ((y * width) + x) / 2; + uint8_t r1 = textureData.GetPixel(y, x).r; + uint8_t r2 = textureData.GetPixel(y, x + 1).r; - rawData[pos] = (uint8_t)(((r1 / 16) << 4) + (r2 / 16)); + textureDataRaw[pos] = (uint8_t)(((r1 / 16) << 4) + (r2 / 16)); } } } -void ZTexture::PrepareRawDataGrayscale8(string grayPath) +void ZTexture::PrepareRawDataGrayscale8(const fs::path& grayPath) { - int32_t width; - int32_t height; - int32_t comp; + textureData.ReadPng(grayPath); - bmpRgb = (uint8_t*)stbi_load(grayPath.c_str(), &width, &height, &comp, STBI_rgb); + width = textureData.GetWidth(); + height = textureData.GetHeight(); + textureDataRaw.clear(); + textureDataRaw.resize(GetRawDataSize()); for (uint16_t y = 0; y < height; y++) { for (uint16_t x = 0; x < width; x++) { - uint16_t pos = (y * width) + x; - rawData[pos] = bmpRgb[(((y * width) + x) * 3) + 0]; + size_t pos = (y * width) + x; + RGBAPixel pixel = textureData.GetPixel(y, x); + textureDataRaw[pos] = pixel.r; } } } -void ZTexture::PrepareRawDataGrayscaleAlpha4(string grayAlphaPath) +void ZTexture::PrepareRawDataGrayscaleAlpha4(const fs::path& grayAlphaPath) { - int32_t width; - int32_t height; - int32_t comp; + textureData.ReadPng(grayAlphaPath); - bmpRgba = (uint8_t*)stbi_load(grayAlphaPath.c_str(), &width, &height, &comp, STBI_rgb_alpha); + width = textureData.GetWidth(); + height = textureData.GetHeight(); + textureDataRaw.clear(); + textureDataRaw.resize(GetRawDataSize()); for (uint16_t y = 0; y < height; y++) { for (uint16_t x = 0; x < width; x += 2) { - uint16_t pos = ((y * width) + x) / 2; + size_t pos = ((y * width) + x) / 2; uint8_t data = 0; for (uint16_t i = 0; i < 2; i++) { - uint8_t cR = bmpRgba[(((y * width) + x + i) * 4) + 0]; - uint8_t alphaBit = bmpRgba[(((y * width) + x + i) * 4) + 3] != 0; + RGBAPixel pixel = textureData.GetPixel(y, x + i); + uint8_t cR = pixel.r; + uint8_t alphaBit = pixel.a != 0; if (i == 0) - data += (((cR / 32) << 1) + alphaBit) << 4; + data |= (((cR / 32) << 1) + alphaBit) << 4; else - data += ((cR / 32) << 1) + alphaBit; + data |= ((cR / 32) << 1) + alphaBit; } - rawData[pos] = data; + textureDataRaw[pos] = data; } } } -void ZTexture::PrepareRawDataGrayscaleAlpha8(string grayAlphaPath) +void ZTexture::PrepareRawDataGrayscaleAlpha8(const fs::path& grayAlphaPath) { - int32_t width; - int32_t height; - int32_t comp; + textureData.ReadPng(grayAlphaPath); - bmpRgba = (uint8_t*)stbi_load(grayAlphaPath.c_str(), &width, &height, &comp, STBI_rgb_alpha); + width = textureData.GetWidth(); + height = textureData.GetHeight(); + textureDataRaw.clear(); + textureDataRaw.resize(GetRawDataSize()); for (uint16_t y = 0; y < height; y++) { for (uint16_t x = 0; x < width; x++) { - uint16_t pos = ((y * width) + x) * 1; + size_t pos = ((y * width) + x) * 1; + RGBAPixel pixel = textureData.GetPixel(y, x); - uint8_t r = bmpRgba[(((y * width) + x) * 4) + 0]; - uint8_t a = bmpRgba[(((y * width) + x) * 4) + 3]; + uint8_t r = pixel.r; + uint8_t a = pixel.a; - rawData[pos] = ((r / 16) << 4) + (a / 16); + textureDataRaw[pos] = ((r / 16) << 4) + (a / 16); } } } -void ZTexture::PrepareRawDataGrayscaleAlpha16(string grayAlphaPath) +void ZTexture::PrepareRawDataGrayscaleAlpha16(const fs::path& grayAlphaPath) { - int32_t width; - int32_t height; - int32_t comp; + textureData.ReadPng(grayAlphaPath); - bmpRgba = (uint8_t*)stbi_load(grayAlphaPath.c_str(), &width, &height, &comp, STBI_rgb_alpha); + width = textureData.GetWidth(); + height = textureData.GetHeight(); + textureDataRaw.clear(); + textureDataRaw.resize(GetRawDataSize()); for (uint16_t y = 0; y < height; y++) { for (uint16_t x = 0; x < width; x++) { - uint16_t pos = ((y * width) + x) * 2; + size_t pos = ((y * width) + x) * 2; + RGBAPixel pixel = textureData.GetPixel(y, x); - uint8_t cR = bmpRgba[(((y * width) + x) * 4) + 0]; - uint8_t aR = bmpRgba[(((y * width) + x) * 4) + 3]; + uint8_t cR = pixel.r; + uint8_t aR = pixel.a; - rawData[pos + 0] = cR; - rawData[pos + 1] = aR; + textureDataRaw[pos + 0] = cR; + textureDataRaw[pos + 1] = aR; } } } -void ZTexture::PrepareRawDataPalette4(string palPath) +void ZTexture::PrepareRawDataPalette4(const fs::path& palPath) { - int32_t width; - int32_t height; - int32_t comp; + textureData.ReadPng(palPath); - bmpRgb = (uint8_t*)stbi_load(palPath.c_str(), &width, &height, &comp, STBI_rgb); + width = textureData.GetWidth(); + height = textureData.GetHeight(); + textureDataRaw.clear(); + textureDataRaw.resize(GetRawDataSize()); for (uint16_t y = 0; y < height; y++) { for (uint16_t x = 0; x < width; x += 2) { - uint16_t pos = ((y * width) + x) / 2; + size_t pos = ((y * width) + x) / 2; - uint8_t cR1 = bmpRgb[(((y * width) + x) * 3) + 0]; - uint8_t cR2 = bmpRgb[(((y * width) + x + 1) * 3) + 0]; + uint8_t cR1 = textureData.GetIndexedPixel(y, x); + uint8_t cR2 = textureData.GetIndexedPixel(y, x + 1); - rawData[pos] = ((cR1 / 16) << 4) + (cR2 / 16); + textureDataRaw[pos] = (cR1 << 4) | (cR2); } } } -void ZTexture::PrepareRawDataPalette8(string palPath) +void ZTexture::PrepareRawDataPalette8(const fs::path& palPath) { - int32_t width; - int32_t height; - int32_t comp; + textureData.ReadPng(palPath); - bmpRgb = (uint8_t*)stbi_load(palPath.c_str(), &width, &height, &comp, STBI_rgb); + width = textureData.GetWidth(); + height = textureData.GetHeight(); + textureDataRaw.clear(); + textureDataRaw.resize(GetRawDataSize()); for (uint16_t y = 0; y < height; y++) { for (uint16_t x = 0; x < width; x++) { - uint16_t pos = ((y * width) + x); + size_t pos = ((y * width) + x); + uint8_t cR = textureData.GetIndexedPixel(y, x); - uint8_t cR = bmpRgb[(((y * width) + x) * 3) + 0]; - rawData[pos] = cR; + textureDataRaw[pos] = cR; } } } -float ZTexture::GetPixelMultiplyer() +float ZTexture::GetPixelMultiplyer() const { - switch (type) + switch (format) { case TextureType::Grayscale4bpp: case TextureType::GrayscaleAlpha4bpp: @@ -716,7 +643,7 @@ size_t ZTexture::GetRawDataSize() std::string ZTexture::GetIMFmtFromType() { - switch (type) + switch (format) { case TextureType::RGBA32bpp: case TextureType::RGBA16bpp: @@ -738,7 +665,7 @@ std::string ZTexture::GetIMFmtFromType() std::string ZTexture::GetIMSizFromType() { - switch (type) + switch (format) { case TextureType::Grayscale4bpp: case TextureType::Palette4bpp: @@ -757,99 +684,78 @@ std::string ZTexture::GetIMSizFromType() } } -uint16_t ZTexture::GetWidth() +std::string ZTexture::GetDefaultName(const std::string& prefix) { - return width; + const char* suffix = "Tex"; + if (isPalette) + suffix = "TLUT"; + return StringHelper::Sprintf("%s%s_%06X", prefix.c_str(), suffix, rawDataIndex); } -uint16_t ZTexture::GetHeight() +uint32_t ZTexture::GetWidth() const { - return height; + return width; } -void ZTexture::SetWidth(uint16_t nWidth) +uint32_t ZTexture::GetHeight() const { - width = nWidth; + return height; } -void ZTexture::SetHeight(uint16_t nHeight) +void ZTexture::SetDimensions(uint32_t nWidth, uint32_t nHeight) { + width = nWidth; height = nHeight; + ParseRawData(); } TextureType ZTexture::GetTextureType() { - return type; + return format; } -void ZTexture::Save(const std::string& outFolder) +void ZTexture::Save(const fs::path& outFolder) { // Optionally generate text file containing CRC information. This is going to be a one time // process for generating the Texture Pool XML. - if (Globals::Instance->testMode) + if (Globals::Instance->outputCrc) { - if (hash != 0) - { - File::WriteAllText(StringHelper::Sprintf("%s/%s.txt", - Globals::Instance->outputPath.c_str(), - outName.c_str()), - StringHelper::Sprintf("%08lX", hash)); - hash = 0; - } + File::WriteAllText(Globals::Instance->outputPath / (outName + ".txt"), + StringHelper::Sprintf("%08lX", hash)); } - std::string outPath = GetPoolOutPath(outFolder); + auto outPath = GetPoolOutPath(outFolder); if (!Directory::Exists(outPath)) Directory::CreateDirectory(outPath); - if (type == TextureType::RGBA32bpp) - stbi_write_png((outPath + "/" + outName + ".rgba32.png").c_str(), width, height, 4, bmpRgba, - width * 4); - else if (type == TextureType::RGBA16bpp) - stbi_write_png((outPath + "/" + outName + ".rgb5a1.png").c_str(), width, height, 4, bmpRgba, - width * 4); - else if (type == TextureType::Grayscale8bpp) - stbi_write_png((outPath + "/" + outName + ".i8.png").c_str(), width, height, 3, bmpRgb, - width * 3); - else if (type == TextureType::Grayscale4bpp) - stbi_write_png((outPath + "/" + outName + ".i4.png").c_str(), width, height, 3, bmpRgb, - width * 3); - else if (type == TextureType::GrayscaleAlpha16bpp) - stbi_write_png((outPath + "/" + outName + ".ia16.png").c_str(), width, height, 4, bmpRgba, - width * 4); - else if (type == TextureType::GrayscaleAlpha8bpp) - stbi_write_png((outPath + "/" + outName + ".ia8.png").c_str(), width, height, 4, bmpRgba, - width * 4); - else if (type == TextureType::GrayscaleAlpha4bpp) - stbi_write_png((outPath + "/" + outName + ".ia4.png").c_str(), width, height, 4, bmpRgba, - width * 4); - else if (type == TextureType::Palette4bpp) - stbi_write_png((outPath + "/" + outName + ".ci4.png").c_str(), width, height, 3, bmpRgb, - width * 3); - else if (type == TextureType::Palette8bpp) - stbi_write_png((outPath + "/" + outName + ".ci8.png").c_str(), width, height, 3, bmpRgb, - width * 3); - - // if (outName != name && outName != "") - // File::WriteAllText(outFolder + "/" + outName + ".cfg", name.c_str()); -} - -string ZTexture::GetSourceOutputCode(const std::string& prefix) -{ - sourceOutput = ""; - - FixRawData(); - - uint8_t* rawDataArr = rawData.data(); - - for (size_t i = 0; i < rawData.size(); i += 8) + auto outFileName = outPath / (outName + "." + GetExternalExtension() + ".png"); + +#ifdef TEXTURE_DEBUG + printf("Saving PNG: %s\n", outFileName.c_str()); + printf("\t Var name: %s\n", name.c_str()); + if (tlut != nullptr) + printf("\t TLUT name: %s\n", tlut->name.c_str()); +#endif + + textureData.WritePng(outFileName); + +#ifdef TEXTURE_DEBUG + printf("\n"); +#endif +} + +std::string ZTexture::GetBodySourceCode() const +{ + std::string sourceOutput = ""; + + for (size_t i = 0; i < textureDataRaw.size(); i += 8) { if (i % 32 == 0) sourceOutput += " "; sourceOutput += - StringHelper::Sprintf("0x%016llX, ", BitConverter::ToUInt64BE(rawDataArr, i)); + StringHelper::Sprintf("0x%016llX, ", BitConverter::ToUInt64BE(textureDataRaw, i)); if (i % 32 == 24) sourceOutput += StringHelper::Sprintf(" // 0x%06X \n", rawDataIndex + ((i / 32) * 32)); @@ -880,21 +786,13 @@ std::string ZTexture::GetSourceTypeName() void ZTexture::CalcHash() { - // Make sure raw data is fixed before we calc the hash... - bool fixFlag = !isRawDataFixed; - - if (fixFlag) - FixRawData(); - - hash = CRC32B(rawData.data(), GetRawDataSize()); - - if (fixFlag) - FixRawData(); + auto parentRawData = parent->GetRawData(); + hash = CRC32B(parentRawData.data() + rawDataIndex, GetRawDataSize()); } std::string ZTexture::GetExternalExtension() { - switch (type) + switch (format) { case TextureType::RGBA32bpp: return "rgba32"; @@ -919,7 +817,7 @@ std::string ZTexture::GetExternalExtension() } } -std::string ZTexture::GetPoolOutPath(std::string defaultValue) +fs::path ZTexture::GetPoolOutPath(const fs::path& defaultValue) { if (Globals::Instance->cfg.texturePool.find(hash) != Globals::Instance->cfg.texturePool.end()) return Path::GetDirectoryName(Globals::Instance->cfg.texturePool[hash].path.string()); @@ -927,12 +825,7 @@ std::string ZTexture::GetPoolOutPath(std::string defaultValue) return defaultValue; } -string ZTexture::GetSourceOutputHeader(const std::string& prefix) -{ - return ""; -} - -TextureType ZTexture::GetTextureTypeFromString(string str) +TextureType ZTexture::GetTextureTypeFromString(std::string str) { TextureType texType = TextureType::Error; @@ -955,6 +848,33 @@ TextureType ZTexture::GetTextureTypeFromString(string str) else if (str == "ci8") texType = TextureType::Palette8bpp; else - fprintf(stderr, "Encountered Unknown Texture Type %s \n", str.c_str()); + fprintf(stderr, "Encountered Unknown Texture format %s \n", str.c_str()); return texType; } + +bool ZTexture::IsColorIndexed() const +{ + switch (format) + { + case TextureType::Palette4bpp: + case TextureType::Palette8bpp: + return true; + + default: + return false; + } +} + +void ZTexture::SetTlut(ZTexture* nTlut) +{ + assert(IsColorIndexed()); + assert(nTlut->isPalette); + tlut = nTlut; + + textureData.SetPalette(tlut->textureData); +} + +bool ZTexture::HasTlut() const +{ + return tlut != nullptr; +} diff --git a/ZAPD/ZTexture.h b/ZAPD/ZTexture.h index ef87441..aea2cd3 100644 --- a/ZAPD/ZTexture.h +++ b/ZAPD/ZTexture.h @@ -1,13 +1,15 @@ #pragma once +#include <vector> + #include "HighLevel/HLTexture.h" +#include "ImageBackend.h" #include "ZResource.h" #include "tinyxml2.h" -#include <vector> - enum class TextureType { + Error, RGBA32bpp, RGBA16bpp, Palette4bpp, @@ -17,25 +19,19 @@ enum class TextureType GrayscaleAlpha4bpp, GrayscaleAlpha8bpp, GrayscaleAlpha16bpp, - Error }; class ZTexture : public ZResource { protected: - TextureType type; - uint16_t width, height; + TextureType format = TextureType::Error; + uint32_t width, height; - uint8_t* bmpRgb; - uint8_t* bmpRgba; - bool isRawDataFixed; + ImageBackend textureData; + std::vector<uint8_t> textureDataRaw; // When reading from a PNG file. + uint32_t tlutOffset = static_cast<uint32_t>(-1); + ZTexture* tlut = nullptr; - void ParseXML(tinyxml2::XMLElement* reader) override; - void FixRawData(); - void ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<uint8_t>& nRawData, - const uint32_t nRawDataIndex) override; // Extract Mode - - void PrepareBitmap(); void PrepareBitmapRGBA16(); void PrepareBitmapRGBA32(); void PrepareBitmapGrayscale8(); @@ -45,52 +41,54 @@ protected: void PrepareBitmapGrayscaleAlpha16(); void PrepareBitmapPalette4(); void PrepareBitmapPalette8(); - void PrepareRawData(std::string inFolder); - void PrepareRawDataRGBA16(std::string rgbaPath); - void PrepareRawDataRGBA32(std::string rgbaPath); - void PrepareRawDataGrayscale4(std::string grayPath); - void PrepareRawDataGrayscale8(std::string grayPath); - void PrepareRawDataGrayscaleAlpha4(std::string grayAlphaPath); - void PrepareRawDataGrayscaleAlpha8(std::string grayAlphaPath); - void PrepareRawDataGrayscaleAlpha16(std::string grayAlphaPath); - void PrepareRawDataPalette4(std::string palPath); - void PrepareRawDataPalette8(std::string palPath); - float GetPixelMultiplyer(); + + void PrepareRawDataFromFile(const fs::path& inFolder); + void PrepareRawDataRGBA16(const fs::path& rgbaPath); + void PrepareRawDataRGBA32(const fs::path& rgbaPath); + void PrepareRawDataGrayscale4(const fs::path& grayPath); + void PrepareRawDataGrayscale8(const fs::path& grayPath); + void PrepareRawDataGrayscaleAlpha4(const fs::path& grayAlphaPath); + void PrepareRawDataGrayscaleAlpha8(const fs::path& grayAlphaPath); + void PrepareRawDataGrayscaleAlpha16(const fs::path& grayAlphaPath); + void PrepareRawDataPalette4(const fs::path& palPath); + void PrepareRawDataPalette8(const fs::path& palPath); public: ZTexture(ZFile* nParent); - ~ZTexture(); - bool isPalette; + bool isPalette = false; - static ZTexture* BuildFromXML(tinyxml2::XMLElement* reader, std::string inFolder, - bool readFile); - // static ZTexture* ExtractFromXML(tinyxml2::XMLElement* reader, std::vector<uint8_t> nRawData, - // uint32_t rawDataIndex, std::string nRelPath, ZFile* nParent); - static ZTexture* FromBinary(TextureType nType, std::vector<uint8_t> nRawData, - uint32_t rawDataIndex, std::string nName, int32_t nWidth, - int32_t nHeight, ZFile* nParent); - static ZTexture* FromPNG(std::string pngFilePath, TextureType texType); - static ZTexture* FromHLTexture(HLTexture* hlTex); + void ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<uint8_t>& nRawData, + const uint32_t nRawDataIndex) override; + void FromBinary(const std::vector<uint8_t>& nRawData, uint32_t nRawDataIndex, int32_t nWidth, + int32_t nHeight, TextureType nType, bool nIsPalette); + void FromPNG(const fs::path& pngFilePath, TextureType texType); + void FromHLTexture(HLTexture* hlTex); static TextureType GetTextureTypeFromString(std::string str); - std::string GetSourceOutputCode(const std::string& prefix) override; - std::string GetSourceOutputHeader(const std::string& prefix) override; - - size_t GetRawDataSize() override; - std::string GetIMFmtFromType(); - std::string GetIMSizFromType(); - uint16_t GetWidth(); - uint16_t GetHeight(); - void SetWidth(uint16_t nWidth); - void SetHeight(uint16_t nHeight); - TextureType GetTextureType(); - void Save(const std::string& outFolder) override; - std::string GetExternalExtension() override; - std::string GetPoolOutPath(std::string defaultValue); + void ParseXML(tinyxml2::XMLElement* reader) override; + void ParseRawData() override; + void DeclareReferences(const std::string& prefix) override; + std::string GetBodySourceCode() const; void CalcHash() override; + void Save(const fs::path& outFolder) override; bool IsExternalResource() override; std::string GetSourceTypeName() override; ZResourceType GetResourceType() override; + std::string GetExternalExtension() override; + + size_t GetRawDataSize() override; + std::string GetIMFmtFromType(); + std::string GetIMSizFromType(); + std::string GetDefaultName(const std::string& prefix); + uint32_t GetWidth() const; + uint32_t GetHeight() const; + void SetDimensions(uint32_t nWidth, uint32_t nHeight); + float GetPixelMultiplyer() const; + TextureType GetTextureType(); + fs::path GetPoolOutPath(const fs::path& defaultValue); + bool IsColorIndexed() const; + void SetTlut(ZTexture* nTlut); + bool HasTlut() const; }; diff --git a/ZAPD/ZVtx.cpp b/ZAPD/ZVtx.cpp index 4c80895..eacf563 100644 --- a/ZAPD/ZVtx.cpp +++ b/ZAPD/ZVtx.cpp @@ -19,8 +19,24 @@ ZVtx::ZVtx(ZFile* nParent) : ZResource(nParent) a = 0; } -void ZVtx::ParseXML(tinyxml2::XMLElement* reader) +void ZVtx::ParseRawData() { + x = BitConverter::ToInt16BE(rawData, rawDataIndex + 0); + y = BitConverter::ToInt16BE(rawData, rawDataIndex + 2); + z = BitConverter::ToInt16BE(rawData, rawDataIndex + 4); + flag = BitConverter::ToInt16BE(rawData, rawDataIndex + 6); + s = BitConverter::ToInt16BE(rawData, rawDataIndex + 8); + t = BitConverter::ToInt16BE(rawData, rawDataIndex + 10); + r = rawData[rawDataIndex + 12]; + g = rawData[rawDataIndex + 13]; + b = rawData[rawDataIndex + 14]; + a = rawData[rawDataIndex + 15]; +} + +std::string ZVtx::GetBodySourceCode() const +{ + return StringHelper::Sprintf("VTX(%i, %i, %i, %i, %i, %i, %i, %i, %i)", x, y, z, s, t, r, g, b, + a); } std::string ZVtx::GetSourceTypeName() @@ -30,8 +46,7 @@ std::string ZVtx::GetSourceTypeName() std::string ZVtx::GetSourceOutputCode(const std::string& prefix) { - std::string output = - StringHelper::Sprintf("VTX(%i, %i, %i, %i, %i, %i, %i, %i, %i)", x, y, z, s, t, r, g, b, a); + std::string output = GetBodySourceCode(); if (parent != nullptr) { @@ -44,22 +59,6 @@ std::string ZVtx::GetSourceOutputCode(const std::string& prefix) return ""; } -void ZVtx::ParseRawData() -{ - const uint8_t* data = rawData.data(); - - x = BitConverter::ToInt16BE(data, rawDataIndex + 0); - y = BitConverter::ToInt16BE(data, rawDataIndex + 2); - z = BitConverter::ToInt16BE(data, rawDataIndex + 4); - flag = BitConverter::ToInt16BE(data, rawDataIndex + 6); - s = BitConverter::ToInt16BE(data, rawDataIndex + 8); - t = BitConverter::ToInt16BE(data, rawDataIndex + 10); - r = data[rawDataIndex + 12]; - g = data[rawDataIndex + 13]; - b = data[rawDataIndex + 14]; - a = data[rawDataIndex + 15]; -} - size_t ZVtx::GetRawDataSize() { return 16; diff --git a/ZAPD/ZVtx.h b/ZAPD/ZVtx.h index d400d44..0caed82 100644 --- a/ZAPD/ZVtx.h +++ b/ZAPD/ZVtx.h @@ -17,18 +17,20 @@ public: ZVtx(ZFile* nParent); - void ParseXML(tinyxml2::XMLElement* reader) override; - std::string GetSourceTypeName() override; - std::string GetSourceOutputCode(const std::string& prefix) override; + void ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<uint8_t>& nRawData, + const uint32_t nRawDataIndex) override; + void ParseRawData() override; - size_t GetRawDataSize() override; + std::string GetBodySourceCode() const; + std::string GetSourceOutputCode(const std::string& prefix) override; + + bool IsExternalResource() override; bool DoesSupportArray() override; + std::string GetSourceTypeName() override; ZResourceType GetResourceType() override; - bool IsExternalResource() override; virtual std::string GetExternalExtension() override; - void ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<uint8_t>& nRawData, - const uint32_t nRawDataIndex) override; + size_t GetRawDataSize() override; protected: };
\ No newline at end of file |
