From ade02997d47ee1bccb5301839ddff04f2708927a Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Sat, 20 Dec 2025 20:20:44 -0300 Subject: [PATCH 01/18] Fixed format string. --- source/gfx/gfx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/gfx/gfx.c b/source/gfx/gfx.c index 5bc9078..df33e02 100644 --- a/source/gfx/gfx.c +++ b/source/gfx/gfx.c @@ -200,7 +200,7 @@ static BOOL initBucketHeap() { sGfxHeapForeground = MEMCreateExpHeapEx(base, size, 0); if (!sGfxHeapForeground) { - WHBLogPrintf("%s: MEMCreateExpHeapEx(0x%08X, 0x%X, 0)", __FUNCTION__, base, size); + WHBLogPrintf("%s: MEMCreateExpHeapEx(%p, 0x%X, 0)", __FUNCTION__, base, size); return FALSE; } @@ -476,4 +476,4 @@ BOOL GfxInitShaderAttribute(WHBGfxShaderGroup *group, attrib->mask = GfxGetAttribFormatSel(format); attrib->endianSwap = GX2_ENDIAN_SWAP_DEFAULT; return TRUE; -} \ No newline at end of file +} From 8f6e0ce46d1bad1440c4ec0bf81e5ea08c6f338f Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Sat, 20 Dec 2025 20:52:50 -0300 Subject: [PATCH 02/18] Try sd:/wiiu as a fallback path for loading splashes. --- source/gfx/SplashScreenDrawer.cpp | 54 ++++++++++++++++++------------- source/gfx/SplashScreenDrawer.h | 6 +++- source/main.cpp | 25 +++++++++++--- 3 files changed, 57 insertions(+), 28 deletions(-) diff --git a/source/gfx/SplashScreenDrawer.cpp b/source/gfx/SplashScreenDrawer.cpp index e9f9793..646fc98 100644 --- a/source/gfx/SplashScreenDrawer.cpp +++ b/source/gfx/SplashScreenDrawer.cpp @@ -142,7 +142,15 @@ static GX2Texture *LoadImageAsTexture(const std::filesystem::path &filename) { return nullptr; } +SplashScreenDrawer::SplashScreenDrawer() +{ + mTexture = PNG_LoadTexture(empty_png); + InitResources(); +} + SplashScreenDrawer::SplashScreenDrawer(const std::filesystem::path &splash_base_path) { + if (splash_base_path.empty()) + throw std::runtime_error{"empty base dir"}; mTexture = LoadImageAsTexture(splash_base_path / "splash.png"); if (!mTexture) { mTexture = LoadImageAsTexture(splash_base_path / "splash.jpg"); @@ -155,35 +163,35 @@ SplashScreenDrawer::SplashScreenDrawer(const std::filesystem::path &splash_base_ } if (!mTexture) { // try to load a random one from "splashes/*" - try { - std::vector candidates; - for (const auto &entry : std::filesystem::directory_iterator{splash_base_path / "splashes"}) { - if (!entry.is_regular_file()) { - continue; - } - auto ext = ToLower(entry.path().extension()); - if (ext == ".png" || ext == ".tga" || ext == ".jpg" || ext == ".jpeg") { - candidates.push_back(entry.path()); - } + std::vector candidates; + for (const auto &entry : std::filesystem::directory_iterator{splash_base_path / "splashes"}) { + if (!entry.is_regular_file()) { + continue; } - if (!candidates.empty()) { - auto t = static_cast(OSGetTime()); - std::seed_seq seed{static_cast(t), - static_cast(t >> 32)}; - std::minstd_rand eng{seed}; - std::uniform_int_distribution dist{0, candidates.size() - 1}; - auto selected = dist(eng); - mTexture = LoadImageAsTexture(candidates[selected]); + auto ext = ToLower(entry.path().extension()); + if (ext == ".png" || ext == ".tga" || ext == ".jpg" || ext == ".jpeg") { + candidates.push_back(entry.path()); } - } catch (std::exception &) {} - } - if (!mTexture) { - mTexture = PNG_LoadTexture(empty_png); + } + if (!candidates.empty()) { + auto t = static_cast(OSGetTime()); + std::seed_seq seed{static_cast(t), + static_cast(t >> 32)}; + std::minstd_rand eng{seed}; + std::uniform_int_distribution dist{0, candidates.size() - 1}; + auto selected = dist(eng); + mTexture = LoadImageAsTexture(candidates[selected]); + } } + if (!mTexture) { - return; + throw std::runtime_error{"failed to load texture"}; } + InitResources(); +} + +void SplashScreenDrawer::InitResources() { // create shader group mVertexShaderWrapper = DeserializeVertexShader(s_textureVertexShaderCompiled); mPixelShaderWrapper = DeserializePixelShader(s_texturePixelShaderCompiled); diff --git a/source/gfx/SplashScreenDrawer.h b/source/gfx/SplashScreenDrawer.h index 2576fa3..2375714 100644 --- a/source/gfx/SplashScreenDrawer.h +++ b/source/gfx/SplashScreenDrawer.h @@ -11,7 +11,9 @@ class SplashScreenDrawer { public: - explicit SplashScreenDrawer(const std::filesystem::path &meta_dir); + + SplashScreenDrawer(); + explicit SplashScreenDrawer(const std::filesystem::path &baseDir); void Draw(); @@ -47,4 +49,6 @@ class SplashScreenDrawer { GX2RBuffer mTexCoordBuffer = {}; GX2Texture *mTexture = nullptr; GX2Sampler mSampler = {}; + + void InitResources(); }; diff --git a/source/main.cpp b/source/main.cpp index 64fef0d..7e2db8b 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,5 +1,7 @@ +#include #include "gfx/SplashScreenDrawer.h" #include "gfx/gfx.h" +#include #include "utils/logger.h" #include "utils/utils.h" #include "version.h" @@ -11,15 +13,30 @@ int32_t main(int32_t argc, char **argv) { initLogging(); DEBUG_FUNCTION_LINE_INFO("Running SplashScreen Module " MODULE_VERSION_FULL ""); - std::filesystem::path basePath = "fs:/vol/external01/wiiu"; + using std::filesystem::path; + path envDir; if (argc >= 1) { - basePath = argv[0]; + envDir = argv[0]; } GfxInit(); { - SplashScreenDrawer splashScreenDrawer(basePath); - splashScreenDrawer.Draw(); + std::optional splashScreenDrawer; + for (const auto& dir : {envDir, path{"fs:/vol/external01/wiiu"}}) { + try { + splashScreenDrawer.emplace(dir); + break; + } + catch (std::exception &e) { + DEBUG_FUNCTION_LINE_INFO("Failed to use %s: %s", dir.c_str(), e.what()); + } + } + // Fallback: use built-in empty splash. + if (!splashScreenDrawer) { + splashScreenDrawer.emplace(); + } + splashScreenDrawer->Draw(); + } GfxShutdown(); From 9c114b88fd91f4a4b3b611d538cc5eff5df154b6 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Sat, 20 Dec 2025 21:13:49 -0300 Subject: [PATCH 03/18] Updated README. --- README.md | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d2c4f61..857f56b 100644 --- a/README.md +++ b/README.md @@ -5,18 +5,25 @@ other modules of the environment are loading. ## Usage 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.jpg` or `[ENVIRONMENT]/splash.jpeg` - 3. `[ENVIRONMENT]/splash.tga` - 4. A random image (PNG, JPEG or TGA) from the directory `[ENVIRONMENT]/splashes/`. +EnvironmentLoader. -If no splash image is found on the sd card, this module will effectively do nothing. +Place your splash images in the folder `SD:/wiiu/splashes/`. One of them will be randomly +loaded during boot. **Notes:** - - `[ENVIRONMENT]` is the directory of the environment, for Aroma with would be `sd:/wiiu/enviroments/aroma/splash.png` - - When using a `tga` make sure its 24 bit and uncompressed - - In theory any (reasonable) resolution is supported, something like 1280x720 is recommended + - `[ENVIRONMENT]` is the directory of the environment, for Aroma with would be `SD:/wiiu/enviroments/aroma`. + - When using a `tga` image, make sure its 24 bit and uncompressed, + - In theory any (reasonable) resolution is supported, something like 1280x720 is recommended. + +## Path priority +The module will attempt to load a splash image from multiple places, in this order: + 1. `[ENVIRONMENT]/splash.{png,jpg,jpeg,tga}` + 2. `[ENVIRONMENT]/splashes/*.{png,jpg,jpeg,tga}` + 3. `SD:/wiiu/splash.{png,jpg,jpeg,tga}` + 4. `SD:/wiiu/splashes/*.{png,jpg,jpeg,tga}` + +You should use the last path (`SD:/wiiu/splashes/`), and leave the others for when you +want to override the splash. ## Buildflags From 2af9ab1b785101ba1f545e79edeb6891c2c06c5f Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Sat, 20 Dec 2025 21:14:50 -0300 Subject: [PATCH 04/18] Better formatting. --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 857f56b..116055e 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,10 @@ This module is supposed to be loaded with the [EnvironmentLoader](https://github other modules of the environment are loading. ## Usage -Place the `01_splashscreen.rpx` in the `[ENVIRONMENT]/modules/setup` folder and run the -EnvironmentLoader. - -Place your splash images in the folder `SD:/wiiu/splashes/`. One of them will be randomly -loaded during boot. + 1. Place the `01_splashscreen.rpx` in the `[ENVIRONMENT]/modules/setup` folder and run + the EnvironmentLoader. + 2. Place your splash images in the folder `SD:/wiiu/splashes/`. One of them will be randomly + loaded during boot. **Notes:** - `[ENVIRONMENT]` is the directory of the environment, for Aroma with would be `SD:/wiiu/enviroments/aroma`. From 3260e255ed9775885c7907edeb8247274cc040b1 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Sat, 20 Dec 2025 21:17:02 -0300 Subject: [PATCH 05/18] Simpler wording. --- README.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 116055e..a51e717 100644 --- a/README.md +++ b/README.md @@ -4,22 +4,20 @@ This module is supposed to be loaded with the [EnvironmentLoader](https://github other modules of the environment are loading. ## Usage - 1. Place the `01_splashscreen.rpx` in the `[ENVIRONMENT]/modules/setup` folder and run - the EnvironmentLoader. - 2. Place your splash images in the folder `SD:/wiiu/splashes/`. One of them will be randomly - loaded during boot. + 1. Place the `01_splashscreen.rpx` in the `[ENVIRONMENT]/modules/setup` folder. + 2. Place your splash images (PNG, TGA, JPEG)) in the folder `SD:/wiiu/splashes/`. **Notes:** - `[ENVIRONMENT]` is the directory of the environment, for Aroma with would be `SD:/wiiu/enviroments/aroma`. - - When using a `tga` image, make sure its 24 bit and uncompressed, + - When using a TGA image, make sure its 24 bit and uncompressed, - In theory any (reasonable) resolution is supported, something like 1280x720 is recommended. ## Path priority The module will attempt to load a splash image from multiple places, in this order: 1. `[ENVIRONMENT]/splash.{png,jpg,jpeg,tga}` - 2. `[ENVIRONMENT]/splashes/*.{png,jpg,jpeg,tga}` + 2. `[ENVIRONMENT]/splashes/*.{png,jpg,jpeg,tga}` (selected randomly) 3. `SD:/wiiu/splash.{png,jpg,jpeg,tga}` - 4. `SD:/wiiu/splashes/*.{png,jpg,jpeg,tga}` + 4. `SD:/wiiu/splashes/*.{png,jpg,jpeg,tga}` (selected randomly) You should use the last path (`SD:/wiiu/splashes/`), and leave the others for when you want to override the splash. From 92f5902fba0657bdaf1411afa6d8e49f7d71c553 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Sat, 20 Dec 2025 21:17:42 -0300 Subject: [PATCH 06/18] Fixed typo. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a51e717..c2a631f 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ other modules of the environment are loading. ## Usage 1. Place the `01_splashscreen.rpx` in the `[ENVIRONMENT]/modules/setup` folder. - 2. Place your splash images (PNG, TGA, JPEG)) in the folder `SD:/wiiu/splashes/`. + 2. Place your splash images (PNG, TGA or JPEG) in the folder `SD:/wiiu/splashes/`. **Notes:** - `[ENVIRONMENT]` is the directory of the environment, for Aroma with would be `SD:/wiiu/enviroments/aroma`. From 0a219d52b0bd97a3bbd56f0ae4228e42e76f361f Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Sat, 20 Dec 2025 21:22:44 -0300 Subject: [PATCH 07/18] Formatting code. --- source/gfx/SplashScreenDrawer.cpp | 3 +-- source/gfx/SplashScreenDrawer.h | 1 - source/main.cpp | 10 ++++------ 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/source/gfx/SplashScreenDrawer.cpp b/source/gfx/SplashScreenDrawer.cpp index 646fc98..a87ae13 100644 --- a/source/gfx/SplashScreenDrawer.cpp +++ b/source/gfx/SplashScreenDrawer.cpp @@ -142,8 +142,7 @@ static GX2Texture *LoadImageAsTexture(const std::filesystem::path &filename) { return nullptr; } -SplashScreenDrawer::SplashScreenDrawer() -{ +SplashScreenDrawer::SplashScreenDrawer() { mTexture = PNG_LoadTexture(empty_png); InitResources(); } diff --git a/source/gfx/SplashScreenDrawer.h b/source/gfx/SplashScreenDrawer.h index 2375714..c4f7291 100644 --- a/source/gfx/SplashScreenDrawer.h +++ b/source/gfx/SplashScreenDrawer.h @@ -11,7 +11,6 @@ class SplashScreenDrawer { public: - SplashScreenDrawer(); explicit SplashScreenDrawer(const std::filesystem::path &baseDir); diff --git a/source/main.cpp b/source/main.cpp index 7e2db8b..e300f07 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,10 +1,10 @@ -#include #include "gfx/SplashScreenDrawer.h" #include "gfx/gfx.h" -#include #include "utils/logger.h" #include "utils/utils.h" #include "version.h" +#include +#include #define MODULE_VERSION "v0.3" #define MODULE_VERSION_FULL MODULE_VERSION SPLASHSCREEN_MODULE_VERSION_EXTRA @@ -22,12 +22,11 @@ int32_t main(int32_t argc, char **argv) { GfxInit(); { std::optional splashScreenDrawer; - for (const auto& dir : {envDir, path{"fs:/vol/external01/wiiu"}}) { + for (const auto &dir : {envDir, path{"fs:/vol/external01/wiiu"}}) { try { splashScreenDrawer.emplace(dir); break; - } - catch (std::exception &e) { + } catch (std::exception &e) { DEBUG_FUNCTION_LINE_INFO("Failed to use %s: %s", dir.c_str(), e.what()); } } @@ -36,7 +35,6 @@ int32_t main(int32_t argc, char **argv) { splashScreenDrawer.emplace(); } splashScreenDrawer->Draw(); - } GfxShutdown(); From 8d438d1634c469f5123ad2d0d5ef0f5bc6b130ff Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Sat, 20 Dec 2025 22:11:48 -0300 Subject: [PATCH 08/18] Avoid seeding RNG more than once. --- source/gfx/SplashScreenDrawer.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/source/gfx/SplashScreenDrawer.cpp b/source/gfx/SplashScreenDrawer.cpp index a87ae13..325b878 100644 --- a/source/gfx/SplashScreenDrawer.cpp +++ b/source/gfx/SplashScreenDrawer.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -147,6 +148,18 @@ SplashScreenDrawer::SplashScreenDrawer() { InitResources(); } +static std::size_t get_random_index(std::size_t size) { + static std::optional engine; + if (!engine) { + auto t = static_cast(OSGetTime()); + std::seed_seq seeder{static_cast(t), + static_cast(t >> 32)}; + engine.emplace(seeder); + } + std::uniform_int_distribution dist{0, size - 1}; + return dist(*engine); +} + SplashScreenDrawer::SplashScreenDrawer(const std::filesystem::path &splash_base_path) { if (splash_base_path.empty()) throw std::runtime_error{"empty base dir"}; @@ -173,12 +186,7 @@ SplashScreenDrawer::SplashScreenDrawer(const std::filesystem::path &splash_base_ } } if (!candidates.empty()) { - auto t = static_cast(OSGetTime()); - std::seed_seq seed{static_cast(t), - static_cast(t >> 32)}; - std::minstd_rand eng{seed}; - std::uniform_int_distribution dist{0, candidates.size() - 1}; - auto selected = dist(eng); + auto selected = get_random_index(candidates.size()); mTexture = LoadImageAsTexture(candidates[selected]); } } From 6db6f49530de7d39ea40bf019d4188b33c476a7e Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Mon, 2 Feb 2026 02:38:29 -0300 Subject: [PATCH 09/18] Refactored to hide all path handling inside SplashScreenDrawer class. --- source/crt.c | 4 -- source/gfx/SplashScreenDrawer.cpp | 83 ++++++++++++++++++------------- source/gfx/SplashScreenDrawer.h | 5 +- source/main.cpp | 19 ++----- 4 files changed, 54 insertions(+), 57 deletions(-) diff --git a/source/crt.c b/source/crt.c index 25bf56f..8fe586a 100644 --- a/source/crt.c +++ b/source/crt.c @@ -2,8 +2,6 @@ void __init_wut_malloc(); void __init_wut_newlib(); -void __init_wut_stdcpp(); - void __init_wut_devoptab(); void __attribute__((weak)) __init_wut_socket(); @@ -24,7 +22,6 @@ void __attribute__((weak)) __init_wut_() { __init_wut_malloc(); __init_wut_newlib(); - __init_wut_stdcpp(); __init_wut_devoptab(); if (&__init_wut_socket) __init_wut_socket(); } @@ -33,7 +30,6 @@ void __attribute__((weak)) __fini_wut_() { __fini(); __fini_wut_devoptab(); - __fini_wut_stdcpp(); __fini_wut_newlib(); __fini_wut_malloc(); } diff --git a/source/gfx/SplashScreenDrawer.cpp b/source/gfx/SplashScreenDrawer.cpp index 325b878..1b6f3d8 100644 --- a/source/gfx/SplashScreenDrawer.cpp +++ b/source/gfx/SplashScreenDrawer.cpp @@ -6,6 +6,8 @@ #include "gfx.h" #include "utils/logger.h" #include "utils/utils.h" +#include +#include #include #include #include @@ -143,11 +145,6 @@ static GX2Texture *LoadImageAsTexture(const std::filesystem::path &filename) { return nullptr; } -SplashScreenDrawer::SplashScreenDrawer() { - mTexture = PNG_LoadTexture(empty_png); - InitResources(); -} - static std::size_t get_random_index(std::size_t size) { static std::optional engine; if (!engine) { @@ -160,39 +157,16 @@ static std::size_t get_random_index(std::size_t size) { return dist(*engine); } -SplashScreenDrawer::SplashScreenDrawer(const std::filesystem::path &splash_base_path) { - if (splash_base_path.empty()) - throw std::runtime_error{"empty base dir"}; - mTexture = LoadImageAsTexture(splash_base_path / "splash.png"); +SplashScreenDrawer::SplashScreenDrawer(const std::filesystem::path &envDir) { + // 1: Use env dir. + LoadTextureFrom(envDir); + // 2: Use general dir. if (!mTexture) { - mTexture = LoadImageAsTexture(splash_base_path / "splash.jpg"); + LoadTextureFrom("fs:/vol/external01/wiiu"); } + // 3: Use fallback empty texture. if (!mTexture) { - mTexture = LoadImageAsTexture(splash_base_path / "splash.jpeg"); - } - if (!mTexture) { - mTexture = LoadImageAsTexture(splash_base_path / "splash.tga"); - } - if (!mTexture) { - // try to load a random one from "splashes/*" - std::vector candidates; - for (const auto &entry : std::filesystem::directory_iterator{splash_base_path / "splashes"}) { - if (!entry.is_regular_file()) { - continue; - } - auto ext = ToLower(entry.path().extension()); - if (ext == ".png" || ext == ".tga" || ext == ".jpg" || ext == ".jpeg") { - candidates.push_back(entry.path()); - } - } - if (!candidates.empty()) { - auto selected = get_random_index(candidates.size()); - mTexture = LoadImageAsTexture(candidates[selected]); - } - } - - if (!mTexture) { - throw std::runtime_error{"failed to load texture"}; + mTexture = PNG_LoadTexture(empty_png); } InitResources(); @@ -237,6 +211,45 @@ void SplashScreenDrawer::InitResources() { GX2InitSampler(&mSampler, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_LINEAR); } +void SplashScreenDrawer::LoadTextureFrom(const std::filesystem::path &dir) { + using namespace std::literals; + + const std::array extensions = { + ".png", + ".jpg", + ".jpeg", + ".tga" + }; + + if (!dir.empty()) { + for (const auto& ext : extensions) { + mTexture = LoadImageAsTexture(dir / ("splash"s + ext)); + if (mTexture) { + return; + } + } + + // Make a list of all candidates in splashes/* to select one at random. + std::vector candidates; + for (const auto &entry : std::filesystem::directory_iterator{dir / "splashes"}) { + if (!entry.is_regular_file()) { + continue; + } + auto ext = ToLower(entry.path().extension()); + if (std::ranges::contains(extensions, ext)) { + candidates.push_back(entry.path()); + } + } + if (!candidates.empty()) { + auto selected = get_random_index(candidates.size()); + mTexture = LoadImageAsTexture(candidates[selected]); + if (mTexture) { + return; + } + } + } +} + void SplashScreenDrawer::Draw() { if (!mTexture) { DEBUG_FUNCTION_LINE_INFO("Texture is missing"); diff --git a/source/gfx/SplashScreenDrawer.h b/source/gfx/SplashScreenDrawer.h index c4f7291..15870c1 100644 --- a/source/gfx/SplashScreenDrawer.h +++ b/source/gfx/SplashScreenDrawer.h @@ -11,8 +11,7 @@ class SplashScreenDrawer { public: - SplashScreenDrawer(); - explicit SplashScreenDrawer(const std::filesystem::path &baseDir); + explicit SplashScreenDrawer(const std::filesystem::path &envDir); void Draw(); @@ -50,4 +49,6 @@ class SplashScreenDrawer { GX2Sampler mSampler = {}; void InitResources(); + + void LoadTextureFrom(const std::filesystem::path &dir); }; diff --git a/source/main.cpp b/source/main.cpp index e300f07..8af27a0 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -4,12 +4,11 @@ #include "utils/utils.h" #include "version.h" #include -#include #define MODULE_VERSION "v0.3" #define MODULE_VERSION_FULL MODULE_VERSION SPLASHSCREEN_MODULE_VERSION_EXTRA -int32_t main(int32_t argc, char **argv) { +int main(int argc, char **argv) { initLogging(); DEBUG_FUNCTION_LINE_INFO("Running SplashScreen Module " MODULE_VERSION_FULL ""); @@ -21,20 +20,8 @@ int32_t main(int32_t argc, char **argv) { GfxInit(); { - std::optional splashScreenDrawer; - for (const auto &dir : {envDir, path{"fs:/vol/external01/wiiu"}}) { - try { - splashScreenDrawer.emplace(dir); - break; - } catch (std::exception &e) { - DEBUG_FUNCTION_LINE_INFO("Failed to use %s: %s", dir.c_str(), e.what()); - } - } - // Fallback: use built-in empty splash. - if (!splashScreenDrawer) { - splashScreenDrawer.emplace(); - } - splashScreenDrawer->Draw(); + SplashScreenDrawer splashScreenDrawer{envDir}; + splashScreenDrawer.Draw(); } GfxShutdown(); From 223da3defa4e183e17a1b6a97c58141b004a9877 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Mon, 2 Feb 2026 02:44:48 -0300 Subject: [PATCH 10/18] Refactored some functions into utils.h, utils.cpp --- source/gfx/SplashScreenDrawer.cpp | 25 +------------------------ source/utils/utils.cpp | 27 +++++++++++++++++++++++++++ source/utils/utils.h | 5 +++++ 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/source/gfx/SplashScreenDrawer.cpp b/source/gfx/SplashScreenDrawer.cpp index 1b6f3d8..8cd8fb5 100644 --- a/source/gfx/SplashScreenDrawer.cpp +++ b/source/gfx/SplashScreenDrawer.cpp @@ -9,13 +9,10 @@ #include #include #include -#include #include #include #include #include -#include -#include #include /* @@ -122,14 +119,6 @@ uint8_t empty_png[119] = { 0x0C, 0x0C, 0x00, 0x00, 0x0E, 0x00, 0x01, 0x7A, 0xB1, 0xB9, 0x30, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82}; -static std::filesystem::path ToLower(const std::filesystem::path &p) { - std::string result; - for (auto c : p.string()) { - result.push_back(std::tolower(static_cast(c))); - } - return result; -} - static GX2Texture *LoadImageAsTexture(const std::filesystem::path &filename) { std::vector buffer; if (LoadFileIntoBuffer(filename, buffer)) { @@ -145,18 +134,6 @@ static GX2Texture *LoadImageAsTexture(const std::filesystem::path &filename) { return nullptr; } -static std::size_t get_random_index(std::size_t size) { - static std::optional engine; - if (!engine) { - auto t = static_cast(OSGetTime()); - std::seed_seq seeder{static_cast(t), - static_cast(t >> 32)}; - engine.emplace(seeder); - } - std::uniform_int_distribution dist{0, size - 1}; - return dist(*engine); -} - SplashScreenDrawer::SplashScreenDrawer(const std::filesystem::path &envDir) { // 1: Use env dir. LoadTextureFrom(envDir); @@ -241,7 +218,7 @@ void SplashScreenDrawer::LoadTextureFrom(const std::filesystem::path &dir) { } } if (!candidates.empty()) { - auto selected = get_random_index(candidates.size()); + auto selected = GetRandomIndex(candidates.size()); mTexture = LoadImageAsTexture(candidates[selected]); if (mTexture) { return; diff --git a/source/utils/utils.cpp b/source/utils/utils.cpp index b657912..5988f51 100644 --- a/source/utils/utils.cpp +++ b/source/utils/utils.cpp @@ -1,7 +1,11 @@ #include "utils.h" #include "logger.h" +#include #include +#include +#include #include +#include #include #include @@ -30,3 +34,26 @@ bool LoadFileIntoBuffer(const std::filesystem::path &filename, std::vector RandomEngine; +} // namespace + +std::size_t GetRandomIndex(std::size_t size) { + if (!RandomEngine) { + auto t = static_cast(OSGetTime()); + std::seed_seq seeder{static_cast(t), + static_cast(t >> 32)}; + RandomEngine.emplace(seeder); + } + std::uniform_int_distribution dist{0, size - 1}; + return dist(*RandomEngine); +} + +std::filesystem::path ToLower(const std::filesystem::path &p) { + std::string result; + for (auto c : p.string()) { + result.push_back(std::tolower(static_cast(c))); + } + return result; +} diff --git a/source/utils/utils.h b/source/utils/utils.h index ff36367..3af0438 100644 --- a/source/utils/utils.h +++ b/source/utils/utils.h @@ -1,7 +1,12 @@ #pragma once +#include #include #include #include bool LoadFileIntoBuffer(const std::filesystem::path &filename, std::vector &buffer); + +std::size_t GetRandomIndex(std::size_t size); + +std::filesystem::path ToLower(const std::filesystem::path &p); From b2d8324181524de65d5df366f82e34786dfc122f Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Mon, 2 Feb 2026 02:50:46 -0300 Subject: [PATCH 11/18] Added missing include, some code cleanup. --- source/gfx/SplashScreenDrawer.cpp | 49 ++++++++++++++++--------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/source/gfx/SplashScreenDrawer.cpp b/source/gfx/SplashScreenDrawer.cpp index 8cd8fb5..0c092bb 100644 --- a/source/gfx/SplashScreenDrawer.cpp +++ b/source/gfx/SplashScreenDrawer.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include /* @@ -189,7 +190,9 @@ void SplashScreenDrawer::InitResources() { } void SplashScreenDrawer::LoadTextureFrom(const std::filesystem::path &dir) { - using namespace std::literals; + if (dir.empty()) { + return; + } const std::array extensions = { ".png", @@ -198,31 +201,31 @@ void SplashScreenDrawer::LoadTextureFrom(const std::filesystem::path &dir) { ".tga" }; - if (!dir.empty()) { - for (const auto& ext : extensions) { - mTexture = LoadImageAsTexture(dir / ("splash"s + ext)); - if (mTexture) { - return; - } + // First try the splash.* image. + for (const auto &ext : extensions) { + auto fname = std::string{"splash"} + ext; + mTexture = LoadImageAsTexture(dir / fname); + if (mTexture) { + return; } + } - // Make a list of all candidates in splashes/* to select one at random. - std::vector candidates; - for (const auto &entry : std::filesystem::directory_iterator{dir / "splashes"}) { - if (!entry.is_regular_file()) { - continue; - } - auto ext = ToLower(entry.path().extension()); - if (std::ranges::contains(extensions, ext)) { - candidates.push_back(entry.path()); - } + // Make a list of all candidates in splashes/* to select one at random. + std::vector candidates; + for (const auto &entry : std::filesystem::directory_iterator{dir / "splashes"}) { + if (!entry.is_regular_file()) { + continue; } - if (!candidates.empty()) { - auto selected = GetRandomIndex(candidates.size()); - mTexture = LoadImageAsTexture(candidates[selected]); - if (mTexture) { - return; - } + auto ext = ToLower(entry.path().extension()); + if (std::ranges::contains(extensions, ext)) { + candidates.push_back(entry.path()); + } + } + if (!candidates.empty()) { + auto selected = GetRandomIndex(candidates.size()); + mTexture = LoadImageAsTexture(candidates[selected]); + if (mTexture) { + return; } } } From 5e3a6be9e33c8920538bb76cecd97c5e8ba34ae0 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Mon, 2 Feb 2026 03:13:41 -0300 Subject: [PATCH 12/18] Added a try-catch block for vector and filesystem exceptions. Hg: Enter commit message. Lines beginning with 'HG:' are removed. --- source/gfx/SplashScreenDrawer.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/source/gfx/SplashScreenDrawer.cpp b/source/gfx/SplashScreenDrawer.cpp index 0c092bb..cd890c6 100644 --- a/source/gfx/SplashScreenDrawer.cpp +++ b/source/gfx/SplashScreenDrawer.cpp @@ -210,23 +210,25 @@ void SplashScreenDrawer::LoadTextureFrom(const std::filesystem::path &dir) { } } - // Make a list of all candidates in splashes/* to select one at random. - std::vector candidates; - for (const auto &entry : std::filesystem::directory_iterator{dir / "splashes"}) { - if (!entry.is_regular_file()) { - continue; + try { + // Make a list of all candidates in splashes/* to select one at random. + std::vector candidates; + for (const auto &entry : std::filesystem::directory_iterator{dir / "splashes"}) { + if (!entry.is_regular_file()) { + continue; + } + auto ext = ToLower(entry.path().extension()); + if (std::ranges::contains(extensions, ext)) { + candidates.push_back(entry.path()); + } } - auto ext = ToLower(entry.path().extension()); - if (std::ranges::contains(extensions, ext)) { - candidates.push_back(entry.path()); + if (!candidates.empty()) { + auto selected = GetRandomIndex(candidates.size()); + mTexture = LoadImageAsTexture(candidates[selected]); } } - if (!candidates.empty()) { - auto selected = GetRandomIndex(candidates.size()); - mTexture = LoadImageAsTexture(candidates[selected]); - if (mTexture) { - return; - } + catch (std::exception &e) { + DEBUG_FUNCTION_LINE_INFO("Loading texture failed: %s", e.what()); } } From f8cdd8b0bb01d436c49aece8cff1eafa718be582 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Mon, 2 Feb 2026 03:16:54 -0300 Subject: [PATCH 13/18] Refactoring: make LoadTextureFrom return a bool. --- source/gfx/SplashScreenDrawer.cpp | 24 +++++++++++++----------- source/gfx/SplashScreenDrawer.h | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/source/gfx/SplashScreenDrawer.cpp b/source/gfx/SplashScreenDrawer.cpp index cd890c6..d1eada9 100644 --- a/source/gfx/SplashScreenDrawer.cpp +++ b/source/gfx/SplashScreenDrawer.cpp @@ -137,14 +137,12 @@ static GX2Texture *LoadImageAsTexture(const std::filesystem::path &filename) { SplashScreenDrawer::SplashScreenDrawer(const std::filesystem::path &envDir) { // 1: Use env dir. - LoadTextureFrom(envDir); - // 2: Use general dir. - if (!mTexture) { - LoadTextureFrom("fs:/vol/external01/wiiu"); - } - // 3: Use fallback empty texture. - if (!mTexture) { - mTexture = PNG_LoadTexture(empty_png); + if (!LoadTextureFrom(envDir)) { + // 2: Use general dir. + if (!LoadTextureFrom("fs:/vol/external01/wiiu")) { + // 3: Use fallback empty texture. + mTexture = PNG_LoadTexture(empty_png); + } } InitResources(); @@ -189,9 +187,9 @@ void SplashScreenDrawer::InitResources() { GX2InitSampler(&mSampler, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_LINEAR); } -void SplashScreenDrawer::LoadTextureFrom(const std::filesystem::path &dir) { +bool SplashScreenDrawer::LoadTextureFrom(const std::filesystem::path &dir) { if (dir.empty()) { - return; + return false; } const std::array extensions = { @@ -206,7 +204,7 @@ void SplashScreenDrawer::LoadTextureFrom(const std::filesystem::path &dir) { auto fname = std::string{"splash"} + ext; mTexture = LoadImageAsTexture(dir / fname); if (mTexture) { - return; + return true; } } @@ -225,11 +223,15 @@ void SplashScreenDrawer::LoadTextureFrom(const std::filesystem::path &dir) { if (!candidates.empty()) { auto selected = GetRandomIndex(candidates.size()); mTexture = LoadImageAsTexture(candidates[selected]); + if (mTexture) { + return true; + } } } catch (std::exception &e) { DEBUG_FUNCTION_LINE_INFO("Loading texture failed: %s", e.what()); } + return false; } void SplashScreenDrawer::Draw() { diff --git a/source/gfx/SplashScreenDrawer.h b/source/gfx/SplashScreenDrawer.h index 15870c1..5776ab8 100644 --- a/source/gfx/SplashScreenDrawer.h +++ b/source/gfx/SplashScreenDrawer.h @@ -50,5 +50,5 @@ class SplashScreenDrawer { void InitResources(); - void LoadTextureFrom(const std::filesystem::path &dir); + bool LoadTextureFrom(const std::filesystem::path &dir); }; From ae5c597137c4254566f813489db5983cdad61e19 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Mon, 2 Feb 2026 03:21:25 -0300 Subject: [PATCH 14/18] Adjusted for clang-format checks. --- source/gfx/SplashScreenDrawer.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/source/gfx/SplashScreenDrawer.cpp b/source/gfx/SplashScreenDrawer.cpp index d1eada9..416fb95 100644 --- a/source/gfx/SplashScreenDrawer.cpp +++ b/source/gfx/SplashScreenDrawer.cpp @@ -193,16 +193,15 @@ bool SplashScreenDrawer::LoadTextureFrom(const std::filesystem::path &dir) { } const std::array extensions = { - ".png", - ".jpg", - ".jpeg", - ".tga" - }; + ".png", + ".jpg", + ".jpeg", + ".tga"}; // First try the splash.* image. for (const auto &ext : extensions) { auto fname = std::string{"splash"} + ext; - mTexture = LoadImageAsTexture(dir / fname); + mTexture = LoadImageAsTexture(dir / fname); if (mTexture) { return true; } @@ -227,8 +226,7 @@ bool SplashScreenDrawer::LoadTextureFrom(const std::filesystem::path &dir) { return true; } } - } - catch (std::exception &e) { + } catch (std::exception &e) { DEBUG_FUNCTION_LINE_INFO("Loading texture failed: %s", e.what()); } return false; From 3eb4b693ec853f9442e434a268672d5887e8941a Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Thu, 5 Feb 2026 01:07:53 -0300 Subject: [PATCH 15/18] Updated Dockerfile, crt for newlib and wut. --- Dockerfile | 2 +- source/crt.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index ca3e689..0c26d05 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,3 @@ -FROM ghcr.io/wiiu-env/devkitppc:20241128 +FROM ghcr.io/wiiu-env/devkitppc:20260204 WORKDIR project diff --git a/source/crt.c b/source/crt.c index 8fe586a..25e77de 100644 --- a/source/crt.c +++ b/source/crt.c @@ -10,8 +10,6 @@ void __fini_wut_malloc(); void __fini_wut_newlib(); -void __fini_wut_stdcpp(); - void __fini_wut_devoptab(); void __fini(); From aed065db89a565af3a1cc78f17cf3461e3469372 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Thu, 5 Feb 2026 07:12:30 -0300 Subject: [PATCH 16/18] Add __init_wut_thread() call. --- source/crt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/crt.c b/source/crt.c index 25e77de..fb47ab2 100644 --- a/source/crt.c +++ b/source/crt.c @@ -2,6 +2,8 @@ void __init_wut_malloc(); void __init_wut_newlib(); +void __init_wut_thread(); + void __init_wut_devoptab(); void __attribute__((weak)) __init_wut_socket(); @@ -18,6 +20,7 @@ void __attribute__((weak)) __fini_wut_socket(); void __attribute__((weak)) __init_wut_() { + __init_wut_thread(); __init_wut_malloc(); __init_wut_newlib(); __init_wut_devoptab(); From 06db2de8352e305ad2b5f59c0e97905835f990f8 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Thu, 5 Feb 2026 08:59:26 -0300 Subject: [PATCH 17/18] Updated README. --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c2a631f..d47dfb5 100644 --- a/README.md +++ b/README.md @@ -5,22 +5,21 @@ other modules of the environment are loading. ## Usage 1. Place the `01_splashscreen.rpx` in the `[ENVIRONMENT]/modules/setup` folder. - 2. Place your splash images (PNG, TGA or JPEG) in the folder `SD:/wiiu/splashes/`. + 2. Place your splash images (PNG, JPEG, TGA or WEBP) in the folder `SD:/wiiu/splashes/`. **Notes:** - `[ENVIRONMENT]` is the directory of the environment, for Aroma with would be `SD:/wiiu/enviroments/aroma`. - When using a TGA image, make sure its 24 bit and uncompressed, - - In theory any (reasonable) resolution is supported, something like 1280x720 is recommended. + - In theory any (reasonable) resolution is supported, **1280x720** is recommended for best quality on both gamepad and TV screens. ## Path priority The module will attempt to load a splash image from multiple places, in this order: - 1. `[ENVIRONMENT]/splash.{png,jpg,jpeg,tga}` - 2. `[ENVIRONMENT]/splashes/*.{png,jpg,jpeg,tga}` (selected randomly) - 3. `SD:/wiiu/splash.{png,jpg,jpeg,tga}` - 4. `SD:/wiiu/splashes/*.{png,jpg,jpeg,tga}` (selected randomly) + 1. `[ENVIRONMENT]/`: an image named `splash.EXT` + 2. `[ENVIRONMENT]/splashes/`: a **random** image in that folder. + 3. `SD:/wiiu/`: an image named `splash.EXT` + 4. `SD:/wiiu/splashes/`: a **random** image in that folder. -You should use the last path (`SD:/wiiu/splashes/`), and leave the others for when you -want to override the splash. +Where `EXT` can be `png`, `jpg`, `jpeg`, `tga` or `webp`. ## Buildflags @@ -36,8 +35,9 @@ If the [LoggingModule](https://github.com/wiiu-env/LoggingModule) is not present ## Building For building, you need to install (via devkitPro's `pacman`): - [wut](https://github.com/devkitPro/wut/) - - ppc-libpng - ppc-libjpeg-turbo + - ppc-libpng + - ppc-libwebp Then use the `make` command. From 52349c6dc580b2dcc4edef496d5ce4f7fa189210 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Thu, 5 Feb 2026 17:48:39 -0300 Subject: [PATCH 18/18] Some cleanup and remove unnecessary code changes. --- source/gfx/SplashScreenDrawer.cpp | 1 + source/main.cpp | 6 ++---- source/utils/utils.cpp | 8 ++++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/source/gfx/SplashScreenDrawer.cpp b/source/gfx/SplashScreenDrawer.cpp index 1ccc4b6..f237aad 100644 --- a/source/gfx/SplashScreenDrawer.cpp +++ b/source/gfx/SplashScreenDrawer.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/source/main.cpp b/source/main.cpp index 8af27a0..86d90b8 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -3,7 +3,6 @@ #include "utils/logger.h" #include "utils/utils.h" #include "version.h" -#include #define MODULE_VERSION "v0.3" #define MODULE_VERSION_FULL MODULE_VERSION SPLASHSCREEN_MODULE_VERSION_EXTRA @@ -12,15 +11,14 @@ int main(int argc, char **argv) { initLogging(); DEBUG_FUNCTION_LINE_INFO("Running SplashScreen Module " MODULE_VERSION_FULL ""); - using std::filesystem::path; - path envDir; + std::filesystem::path envDir; if (argc >= 1) { envDir = argv[0]; } GfxInit(); { - SplashScreenDrawer splashScreenDrawer{envDir}; + SplashScreenDrawer splashScreenDrawer(envDir); splashScreenDrawer.Draw(); } GfxShutdown(); diff --git a/source/utils/utils.cpp b/source/utils/utils.cpp index 5988f51..d8eba44 100644 --- a/source/utils/utils.cpp +++ b/source/utils/utils.cpp @@ -36,18 +36,18 @@ bool LoadFileIntoBuffer(const std::filesystem::path &filename, std::vector RandomEngine; + std::optional sRandomEngine; } // namespace std::size_t GetRandomIndex(std::size_t size) { - if (!RandomEngine) { + if (!sRandomEngine) { auto t = static_cast(OSGetTime()); std::seed_seq seeder{static_cast(t), static_cast(t >> 32)}; - RandomEngine.emplace(seeder); + sRandomEngine.emplace(seeder); } std::uniform_int_distribution dist{0, size - 1}; - return dist(*RandomEngine); + return dist(*sRandomEngine); } std::filesystem::path ToLower(const std::filesystem::path &p) {