IOS LLE: optional emulated Wii Remotes in bootstrap mode (StarletOS phase 11 M1)
With REV_BOOTSTRAP_WIIMOTE=1 a bootstrap-ELF session gets the emulated Wii Remotes of the original-IOS mode, using the identities paired in the attached NAND's SYSCONF. The NAND is never rewritten for it; without the variable nothing changes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
09fba9bbb5
commit
3ce435786c
5 files changed
+83
-8
No files matched your search
@@ -128,6 +128,17 @@ bool Starlet::Init(const std::string& dump_directory, std::string* error)
|
|||||||
}
|
}
|
||||||
INFO_LOG_FMT(IOS, "Starlet bootstrap keys attached");
|
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
|
// ARMCore owns generation-tagged software TLB and instruction caches, so
|
||||||
// construct it only after the complete physical bus exists.
|
// construct it only after the complete physical bus exists.
|
||||||
|
|||||||
@@ -792,6 +792,26 @@ bool StarletMemory::AttachDisposableNAND(const std::string& source, const std::s
|
|||||||
return true;
|
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)
|
bool StarletMemory::AttachKeys(const std::string& path, std::string* error)
|
||||||
{
|
{
|
||||||
File::IOFile keys_file(path, "rb");
|
File::IOFile keys_file(path, "rb");
|
||||||
@@ -4259,7 +4279,7 @@ bool StarletMemory::CommitNANDPages(const NANDJournal::Pages& pages)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StarletMemory::InstallEmulatedWiimotePairings()
|
bool StarletMemory::InstallEmulatedWiimotePairings(bool allow_nand_rewrite)
|
||||||
{
|
{
|
||||||
using NANDSuperblock = DiscIO::NANDImporter::NANDSuperblock;
|
using NANDSuperblock = DiscIO::NANDImporter::NANDSuperblock;
|
||||||
using NANDFSTEntry = DiscIO::NANDImporter::NANDFSTEntry;
|
using NANDFSTEntry = DiscIO::NANDImporter::NANDFSTEntry;
|
||||||
@@ -4499,6 +4519,12 @@ bool StarletMemory::InstallEmulatedWiimotePairings()
|
|||||||
trusted_count);
|
trusted_count);
|
||||||
return true;
|
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<ptrdiff_t>(*pairing_offset));
|
std::ranges::copy(pairing, sysconf.begin() + static_cast<ptrdiff_t>(*pairing_offset));
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,11 @@ public:
|
|||||||
// Revolution IOS Phase 04C: bootstrap mode loads no keys, so the OTP reads zero. This
|
// 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.
|
// 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);
|
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 Reset();
|
||||||
void DoState(PointerWrap& p);
|
void DoState(PointerWrap& p);
|
||||||
|
|
||||||
@@ -202,7 +207,7 @@ private:
|
|||||||
void CompleteNANDCommand(u32 command);
|
void CompleteNANDCommand(u32 command);
|
||||||
bool ReadRawNANDPage(u32 page, NANDPage* raw);
|
bool ReadRawNANDPage(u32 page, NANDPage* raw);
|
||||||
bool CommitNANDPages(const NANDJournal::Pages& pages);
|
bool CommitNANDPages(const NANDJournal::Pages& pages);
|
||||||
bool InstallEmulatedWiimotePairings();
|
bool InstallEmulatedWiimotePairings(bool allow_nand_rewrite = true);
|
||||||
bool ReadNANDPage(u32 command);
|
bool ReadNANDPage(u32 command);
|
||||||
bool ReadNANDID(u32 command);
|
bool ReadNANDID(u32 command);
|
||||||
bool ReadNANDStatus(u32 command);
|
bool ReadNANDStatus(u32 command);
|
||||||
|
|||||||
@@ -68,8 +68,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "Source/Core/Core/IOS/Starlet/Starlet.cpp",
|
"path": "Source/Core/Core/IOS/Starlet/Starlet.cpp",
|
||||||
"sha256": "78e3b006501af06fbef220d95213690f8a31ed5b3c36699c6e07ba58be3ba852",
|
"sha256": "9654635b4892f1e07bb72256cbf34b7bebd89eee8389154af946b47eab011f29",
|
||||||
"bytes": 26039
|
"bytes": 26516
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "Source/Core/Core/IOS/Starlet/Starlet.h",
|
"path": "Source/Core/Core/IOS/Starlet/Starlet.h",
|
||||||
@@ -78,13 +78,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "Source/Core/Core/IOS/Starlet/StarletMemory.cpp",
|
"path": "Source/Core/Core/IOS/Starlet/StarletMemory.cpp",
|
||||||
"sha256": "34900b6c340e412f99ddb3ce6ba17bdb4d85ba7b27b2adc522315b158b675fca",
|
"sha256": "da5267d0cede011e74ed56155999ec721a562680c07b9c928f56fcea191f20c9",
|
||||||
"bytes": 189757
|
"bytes": 190485
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "Source/Core/Core/IOS/Starlet/StarletMemory.h",
|
"path": "Source/Core/Core/IOS/Starlet/StarletMemory.h",
|
||||||
"sha256": "cfa3aee13f260590ae9f7cdd48f8f08d1c67e4e6d647ef3eca6e01d472dbdd29",
|
"sha256": "954cf8d3253eeebe6910ef9fb92137e3a551d04551ed8f1fbfc6fff907c591ce",
|
||||||
"bytes": 14873
|
"bytes": 15322
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "Source/Core/DolphinNoGUI/PlatformHeadless.cpp",
|
"path": "Source/Core/DolphinNoGUI/PlatformHeadless.cpp",
|
||||||
@@ -135,6 +135,15 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"Source/Core/Core/HW/WII_IPC.cpp"
|
"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"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -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
|
emulated Wii Remotes are not initialized (`m_initialized` stays false), so
|
||||||
nobody can point at a channel there. Changing that is proposed in the
|
nobody can point at a channel there. Changing that is proposed in the
|
||||||
companion (proposal M1), not done.
|
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).
|
||||||
Reference in new issue
Block a user