A complete, buildable .cemod for CemuExtend,
written so that nothing in it is tied to a particular game.
It ships the same mod as both payload formats a .cemod can carry, and the
mod itself — connecting to Cemu over the CEX2 transport, logging, reading and
writing host configuration, timing a round trip — is ordinary C++ with no
per-title knowledge in it at all. Everything a specific game needs lives in
one JSON file under games/, and switching targets is
--game <profile> on the command line.
./docker-build.sh # trusted-native ELF, example-generic
./docker-build.sh --wups # WUPS plugin, example-generic
./docker-build.sh --game minecraft-wiiu # same mod, a real title
Docker is the only supported build environment. There is nothing to install beyond Docker itself: the toolchains live in images built from cemod-sdk.
| One mod, two payloads | src/ExampleMod.cpp is compiled unchanged into a trusted-native ELF that runs from a codecave inside the game's process, and into a WUPS plugin loaded alongside it. Only the entry points differ. |
| Game data as data | Title IDs, the hooked instruction, the CMB1 bootstrap records and the address of the game's loader stubs all come from games/<id>/game.json. Adding a game adds a directory. |
| A payload that owns its runtime | The ELF has no crt0. src/native/ is the whole of it: the codecave entry stub, a heap, newlib's syscalls, the gthreads hooks, and the loader bootstrap that reaches Cafe OS through the game's own import stubs. |
| Failing closed | A profile whose hook point no longer matches the game is refused by CemuExtend before anything is patched; a mismatched profile is refused by verify-profile before the package is built; a missing CEX2 host leaves the mod detached instead of crashing the game. |
games/<id>/game.json the only game-specific data in the repository
tools/generate_game.py turns it into manifest.json, game_profile.h, game.mk
src/ExampleMod.cpp the mod: game-independent, payload-independent
src/native/ trusted-native payload: entry stub and runtime
platforms/wups/ WUPS payload: plugin lifecycle and its Makefile
tools/verify_profile.py checks the linked image against the profile
infra/docker/ vendored toolchain archive and preflight checks
See BUILD.md for prerequisites, the two payload formats, and what each build step actually does. In short:
git submodule update --init --recursive
sh infra/docker/vendor/fetch-devkitppc.sh
./docker-build.sh --game <profile> [--wups] [--install <Cemu data directory>]Packages land in out/dist/, and --install copies the one that build just
produced into <Cemu data directory>/cemuextend/mods/.
docs/game-profiles.md walks through every field of a
profile: where the title IDs come from, how to pick a hook point the generic
entry stub can resume from, how to find the RPX hashes and the loader stubs,
and what to do when a game has no suitable hook point at all (build the WUPS
payload; see the example-wups-only profile).
MIT, see LICENSE. The submodules under third_party/ carry their
own licences.