Introduction

Welcome!

This guide aims to facilitate your initial steps in developing applications for the Wii U using the Rust programming language. It will walk you through the necessary environment setup and the process of writing your first lines of code for the platform. While more detailed information can always be found in the documentation of the specific Rust crates utilized, this book will provide you with the foundational knowledge to get started and running quickly.

Need assistance?

Please consult the FAQ for answers to common questions. For further inquiries or to engage with the development community, please reach out through our community channels.

Discord

Requirements

This page provides a brief overview and checklist of recommended items to begin Wii U development. Required items are marked with an asterisk (*). For more comprehensive explanations, please refer to the Installation section.

Software

Skills

  • Rust*
  • C / C++
  • Debugging 1

This guide assumes a foundational understanding of the Rust programming language. It will not cover Rust basics, as numerous excellent free resources are readily available. However, concepts related to no_std environments will be briefly introduced and explained as they arise.

While the underlying SDK is built upon C libraries, direct interaction with them will generally not be necessary unless you intend to extend beyond the provided standard library-like features and venture into unsafe Rust. Most C functions are bound using extern "C" and can be called directly which requires some understanding of the C calling convention / ABI. This should be mainly relevant for contributors to this project.

Hardware

  • Wii U Console
  • SD Card
  • SD Card Reader

While a physical Wii U console is not strictly required for development, it is strongly recommended. Emulators, while valuable, may not accurately replicate the behavior of all application types or features due to incomplete implementations, inherent differences, or other platform-specific quirks. Consequently, software that functions correctly on an emulator may encounter issues on actual Wii U hardware, and vice versa.


  1. While debugging tools like the Cemu PPC Debugger can be useful in certain situations, the Rust compiler is generally effective at catching many potential issues during the development process.

Wii U Architecture

This document provides essential insights and relevant information about the Wii U platform, specifically tailored for developers. Its purpose is to familiarize you with the system's capabilities and constraints. For those seeking a more comprehensive understanding, a list of detailed resources discussing the platform extensively is provided below.

Summary

  • CPU: "Espresso" PowerPC
    • 32-bit architecture
    • Big-endian byte order
  • GPU: "Latte" AMD
  • Memory: 2 GB DDR3 RAM
    • 1 GB reserved for the operating system
    • 1 GB available for user applications
  • Operating System: CafeOS
    • POSIX-like?
    • Supports foreground and background applications
    • Implements threads and scheduling mechanisms
    • Features a separation between user space and kernel space
    • Utilizes virtual memory addressing
    • Includes an OpenGL-like graphics library

Further Information

Installation

This chapter will guide you through the installation and setup process required to begin development.

Homebrew

warning

Modifying your system carries inherent risks. However, the Wii U homebrew community generally considers the process reasonably safe. If you encounter any issues, do not hesitate to seek assistance from the community.

Currently, Aroma is the recommended homebrew environment for the Wii U. For installation, we suggest following the comprehensive guide available at https://wiiu.hacks.guide. Numerous other resources, including tutorials on Google and YouTube, are also available.

After successfully installing Aroma, we highly recommend setting up the Homebrew App Store. This application streamlines the installation and updating of homebrew software. Any Wii U software recommended within this documentation should be accessible through this store. Some essential tools include:

  • Wiiload Plugin: This plugin eliminates the need for repeated SD card removal and insertion. It enables direct uploading of executables from your command line interface, avoiding system reboots.
  • FTPiiU Plugin: Facilitate the transfer of general files between your PC1 and the Wii U using the FTP protocol. This tool also provides the capability to inspect the Wii U's local file system, which can be valuable for debugging purposes.

  1. To transfer files between your PC and the Wii U, an FTP client is required. We use FileZilla for a GUI and curl for a CLI, but you are free to use any FTP client that meets your requirements.

Emulator

Utilizing an emulator during the development process offers significant time savings by minimizing the overhead associated with compilation and testing cycles. In particular, when encountering crashes (which are not uncommon, especially when working with advanced features of WUT), restarting an emulator is considerably faster than rebooting a physical console.

