From e8818424f1cde7dfabca24808ee277a901170539 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Sat, 22 Feb 2025 00:59:29 -0300 Subject: [PATCH 1/3] Added support for loading JPEG images. --- Makefile | 2 +- README.md | 20 +++++--- source/gfx/JPEGTexture.cpp | 84 +++++++++++++++++++++++++++++++ source/gfx/JPEGTexture.h | 7 +++ source/gfx/SplashScreenDrawer.cpp | 16 ++++-- 5 files changed, 118 insertions(+), 11 deletions(-) create mode 100644 source/gfx/JPEGTexture.cpp create mode 100644 source/gfx/JPEGTexture.h diff --git a/Makefile b/Makefile index 1b10a26..3a59eae 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ CXXFLAGS := $(CFLAGS) -std=c++23 -fno-rtti ASFLAGS := -g $(ARCH) LDFLAGS = -g $(ARCH) $(RPXSPECS) --entry=_start -Wl,-Map,$(notdir $*.map) -LIBS := -lpng -lwut -lz +LIBS := -lpng -lturbojpeg -lwut -lz ifeq ($(DEBUG),1) CXXFLAGS += -DDEBUG -g diff --git a/README.md b/README.md index b52e6f5..d2c4f61 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,11 @@ other modules of the environment are loading. Place the `01_splashscreen.rpx` in the `[ENVIRONMENT]/modules/setup` folder and run the EnvironmentLoader. The module will attempt to load the splash image, in this order: 1. `[ENVIRONMENT]/splash.png` - 2. `[ENVIRONMENT]/splash.tga` - 3. A random image from the directory `[ENVIRONMENT]/splashes/`. + 2. `[ENVIRONMENT]/splash.jpg` or `[ENVIRONMENT]/splash.jpeg` + 3. `[ENVIRONMENT]/splash.tga` + 4. A random image (PNG, JPEG or TGA) from the directory `[ENVIRONMENT]/splashes/`. -If no splash screen is found on the sd card, this module will effectively do nothing. +If no splash image is found on the sd card, this module will effectively do nothing. **Notes:** - `[ENVIRONMENT]` is the directory of the environment, for Aroma with would be `sd:/wiiu/enviroments/aroma/splash.png` @@ -22,14 +23,19 @@ If no splash screen is found on the sd card, this module will effectively do not ### Logging Building via `make` only logs errors (via OSReport). To enable logging via the [LoggingModule](https://github.com/wiiu-env/LoggingModule) set `DEBUG` to `1` or `VERBOSE`. -`make` Logs errors only (via OSReport). -`make DEBUG=1` Enables information and error logging via [LoggingModule](https://github.com/wiiu-env/LoggingModule). -`make DEBUG=VERBOSE` Enables verbose information and error logging via [LoggingModule](https://github.com/wiiu-env/LoggingModule). + - `make` Logs errors only (via OSReport). + - `make DEBUG=1` Enables information and error logging via [LoggingModule](https://github.com/wiiu-env/LoggingModule). + - `make DEBUG=VERBOSE` Enables verbose information and error logging via [LoggingModule](https://github.com/wiiu-env/LoggingModule). If the [LoggingModule](https://github.com/wiiu-env/LoggingModule) is not present, it'll fall back to UDP (Port 4405) and [CafeOS](https://github.com/wiiu-env/USBSerialLoggingModule) logging. ## Building -For building, you just need [wut](https://github.com/devkitPro/wut/) installed, then use the `make` command. +For building, you need to install (via devkitPro's `pacman`): + - [wut](https://github.com/devkitPro/wut/) + - ppc-libpng + - ppc-libjpeg-turbo + +Then use the `make` command. ## Building using the Dockerfile diff --git a/source/gfx/JPEGTexture.cpp b/source/gfx/JPEGTexture.cpp new file mode 100644 index 0000000..43b92cf --- /dev/null +++ b/source/gfx/JPEGTexture.cpp @@ -0,0 +1,84 @@ +#include "JPEGTexture.h" +#include +#include +#include +#include + +GX2Texture *JPEG_LoadTexture(std::span data) { + GX2Texture *texture = nullptr; + + tjhandle handle = tjInitDecompress(); + if (!handle) { + return nullptr; + } + + int height; + int width; + int subsamp; + int colorspace; + if (tjDecompressHeader3(handle, + data.data(), data.size(), + &width, &height, + &subsamp, &colorspace)) { + goto error; + } + + texture = static_cast(std::malloc(sizeof(GX2Texture))); + if (!texture) { + goto error; + } + + std::memset(texture, 0, sizeof(GX2Texture)); + texture->surface.width = width; + texture->surface.height = height; + texture->surface.depth = 1; + texture->surface.mipLevels = 1; + texture->surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8; + texture->surface.aa = GX2_AA_MODE1X; + texture->surface.use = GX2_SURFACE_USE_TEXTURE; + texture->surface.dim = GX2_SURFACE_DIM_TEXTURE_2D; + texture->surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED; + texture->surface.swizzle = 0; + texture->viewFirstMip = 0; + texture->viewNumMips = 1; + texture->viewFirstSlice = 0; + texture->viewNumSlices = 1; + texture->compMap = 0x0010203; + GX2CalcSurfaceSizeAndAlignment(&texture->surface); + GX2InitTextureRegs(texture); + + if (texture->surface.imageSize == 0) { + goto error; + } + + texture->surface.image = std::aligned_alloc(texture->surface.alignment, + texture->surface.imageSize); + if (!texture->surface.image) { + goto error; + } + + if (tjDecompress2(handle, + data.data(), data.size(), + static_cast(texture->surface.image), + width, + texture->surface.pitch * 4, + height, + TJPF_RGBA, + 0)) { + goto error; + } + + tjDestroy(handle); + + GX2Invalidate(GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_TEXTURE, + texture->surface.image, texture->surface.imageSize); + return texture; + + error: + if (texture) { + std::free(texture->surface.image); + } + std::free(texture); + tjDestroy(handle); + return nullptr; +} diff --git a/source/gfx/JPEGTexture.h b/source/gfx/JPEGTexture.h new file mode 100644 index 0000000..d4cb56d --- /dev/null +++ b/source/gfx/JPEGTexture.h @@ -0,0 +1,7 @@ +#pragma once + +#include +#include +#include + +GX2Texture *JPEG_LoadTexture(std::span data); diff --git a/source/gfx/SplashScreenDrawer.cpp b/source/gfx/SplashScreenDrawer.cpp index 0cd1edf..e9f9793 100644 --- a/source/gfx/SplashScreenDrawer.cpp +++ b/source/gfx/SplashScreenDrawer.cpp @@ -1,4 +1,5 @@ #include "SplashScreenDrawer.h" +#include "JPEGTexture.h" #include "PNGTexture.h" #include "ShaderSerializer.h" #include "TGATexture.h" @@ -7,6 +8,7 @@ #include "utils/utils.h" #include #include +#include #include #include #include @@ -131,6 +133,8 @@ static GX2Texture *LoadImageAsTexture(const std::filesystem::path &filename) { auto ext = ToLower(filename.extension()); if (ext == ".png") { return PNG_LoadTexture(buffer); + } else if (ext == ".jpg" || ext == ".jpeg") { + return JPEG_LoadTexture(buffer); } else if (ext == ".tga") { return TGA_LoadTexture(buffer); } @@ -140,6 +144,12 @@ static GX2Texture *LoadImageAsTexture(const std::filesystem::path &filename) { SplashScreenDrawer::SplashScreenDrawer(const std::filesystem::path &splash_base_path) { mTexture = LoadImageAsTexture(splash_base_path / "splash.png"); + if (!mTexture) { + mTexture = LoadImageAsTexture(splash_base_path / "splash.jpg"); + } + if (!mTexture) { + mTexture = LoadImageAsTexture(splash_base_path / "splash.jpeg"); + } if (!mTexture) { mTexture = LoadImageAsTexture(splash_base_path / "splash.tga"); } @@ -152,7 +162,7 @@ SplashScreenDrawer::SplashScreenDrawer(const std::filesystem::path &splash_base_ continue; } auto ext = ToLower(entry.path().extension()); - if (ext == ".png" || ext == ".tga") { + if (ext == ".png" || ext == ".tga" || ext == ".jpg" || ext == ".jpeg") { candidates.push_back(entry.path()); } } @@ -241,10 +251,10 @@ SplashScreenDrawer::~SplashScreenDrawer() { GX2RDestroyBufferEx(&mTexCoordBuffer, GX2R_RESOURCE_BIND_NONE); if (mTexture) { if (mTexture->surface.image != nullptr) { - free(mTexture->surface.image); + std::free(mTexture->surface.image); mTexture->surface.image = nullptr; } - ::free(mTexture); + std::free(mTexture); mTexture = nullptr; } } From 97be03f5902e387729df7a269328d8bdc66caa55 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Sat, 22 Feb 2025 01:01:53 -0300 Subject: [PATCH 2/3] Sorted headers. --- source/gfx/JPEGTexture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gfx/JPEGTexture.cpp b/source/gfx/JPEGTexture.cpp index 43b92cf..7bdb497 100644 --- a/source/gfx/JPEGTexture.cpp +++ b/source/gfx/JPEGTexture.cpp @@ -1,7 +1,7 @@ #include "JPEGTexture.h" -#include #include #include +#include #include GX2Texture *JPEG_LoadTexture(std::span data) { From 12218ccce004df59c08f470d011f783a116cc9e7 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Sat, 22 Feb 2025 01:05:39 -0300 Subject: [PATCH 3/3] Formatting for clang-format. --- source/gfx/JPEGTexture.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/gfx/JPEGTexture.cpp b/source/gfx/JPEGTexture.cpp index 7bdb497..09ebf32 100644 --- a/source/gfx/JPEGTexture.cpp +++ b/source/gfx/JPEGTexture.cpp @@ -23,7 +23,7 @@ GX2Texture *JPEG_LoadTexture(std::span data) { goto error; } - texture = static_cast(std::malloc(sizeof(GX2Texture))); + texture = static_cast(std::malloc(sizeof(GX2Texture))); if (!texture) { goto error; } @@ -59,7 +59,7 @@ GX2Texture *JPEG_LoadTexture(std::span data) { if (tjDecompress2(handle, data.data(), data.size(), - static_cast(texture->surface.image), + static_cast(texture->surface.image), width, texture->surface.pitch * 4, height, @@ -74,7 +74,7 @@ GX2Texture *JPEG_LoadTexture(std::span data) { texture->surface.image, texture->surface.imageSize); return texture; - error: +error: if (texture) { std::free(texture->surface.image); }