Add WiiForwarder: disc image channels on the Wii System Menu#14508
Add WiiForwarder: disc image channels on the Wii System Menu#14508Gavin-S-Dev wants to merge 2 commits intodolphin-emu:masterfrom
Conversation
Adds a virtual forwarder channel system that maps disc images (.rvz, .iso, .wbfs, .gcz, .ciso, .wia) to launchable channel tiles on the Wii System Menu with real animated banners. Features: - Auto-install forwarder channels when Wii disc games are added to the game list; auto-remove when games are removed - Right-click context menu: "Add to Wii Menu" / "Remove from Wii Menu" - Tools menu: "Add Disc Image to Wii Menu..." file picker - Extracts real opening.bnr from disc (icon, banner animation, sound); falls back to minimal text-only IMET if extraction fails - ES intercepts forwarder title launch and boots the disc image - Skips stop-confirmation dialog for forwarder-initiated boots - Forwarder state stored in dolphin_forwarders.ini on host filesystem - Writes directly to emulated NAND (bypasses ES import encryption) - Deterministic title IDs via SHA1 hash of game ID XOR'd with "DFWD"
|
I don't think auto installing every game in the game list should be the default behavior. |
sepalani
left a comment
There was a problem hiding this comment.
Here is a cursory review of what I could find. Though, I'm clearly not familiar enough to review some of the implementation details related to the boot process and IOS/ES codebase.
Just wondering but what happen when you add a forwarder and the NAND is/becomes full?
- Add MAIN_WII_FORWARDER_AUTO_SYNC setting (off by default) with
checkbox in Wii > Misc Settings, gating auto-install/remove behavior
- Sync existing games when the setting is toggled on
- Use std::span<const u8> instead of const std::vector<u8>&
- Use std::size_t and constexpr throughout
- Replace TryParse("0x" + key) with std::stoull(key, nullptr, 16)
- Make disc_file const in MenuBar
- Update copyright to 2026
- Remove superfluous header comments
There's now a checkbox in Config > Wii > Misc Settings to enable it. I set it to auto off, unless of course the user wants the feature on. |
If the NAND is full, the file writes in InstallForwarder will fail, and the function returns false with an error log. When in silent mode (auto-sync) it would be logged and skipped. In manual mode, the user would get a error dialog. |
|
Pushed a new commit addressing/implementing all the new feedback. Willing to work any new issues out to get this pushed. |
sepalani
left a comment
There was a problem hiding this comment.
Please ensure the changes you're committing compile properly and make sense before pushing them.
For instance, your last commit description is slightly off, e.g. Use std::size_t and constexpr throughout whereas your commit doesn't change constexprness. It does affect constness but isn't relevant to the std:: namespace change.
Moreover, on top of the review comments below, you also need to update the appropriate Visual Studio project files (.props and/or .vcxproj), see the git history for some examples.
Source/Core/Core/WiiForwarder.cpp
Outdated
| if (TryParse(std::string("0x") + key, &title_id)) | ||
| try | ||
| { | ||
| title_id = std::stoull(key, nullptr, 16); | ||
| result[title_id] = value; | ||
| } | ||
| catch (const std::exception&) | ||
| { | ||
| } |
There was a problem hiding this comment.
IIRC, Dolphin has exceptions disabled (it might work on Windows but that's an exception). Not sure why you changed it that way, couldn't you use TryParse(key, &title_id, 16) as previously suggested?
| connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { | ||
| const bool now_enabled = Config::Get(Config::MAIN_WII_FORWARDER_AUTO_SYNC); | ||
| if (now_enabled && !m_forwarder_auto_sync_enabled) | ||
| SyncForwarders(); | ||
| m_forwarder_auto_sync_enabled = now_enabled; | ||
| }); | ||
| m_forwarder_auto_sync_enabled = Config::Get(Config::MAIN_WII_FORWARDER_AUTO_SYNC); |
There was a problem hiding this comment.
Isn't this hook overkill? Wouldn't it be better to only monitor m_forwarder_auto_sync_checkbox's state instead?
Source/Core/Core/WiiForwarder.h
Outdated
| // Uninstall a forwarder channel from NAND and remove the mapping entry. | ||
| bool UninstallForwarder(u64 forwarder_title_id); | ||
|
|
||
| // Get the disc image path associated with a forwarder title ID. | ||
| std::optional<std::string> GetDiscImagePath(u64 forwarder_title_id); | ||
|
|
||
| // Check if a forwarder is already installed for a given disc image path. | ||
| bool IsForwarderInstalled(const std::string& disc_image_path); | ||
|
|
||
| // Get all installed forwarders as {title_id -> disc_image_path}. | ||
| std::map<u64, std::string> GetInstalledForwarders(); | ||
|
|
||
| // Get the path to the forwarder mapping file on the host filesystem. |
There was a problem hiding this comment.
We usually don't leave blank lines between each function declaration, see other header files. We usually use a blank line:
- to divide function declarations into logical blocks; or
- when we use comments to describe them.
This comment applies to this highlighted piece of code and to the ones before and after it.
Adds a virtual forwarder channel system that maps disc images (.rvz, .iso, .wbfs, .gcz, .ciso, .wia) to launchable channel tiles on the Wii System Menu with animated banners.
Features:
AI Disclosure
Yes, I have thoroughly read the "Generative AI" section, and I'm not going to sugarcoat things, Claude Code was heavily used throughout the development of this. This is moreso just a "Hey, I made this, if you want to add it to the main, go for it" sort of thing. Was thinking it was worth a pitch, if you, of course, justifiably turn down this request ill be sure to keep developing more quality of life builds going solo, as I know the approval of this PR goes against your contributing section. Just for your guys' sanity, AI was not used to obtain any information about Wii/IOS console behavior, and the forwarder system is a host-side Dolphin feature that writes synthetic data to the emulated NAND and does not change how the emulated console behaves.