Fortunately, a free and open-source Wii U emulator, Cemu, is available. This emulator is actively maintained and widely recognized as the standard for Wii U emulation. Cemu facilitates rapid testing and provides valuable debugging capabilities, including memory viewers and call stack inspection, among others. These tools are invaluable for diagnosing and resolving issues that are not immediately apparent. You can download Cemu here and extract the archive to a convenient directory on your system.

Other emulators like decaf-emu exist, but we recommend you sticking with Cemu.

Development

Docker

To ensure a consistent and reproducible build environment for rust-wiiu projects, a Docker image is available on the rust-wiiu/build repository. Leveraging this Docker image eliminates the "It works on my machine" problem and mitigates potential issues arising from version discrepancies and differing local configurations.

By utilizing Docker, developers can build rust-wiiu code with only Docker installed on their system. For detailed instructions and further information on using this Docker image, please refer to the README file within the repository.

Local Install

tip

For developers working on Windows, utilizing the Windows Subsystem for Linux (WSL) is highly recommended. WSL significantly streamlines development workflows by providing a seamless integration of Windows and Linux environments. Popular IDEs such as VSCode offer excellent support for WSL.

For developers intending to engage in Wii U homebrew development on an ongoing basis, establishing a local development environment is recommended. The following setup instructions primarily target Linux and Windows Subsystem for Linux (WSL) environments. Installation guides for the respective tools on other operating systems can be found on their official websites. Refer to the rust-wiiu/build repository for the currently supported versions of key build dependencies.

DevkitPro

DevkitPro serves as the foundational toolchain for Wii U homebrew development, with additional support for other Nintendo platforms such as the GBA, DS, GameCube, Wii, and Switch. It provides essential toolchains for compiling code targeting specific Nintendo consoles. For Wii U development, the devkitPPC (PowerPC) toolchain is required.

To install DevkitPro, please follow the comprehensive Getting Started guide available on their website. Once dkp-pacman is configured, install the necessary wiiu-dev package using the following command in your terminal:

sudo dkp-pacman -S wiiu-dev

Rust

An up-to-date installation of the Rust programming language is required. You can set up Rust by adhering to the official installation guide. After installation, verify the Rust version and confirm successful installation by executing the following command:

cargo --version

cargo-make

cargo-make is a versatile task runner that uses a simple TOML configuration to define and execute multi-platform build scripts by a single command. It is used to hide the more complex build- and linking commands.

cargo install cargo-make

cargo-generate

Optional! cargo-generate is a utility that facilitates starting new projects from predefined templates instead of creating empty Cargo projects. While this functionality can be achieved through a few manual commands, cargo-generate can streamline the initial project setup.

cargo install cargo-generate

Crates within rust-wiiu

