From 6a565e324415c8f3bc1d08c1849925b6b0bf6662 Mon Sep 17 00:00:00 2001 From: modeco80 Date: Thu, 16 Jan 2025 20:56:42 -0500 Subject: [PATCH] libeuropa/util: Move 4bpp/8bpp paint support --- include/europa/structs/Yatf.hpp | 5 ++-- include/europa/util/ImageSurface.hpp | 15 ++++++++++++ src/libeuropa/io/yatf/Reader.cpp | 34 +++------------------------- src/libeuropa/util/ImageSurface.cpp | 25 ++++++++++++++++++++ 4 files changed, 46 insertions(+), 33 deletions(-) diff --git a/include/europa/structs/Yatf.hpp b/include/europa/structs/Yatf.hpp index ae4492d..598b485 100644 --- a/include/europa/structs/Yatf.hpp +++ b/include/europa/structs/Yatf.hpp @@ -17,6 +17,7 @@ namespace europa::structs { struct [[gnu::packed]] YatfHeader { enum class TextureFormat : u8 { + // V1 formats. kTextureFormatV1_8Bpp = 0, kTextureFormatV1_24Bpp = 2, kTextureFormatV1_32Bpp = 3, @@ -34,11 +35,11 @@ namespace europa::structs { u32 magic; - u16 version; // 0x1 for starfighter, 0x2 for jsf + u16 version; // 0x1 for starfighter, 0x2 for new jsf files TextureFormat format; - u8 unkThing2; // flags? some palbpp? + u8 unkThing2; // flags? some palbpp? V2 seems to end up usually matching // Always zeroed. u32 zero; diff --git a/include/europa/util/ImageSurface.hpp b/include/europa/util/ImageSurface.hpp index 7d34ac6..9f67a82 100644 --- a/include/europa/util/ImageSurface.hpp +++ b/include/europa/util/ImageSurface.hpp @@ -78,6 +78,21 @@ namespace europa::util { void Resize(Size newSize); + // FIXME: For now, these APIs will work. It may actually make sense + // to have a ImageSurface hold a Unique, that knows about + // format and can optionally output pixels or provide raw buffer access + // if desired. + // + // basically support other than RGBA8888 out of the box and deal with it nicely + + /// Paint from a 4bpp source. + /// Assumes this image has been initalized to the proper size already. + void PaintFromSource_4bpp(std::uint8_t const* pSrc, Pixel const* pPalette); + + /// Paint from a 8bpp source. + /// Assumes this image has been initalized to the proper size already. + void PaintFromSource_8bpp(std::uint8_t const* pSrc, Pixel const* pPalette); + private: UniqueArray imageBuffer; Size size; diff --git a/src/libeuropa/io/yatf/Reader.cpp b/src/libeuropa/io/yatf/Reader.cpp index 24678c2..ff7f9e8 100644 --- a/src/libeuropa/io/yatf/Reader.cpp +++ b/src/libeuropa/io/yatf/Reader.cpp @@ -46,16 +46,7 @@ namespace europa::io::yatf { stream.read(reinterpret_cast(&palette[0]), sizeof(palette)); stream.read(reinterpret_cast(&palettizedData[0]), imageSize.Linear()); - - auto* pDestBuffer = reinterpret_cast(surface.GetBuffer()); - - for(std::size_t y = 0; y < imageSize.height; ++y) { - for(std::size_t x = 0; x < imageSize.width; ++x) { - auto& pp = palettizedData[y * imageSize.width + x]; - auto& dst = pDestBuffer[y * imageSize.width + x]; - dst = palette[static_cast(pp)]; - } - } + surface.PaintFromSource_8bpp(&palettizedData[0], &palette[0]); } break; case kTextureFormatV1_24Bpp: { @@ -90,20 +81,9 @@ namespace europa::io::yatf { case kTextureFormatV2_4Bpp: { util::Pixel palette[16] {}; util::UniqueArray palettizedData(imageSize.Linear() / 2); - stream.read(reinterpret_cast(&palette[0]), sizeof(palette)); stream.read(reinterpret_cast(&palettizedData[0]), imageSize.Linear() / 2); - - auto* pDestBuffer = reinterpret_cast(surface.GetBuffer()); - - // can't really get a better loop to work, so i guess this has to do - for(std::size_t y = 0; y < (imageSize.width * imageSize.height) / 2; ++y) { - auto& pp = palettizedData[y]; - for(std::size_t b = 0; b < 2; ++b) { - auto col = ((pp & (0x0F << (b * 4))) >> (b * 4)); - (*pDestBuffer++) = palette[static_cast(col)]; - } - } + surface.PaintFromSource_4bpp(&palettizedData[0], &palette[0]); } break; case kTextureFormatV2_8Bpp: { @@ -113,15 +93,7 @@ namespace europa::io::yatf { stream.read(reinterpret_cast(&palette[0]), sizeof(palette)); stream.read(reinterpret_cast(&palettizedData[0]), imageSize.Linear()); - auto* pDestBuffer = reinterpret_cast(surface.GetBuffer()); - - for(std::size_t y = 0; y < imageSize.height; ++y) { - for(std::size_t x = 0; x < imageSize.width; ++x) { - auto& pp = palettizedData[y * imageSize.width + x]; - auto& dst = pDestBuffer[y * imageSize.width + x]; - dst = palette[static_cast(pp)]; - } - } + surface.PaintFromSource_8bpp(&palettizedData[0], &palette[0]); } break; case kTextureFormatV2_24Bpp: { diff --git a/src/libeuropa/util/ImageSurface.cpp b/src/libeuropa/util/ImageSurface.cpp index 3139df7..6e62581 100644 --- a/src/libeuropa/util/ImageSurface.cpp +++ b/src/libeuropa/util/ImageSurface.cpp @@ -26,4 +26,29 @@ namespace europa::util { return imageBuffer.Data(); } + void ImageSurface::PaintFromSource_4bpp(std::uint8_t const* pSrc, Pixel const* pPalette) { + auto* pDestBuffer = reinterpret_cast(imageBuffer.Data()); + + // can't really get a better loop to work, so i guess this has to do + for(std::size_t y = 0; y < size.Linear() / 2; ++y) { + auto& pp = pSrc[y]; + for(std::size_t b = 0; b < 2; ++b) { + auto col = ((pp & (0x0F << (b * 4))) >> (b * 4)); + (*pDestBuffer++) = pPalette[static_cast(col)]; + } + } + } + + void ImageSurface::PaintFromSource_8bpp(std::uint8_t const* pSrc, Pixel const* pPalette) { + auto* pDestBuffer = reinterpret_cast(imageBuffer.Data()); + + for(std::size_t y = 0; y < size.height; ++y) { + for(std::size_t x = 0; x < size.width; ++x) { + auto& pp = pSrc[y * size.width + x]; + auto& dst = pDestBuffer[y * size.width + x]; + dst = pPalette[static_cast(pp)]; + } + } + } + } // namespace europa::util \ No newline at end of file