diff --git a/src/Cafe/HW/Latte/Core/LatteTextureLoader.h b/src/Cafe/HW/Latte/Core/LatteTextureLoader.h index 353ea924..f6de57d6 100644 --- a/src/Cafe/HW/Latte/Core/LatteTextureLoader.h +++ b/src/Cafe/HW/Latte/Core/LatteTextureLoader.h @@ -1203,6 +1203,58 @@ public: } }; +class TextureDecoder_R5_G5_B5_A1_UNORM_swappedRB_To_RGBA8 : public TextureDecoder, public SingletonClass +{ +public: +//2656 + sint32 getBytesPerTexel(LatteTextureLoaderCtx* textureLoader) override + { + return 4; + } + + void decode(LatteTextureLoaderCtx* textureLoader, uint8* outputData) override + { + for (sint32 y = 0; y < textureLoader->height; y += textureLoader->stepY) + { + sint32 yc = y; + for (sint32 x = 0; x < textureLoader->width; x += textureLoader->stepX) + { + uint16* blockData = (uint16*)LatteTextureLoader_GetInput(textureLoader, x, y); + sint32 pixelOffset = (x + yc * textureLoader->width) * 4; + uint32 colorData = (*(uint16*)(blockData + 0)); + // swap order of components + uint8 red = (colorData >> 0) & 0x1F; + uint8 green = (colorData >> 5) & 0x1F; + uint8 blue = (colorData >> 10) & 0x1F; + uint8 alpha = (colorData >> 15) & 0x1; + + red = red << 3 | red >> 2; + green = green << 3 | green >> 2; + blue = blue << 3 | blue >> 2; + alpha = alpha * 0xff; + + // MSB...LSB : ABGR + colorData = (alpha << 24) | (blue << 16) | (green << 8) | red; + *(uint32*)(outputData + pixelOffset + 0) = colorData; + } + } + } + + void decodePixelToRGBA(uint8* blockData, uint8* outputPixel, uint8 blockOffsetX, uint8 blockOffsetY) override + { + uint16 colorData = (*(uint16*)blockData); + uint8 red = (colorData >> 0) & 0x1F; + uint8 green = (colorData >> 5) & 0x1F; + uint8 blue = (colorData >> 10) & 0x1F; + uint8 alpha = (colorData >> 15) & 0x1; + *(outputPixel + 0) = (red << 3) | (red >> 2); + *(outputPixel + 1) = (green << 3) | (green >> 2); + *(outputPixel + 2) = (blue << 3) | (blue >> 2); + *(outputPixel + 3) = alpha * 0xff; + } + +}; + class uint16_R5_G5_B5_A1_swapOpenGL { public: @@ -1316,6 +1368,56 @@ public: } }; +class TextureDecoder_A1_B5_G5_R5_UNORM_vulkan_To_RGBA8 : public TextureDecoder, public SingletonClass +{ +public: + sint32 getBytesPerTexel(LatteTextureLoaderCtx* textureLoader) override + { + return 4; + } + + void decode(LatteTextureLoaderCtx* textureLoader, uint8* outputData) override + { + for (sint32 y = 0; y < textureLoader->height; y += textureLoader->stepY) + { + sint32 yc = y; + for (sint32 x = 0; x < textureLoader->width; x += textureLoader->stepX) + { + uint16* blockData = (uint16*)LatteTextureLoader_GetInput(textureLoader, x, y); + sint32 pixelOffset = (x + yc * textureLoader->width) * 4; + uint32 colorData = (*(uint16*)(blockData + 0)); + // swap order of components + uint8 red = (colorData >> 11) & 0x1F; + uint8 green = (colorData >> 6) & 0x1F; + uint8 blue = (colorData >> 1) & 0x1F; + uint8 alpha = (colorData >> 0) & 0x1; + + red = red << 3 | red >> 2; + green = green << 3 | green >> 2; + blue = blue << 3 | blue >> 2; + alpha = alpha * 0xff; + + // MSB...LSB ABGR + colorData = red | (green << 8) | (blue << 16) | (alpha << 24); + *(uint32*)(outputData + pixelOffset + 0) = colorData; + } + } + } + + void decodePixelToRGBA(uint8* blockData, uint8* outputPixel, uint8 blockOffsetX, uint8 blockOffsetY) override + { + uint16 colorData = (*(uint16*)blockData); + uint8 red5 = (colorData >> 11) & 0x1F; + uint8 green5 = (colorData >> 6) & 0x1F; + uint8 blue5 = (colorData >> 1) & 0x1F; + uint8 alpha1 = (colorData >> 0) & 0x1; + *(outputPixel + 0) = (red5 << 3) | (red5 >> 2); + *(outputPixel + 1) = (green5 << 3) | (green5 >> 2); + *(outputPixel + 2) = (blue5 << 3) | (blue5 >> 2); + *(outputPixel + 3) = (alpha1 << 3); + } +}; + class TextureDecoder_R10_G10_B10_A2_UNORM : public TextureDecoder, public SingletonClass { diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index 759dac59..249d06b7 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -2653,7 +2653,7 @@ void VulkanRenderer::GetTextureFormatInfoVK(Latte::E_GX2SURFFMT format, bool isD case Latte::E_GX2SURFFMT::R5_G5_B5_A1_UNORM: if (m_supportedFormatInfo.fmt_a1r5g5b5_unorm_pack == false) { formatInfoOut->vkImageFormat = VK_FORMAT_R8G8B8A8_UNORM; - formatInfoOut->decoder = nullptr; + formatInfoOut->decoder = TextureDecoder_R5_G5_B5_A1_UNORM_swappedRB_To_RGBA8::getInstance(); } else { // used in Super Mario 3D World for the hidden Luigi sprites @@ -2665,7 +2665,7 @@ void VulkanRenderer::GetTextureFormatInfoVK(Latte::E_GX2SURFFMT format, bool isD case Latte::E_GX2SURFFMT::A1_B5_G5_R5_UNORM: if (m_supportedFormatInfo.fmt_a1r5g5b5_unorm_pack == false) { formatInfoOut->vkImageFormat = VK_FORMAT_R8G8B8A8_UNORM; - formatInfoOut->decoder = nullptr; + formatInfoOut->decoder = TextureDecoder_A1_B5_G5_R5_UNORM_vulkan_To_RGBA8::getInstance(); } else { // used by VC64 (e.g. Ocarina of Time)