WiiUSharp 0.10.0
dotnet add package WiiUSharp --version 0.10.0
NuGet\Install-Package WiiUSharp -Version 0.10.0
<PackageReference Include="WiiUSharp" Version="0.10.0" />
<PackageVersion Include="WiiUSharp" Version="0.10.0" />
<PackageReference Include="WiiUSharp" />
paket add WiiUSharp --version 0.10.0
#r "nuget: WiiUSharp, 0.10.0"
#:package WiiUSharp@0.10.0
#addin nuget:?package=WiiUSharp&version=0.10.0
#tool nuget:?package=WiiUSharp&version=0.10.0
WiiUSharp
.NET libraries for Wii U file formats and title concepts.
Not affiliated with or endorsed by Nintendo. Wii U is a trademark of Nintendo.
The NFS container format was worked out from nfs2iso2nfs by sabykos, piratesephiroth and FIX94, the NUS package layout from NUSPacker by Maschell (timogus) and CDecrypt by crediar, and RPX compression from wiiurpxtool by CBH. WiiUSharp.Nfs, WiiUSharp.Nus and WiiUSharp.Rpx are new implementations of those formats, not ports of their code.
No keys ship with these packages. The common key, title keys and htk.bin are yours to supply.
Packages
| Package | Targets | Purpose |
|---|---|---|
WiiUSharp |
net48, net6.0, net8.0, net10.0 | Title identity and presentation (TitleId, GroupId, ProductCode, Region, Language, per-language names, ImageSlot / BootSound formats, meta and app XML); WiiUSharp.Nus: pack a code/content/meta folder into an installable title (FST, hashed and plain contents, fake-signed TMD and ticket), download a title from the update server, unpack it back; WiiUSharp.Nfs: the vWii disc container (content/hif_*.nfs); WiiUSharp.Rpx: RPX/RPL executables with sections plain, replaceable and re-compressed; WiiUSharp.Wud: .wud/.wux disc dumps opened with their game.key, each game title written out as an installable package; WiiUSharp.Menu: the Wii U Menu's per-account layout file (BaristaAccountSaveFile.dat) as a 20-page grid plus folders, read and patched back; WiiUSharp.Homebrew: Aroma and homebrew_on_menu SD paths and the fake title IDs SD homebrew is listed under. No dependencies. |
WiiUSharp.Imaging |
net48, net6.0, net8.0, net10.0 | Turns PNG, JPEG, BMP, WebP or TGA into the exact TGA an ImageSlot needs. SkiaSharp + TargaSharp; no System.Drawing. |
WiiUSharp.Audio |
net48, net6.0, net8.0, net10.0 | Turns WAV, MP3 or AIFF into bootSound.btsnd: 48 kHz stereo 16-bit, six seconds. NAudio.Core + NLayer; no Windows codecs. |
WiiUSharp.Nfs, WiiUSharp.Nus and WiiUSharp.Rpx shipped as separate packages up to 0.7.2; from 0.8.0 they live inside WiiUSharp under the same namespaces.
dotnet add package WiiUSharp
dotnet add package WiiUSharp.Nfs
dotnet add package WiiUSharp.Imaging
dotnet add package WiiUSharp.Audio
dotnet add package WiiUSharp.Nus
dotnet add package WiiUSharp.Rpx
Usage
Title metadata
using WiiUSharp;
var game = new Game(
new TitleId(TitleType.Demo, 0x12345678),
new GroupId(0x5678),
new ProductCode(ProductCode.EShop, "FAAE"))
{
Region = Region.All,
Names = LocalizedName.ForAllLanguages(new LocalizedName("Super Metroid")),
};
string id = game.TitleId.ToString(); // "0005000212345678"
ImageSlot icon = ImageSlot.Icon; // iconTex.tga, 128x128, 32 bpp
using WiiUSharp.Wud;
using Stream image = WudImage.Open("game.wux"); // .wud, .wux or game_part1.wud...
WudDisc disc = WudDisc.Read(image, DiscKey.Beside("game.wux")!.Value);
foreach (WudTitle title in disc.Titles) // the game, plus any update or DLC on the disc
title.WritePackage(image, commonKey, $"install/{title.TitleId}"); // title.tmd, title.tik, title.cert, *.app, *.h3
Title images
using WiiUSharp.Imaging;
TitleImage.Convert("icon.png", ImageSlot.Icon, @"title\meta\iconTex.tga"); // resized to 128x128, 32 bpp, uncompressed, no footer
var problems = TitleImage.Problems(new TgaFile("bootTvTex.tga"), ImageSlot.BootTv); // empty when it fits
Boot sound
using WiiUSharp.Audio;
BootSoundConverter.Convert("boot.mp3", @"title\meta\bootSound.btsnd"); // resampled, stereo, first six seconds
BootSound sound = BootSound.Load(@"title\meta\bootSound.btsnd"); // header + samples of an existing one
NFS container
using WiiUSharp.Nfs;
var key = NfsKey.FromFile(@"title\code\htk.bin");
// read: a seekable stream of the decrypted payload, no temp file
using Stream payload = NfsReader.Open(@"title\content", key).OpenPayload();
// write: pack, encrypt and split in one pass
new NfsWriter(key).Write(payload, new DiscDataSpan(0xF800000, gameLength), @"out\content");
The payload is a Wii disc image with its game partitions decrypted. Converting to or from a normal ISO needs Wii partition crypto, which WiiUSharp.Nfs does not implement — supply an IPartitionCipher and use NfsConverter. See .docs/WiiUSharp.Nfs.md.
Packing a title
using WiiUSharp.Nus;
var packer = new NusPacker(CommonKey.Parse("<wii u common key>"));
NusPackage package = packer.Pack(@"title", @"out", TitleKey.Parse("13371337133713371337133713371337"));
// out\title.tmd, title.tik, title.cert, 00000000.app (FST), 00000001.app ... and a .h3 per hashed content
Title values come from code/app.xml; pass a TitleInfo to override them, your own ContentRule list to change which files share a content, or a real title.cert to replace the generated stub. Output is fake-signed and installs with the usual signature patches. See .docs/WiiUSharp.Nus.md.
Downloading and unpacking a title
using WiiUSharp.Nus;
var commonKey = CommonKey.Parse("<wii u common key>");
var titleKey = EncryptedTitleKey.Parse("<title key as the ticket stores it>"); // what title key lists carry
var downloader = new NusDownloader(new HttpClient());
await downloader.DownloadAsync(TitleId.Parse("00050000101BAF00"), @"package", titleKey, commonKey);
// package\title.tmd, title.tik (built from the key; retail games have none on the server), 00000000.app ... and .h3 files
// With the common key given, content 0 must decrypt to an FST before anything large is fetched.
new NusUnpacker(commonKey).Unpack(@"package", @"title"); // title\code, content, meta — every hash verified
Nothing is needed to download but the title ID; the keys only decrypt. See .docs/WiiUSharp.Nus.md.
Reading a package folder
using WiiUSharp.Nus;
NusPackageDirectory package = NusPackageDirectory.Open(@"package"); // title.tmd, title.tik, title.cert, *.app, *.h3 - nothing else
foreach (NusPackageFile file in package.Files) // ordinal name order
Console.WriteLine($"{file.Name} {file.Length}");
IReadOnlyList<string> problems = package.Problems(); // missing tmd/tik, no .app files
Wii U Menu layout
using WiiUSharp.Menu;
using WiiUSharp.Homebrew;
string path = HomebrewOnMenu.AccountSavePath("FW551", 0x8000ABCD); // /wiiu/homebrew_on_menu_plugin/FW551/save/8000ABCD/BaristaAccountSaveFile.dat
byte[] original = ReadFromSd(path); // BaristaAccountSave.FileSize bytes
MenuLayout layout = BaristaAccountSave.Parse(original);
int slot = MenuLayout.SlotIndex(page: 1, row: 0, column: 2);
layout.Grid[slot] = MenuEntry.Title(TitleId.Parse("0005000010101D00")); // kind picked by MenuEntry.DefaultKindFor
int folder = layout.FindFreeFolder();
layout.Folders[folder].Name = "NES"; // 21 chars at most
layout.Grid[slot + 1] = MenuEntry.Folder(folder);
byte[] updated = BaristaAccountSave.Serialize(layout, original); // untouched bytes kept, per-boot edit counter bumped
bool unchanged = BaristaAccountSave.SameLayout(original, updated); // false: compares everything but the counter
Titles HomebrewTitleId.IsFake flags (type 0005000F) are SD homebrew the homebrew_on_menu plugin lists; nothing is installed for them. The menu shows at most MenuLimits.TitlesPerDevice (300) titles per NAND or USB. AromaPaths.PluginFile("name") is /wiiu/environments/aroma/plugins/name.wps.
Executables
using WiiUSharp.Rpx;
RpxFile rpx = RpxFile.Load(@"title\code\WUP-JAAE.rpx"); // compressed sections are inflated on load
Section rodata = rpx.FindSection(".rodata")!;
rodata.Data = Patched(rodata.Data); // any byte change, any length
rpx.Save(@"title\code\WUP-JAAE.rpx", compress: true); // CRC table rebuilt, layout as wiiurpxtool writes it
Building
dotnet build WiiUSharp.sln
dotnet test WiiUSharp.sln
Requires the .NET 10 SDK (global.json). dotnet pack -c Release produces the NuGet packages.
License
MIT — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Framework | net48 is compatible. net481 was computed. |
-
.NETFramework 4.8
- No dependencies.
-
net10.0
- No dependencies.
-
net6.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages (4)
Showing the top 4 NuGet packages that depend on WiiUSharp:
| Package | Downloads |
|---|---|
|
WiiUSharp.Imaging
Turns PNG, JPEG, BMP, WebP or TGA sources into the exact TGA images a Wii U title needs (icon, boot screens, logo). Cross-platform via SkiaSharp. |
|
|
WiiUSharp.Audio
Turns WAV, MP3 or AIFF into the bootSound.btsnd a Wii U title plays at launch: 48 kHz stereo 16-bit, trimmed to six seconds. Cross-platform via NAudio.Core and NLayer. |
|
|
WiiUSharp.Rpx
Reads and writes Wii U RPX/RPL executables: ELF sections with zlib compression and the per-section CRC table. |
|
|
WiiUSharp.Nus
Packs an unpacked Wii U title (code, content, meta) into the installable NUS layout: FST, hashed and plain contents, fake-signed TMD and ticket. Downloads a title's package from the update server and unpacks it back into those folders with every hash verified. |
GitHub repositories
This package is not used by any popular GitHub repositories.
0.10.0: WiiUSharp.Menu reads and patches the Wii U Menu layout file (BaristaAccountSaveFile.dat); WiiUSharp.Homebrew has the Aroma and homebrew_on_menu SD paths and the fake homebrew title type; NusPackageDirectory lists the installable files of a package folder.