Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,23 @@ 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. 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/`.

If no splash image is found on the sd card, this module will effectively do nothing.
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/`.

**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}` (selected randomly)
3. `SD:/wiiu/splash.{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.

## Buildflags

Expand Down
61 changes: 38 additions & 23 deletions source/gfx/SplashScreenDrawer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <gx2/draw.h>
#include <gx2/mem.h>
#include <gx2r/draw.h>
#include <optional>
#include <random>
#include <whb/log.h>

Expand Down Expand Up @@ -142,7 +143,26 @@ 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<std::minstd_rand> engine;
if (!engine) {
auto t = static_cast<std::uint64_t>(OSGetTime());
std::seed_seq seeder{static_cast<std::uint32_t>(t),
static_cast<std::uint32_t>(t >> 32)};
engine.emplace(seeder);
}
std::uniform_int_distribution<std::size_t> 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"};
mTexture = LoadImageAsTexture(splash_base_path / "splash.png");
if (!mTexture) {
mTexture = LoadImageAsTexture(splash_base_path / "splash.jpg");
Expand All @@ -155,35 +175,30 @@ SplashScreenDrawer::SplashScreenDrawer(const std::filesystem::path &splash_base_
}
if (!mTexture) {
// try to load a random one from "splashes/*"
try {
std::vector<std::filesystem::path> 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<std::filesystem::path> 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<std::uint64_t>(OSGetTime());
std::seed_seq seed{static_cast<std::uint32_t>(t),
static_cast<std::uint32_t>(t >> 32)};
std::minstd_rand eng{seed};
std::uniform_int_distribution<std::size_t> 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 selected = get_random_index(candidates.size());
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);
Expand Down
5 changes: 4 additions & 1 deletion source/gfx/SplashScreenDrawer.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@

class SplashScreenDrawer {
public:
explicit SplashScreenDrawer(const std::filesystem::path &meta_dir);
SplashScreenDrawer();
explicit SplashScreenDrawer(const std::filesystem::path &baseDir);

void Draw();

Expand Down Expand Up @@ -47,4 +48,6 @@ class SplashScreenDrawer {
GX2RBuffer mTexCoordBuffer = {};
GX2Texture *mTexture = nullptr;
GX2Sampler mSampler = {};

void InitResources();
};
4 changes: 2 additions & 2 deletions source/gfx/gfx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -476,4 +476,4 @@ BOOL GfxInitShaderAttribute(WHBGfxShaderGroup *group,
attrib->mask = GfxGetAttribFormatSel(format);
attrib->endianSwap = GX2_ENDIAN_SWAP_DEFAULT;
return TRUE;
}
}
23 changes: 19 additions & 4 deletions source/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "utils/logger.h"
#include "utils/utils.h"
#include "version.h"
#include <exception>
#include <optional>

#define MODULE_VERSION "v0.3"
#define MODULE_VERSION_FULL MODULE_VERSION SPLASHSCREEN_MODULE_VERSION_EXTRA
Expand All @@ -11,15 +13,28 @@ 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> 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();

Expand Down