The rust-wiiu project is structured as a collection of interconnected crates (Rust's package management units). These crates serve various purposes:

  • Fundamental Toolchain Crates: These provide the core building blocks for Wii U development, such as rust-wiiu/wut and rust-wiiu/wups.
  • C Library Wrappers: These crates encapsulate and extend the functionality of existing C libraries, offering a safer and more idiomatic Rust interface. Examples include rust-wiiu/notifications and rust-wiiu/kernel.
  • Pure Rust Crates: These are newly developed crates written entirely in Rust and do not rely on pre-existing C code.

From a developer's perspective, all these crates are used in the same way. However, understanding their underlying nature can be helpful when troubleshooting errors, particularly during the compilation phase.

While it is technically possible to install these crates in arbitrary locations, it would necessitate manual configuration adjustments and is generally not recommended. Instead, the suggested approach is to create a dedicated parent directory to house all rust-wiiu code. This facilitates easier access to files across different crates using relative paths. (Note: The feasibility of utilizing Cargo's Git dependencies for this purpose is currently under investigation.)

Once you have created a parent folder in your preferred location, you can obtain any of the provided crates by cloning their respective repositories into this directory. For example, to get the wut crate, you would execute the following command:

git clone https://github.com/rust-wiiu/wut.git

Getting Started

Now that everything is setup, lets get to working Homebrew software.

Project Initialization

This section outlines the steps to create a new Wii U development project using provided templates. Several project templates are available, catering to different application types:

Refer to the different file formats documentation for detailed information on Wii U file formats.

The recommended method for creating a new project is using the cargo-generate tool. This provides an interactive CLI to streamline the setup process.

cargo generate rust-wiiu/application-template

Executing this command will prompt you for the project name. This name will be used for the project directory and the final binary name.

Alternative Method: Git Template

Alternatively, you can utilize the "Use this template" button on the respective GitHub repository to create a new repository based on the chosen template.

  1. Create a new repository: On GitHub, use the "Use this template" button and name your new repository according to your project (e.g., <Project>).

  2. Clone the repository: Clone the newly created repository to your local machine, replacing <Username> and <Project> with your GitHub username and project name respectively.

git clone https://github.com/<Username>/<Project>.git
  1. Configure Cargo.toml: Navigate to the cloned project directory and open the Cargo.toml file. Modify the {{project-name}} and {{authors}} placeholders with the appropriate values for your project.

Building and Running

This section describes the initial build and execution process for your new project.

1. Build the project

Execute the following command to compile your project in release mode.

cargo make --profile release build

Upon successful compilation, the resulting RPX executable will be located at /target/powerpc-none-eabi/release/<Project>.rpx.

2. Run the application (via Cemu)

To execute the compiled application, you can use the Cemu Wii U emulator.

  • Open Cemu.
  • Navigate to File > Load.
  • Select the generated RPX file (/target/powerpc-none-eabi/release/<Project>.rpx).

If the setup is correct, your application should now run within the emulator.

Automated Execution (Optional)

You can configure the run task within the Makefile.toml file1 to automatically launch Cemu with your compiled application. Modify the path to your Cemu installation within the run task definition. Once configured, you can execute the application using:

cargo make --profile release run

3. Run on hardware

You can remove the comments and add your Wii U's IP to the upload task to upload the build file via FTP. Then you can upload and start the application from the Wii U Home-Menu so see the same result as Cemu.

cargo make --profile release upload

Congratulations! You have successfully set up your development environment and are now ready to develop Wii U software using Rust.


  1. The documentation of cargo-make can be found at: github.com/sagiegurari/cargo-make.

First Homebrew Application

With the development environment now set up, let's examine the fundamental code structure of a basic rust-wiiu application. Upon opening the src/main.rs file, you will typically find code resembling the following:

#![no_std]
#![no_main]

use wut;
use wut::prelude::*;
use wut::time::Duration;

#[wut::main(Console)]
fn main() {
    while wut::process::running() {
        println!("{}", wut::time::DateTime::now());
        wut::thread::sleep(Duration::from_secs(1));
    }
}

Let's dissect this code snippet part by part to understand its function and significance within the Wii U environment.

1. !#[no_std] Attribute

The !#[no_std] attribute signifies that this Rust code will not link against the standard Rust library (std). Unlike typical desktop or server environments, embedded systems like the Wii U require a more minimal runtime environment. The Rust ecosystem provides a tiered approach to library support:

  • core: This is the foundational tier, providing essential language features without any platform-specific dependencies or dynamic memory allocation. Only stack-based memory management is available here.
  • alloc: This tier builds upon core and introduces an interface to a memory allocator, enabling dynamic memory allocation capabilities such as String and Vec. However, it still requires platform-specific implementations for the allocator itself.
  • std: This is the default tier for typical platforms1, offering the complete Rust standard library with platform-specific implementations for functionalities like file I/O, networking, and concurrency.

While the Wii U / CafeOS does not have official Rust support in the traditional sense, rust-wiiu bridges this gap by providing a custom allocator and implementing many relevant std features. This allows developers to leverage their existing Rust knowledge while targeting the Wii U. The !#[no_std] attribute informs the compiler and linker about this embedded environment.

2. !#[no_main] Attribute

The !#[no_main] attribute is another embedded Rust macro. It instructs the linker not to generate the conventional main function that serves as the program's entry point in standard Rust environments. In embedded systems, the program execution flow often involves platform-specific initialization routines that occur before the user's main function would typically be called. In the context of Wii U homebrew development using devkitPro, the toolchain provides its own pre-main setup procedures. Therefore, we use !#[no_main] to prevent Rust from generating its default main entry point.

3. use Statements

These lines are standard Rust import statements, bringing specific modules and types into the current scope for easier use.

  • use wut;: Imports the top-level wut crate, which contains the Wii U-specific functionalities provided by rust-wiiu.
  • use wut::prelude::*;: Imports commonly used items from the wut prelude. This is a convention to bring frequently used types and traits into scope for convenience.
  • use wut::time::Duration;: Imports the Duration type specifically from the wut::time module, representing a span of time.

It's worth noting that wut::time::Duration is semantically equivalent to std::time::Duration. Both are ultimately re-exports of core::time::Duration, which houses the fundamental implementation. The wut crate, like std, re-exports parts of the core module for a more unified and accessible API.

4. !#[wut::main(Console)] Attribute

This macro performs platform-specific initialization tasks that enhance the development experience by mimicking a more standard environment. While not strictly necessary for the program to execute, it provides conveniences such as initializing a logging mechanism and ensuring a cleaner program exit. You can consult the rust-wiiu documentation for a comprehensive understanding of its functionality. This macro can be replaced with custom initialization code if needed.

The Console attribute passed to the wut::main macro is particularly important for early development and debugging. It configures the system to output log messages and println! statements to an on-screen console. Be aware that this on-screen console output may conflict with any graphical rendering you implement later in your application. The Console attribute can be omitted, changed to a different logger type, or combined with other logging configurations as detailed in the rust-wiiu documentation.

6. while wut::process::running() {…} Loop

This is the primary execution loop of the application. The code within this loop will continue to execute indefinitely until the application is terminated. An alternative, but functionally similar, way to write this loop is:

#![allow(unused)]
fn main() {
loop {
    if !wut::process::running() {
        break;
    }
}
}

A crucial aspect of this loop is the frequent call to wut::process::running(). This function checks if the application is still running in the foreground. It is essential for the proper functioning of the foreground release mechanism, specifically the HOME button. When the HOME button is pressed, the system relies on this check to move the application out of the foreground. Therefore, if the main thread within this loop becomes blocked for an extended period without calling wut::process::running(), the application may become unresponsive to the HOME button.

7. println!(…) Macro

The println!() macro is used for printing formatted text to the console. While typically defined in the standard library (std), in this no_std environment, its functionality is provided by the wut crate and is set up by the wut::main(Console) macro. It is part of the commonly used items imported via wut::prelude::*.

8. wut::time::DateTime::now() & wut::thread::sleep() Functions

These are examples of standard library-like features that have been implemented within the wut crate to provide familiar functionalities in the embedded Wii U environment. They are designed to behave similarly to their counterparts in the standard Rust library, offering time-related operations and thread pausing capabilities.


  1. For a comprehensive list of officially supported Rust platforms, please refer to the Rust Platform Support documentation.

Your Second Homebrew Application

Having grasped the fundamentals of writing Rust code for the Wii U, it's now time to put that knowledge into practice and embark on your own creative endeavors. Feel free to explore and implement any functionality that sparks your interest.

The rust-wiiu documentation serves as a valuable resource, detailing the available standard library-like features and additional tools at your disposal. These include modules such as wut::screen for rendering basic graphics and wut::gamepad for handling controller inputs.

A highly effective way to gain inspiration and accelerate your learning is to examine existing homebrew applications. By studying their code, understanding their design patterns, and adapting their techniques to your specific needs, you can significantly enhance your development skills and create compelling Wii U applications.

Example 1

TODO: An example on how to use screen

Example 2

TODO: An example on how to use fs & path

Exploring Unsafe Territory

important

While the raw bindings are primarily intended for contributors to rust-wiiu, there are scenarios where the currently available high-level features may not suffice, necessitating their use.

As you've likely gathered by now, rust-wiiu aims to be more than just a thin wrapper around C libraries; it provides a comprehensive, Rusty abstraction layer for Wii U development. However, for situations requiring direct interaction with the underlying system or when higher-level abstractions are insufficient, rust-wiiu exposes raw bindings to most C symbols through the wut::bindings module. These bindings are automatically generated using bindgen, leveraging Rust's Foreign Function Interface (FFI).

It is crucial to understand that these FFI functions are inherently marked as unsafe in Rust. This is because the Rust compiler cannot provide any guarantees regarding memory safety, ownership, or the behavior of the external C code being called. When interacting with these raw bindings, it is the developer's responsibility to ensure the correctness and safety of the operations performed.

TODO: Refer to the wut docs and explain an example using the C ABI

Frequently Asked Questions

What is Homebrew?

Homebrew software encompasses unofficial applications and tools created by the community, operating outside of the manufacturer's officially supported ecosystem. It empowers users to expand a console's capabilities, unlocking functionalities such as custom games, supplementary software, and system modifications.

Will it every be a real std version?

It is highly unlikely that rust-wiiu will ever become a fully integrated standard Rust environment. Several aspects of the underlying toolchain are fundamentally incompatible with standard Rust configurations. While a future integration might theoretically be possible given sufficient interest and a dedicated team of contributors, it is not feasible in the foreseeable future. Therefore, rust-wiiu will continue to exist as an external toolchain that strives to offer a developer experience (DX) as close as possible to a standard Rust environment.

Furthermore, the freedom from strict adherence to the standard library (std) API can offer significant convenience, particularly for rapid development. While this flexibility might occasionally result in APIs that are less optimal or non-standardized in terms of performance, security, or other aspects, the trade-off in terms of ease and speed of development is often considered worthwhile.

How to learn Rust?

Start using it. If you have no prior programming experience, it's worth noting that Rust, with its explicit and strict nature (qualities that ultimately contribute to its strength and reliability), might present a steeper initial learning curve compared to some other languages. However, I would never want to discourage anyone from embarking on the journey of learning Rust. To support you in this endeavor, here's a curated list of resources that I personally recommend or that are highly regarded within the Rust community:

Why Rust on the Wii U?

I am a Rust developer. Of course, I’ve spent six months rewriting everything in Rust. So let me tell you about it...

I was tired of the chaos that is C & C++. The fragmented compiler ecosystem, the ever-evolving standards, and the compiler's tendency to let programmers reek havoc can make C feel less like a language and more like an intricate maze. Add to that the sheer number of opportunities for bugs or undefined behavior, and you have a recipe for frustration. Rust, by comparison, feels like a breath of fresh air: modern, well-structured, and designed to make your code both safe and sane.

But it’s not just about my personal vendetta against C. I firmly believe that modern languages like Rust have a valuable role to play even especially on legacy hardware. They lowers the barrier to entry for new developers. Okay, I know Rust has a reputation for a steeper learning curve, but at least Rust comes with fantastic default tools for managing packages, formatting, error handling, ... and the compiler is flipping awesome once you develop Stockholm syndrome.

Ultimately, there's a bigger vision here. By introducing Rust to legacy environments, we can help sustain niche communities and ensure their codebases remain manageable, readable, and understandable. So much existing homebrew code reflects individual formatting and coding styles, making it challenging for others to contribute. Rust, with its inherent clean structure, great tooling, and increasing popularity, offers a promising path forward. So, whether you're drawn by the technical sophistication, the desire for a bit of nostalgia, or simply the curiosity to explore something new, welcome—let's build something great together.

Contributions

Here is a list of the contributors who have helped to write this book.

If you contributed to this book, feel free to add yourself in a PR.