From a5d521b6521952c9dd13eb1383ffb407ad7f437e Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Mon, 14 Apr 2025 18:25:38 -0700 Subject: [PATCH] Port over CTexture::MangleMipmap from decomp --- Runtime/CMemoryCardSys.cpp | 12 +++--- Runtime/Graphics/CTexture.cpp | 71 ++++++++++++++++++++++++++++++++++- Runtime/Graphics/CTexture.hpp | 2 +- 3 files changed, 77 insertions(+), 8 deletions(-) diff --git a/Runtime/CMemoryCardSys.cpp b/Runtime/CMemoryCardSys.cpp index 300c7425b..93896873c 100644 --- a/Runtime/CMemoryCardSys.cpp +++ b/Runtime/CMemoryCardSys.cpp @@ -184,7 +184,7 @@ void CMemoryCardSys::CCardFileInfo::LockIconToken(CAssetId iconTxtr, kabufuda::E u32 CMemoryCardSys::CCardFileInfo::CalculateBannerDataSize() const { u32 ret = 68; if (x3c_bannerTex.IsValid()) { - if ((*x40_bannerTok)->GetTextureFormat() == ETexelFormat::RGB5A3) { + if ((*x40_bannerTok)->GetTexelFormat() == ETexelFormat::RGB5A3) { ret = 6212; } else { ret = 3652; @@ -193,7 +193,7 @@ u32 CMemoryCardSys::CCardFileInfo::CalculateBannerDataSize() const { bool paletteTex = false; for (const Icon& icon : x50_iconToks) { - if (icon.x8_tex->GetTextureFormat() == ETexelFormat::RGB5A3) { + if (icon.x8_tex->GetTexelFormat() == ETexelFormat::RGB5A3) { ret += 2048; } else { ret += 1024; @@ -236,7 +236,7 @@ void CMemoryCardSys::CCardFileInfo::BuildCardBuffer() { void CMemoryCardSys::CCardFileInfo::WriteBannerData(COutputStream& out) const { if (x3c_bannerTex.IsValid()) { const TLockedToken& tex = *x40_bannerTok; - const auto format = tex->GetTextureFormat(); + const auto format = tex->GetTexelFormat(); const auto* texels = tex->GetConstBitMapData(0); if (format == ETexelFormat::RGB5A3) { out.Put(texels, 6144); @@ -252,7 +252,7 @@ void CMemoryCardSys::CCardFileInfo::WriteBannerData(COutputStream& out) const { void CMemoryCardSys::CCardFileInfo::WriteIconData(COutputStream& out) const { const u8* palette = nullptr; for (const Icon& icon : x50_iconToks) { - const auto format = icon.x8_tex->GetTextureFormat(); + const auto format = icon.x8_tex->GetTexelFormat(); const auto* texels = icon.x8_tex->GetConstBitMapData(0); if (format == ETexelFormat::RGB5A3) { out.Put(texels, 2048); @@ -305,7 +305,7 @@ ECardResult CMemoryCardSys::CCardFileInfo::GetStatus(kabufuda::CardStat& stat) c kabufuda::EImageFormat bannerFmt; if (x3c_bannerTex.IsValid()) { - if ((*x40_bannerTok)->GetTextureFormat() == ETexelFormat::RGB5A3) { + if ((*x40_bannerTok)->GetTexelFormat() == ETexelFormat::RGB5A3) { bannerFmt = kabufuda::EImageFormat::RGB5A3; } else { bannerFmt = kabufuda::EImageFormat::C8; @@ -317,7 +317,7 @@ ECardResult CMemoryCardSys::CCardFileInfo::GetStatus(kabufuda::CardStat& stat) c int idx = 0; for (const Icon& icon : x50_iconToks) { - stat.SetIconFormat(icon.x8_tex->GetTextureFormat() == ETexelFormat::RGB5A3 ? kabufuda::EImageFormat::RGB5A3 + stat.SetIconFormat(icon.x8_tex->GetTexelFormat() == ETexelFormat::RGB5A3 ? kabufuda::EImageFormat::RGB5A3 : kabufuda::EImageFormat::C8, idx); stat.SetIconSpeed(icon.x4_speed, idx); diff --git a/Runtime/Graphics/CTexture.cpp b/Runtime/Graphics/CTexture.cpp index 13b4870ee..ee7dcd3bb 100644 --- a/Runtime/Graphics/CTexture.cpp +++ b/Runtime/Graphics/CTexture.cpp @@ -3,6 +3,8 @@ #include "Runtime/CToken.hpp" #include "Runtime/Formatting.hpp" +#include "Runtime/CBasics.hpp" + #include #include @@ -252,7 +254,74 @@ void CTexture::UncountMemory() { } void CTexture::MangleMipmap(u32 mip) { - // TODO(phil): Mangle mipmap + if (mip >= x8_mips) { + return; + } + + const uint colors[4] = { + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0x0000FFFF, +}; + const uint color = colors[(mip - 1) & 3]; + ushort rgb565Color = ((color >> 3) & 0x001F) | // B + ((color >> 5) & 0x07E0) | // G + ((color >> 8) & 0xF800); // R + ushort rgb555Color = ((color >> 3) & 0x001F) | // B + ((color >> 6) & 0x03E0) | // G + ((color >> 9) & 0x7C00); // R + ushort rgb4Color = ((color >> 4) & 0x000F) | // B + ((color >> 8) & 0x00F0) | // G + ((color >> 12) & 0x0F00); // R + + int width = GetWidth(); + int height = GetHeight(); + + int offset = 0; + for (int i = 0; i < mip; i++) { + offset += width * height; + width /= 2; + height /= 2; + } + + switch (GetTexelFormat()) { + case ETexelFormat::RGB565: { + ushort* ptr = reinterpret_cast< ushort* >(x44_aramToken_x4_buff.get());//mARAMToken.GetMRAMSafe()); + for (int i = 0; i < width * height; ++i) { + ptr[i + offset] = rgb565Color; + CBasics::Swap2Bytes(reinterpret_cast(&ptr[i + offset])); + } + break; + } + case ETexelFormat::CMPR: { + ushort* ptr = reinterpret_cast< ushort* >(x44_aramToken_x4_buff.get()) + offset / 4; + for (int i = 0; i < width * height / 16; ++i, ptr += 4) { + ptr[0] = rgb565Color; + CBasics::Swap2Bytes(reinterpret_cast(&ptr[0])); + ptr[1] = rgb565Color; + CBasics::Swap2Bytes(reinterpret_cast(&ptr[1])); + ptr[2] = 0; + ptr[3] = 0; + } + break; + } + case ETexelFormat::RGB5A3: { + ushort* ptr = reinterpret_cast< ushort* >(x44_aramToken_x4_buff.get()); + for (int i = 0; i < width * height; ++i) { + ushort& val = ptr[i + offset]; + if (val & 0x8000) { + val = rgb555Color | 0x8000; + } else { + val = (val & 0xF000) | rgb4Color; + } + CBasics::Swap2Bytes(reinterpret_cast(&val)); + } + break; + } + default: + break; + } } u32 CTexture::TexelFormatBitsPerPixel(ETexelFormat fmt) { diff --git a/Runtime/Graphics/CTexture.hpp b/Runtime/Graphics/CTexture.hpp index 96c68df3a..4de362ed1 100644 --- a/Runtime/Graphics/CTexture.hpp +++ b/Runtime/Graphics/CTexture.hpp @@ -106,7 +106,7 @@ public: EBlackKey blackKey = EBlackKey::Zero); ~CTexture(); - [[nodiscard]] ETexelFormat GetTextureFormat() const { return x0_fmt; } + [[nodiscard]] ETexelFormat GetTexelFormat() const { return x0_fmt; } [[nodiscard]] u16 GetWidth() const { return x4_w; } [[nodiscard]] u16 GetHeight() const { return x6_h; } [[nodiscard]] u8 GetNumberOfMipMaps() const { return x8_mips; }