diff --git a/src/graphic/Fast3D/gfx_pc.cpp b/src/graphic/Fast3D/gfx_pc.cpp index 4b6fcb3e0..72a3471bb 100644 --- a/src/graphic/Fast3D/gfx_pc.cpp +++ b/src/graphic/Fast3D/gfx_pc.cpp @@ -21,7 +21,7 @@ #endif #include "graphic/Fast3D/debug/GfxDebugger.h" #include "libultraship/libultra/types.h" -//#include "libultraship/libultra/gs2dex.h" +// #include "libultraship/libultra/gs2dex.h" #include #include "gfx_pc.h" @@ -879,6 +879,19 @@ static void import_texture_ci8(int tile, bool importReplacement) { gfx_rapi->upload_texture(tex_upload_buffer, width, height); } +static void import_texture_img(int tile, bool importReplacement) { + const RawTexMetadata* metadata = &g_rdp.loaded_texture[g_rdp.texture_tile[tile].tmem_index].raw_tex_metadata; + const uint8_t* addr = + importReplacement && (metadata->resource != nullptr) + ? masked_textures.find(gfx_get_base_texture_path(metadata->resource->GetInitData()->Path)) + ->second.replacementData + : g_rdp.loaded_texture[g_rdp.texture_tile[tile].tmem_index].addr; + + uint16_t width = metadata->width; + uint16_t height = metadata->height; + gfx_rapi->upload_texture(addr, width, height); +} + static void import_texture_raw(int tile, bool importReplacement) { const RawTexMetadata* metadata = &g_rdp.loaded_texture[g_rdp.texture_tile[tile].tmem_index].raw_tex_metadata; const uint8_t* addr = @@ -982,6 +995,11 @@ static void import_texture(int i, int tile, bool importReplacement) { return; } + if ((texFlags & TEX_FLAG_LOAD_AS_IMG) != 0) { + import_texture_img(tile, importReplacement); + return; + } + // if load as raw is set then we load_raw(); if ((texFlags & TEX_FLAG_LOAD_AS_RAW) != 0) { import_texture_raw(tile, importReplacement); diff --git a/src/resource/File.h b/src/resource/File.h index 408a5616a..22ca534dd 100644 --- a/src/resource/File.h +++ b/src/resource/File.h @@ -14,6 +14,7 @@ class Archive; #define RESOURCE_FORMAT_BINARY 0 #define RESOURCE_FORMAT_XML 1 +#define RESOURCE_FORMAT_IMG 2 struct ResourceInitData { std::shared_ptr Parent; diff --git a/src/resource/ResourceFactoryImg.cpp b/src/resource/ResourceFactoryImg.cpp new file mode 100644 index 000000000..6cc0d9cb6 --- /dev/null +++ b/src/resource/ResourceFactoryImg.cpp @@ -0,0 +1,19 @@ +#include "ResourceFactoryImg.h" +#include +#include "spdlog/spdlog.h" + +namespace Ship { +bool ResourceFactoryImg::FileHasValidFormatAndReader(std::shared_ptr file) { + if (file->InitData->Format != RESOURCE_FORMAT_IMG) { + SPDLOG_ERROR("resource file format does not match factory format."); + return false; + } + + if (!std::holds_alternative>(file->Reader)) { + SPDLOG_ERROR("Failed to load resource: File has Reader ({} - {})", file->InitData->Type, file->InitData->Path); + return false; + } + + return true; +}; +} // namespace Ship \ No newline at end of file diff --git a/src/resource/ResourceFactoryImg.h b/src/resource/ResourceFactoryImg.h new file mode 100644 index 000000000..261f73ed8 --- /dev/null +++ b/src/resource/ResourceFactoryImg.h @@ -0,0 +1,10 @@ +#pragma once + +#include "ResourceFactory.h" + +namespace Ship { +class ResourceFactoryImg : public ResourceFactory { + protected: + bool FileHasValidFormatAndReader(std::shared_ptr file) override; +}; +} // namespace Ship \ No newline at end of file diff --git a/src/resource/archive/Archive.cpp b/src/resource/archive/Archive.cpp index 9d3f14559..067439863 100644 --- a/src/resource/archive/Archive.cpp +++ b/src/resource/archive/Archive.cpp @@ -5,6 +5,7 @@ #include "Context.h" #include "resource/File.h" #include "resource/ResourceLoader.h" +#include "resource/ResourceType.h" #include "utils/binarytools/MemoryStream.h" #include "utils/glob.h" #include "utils/StrHash64.h" @@ -142,8 +143,13 @@ std::shared_ptr Archive::ReadResourceInitData(const std::strin std::shared_ptr Archive::ReadResourceInitDataLegacy(const std::string& filePath, std::shared_ptr fileToLoad) { - // Determine if file is binary or XML... - if (fileToLoad->Buffer->at(0) == '<') { + if (stbi_info_from_memory((const uint8_t*)fileToLoad->Buffer->data(), fileToLoad->Buffer->size(), nullptr, nullptr, + nullptr) != 0) { + auto stream = std::make_shared(fileToLoad->Buffer); + auto binaryReader = std::make_shared(stream); + + return ReadResourceInitDataPng(filePath, binaryReader); + } else if (fileToLoad->Buffer->at(0) == '<') { // Determine if file is binary or XML... // File is XML // Read the xml document auto stream = std::make_shared(fileToLoad->Buffer); @@ -229,6 +235,7 @@ std::shared_ptr Archive::LoadFile(const std::string& filePath, std::shared switch (fileToLoad->InitData->Format) { case RESOURCE_FORMAT_BINARY: + case RESOURCE_FORMAT_IMG: fileToLoad->Reader = CreateBinaryReader(fileToLoad); break; case RESOURCE_FORMAT_XML: @@ -264,7 +271,7 @@ std::shared_ptr Archive::ReadResourceInitDataBinary(const std: resourceInitData->Path = filePath; if (headerReader == nullptr) { - SPDLOG_ERROR("Error reading OTR header from XML: No header buffer document for file {}", filePath); + SPDLOG_ERROR("Error reading OTR header from Binary: No header buffer document for file {}", filePath); return resourceInitData; } @@ -320,4 +327,24 @@ std::shared_ptr Archive::ReadResourceInitDataXml(const std::st return resourceInitData; } +std::shared_ptr Archive::ReadResourceInitDataPng(const std::string& filePath, + std::shared_ptr headerReader) { + auto resourceInitData = CreateDefaultResourceInitData(); + resourceInitData->Path = filePath; + + if (headerReader == nullptr) { + SPDLOG_ERROR("Error reading OTR header from XML: No header buffer document for file {}", filePath); + return resourceInitData; + } + + resourceInitData->IsCustom = true; + resourceInitData->Format = RESOURCE_FORMAT_IMG; + resourceInitData->Type = + Context::GetInstance()->GetResourceManager()->GetResourceLoader()->GetResourceType("Texture"); + resourceInitData->ResourceVersion = 0; + + headerReader->Seek(0, SeekOffsetType::Start); + return resourceInitData; +} + } // namespace Ship diff --git a/src/resource/archive/Archive.h b/src/resource/archive/Archive.h index c7fe2bd84..e4a27bbbe 100644 --- a/src/resource/archive/Archive.h +++ b/src/resource/archive/Archive.h @@ -57,6 +57,8 @@ class Archive : public std::enable_shared_from_this { std::shared_ptr headerReader); static std::shared_ptr ReadResourceInitDataXml(const std::string& filePath, std::shared_ptr document); + static std::shared_ptr ReadResourceInitDataPng(const std::string& filePath, + std::shared_ptr headerReader); std::shared_ptr CreateBinaryReader(std::shared_ptr fileToLoad); std::shared_ptr CreateXMLReader(std::shared_ptr fileToLoad); diff --git a/src/resource/factory/PngFactory.cpp b/src/resource/factory/PngFactory.cpp new file mode 100644 index 000000000..b2229aea7 --- /dev/null +++ b/src/resource/factory/PngFactory.cpp @@ -0,0 +1,40 @@ +#include "resource/factory/PngFactory.h" +#include "resource/type/Texture.h" +#include "spdlog/spdlog.h" + +#include + +namespace Fast { + +std::shared_ptr ResourceFactoryImageTexture::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto texture = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); + + auto callback = stbi_io_callbacks{ [](void* user, char* data, int size) { + auto reader = static_cast(user); + reader->Read(data, size); + return size; + }, + [](void* user, int size) { + auto reader = static_cast(user); + reader->Seek(size, Ship::SeekOffsetType::Current); + }, + [](void* user) { return 0; } }; + int height, width = 0; + + texture->ImageData = stbi_load_from_callbacks(&callback, reader.get(), &width, &height, nullptr, 4); + + texture->Width = width; + texture->Height = height; + texture->Type = TextureType::RGBA32bpp; + texture->ImageDataSize = texture->Width * texture->Height * 4; + texture->Flags = TEX_FLAG_LOAD_AS_IMG; + + return texture; +} + +} // namespace Fast \ No newline at end of file diff --git a/src/resource/factory/PngFactory.h b/src/resource/factory/PngFactory.h new file mode 100644 index 000000000..4683e3ad6 --- /dev/null +++ b/src/resource/factory/PngFactory.h @@ -0,0 +1,11 @@ +#pragma once + +#include "resource/Resource.h" +#include "resource/ResourceFactoryImg.h" + +namespace Fast { +class ResourceFactoryImageTexture : public Ship::ResourceFactoryImg { + public: + std::shared_ptr ReadResource(std::shared_ptr file) override; +}; +} // namespace Fast \ No newline at end of file diff --git a/src/resource/type/Texture.h b/src/resource/type/Texture.h index b7179456d..8cac4ed3a 100644 --- a/src/resource/type/Texture.h +++ b/src/resource/type/Texture.h @@ -3,6 +3,7 @@ #include "resource/Resource.h" #define TEX_FLAG_LOAD_AS_RAW (1 << 0) +#define TEX_FLAG_LOAD_AS_IMG (1 << 1) namespace Fast { enum class TextureType {