From 2878b97ca6f0a6766bd419b17e3f6e1b5475dc00 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 31 Oct 2025 00:22:37 -0500 Subject: [PATCH] feat(component): implement CCharacterComponent::PasteTransparent8Bit --- src/component/CCharacterComponent.cpp | 68 ++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/src/component/CCharacterComponent.cpp b/src/component/CCharacterComponent.cpp index c9117aa..bc48a98 100644 --- a/src/component/CCharacterComponent.cpp +++ b/src/component/CCharacterComponent.cpp @@ -423,7 +423,73 @@ void CCharacterComponent::PasteTransparent4Bit(void* srcTexture, const BlpPalPix } void CCharacterComponent::PasteTransparent8Bit(void* srcTexture, const BlpPalPixel* srcPal, MipBits* dstMips, const C2iVector& dstPos, uint32_t dstWidth, const C2iVector& srcPos, const C2iVector& srcSize, TCTEXTUREINFO& srcInfo, int32_t srcMipLevel, int32_t dstMipLevelOfs) { - WHOA_UNIMPLEMENTED(); + // Prepare first mip level + + C2iVector curSrcSize = srcSize; + + C2iVector curSrcPos = srcPos; + C2iVector curDstPos = dstPos; + + uint32_t curSrcWidth = srcInfo.width >> srcMipLevel; + uint32_t curDstWidth = dstWidth; + + uint32_t curSrcHeight = srcInfo.height >> srcMipLevel; + + // Paste texture for each mip level + + for (int32_t curMipLevel = srcMipLevel; curMipLevel < srcInfo.mipCount; curMipLevel++) { + auto srcMip = TextureCacheGetMip(srcTexture, curMipLevel); + auto srcRow = &srcMip[(curSrcPos.y * curSrcWidth) + curSrcPos.x]; + auto srcAlphaRow = &srcMip[(curSrcWidth * curSrcHeight) + (curSrcPos.y * curSrcWidth) + curSrcPos.x]; + + auto dstMip = reinterpret_cast(dstMips[curMipLevel + dstMipLevelOfs].mip[0]); + auto dstRow = &dstMip[(curDstPos.y * curDstWidth) + (curDstPos.x * 4)]; + + // Calculate the end of the source region + auto srcEnd = srcRow + curSrcWidth * curSrcSize.y; + + // Copy each row + while (srcRow < srcEnd) { + auto dst = reinterpret_cast(dstRow); + + for (uint32_t x = 0; x < curSrcSize.x; x++) { + // Get palette entry + auto& src = srcPal[srcRow[x]]; + + // Get alpha + uint8_t alpha = srcAlphaRow[x]; + uint8_t invAlpha = 0xFF - alpha; + + // Blend src color with dst + dst->b = (src.b * alpha + dst->b * invAlpha) / 0xFF; + dst->g = (src.g * alpha + dst->g * invAlpha) / 0xFF; + dst->r = (src.r * alpha + dst->r * invAlpha) / 0xFF; + dst->a = 0xFF; + + dst++; + } + + // Move to next row + srcRow += curSrcWidth; + srcAlphaRow += curSrcWidth; + dstRow += curDstWidth; + } + + // Prepare next mip level + + curSrcSize.x = std::max(1, curSrcSize.x / 2); + curSrcSize.y = std::max(1, curSrcSize.y / 2); + + curSrcPos.x /= 2; + curSrcPos.y /= 2; + curDstPos.x /= 2; + curDstPos.y /= 2; + + curDstWidth /= 2; + curSrcWidth /= 2; + + curSrcHeight /= 2; + } } void CCharacterComponent::UpdateBaseTexture(EGxTexCommand cmd, uint32_t width, uint32_t height, uint32_t depth, uint32_t mipLevel, void* userArg, uint32_t& texelStrideInBytes, const void*& texels) {