diff --git a/Source/Core/Core/IOS/Starlet/Starlet.cpp b/Source/Core/Core/IOS/Starlet/Starlet.cpp index a7ea85f84f..ef6ffae722 100644 --- a/Source/Core/Core/IOS/Starlet/Starlet.cpp +++ b/Source/Core/Core/IOS/Starlet/Starlet.cpp @@ -128,6 +128,17 @@ bool Starlet::Init(const std::string& dump_directory, std::string* error) } INFO_LOG_FMT(IOS, "Starlet bootstrap keys attached"); } + // StarletOS phase 11 (M1), emulator only: the emulated Wii Remotes for a Revolution session, + // with the identity paired in the attached NAND. Off unless asked for. + if (const char* wiimotes = std::getenv("REV_BOOTSTRAP_WIIMOTE"); wiimotes && *wiimotes == '1') + { + if (!m_memory->EnableBootstrapWiimotes(error)) + { + m_memory.reset(); + return false; + } + INFO_LOG_FMT(IOS, "Starlet bootstrap emulated Wii Remotes enabled"); + } } // ARMCore owns generation-tagged software TLB and instruction caches, so // construct it only after the complete physical bus exists. diff --git a/Source/Core/Core/IOS/Starlet/StarletMemory.cpp b/Source/Core/Core/IOS/Starlet/StarletMemory.cpp index d25600e6f1..4e3b081571 100644 --- a/Source/Core/Core/IOS/Starlet/StarletMemory.cpp +++ b/Source/Core/Core/IOS/Starlet/StarletMemory.cpp @@ -792,6 +792,26 @@ bool StarletMemory::AttachDisposableNAND(const std::string& source, const std::s return true; } +bool StarletMemory::EnableBootstrapWiimotes(std::string* error) +{ + if (!m_nand) + { + if (error) + *error = "REV_BOOTSTRAP_WIIMOTE needs a bootstrap NAND"; + return false; + } + // The identities are chosen before the devices exist (see Init). + if (!InstallEmulatedWiimotePairings(false)) + { + if (error) + *error = "could not read the Wii Remote pairings of the bootstrap NAND"; + return false; + } + m_initialized = true; + InitializeWiimotes(); + return true; +} + bool StarletMemory::AttachKeys(const std::string& path, std::string* error) { File::IOFile keys_file(path, "rb"); @@ -4259,7 +4279,7 @@ bool StarletMemory::CommitNANDPages(const NANDJournal::Pages& pages) return true; } -bool StarletMemory::InstallEmulatedWiimotePairings() +bool StarletMemory::InstallEmulatedWiimotePairings(bool allow_nand_rewrite) { using NANDSuperblock = DiscIO::NANDImporter::NANDSuperblock; using NANDFSTEntry = DiscIO::NANDImporter::NANDFSTEntry; @@ -4499,6 +4519,12 @@ bool StarletMemory::InstallEmulatedWiimotePairings() trusted_count); return true; } + if (!allow_nand_rewrite) + { + INFO_LOG_FMT(IOS_WIIMOTE, "No paired Wii Remote identity in the raw NAND; keeping the " + "default identities without modifying NAND"); + return true; + } std::ranges::copy(pairing, sysconf.begin() + static_cast(*pairing_offset)); diff --git a/Source/Core/Core/IOS/Starlet/StarletMemory.h b/Source/Core/Core/IOS/Starlet/StarletMemory.h index 03ea2df92a..46a3b5cf36 100644 --- a/Source/Core/Core/IOS/Starlet/StarletMemory.h +++ b/Source/Core/Core/IOS/Starlet/StarletMemory.h @@ -72,6 +72,11 @@ public: // Revolution IOS Phase 04C: bootstrap mode loads no keys, so the OTP reads zero. This // loads a 1024-byte BootMii keys.bin so OTP reads return the console's own words. bool AttachKeys(const std::string& path, std::string* error); + // StarletOS phase 11 (M1), emulator only: give a bootstrap-ELF session the emulated Wii + // Remotes of the original-IOS mode, with the identities already paired in the attached NAND's + // SYSCONF (keys needed to decrypt it). Never writes the NAND: without a paired identity the + // remotes keep their default addresses. Call after AttachKeys and a NAND attach. + bool EnableBootstrapWiimotes(std::string* error); void Reset(); void DoState(PointerWrap& p); @@ -202,7 +207,7 @@ private: void CompleteNANDCommand(u32 command); bool ReadRawNANDPage(u32 page, NANDPage* raw); bool CommitNANDPages(const NANDJournal::Pages& pages); - bool InstallEmulatedWiimotePairings(); + bool InstallEmulatedWiimotePairings(bool allow_nand_rewrite = true); bool ReadNANDPage(u32 command); bool ReadNANDID(u32 command); bool ReadNANDStatus(u32 command); diff --git a/docs/StarletOS_Checkpoint.json b/docs/StarletOS_Checkpoint.json index d4368f98b8..d3f11fbf70 100644 --- a/docs/StarletOS_Checkpoint.json +++ b/docs/StarletOS_Checkpoint.json @@ -68,8 +68,8 @@ }, { "path": "Source/Core/Core/IOS/Starlet/Starlet.cpp", - "sha256": "78e3b006501af06fbef220d95213690f8a31ed5b3c36699c6e07ba58be3ba852", - "bytes": 26039 + "sha256": "9654635b4892f1e07bb72256cbf34b7bebd89eee8389154af946b47eab011f29", + "bytes": 26516 }, { "path": "Source/Core/Core/IOS/Starlet/Starlet.h", @@ -78,13 +78,13 @@ }, { "path": "Source/Core/Core/IOS/Starlet/StarletMemory.cpp", - "sha256": "34900b6c340e412f99ddb3ce6ba17bdb4d85ba7b27b2adc522315b158b675fca", - "bytes": 189757 + "sha256": "da5267d0cede011e74ed56155999ec721a562680c07b9c928f56fcea191f20c9", + "bytes": 190485 }, { "path": "Source/Core/Core/IOS/Starlet/StarletMemory.h", - "sha256": "cfa3aee13f260590ae9f7cdd48f8f08d1c67e4e6d647ef3eca6e01d472dbdd29", - "bytes": 14873 + "sha256": "954cf8d3253eeebe6910ef9fb92137e3a551d04551ed8f1fbfc6fff907c591ce", + "bytes": 15322 }, { "path": "Source/Core/DolphinNoGUI/PlatformHeadless.cpp", @@ -135,6 +135,15 @@ "files": [ "Source/Core/Core/HW/WII_IPC.cpp" ] + }, + { + "recordedAt": "2026-10-06", + "purpose": "StarletOS Phase 11 proposal M1: REV_BOOTSTRAP_WIIMOTE=1 gives a bootstrap-ELF (Revolution) session the emulated Wii Remotes with the identity paired in the attached NAND; never writes the NAND; off by default", + "files": [ + "Source/Core/Core/IOS/Starlet/Starlet.cpp", + "Source/Core/Core/IOS/Starlet/StarletMemory.cpp", + "Source/Core/Core/IOS/Starlet/StarletMemory.h" + ] } ] } diff --git a/docs/StarletOS_Handoff.md b/docs/StarletOS_Handoff.md index 69191eb61b..cef65d341a 100644 --- a/docs/StarletOS_Handoff.md +++ b/docs/StarletOS_Handoff.md @@ -135,3 +135,27 @@ Known limit for the next companion step: in bootstrap (Revolution) mode the emulated Wii Remotes are not initialized (`m_initialized` stays false), so nobody can point at a channel there. Changing that is proposed in the companion (proposal M1), not done. + +## Emulated Wii Remotes for a Revolution session — 2026-10-06 + +Companion proposal M1 (approved by the user): replay the reference launch +with Revolution instead of the original IOS, to see where Broadway stops. + +- `REV_BOOTSTRAP_WIIMOTE=1` (bootstrap-ELF mode, after the NAND and keys + attaches): `StarletMemory::EnableBootstrapWiimotes` selects the identities + paired in the attached NAND's SYSCONF (`BT.DINF`, decrypted with the keys) + and creates the emulated Wii Remotes exactly as the original-IOS mode does. + `InstallEmulatedWiimotePairings(false)` never rewrites SYSCONF: without a + paired identity the remotes keep their default addresses. Without the + variable nothing changes (the remotes stay absent, as before). +- Checkpoint hashes updated for `Starlet.cpp`, `StarletMemory.cpp`, + `StarletMemory.h`. +- Build: `.starlet_linux` (`dolphin-emu-nogui`, `tests`) and + `.starlet_linux_x11`; the 95 selected Starlet tests passed. +- Without the variable, the companion's headless P11-H06 Menu regression + (`tools/regression/phase11_menu.py --step H06 --outcome Phase9Running + --timeout 600`) still passes on this build, NAND source and disposable + copy identical. + +Next: the companion's M1b (smoke test with the variable, no window) and M1c +(the user launches the Mii Channel under Revolution in the X11 window).