From 017ca1ed83750bbd75659481f68337808609f908 Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Wed, 12 Feb 2025 11:52:45 -0300 Subject: [PATCH 1/3] Added support for loading random splash images from the `splashes` directory. --HG-- branch : randomize-splash-hg --- Makefile | 4 +- README.md | 16 +++++--- source/gfx/SplashScreenDrawer.cpp | 65 ++++++++++++++++++++++++------- source/gfx/SplashScreenDrawer.h | 3 +- source/main.cpp | 4 +- source/utils/utils.cpp | 23 ++++++----- source/utils/utils.h | 5 +-- 7 files changed, 83 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index ae324af..1b10a26 100644 --- a/Makefile +++ b/Makefile @@ -28,12 +28,12 @@ INCLUDES := source include #------------------------------------------------------------------------------- # options for code generation #------------------------------------------------------------------------------- -CFLAGS := -g -Wall -O2 -ffunction-sections -fno-exceptions \ +CFLAGS := -g -Wall -Os -ffunction-sections \ $(MACHDEP) CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -CXXFLAGS := $(CFLAGS) -std=c++20 -fno-rtti +CXXFLAGS := $(CFLAGS) -std=c++23 -fno-rtti ASFLAGS := -g $(ARCH) LDFLAGS = -g $(ARCH) $(RPXSPECS) --entry=_start -Wl,-Map,$(notdir $*.map) diff --git a/README.md b/README.md index 6ec3176..b52e6f5 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,18 @@ 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. -- Requires a `splash.png` (recommended) or `splash.tga` in the `[ENVIRONMENT]` directory. - - When using a `tga` make sure its 24 bit and uncompressed - - In theory any (reasonable) resolution is supported, something like 1280x720 is recommended +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/`. If no splash screen is found on the sd card, this module will effectively do nothing. -**Note:** `[ENVIRONMENT]` is the directory of the environment, for Aroma with would be `sd:/wiiu/enviroments/aroma/splash.png` +**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 ## Buildflags @@ -48,4 +52,4 @@ docker run -it --rm -v ${PWD}:/project splashscreenmodule-builder make clean ## Credits - Maschell -- Crementif \ No newline at end of file +- Crementif diff --git a/source/gfx/SplashScreenDrawer.cpp b/source/gfx/SplashScreenDrawer.cpp index 4f5c57b..0848c9d 100644 --- a/source/gfx/SplashScreenDrawer.cpp +++ b/source/gfx/SplashScreenDrawer.cpp @@ -5,10 +5,12 @@ #include "gfx.h" #include "utils/logger.h" #include "utils/utils.h" -#include +#include +#include #include #include #include +#include #include /* @@ -115,24 +117,59 @@ 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 GX2Texture *LoadImageAsTexture(std::string_view path) { +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(std::string(path).append("splash.png"), buffer)) { - auto *texture = PNG_LoadTexture(buffer); - if (texture) { - return texture; - } - } else if (LoadFileIntoBuffer(std::string(path).append("splash.tga"), buffer)) { - auto *texture = TGA_LoadTexture(buffer); - if (texture) { - return texture; + if (LoadFileIntoBuffer(filename, buffer)) { + auto ext = ToLower(filename.extension()); + if (ext == ".png") { + return PNG_LoadTexture(buffer); + } else if (ext == ".tga") { + return TGA_LoadTexture(buffer); } } - return PNG_LoadTexture(empty_png); + return nullptr; } -SplashScreenDrawer::SplashScreenDrawer(std::string_view splash_base_path) { - mTexture = LoadImageAsTexture(splash_base_path); +SplashScreenDrawer::SplashScreenDrawer(const std::filesystem::path &splash_base_path) { + mTexture = LoadImageAsTexture(splash_base_path / "splash.png"); + if (!mTexture) { + mTexture = LoadImageAsTexture(splash_base_path / "splash.tga"); + } + 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") { + candidates.push_back(entry.path()); + } + } + 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]); + } + } catch (std::exception &) {} + } + if (!mTexture) { + mTexture = PNG_LoadTexture(empty_png); + } if (!mTexture) { return; } diff --git a/source/gfx/SplashScreenDrawer.h b/source/gfx/SplashScreenDrawer.h index 715ab04..2576fa3 100644 --- a/source/gfx/SplashScreenDrawer.h +++ b/source/gfx/SplashScreenDrawer.h @@ -2,6 +2,7 @@ #include "ShaderSerializer.h" #include "gfx.h" +#include #include #include #include @@ -10,7 +11,7 @@ class SplashScreenDrawer { public: - explicit SplashScreenDrawer(std::string_view meta_dir); + explicit SplashScreenDrawer(const std::filesystem::path &meta_dir); void Draw(); diff --git a/source/main.cpp b/source/main.cpp index c669a3e..9b6ecd6 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -12,14 +12,14 @@ int32_t main(int32_t argc, char **argv) { initLogging(); DEBUG_FUNCTION_LINE_INFO("Running SplashScreen Module " MODULE_VERSION_FULL ""); - std::string basePath = "fs:/vol/external01/wiiu"; + std::filesystem::path basePath = "fs:/vol/external01/wiiu"; if (argc >= 1) { basePath = argv[0]; } GfxInit(); { - SplashScreenDrawer splashScreenDrawer(basePath + "/"); + SplashScreenDrawer splashScreenDrawer(basePath); splashScreenDrawer.Draw(); } GfxShutdown(); diff --git a/source/utils/utils.cpp b/source/utils/utils.cpp index 18922b0..b657912 100644 --- a/source/utils/utils.cpp +++ b/source/utils/utils.cpp @@ -1,27 +1,32 @@ +#include "utils.h" #include "logger.h" -#include #include -#include +#include #include #include -bool LoadFileIntoBuffer(std::string_view path, std::vector &buffer) { +bool LoadFileIntoBuffer(const std::filesystem::path &filename, std::vector &buffer) { struct stat st {}; - if (stat(path.data(), &st) < 0 || !S_ISREG(st.st_mode)) { - DEBUG_FUNCTION_LINE_INFO("\"%s\" doesn't exists", path.data()); + if (stat(filename.c_str(), &st) < 0 || !S_ISREG(st.st_mode)) { + DEBUG_FUNCTION_LINE_INFO("\"%s\" doesn't exists", filename.c_str()); return false; } - FILE *f = fopen(path.data(), "rb"); + FILE *f = fopen(filename.c_str(), "rb"); if (!f) { return false; } - buffer.resize(st.st_size); + try { + buffer.resize(st.st_size); + } catch (std::bad_alloc &e) { + DEBUG_FUNCTION_LINE_WARN("Failed allocate memory for %s: %s", filename.c_str(), e.what()); + } if (fread(buffer.data(), 1, st.st_size, f) != st.st_size) { - DEBUG_FUNCTION_LINE_WARN("Failed load %s", path.data()); + DEBUG_FUNCTION_LINE_WARN("Failed load %s", filename.c_str()); + fclose(f); return false; } fclose(f); return true; -} \ No newline at end of file +} diff --git a/source/utils/utils.h b/source/utils/utils.h index 8fe92b9..ff36367 100644 --- a/source/utils/utils.h +++ b/source/utils/utils.h @@ -1,8 +1,7 @@ #pragma once #include -#include -#include +#include #include -bool LoadFileIntoBuffer(std::string_view path, std::vector &buffer); +bool LoadFileIntoBuffer(const std::filesystem::path &filename, std::vector &buffer); From 558e57183fba41a04959ffe13cf09406d78c7cea Mon Sep 17 00:00:00 2001 From: Maschell Date: Sat, 15 Feb 2025 15:24:17 +0100 Subject: [PATCH 2/3] Add error handling on libpng errors --- source/gfx/PNGTexture.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/source/gfx/PNGTexture.cpp b/source/gfx/PNGTexture.cpp index 17ad117..f2808ff 100644 --- a/source/gfx/PNGTexture.cpp +++ b/source/gfx/PNGTexture.cpp @@ -3,6 +3,7 @@ #include #include #include +#include static void png_read_data(png_structp png_ptr, png_bytep outBytes, png_size_t byteCountToRead) { void **data = (void **) png_get_io_ptr(png_ptr); @@ -11,6 +12,15 @@ static void png_read_data(png_structp png_ptr, png_bytep outBytes, png_size_t by *((uint8_t **) data) += byteCountToRead; } +void my_png_error_fn(png_structp png_ptr, png_const_charp error_msg) { + DEBUG_FUNCTION_LINE_ERR("libpng error: %s\n", error_msg); + longjmp(png_jmpbuf(png_ptr), 1); +} + +void my_png_warning_fn(png_structp png_ptr, png_const_charp warning_msg) { + DEBUG_FUNCTION_LINE_ERR("libpng warning: %s\n", warning_msg); +} + GX2Texture *PNG_LoadTexture(std::span data) { png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (png_ptr == nullptr) { @@ -23,6 +33,14 @@ GX2Texture *PNG_LoadTexture(std::span data) { return nullptr; } + png_set_error_fn(png_ptr, nullptr, my_png_error_fn, my_png_warning_fn); + // Error handling using setjmp/longjmp + if (setjmp(png_jmpbuf(png_ptr))) { + DEBUG_FUNCTION_LINE_ERR("An error occurred while processing the PNG file\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); + return nullptr; + } + png_set_read_fn(png_ptr, (void *) &data, png_read_data); png_read_info(png_ptr, info_ptr); From a8a711b94a55decc614d319cbbd298cbce9f88da Mon Sep 17 00:00:00 2001 From: Maschell Date: Sat, 15 Feb 2025 15:24:26 +0100 Subject: [PATCH 3/3] Update Dockerifles --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d78def6..ca3e689 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,3 @@ -FROM ghcr.io/wiiu-env/devkitppc:20240704 +FROM ghcr.io/wiiu-env/devkitppc:20241128 WORKDIR project