From f5a58278db90edec7851c219d5cdf20d8ba0feca Mon Sep 17 00:00:00 2001 From: tobid7 Date: Thu, 8 Jan 2026 18:59:47 +0100 Subject: [PATCH] Add support to more color formats - RGBA4444: fully working - RGBA5551: fully not working - LA8, LA4: fully working --- README.md | 2 +- include/ctrff/bclim.hpp | 10 ++-- include/ctrff/pica.hpp | 10 ++-- source/pica.cpp | 114 ++++++++++++++++++++++++++++++++++++ tools/ctrff/source/main.cpp | 14 ++++- 5 files changed, 137 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 7d76801..3f688db 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Not all Planned formates are listed here yet | 3dsx | Basic Loading and Viewing of Meta Data Smdh | | | bcstm | Loading of almost every Data | Fully done and playable by BCSTM-Player | | bcwav | Basic Loading (not tested yet) | Not finished yet | -| bclim | Creating A8,RGBA32,RGB565 done | WIP | +| bclim | Creating A4,A8,LA4,LA8,L4,L8,RGB24,RGBA32,RGBA4444,RGB565 done | WIP | | lz11 | Encoder done, Decoder missing | WIP | | romfs | Nothing Done yet (Started creating header) | | | smdh | Almost done | missing safetey checks | diff --git a/include/ctrff/bclim.hpp b/include/ctrff/bclim.hpp index 8055e46..c123504 100644 --- a/include/ctrff/bclim.hpp +++ b/include/ctrff/bclim.hpp @@ -13,15 +13,15 @@ class CTRFF_API BCLIM : public BinFile { ~BCLIM() {} enum Format : u32 { - L8, // tested - A8, // tested - LA4, - LA8, + L8, // tested + A8, // tested + LA4, // tested + LA8, // tested HILO8, RGB565, // tested RGB888, // tested RGBA5551, - RGBA4444, + RGBA4444, // tested RGBA8888, // tested ETC1, ETC1A4, diff --git a/include/ctrff/pica.hpp b/include/ctrff/pica.hpp index d1a5cfc..2ff17df 100644 --- a/include/ctrff/pica.hpp +++ b/include/ctrff/pica.hpp @@ -9,15 +9,15 @@ namespace ctrff { namespace Pica { enum Color : u32 { - L8, // tested - A8, // tested - LA4, - LA8, + L8, // tested + A8, // tested + LA4, // tested + LA8, // tested HILO8, RGB565, // tested RGB888, // tested RGBA5551, - RGBA4444, + RGBA4444, // tested RGBA8888, // tested ETC1, ETC1A4, diff --git a/source/pica.cpp b/source/pica.cpp index ac1be69..4e883c0 100644 --- a/source/pica.cpp +++ b/source/pica.cpp @@ -85,6 +85,64 @@ CTRFF_API void EncodeImage(std::vector& ret, } } break; + case RGBA4444: + ret.resize(w * h * 2); + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int src = (y * w + x) * 4; // basic rgba indexing btw + int dst = ctrff::TileIndex(x, y, w) * 2; + ret[dst + 0] = rgba[src + 3] >> 4; + ret[dst + 0] |= (rgba[src + 2] >> 4) << 4; + ret[dst + 1] = rgba[src + 1] >> 4; + ret[dst + 1] |= (rgba[src + 0] >> 4) << 4; + } + } + break; + case RGBA5551: // not working ??? + ret.resize(w * h * 2); + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int src = (y * w + x) * 4; // basic rgba indexing btw + int dst = ctrff::TileIndex(x, y, w) * 2; + ctrff::u16 px = 0; + px |= (rgba[src + 3] < 128 ? 0 : 1) << 15; // A + px |= ((rgba[src + 2] >> 3) & 0x1f) << 10; // BBBBB + px |= ((rgba[src + 1] >> 3) & 0x1f) << 5; // GGGGG + px |= ((rgba[src + 0] >> 3) & 0x1f); // RRRRR + ret[dst] = px & 0xff; + ret[dst + 1] = (px << 8) & 0xff; + } + } + break; + case LA8: + ret.resize(w * h * 2); + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int src = (y * w + x) * 4; // basic rgba indexing btw + int dst = ctrff::TileIndex(x, y, w) * 2; + ret[dst] = + (rgba[src + 0] * 77 + rgba[src + 1] * 150 + rgba[src + 2] * 29) >> + 8; + ret[dst + 1] = rgba[src + 3]; + } + } + break; + case LA4: + ret.resize(w * h); + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int src = (y * w + x) * 4; // basic rgba indexing btw + int dst = ctrff::TileIndex(x, y, w); + ret[dst] = 0; + ret[dst] |= (((rgba[src + 0] * 77 + rgba[src + 1] * 150 + + rgba[src + 2] * 29) >> + 8) >> + 4) & + 0xf; + ret[dst] |= (((rgba[src + 3] >> 4) & 0xf) << 4) | ret[dst]; + } + } + break; default: throw std::runtime_error("[ctrff] Pica: Unsupported Color format: " + @@ -186,6 +244,62 @@ CTRFF_API void DecodeImage(std::vector& ret, } } break; + case RGBA4444: + ret.resize(w * h * 4); + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int src = ctrff::TileIndex(x, y, w) * 2; + int dst = (y * w + x) * 4; // basic rgba indexing btw + ret[dst + 0] = ((pixels[src + 1] >> 4) & 0xf) << 4; + ret[dst + 1] = (pixels[src + 1] & 0xf) << 4; + ret[dst + 2] = ((pixels[src + 0] >> 4) & 0xf) << 4; + ret[dst + 3] = (pixels[src + 0] & 0xf) << 4; + } + } + break; + case RGBA5551: // not working + ret.resize(w * h * 4); + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int src = ctrff::TileIndex(x, y, w) * 2; + int dst = (y * w + x) * 4; // basic rgba indexing btw + ctrff::u16 px = ret[src] | (ret[src + 1] << 8); + + ret[dst + 0] = (px & 0x1f) * 0x1f; + ret[dst + 1] = ((px >> 5) & 0x1f) * 0x1f; + ret[dst + 2] = ((px >> 10) & 0x1f) * 0x1f; + ret[dst + 3] = 255; // ((*px >> 15) & 0x1) ? 255 : 0; + } + } + break; + case LA8: + ret.resize(w * h * 4); + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int src = ctrff::TileIndex(x, y, w) * 2; + int dst = (y * w + x) * 4; + ret[dst + 0] = pixels[src]; + ret[dst + 1] = pixels[src]; + ret[dst + 2] = pixels[src]; + ret[dst + 3] = pixels[src + 1]; + } + } + break; + case LA4: + ret.resize(w * h * 4); + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int src = ctrff::TileIndex(x, y, w); + int dst = (y * w + x) * 4; + uint8_t l = (pixels[src] & 0xf) * 0x11; + uint8_t a = ((pixels[src] >> 4) & 0xf) * 0x11; + ret[dst + 0] = l; + ret[dst + 1] = l; + ret[dst + 2] = l; + ret[dst + 3] = a; + } + } + break; default: throw std::runtime_error("[ctrff] Pica: Unsupported Color format: " + diff --git a/tools/ctrff/source/main.cpp b/tools/ctrff/source/main.cpp index c97ff15..12ef797 100644 --- a/tools/ctrff/source/main.cpp +++ b/tools/ctrff/source/main.cpp @@ -474,13 +474,21 @@ void BCLIMMaker(const cf7::command::ArgumentList &data) { } else if (f == "l4") { fmt = ctrff::Pica::L4; } else if (f == "a8") { - fmt = ctrff::Pica::L8; + fmt = ctrff::Pica::A8; } else if (f == "l8") { fmt = ctrff::Pica::L8; + } else if (f == "la4") { + fmt = ctrff::Pica::LA4; + } else if (f == "la8") { + fmt = ctrff::Pica::LA8; } else if (f == "rgb565") { fmt = ctrff::Pica::RGB565; } else if (f == "rgb888") { fmt = ctrff::Pica::RGB888; + } else if (f == "rgba4444") { + fmt = ctrff::Pica::RGBA4444; + } else if (f == "rgba5551") { + fmt = ctrff::Pica::RGBA5551; } else if (f == "rgba8888") { fmt = ctrff::Pica::RGBA8888; } @@ -555,7 +563,9 @@ int main(int argc, char *argv[]) { .AddSubEntry(cf7::command::sub("o", "output", "Output path of .bclim file", true)) .AddSubEntry(cf7::command::sub( - "f", "format", "Image format rgba8888|rgb888|rgb565|a8|l8|a4|l4", + "f", "format", + "Image format " + "rgba8888|rgb888|rgba4444|rgba5551|rgb565|a8|l8|a4|l4|la4|la8", false)) .SetFunction(BCLIMMaker)); mgr.Execute();