ZeldaWWHDRecomp

ZeldaWWHDRecomp is a native PC port of The Legend of Zelda: The Wind Waker HD for Windows, Linux, and macOS with features like save states and an in-game settings overlay.

README

The Legend of Zelda: The Wind Waker HD — native PC port (macOS, Linux, Windows)

A static recompilation of the Wii U version (USA) that runs natively on macOS (Apple Silicon), Linux and Windows. The game's PowerPC code is translated to C ahead of time, the Cafe OS libraries the game uses are reimplemented natively, and GX2 graphics are implemented directly on Metal (macOS) or Vulkan (all three platforms), with no Cemu runtime and no GPU command emulation.

How it works and how it differs from running the game in Cemu: docs/how-it-works.md.

What's new in this update

  • v0.2.0: portable releases. Unzip anywhere and start Wind Waker HD: the first start prepares the game once from your own dump (releases never contain game code, so it is built on your computer); later starts launch the game directly. Everything — the built game, the game files, saves, settings, save states, shader caches, logs and the downloaded compiler — stays in the release folder; nothing goes to your user folders unless you ask for a shortcut. An extracted game folder is used where it is instead of being copied. Saves and settings can be copied over from an earlier installation. Hold Shift while starting (or --setup) to repair, update or change the game.
  • Settings overlay (Dear ImGui): an in-game menu for everything in one place — save states and Crash Recovery, graphics (renderer, frame rate, resolution, aspect ratio, AO, filtering, FXAA, performance overlay), display, gameplay mods and cheats (Graphics also has the Vulkan presentation mode), controls and language. Open it with F1 (Fn+F1 on most Mac keyboards), Cmd+, / Settings… on macOS, or hold Select / press Home on a controller; it works with mouse, keyboard and controller on every platform and renderer. The Controls tab shows the controller drawing with live feedback of pressed buttons. Shift+F1 still saves state slot 1; slot 1 now loads from the overlay.
  • Performance pass (PR #15 by Sean13128): much less render-thread CPU on Metal (no more stutter while the shader cache warms up), a lighter vsync wait on Vulkan, and a fix for the both-renderer build crashing with Homebrew boost installed.
  • Cheats (Gameplay menu / overlay, PR #15): all items, best sword and shield, 20 hearts, double magic, 5000 rupees, infinite health/magic/ammo, and story cheats (songs, Triforce shards, dungeon items, keys) — use a spare save file for those.
  • Graphics options are remembered between launches (macOS since PR #15; Linux/Windows in settings.ini).
  • Controller rumble (PR #13 by arcadematicas).
  • Linux/Windows: GamePad touch with the mouse in the GamePad window, F11 / Alt+Enter full screen, closing the TV window quits (closing the GamePad window hides it), the name-entry text prompt works again (PR #14 by rhemfur), 1 ms timer resolution on Windows for smoother frame pacing (PR #12 by rhemfur), and a --unwindlib=libgcc build note for clang setups with libunwind.
  • Console language: WWHD_LANGUAGE=<code> (or the overlay's Language tab) picks the game's language from those on the disc.
  • Native Windows LLVM builds (PR #17 by resadent): build with clang and Visual Studio's Windows SDK, without MSYS2 (missing dependencies are built from pinned sources); smoother Vulkan frame pacing on Windows via SDL's high-resolution sleeps.
  • Vulkan presentation mode (overlay → Graphics): Vsync (FIFO, default), Low latency (MAILBOX, where the driver offers it) or Off (IMMEDIATE); switches live and is remembered. WWHD_VK_PRESENT_MODE overrides it.
  • Faster Vulkan on Windows/Linux (PR #18 by resadent): bounded draw batching and a higher game/render thread priority are now on by default, as on macOS.
  • GameCube save converter (tools/savegame): bring your GameCube save file into HD — see Optional: bring your GameCube save to HD.

Earlier updates

  • Linux and Windows builds (Vulkan renderer with an SDL3 host), with automatic CI builds for both. Fixes from the first Linux reports: game paths are resolved case-insensitively (the game asks for Audiores, the disc folder is AudioRes; this crashed the game right after startup), build fixes for newer compilers, WWHD_NO_GAMEPAD only hides the GamePad window (WWHD_NO_CONTROLLERS turns off controllers), and a hint where to type when the game asks for text.

  • Crash logs and Crash Recovery: every crash writes captures/crash-<time>.log. Crash Recovery (Save States menu, off by default) keeps automatic save states plus the recorded input, so a crash can be reproduced with WWHD_REPLAY=<n>.

  • wudextract.py: the disc key file can be 16 raw bytes or 32 hex digits, with clear errors for a missing or non-matching key.

  • True 60 (key 7, experimental): every 30 Hz step is now exactly the 30 fps game's step (game logic, saves and quests stay as in the original); hookshot crash fixed. For smooth 60 fps, interpolation (key 6) is the recommended mode.

  • Vulkan renderer (by OpenAI Codex), built into the same app next to Metal. Pick one in Graphics › Renderer; the choice is saved and used from the next start ("Restart Now" relaunches right away). Both share the same windows, menus, display modes, controls and mods. If Vulkan can't start (no Vulkan loader or MoltenVK installed), the game falls back to Metal and says why. Details: docs/vulkan.md.

  • Full screen and GamePad screen modes (Display menu): full screen for the TV window (⌘F), picture scaling (smooth, sharp, integer), and the GamePad screen as its own window, a picture-in-picture overlay, an automatic overlay that pops up when the GamePad picture changes, or off (⌘G shows/hides it).

  • Aspect ratio (Graphics › Aspect ratio): 16:9 (original), match the window, 16:10, 21:9 or 32:9. Wider screens see more to the sides (same vertical view); the HUD stays at the edges and menus stay centred.

  • Fixes: misplaced Yes/No cursor in text boxes at 16:10, quitting with ⌘Q could hang, garbled characters in the window title. Community fixes from pull requests #1 and #2 (Miiverse manager throttling, shared shader-cache memory) are included.

  • 60 fps. Two modes in the Graphics menu:

    • 60 fps (key 6): frame interpolation. The game logic keeps its original 30 steps per second; every second frame is drawn halfway between two steps (camera, models, particles, sea, wave crests, grass and trees, cloth, weather, lighting). Input, sound and menus behave as at 30 fps.
    • True 60 (key 7, experimental): Link and the follow camera run their logic at 60 steps per second (for the actions that have been converted and measured against the original); everything else runs at 30 and is interpolated.
  • Higher internal resolution (1x / 1.5x / 2x / 3x, key R) and edge smoothing (FXAA, key 8).

  • Save states: a Save States menu with 5 slots (Shift+F1–F5 save, F1–F5 load), kept across sessions in ~/Library/Application Support/wwhd/states/.

  • Controls window (Input › Controls…): a drawing of the Wii U GamePad or Pro Controller; click a button to remap it to a key or a controller input, live feedback of pressed buttons and stick positions, conflict warnings.

  • Optional gameplay mods (Gameplay menu, all off by default): climb any wall, direct right-stick camera, mouse camera, first person on the mouse wheel, quick doors, fast scene changes.

  • Fixes: shadow streaks, flicker after loading, doubled wave sounds at 60 fps, camera issues.

  • Tools: function naming against the GameCube decompilation (tools/decomp/), a differential harness that verifies hand-written source against the recompiled original (tools/verify/), and the 60 fps conversion tools (tools/true60/). See "Optional: decompilation tools" below.

Legal notice

This is an unofficial fan project. It is not affiliated with, endorsed or sponsored by Nintendo. "The Legend of Zelda", "The Wind Waker", "Wii U" and related names are trademarks of their respective owners and are used here only to describe what this software is compatible with.

This repository contains no game code, no game assets and no keys: no executable, no recompiled or disassembled game code, no textures, models, audio, shaders, screenshots or other material from the game, and no console encryption keys. It contains only the tools and the runtime written for this project (plus the third-party code listed under Credits).

To use it you need your own, legally obtained copy of the game, dumped from your own Wii U disc and console. Everything game-specific (the extracted files, the recompiled code in build/gen/, shader caches) is generated locally on your machine from your dump, and must not be redistributed. The .gitignore keeps all of it out of the repository.

Install (releases)

Releases are portable: unzip, start Wind Waker HD, choose your dump. Releases contain only this project's runtime, tools and setup: no game files, no game code and no keys. The game's code can only exist once it is built from your own dump, so the first start prepares the game once, on your computer (about two minutes); every later start launches the game directly.

  1. Download the zip for your system from the Releases page and unzip it anywhere (a games folder, an external drive):

    • macOS: Apple Silicon, macOS 14 or newer (Metal renderer)
    • Windows: x86-64, Windows 10 or 11, a GPU with Vulkan 1.3 drivers
    • Linux: x86-64, glibc 2.35 or newer (Ubuntu 22.04+, Debian 12+, Fedora 36+, Arch, SteamOS 3), a GPU with Vulkan 1.3 drivers
  2. Start Wind Waker HD (Wind Waker HD.app, Wind Waker HD.exe, or wind-waker-hd / Wind Waker HD.desktop on Linux). The first start asks for:

    • your disc image (.wux or .wud), or an already extracted game folder (with code, content and meta, e.g. from dumpling or Cemu). An extracted folder is used where it is, nothing is copied; a disc image is extracted into the release folder (about 1.7 GB);
    • for a disc image, its disc key (a .key file with the image's name next to it is used automatically) and the Wii U common key (16 bytes, the same on every console; choose a key file or paste the 32 hex digits into the hidden field; a common.key next to the image or in the release folder is used automatically). Keys are checked before anything is extracted, never stored, and not part of any log.

    Then it prepares the game (extract, translate the code to C, compile with a pinned compiler) and offers to bring in a save: a Wind Waker HD cking.sav folder (Cemu, Wii U), a GameCube .gci (converted to HD), or the saves and settings of an earlier installation or another Wind Waker HD folder (copied, never moved). Only the USA version (title 00050000-10143500) is supported.

  3. That's it: start Wind Waker HD to play. To repair, update or change the game, hold Shift while starting it (macOS, Windows) or start it with --setup (Linux; also the "Setup" action of its menu entry).

First start, per system:

  • macOS: the release is not signed by Apple, so the first time macOS says the app "cannot be opened". macOS 14: right-click (Ctrl-click) the app, Open, Open. macOS 15 and newer: click Done, then System Settings › Privacy & Security › Open Anyway. If Apple's Command Line Tools (the free compiler, which also brings Python) are missing, Wind Waker HD offers Apple's installer.
  • Windows: the release is not code-signed, so SmartScreen may say "Windows protected your PC": More info › Run anyway. The first start downloads Python (11 MB) and the compiler (llvm-mingw, 190 MB) into the release folder, SHA-256 checked, no administrator rights; at the end you can remove the compiler again (it is only needed to repair, and downloaded again then).
  • Linux: start wind-waker-hd (or Wind Waker HD.desktop; some desktops ask to allow launching it first). It uses your Python 3 and downloads the compiler (zig, 55 MB) into the release folder; you can remove it at the end.

Everything stays in the release folder (in data/): the built game, the extracted game files, saves (data/save), settings, controls, save states and shader caches (data/user), crash logs (data/captures), the setup log and the downloaded compiler. Nothing is written to your user folders (Application Support, AppData, .config, Applications, Start menu) unless you tick "add a shortcut" at the end. To remove everything, delete the folder. Starting a newer release: unzip it next to the old one, start it, choose your game (the old folder's data/game can be used in place) and copy your saves and settings from the old folder.

The setup also runs in a terminal (the fallback): tools/Setup in Terminal.command (macOS), tools/Setup in a console window.bat (Windows), tools/setup-in-terminal.sh (Linux). How it works and the interface between the window and tools/installer/setup.py: tools/installer/README.md. Scripted use: tools/installer/setup.py --help.

Source builds (below) are not portable: they keep using ~/Library/Application Support/wwhd, %APPDATA%\WWHD or ~/.config/wwhd, as before.

Requirements (building from source)

  • macOS on Apple Silicon, Linux (x86-64, Vulkan) or Windows (x86-64, Vulkan); the platform-specific build steps are under "Building" below
  • macOS: Xcode command line tools (xcode-select --install)
  • CMake 3.20 or newer
  • Python 3 with pycryptodome for tools/wudextract.py (pip3 install pycryptodome); the native wwhd-extract built with the project (build/cmake/wwhd-extract --help) needs neither
  • optional: capstone (pip3 install capstone) for the disassembler helper tools/ppcdis.py
  • optional, decompilation tools only: ninja and the requirements of the zeldaret/tww build (see below)

You also need, from your own console and disc:

  • a disc image of The Wind Waker HD (USA) in .wud or .wux format;
  • its disc key (16 bytes) in a .key file next to the image, with the same base name;
  • the Wii U common key, either in a file common.key (16 raw bytes or 32 hex digits) next to the image or in the current directory, or in the WIIU_COMMON_KEY environment variable (32 hex digits). As a text file it is one line of 32 hex digits, nothing else; a wrong or malformed common key also makes the extraction fail with a decryption error.

None of these are included or will be provided.

Building

For the Vulkan renderer also: brew install vulkan-headers vulkan-loader molten-vk glslang (the build needs them; the app still runs with Metal on a Mac without them). -DWWHD_RENDERER=METAL builds a Metal-only app without any Vulkan dependency.

# 1. extract the game into game/ (game.wux with game.key next to it, plus your common key)
python3 tools/wudextract.py game.wux extract game
#    -> game/code/cking.rpx, game/content/..., game/meta/...

# 2. recompile the game code to C (writes build/gen/; stays on your machine)
python3 tools/recomp/recomp.py game/code/cking.rpx build/gen

# 3. build
cmake -S . -B build/cmake && make -C build/cmake -j$(sysctl -n hw.ncpu) wwhd
Linux

The Linux build uses the Vulkan renderer with the SDL3 host (windows, input, audio). On Ubuntu 24.04:

sudo apt install clang cmake ninja-build zlib1g-dev liblz4-dev libvulkan-dev glslang-dev \
  mesa-vulkan-drivers libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev libxss-dev \
  libxfixes-dev libxkbcommon-dev libwayland-dev libasound2-dev libpulse-dev libudev-dev libdbus-1-dev
# SDL3 is not packaged in 24.04: build it from source (https://github.com/libsdl-org/SDL, release-3.2.x)
cmake -S . -B build/linux -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
cmake --build build/linux
./build/linux/wwhd --renderer-smoke     # checks the Vulkan renderer, no game files needed

If linking fails with unwinder errors (missing _Unwind_* symbols or -lunwind), your clang is set up to use LLVM's libunwind. Configure with the GCC unwinder instead:

cmake -S . -B build/linux -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \
  -DCMAKE_EXE_LINKER_FLAGS="--unwindlib=libgcc"

Closing the TV window ends the game; closing the GamePad window only hides it. F11 or Alt+Enter toggles full screen for the focused window.

On Arch-based systems (Arch, CachyOS, Manjaro):

sudo pacman -S clang cmake ninja sdl3 vulkan-headers vulkan-icd-loader glslang shaderc python-pycryptodome
# plus the Vulkan driver for your GPU, e.g. vulkan-radeon (AMD) or vulkan-intel

Wii U volumes are case-insensitive and the game asks for paths in a different case than the extracted folders (e.g. Audiores vs AudioRes); the runtime resolves such paths itself on case-sensitive file systems. When the game asks for text (your name), type it into the game window: the text appears in the window title, Enter confirms, Escape cancels (WWHD_SWKBD_TEXT=<name> answers automatically).

On Linux and Windows, F11 or Alt+Enter switches the focused window (TV or GamePad) to full screen and back, and clicking/dragging with the left mouse button in the GamePad window uses the touch screen. The GamePad screen has the macOS modes (settings overlay, Display): a separate window, a picture-in-picture overlay in a corner of the TV window (corner, size and opacity selectable; click it to touch), the automatic overlay, off, or the GamePad picture alone in the TV window (click it to touch); Ctrl+G shows/hides it, and the choices are saved in settings.ini. The macOS menus (Graphics, Display, Input, Save States) don't exist in these builds yet; their settings are available as environment variables (below) and the number-key shortcuts.

Settings, controls and save states live under ~/.config/wwhd (or $XDG_CONFIG_HOME/wwhd). To check the build without the game, python3 tools/recomp/stubgen.py build/gen-stub writes placeholder guest code and -DGEN_DIR=$PWD/build/gen-stub builds against it (the result cannot run the game).

Windows

The Windows build uses the same Vulkan renderer and SDL3 host as Linux. Both native LLVM and MSYS2 CLANG64 builds are supported. Choose either method below and use separate build directories when switching toolchains. Both require the generated build/gen from the recompiler steps above.

Native LLVM (PowerShell, without MSYS2)

Install LLVM (with clang and clang++), CMake, Ninja, Visual Studio's Desktop development with C++ workload (for the Windows headers and runtime libraries), and the Vulkan SDK. Ensure clang, clang++, cmake and ninja are on PATH, and VULKAN_SDK points to the SDK installation. Run from PowerShell:

cmake -S . -B build/windows -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release
cmake --build build/windows
ctest --test-dir build/windows --output-on-failure
./build/windows/wwhd.exe --renderer-smoke

CMake uses installed native dependency packages where available and downloads pinned source releases of missing glslang, SDL3, zlib and LZ4 dependencies into the build directory. The first configure therefore needs internet access. SDL3's DLL is copied next to the executable. To use an existing zlib installation, set ZLIB_ROOT or the standard ZLIB_INCLUDE_DIR, ZLIB_LIBRARY_RELEASE and ZLIB_LIBRARY_DEBUG cache variables.

MSYS2 (CLANG64 shell)

Install MSYS2, open its CLANG64 shell, and install the toolchain and dependencies with pacman. This method uses MSYS2 packages and does not require Visual Studio Buil