# Wii IOS LLE / Starlet This experimental mode replaces Dolphin's IOS HLE kernel with an emulated ARM926EJ-S (Starlet) and executes the console-specific Wii firmware from local dumps. It is disabled by default. The validated path now reaches the original IOS title launch, `IOS_StartPPC`, the EXI Broadway boot stub, release of both Broadway reset lines, and execution of the IOS-loaded PowerPC title image in Dolphin's normal Broadway core. The end-to-end path has rendered the original French System Menu health-and-safety screen through Dolphin's Direct3D 11 backend. The original IOS80 Bluetooth stack has also accepted an emulated paired Wii Remote, completed both L2CAP HID channels, exchanged the Menu's setup reports, and delivered sustained input reports. Later validation launched the Homebrew Channel through an original IOS58 reload, ran an unmodified HackMii Installer through LetterBomb, and reached the original BootMii menu from its boot2 installation. The implementation never writes to `nand.bin`. The whole `dumps/` directory is ignored by Git so that boot ROMs, console keys, and NAND contents cannot accidentally be committed. ## Configuration Add the following values to Dolphin's main configuration: ```ini [Core] WiiIOSLLE = True CPUThread = True [General] WiiIOSLLEDumpPath = C:/absolute/path/to/dumps ``` The selected directory must contain the three matching files from one console: | File | Exact size | Purpose | |---|---:|---| | `boot0.bin` | `0x2000` bytes | Immutable Starlet reset ROM | | `keys.bin` | `0x400` bytes | BootMii-format OTP/key dump | | `nand.bin` | `0x21000000` or `0x21000400` bytes | Raw NAND with spare/ECC, optionally followed by the BootMii keys footer | For a `0x21000400`-byte BootMii dump, Dolphin compares the OTP and SEEPROM portions of the appended footer with the separate `keys.bin`. A mismatch is rejected before any firmware executes. The footer is validation metadata and is never exposed as NAND pages. If validation fails, Dolphin reports the reason and stops the LLE boot. It never falls back to IOS HLE while the mode is selected, because silently switching kernels would invalidate hardware and exploit testing. The dump path and file data are not logged. To request a normal NAND boot in Dolphin NoGUI, select the System Menu title ID. In LLE mode this is a boot-chain selector, not a direct HLE title launch: ```text DolphinNoGUI --nand_title 0000000100000002 ``` The host does not look up or inject the System Menu TMD/content for this path. boot2 and the original IOS select, authenticate, load, and start the title from the raw NAND. Other direct NAND-title, WAD, and DOL/ELF launch requests remain rejected in LLE mode. ## Execution path ```text Dolphin CoreTiming (Broadway clock domain, 729 MHz) | +-- active: 12,288 Broadway cycles --> 4,096 Starlet cycles (243 MHz) +-- WFI idle: 72,900 Broadway cycles --> 24,300 Starlet cycles | v ARMv5TE interpreter or x64 JIT + software TLB/I-cache | +-------------------------------+------------------------------+ | | | boot0 ROM SRAM / MEM1 / MEM2 Hollywood MMIO 0xffff0000 shared memory NAND, AES, SHA, OTP, timer, IRQ and IPC mailboxes | v original IOS `/dev/*` (when IOS is reached) ``` On reset, Dolphin parks Broadway on a host-only branch while CoreTiming continues to run; no word in MEM1 is overwritten to create that loop. Starlet owns the normal boot sequence. Writes to `HW_RESETS` reproduce the console's SRESET/HRESET transitions. The 64-byte EXI boot buffer written by IOS at `0x0d806840` is exposed to Broadway at its real high reset vector, `0xfff00100`, once `DIFLAGS_BOOT_CODE` enables the mapping. Releasing both reset lines resets the Broadway register/cache state and executes those original instructions. The observed stub sets `SRR0` to `0x3400` and reaches it through `rfi`; the code there establishes the BAT/MSR state and branches to the IOS-loaded title entry at `0x81000000`. There is no host-side jump to either address. Direct disc BS2, DOL/ELF, WAD, and arbitrary NAND-title launch paths are deliberately not mixed with this mode because they depend on IOS HLE. Selecting the System Menu is the one exception: it starts the raw NAND boot chain and does not directly launch the selected title. PPC-to-Starlet commands use the existing Wii IPC registers. In LLE mode, an X1 request asserts the Starlet IPC interrupt instead of calling `IOS::HLE::Kernel::EnqueueIPCRequest`. ARM replies and acknowledgements update the same mailbox/control state and can interrupt Broadway. Consequently, `/dev/fs`, `/dev/es`, and the other resource managers are intended to be created and executed by the original IOS image—not reimplemented as LLE-specific HLE services. The X1/X2 and Y1/Y2 producer bits are hardware latches rather than ordinary writable fields. A producer write of zero leaves its pending bit unchanged; only the peer's write-one-to-clear bit acknowledges it. This matters for back-to-back traffic: libogc can acknowledge one IOS reply with X2 and immediately submit the next request with X1 before Starlet is scheduled again. ## Implemented hardware - ARM and Thumb instruction interpretation needed by the observed boot, including banked CPU modes, user-bank block transfers, SPSRs, high Starlet exception vectors, IRQ/FIQ entry, ARM/Thumb interworking, ARMv5TE branches/multiplies, and CP15 registers. - Initial ARM926 MMU translation for sections, coarse/fine page tables, and FCSE process IDs. A generation-tagged 1 KiB software TLB caches resolved translations and is invalidated by the original CP15 control/table/process-ID/TLB-maintenance writes. - A physically tagged 64 KiB instruction cache avoids repeated bus fetches in hot IOS loops. CP15 `c7` maintenance invalidates it in O(1) through generation tags. ARM926 wait-for-interrupt stops instruction issue, fast-forwards device time, and wakes on an asserted IRQ/FIQ even when masked. - Native aligned 16-/32-bit reads translate a virtual address once and directly access boot ROM, SRAM, MEM1, or MEM2. Direct writes remain enabled for MEM1/MEM2, while SRAM writes deliberately retain byte-lane dispatch: treating a multi-byte SRAM store as one host write corrupted the IOS-to-System-Menu handoff and produced the Wii fatal-error screen. Active execution advances timer, NAND, OHCI, and Wiimote clocks once per 4,096-cycle scheduler slice instead of once per interpreted instruction; external IRQ delivery remains bounded to about 16.9 microseconds and WFI polling to 100 microseconds. - An x86-64 Starlet JIT translates the observed ARM and Thumb integer, branch, interworking and memory-transfer subset. Its inline generation-tagged TLB and direct fastmem paths cover ordinary MEM1/MEM2 accesses plus a measured, direction-specific subset of single SRAM reads. Every SRAM write, register-list transfer, TLB miss, MMIO access, protected boot0 overlay, invalid SRAM aperture or unsupported instruction remains an architectural side exit: registers are flushed, the exact interpreter/device operation runs, and the dispatcher re-samples IRQ/FIQ, IPC yield, CP15 and translation state before another native block executes. - Big-endian Starlet address space, 96 KiB of physical SRAM (64 KiB bank A plus 32 KiB bank B) exposed through the hardware's unusual 128 KiB windows, plus shared MEM1/MEM2 access. - Raw NAND reads, chip identification/status, Wii ECC generation, ECC-enabled page programming (including the calculated-ECC DMA side buffer and random spare input), and 64-page block erase. Programming obeys the NAND 1-to-0 bit rule. - NAND and SEEPROM writes are session-local copy-on-write data. They participate in save states and are discarded on a fresh emulated reset; the dump and `keys.bin` remain opened/read as immutable source material. - AES-CBC encrypt/decrypt DMA with the hardware key/IV FIFOs, SHA-1 compression, and the OTP boot1-hash reads used by boot0. - The 19.2 MHz Hollywood timer/alarm comparator, including immediate matches when programmed to the current counter value, separate write-one-to-clear acknowledgement, completion causes, and Starlet IRQ/FIQ masks. - BootMii SEEPROM data exposed through the original 93C56-style GPIO serial protocol, including read, write-enable/disable, word write/erase, and whole-array write/erase commands in COW memory. - Hollywood's Starlet GPIO bank, including enable/output/direction/input, ownership, straps, interrupt level/mask, and write-one-to-clear interrupt flags. POWER and EJECT have their idle levels and the EEPROM MISO pin remains connected to the existing serial model. Writes to the public BootMii diagnostic byte on GPIO bits 23:16 are logged as stage codes with the Starlet PC; this observes the firmware's own progress/panic channel without modifying its control flow. - Immediate AHM memory-flush acknowledgement, the indirect DDR/SEQ/BIST register banks used by boot1 training, and the hardware-controlled boot0 ROM overlay/SRAM-bank swap. - PPC/ARM IPC mailboxes, Starlet-side access to both control registers, and Broadway SRESET/HRESET hold/release transitions. - The Starlet EXI window at `0x0d806800` is forwarded to Dolphin's existing EXI controller at `0x0d006800`, while the adjacent reset-vector aperture remains backed by Starlet memory. This exposes the original EXI device state and transfer completion semantics used by MINI. - The Broadway Serial Interface keeps an outgoing request latch separate from the readable response RAM. Starting another transfer without rewriting communication RAM therefore repeats the previous command, matching the controller probing performed by BootMii's `ppcboot.elf`. - External SD host-controller and card path at `0x0d070000`: reversed-little-endian SDHCI capabilities/version, card-detect state, self-clearing software reset, internal-clock stabilization, write-one-to-clear interrupt status, the IOS initialization command subset, and simple block DMA to Dolphin's copy-on-write-configured `WiiSD.raw` image. The implemented commands cover identification/selection, OCR/CID/CSD/SCR, block-size setup, status, and single/multiple-block reads and writes against Dolphin's copy-on-write SD image. - The Starlet DI window at `0x0d806000` is forwarded to Dolphin's existing drive-interface MMIO implementation (the `0x0d006000` hardware block), including byte-lane accesses and Hollywood DI interrupt source `0x200`. This lets the original `/dev/di` resource manager service the System Menu's post-health-screen cover/status commands instead of timing out and creating `/shared2/test2/dvderror.dat`. - Initial OpenHCI 1.0 host-controller path at `0x0d050000`/`0x0d060000`: controller reset and functional states, interrupt status/enable/disable, 1 ms frame clock, HCCA frame/done-head writeback, control/bulk/periodic list traversal, little-endian ED/TD DMA, and root-hub power/connect/reset/change semantics routed through Hollywood IRQs 5 and 6. OHCI0 currently has two empty external ports; OHCI1 exposes the internal `057e:0305` Bluetooth module and its USB device/configuration/interface/endpoint descriptors. The emulated reset descriptor advertises a nonzero two-unit power-on-to-power-good delay (4 ms in OpenHCI units), which the original driver consumes through the original IOS timer service before scanning the hub. Standard endpoint-zero enumeration is implemented without synthesizing an IOS IPC reply. The internal BCM2045 model handles the HCI command/event subset used while IOS80 initializes Bluetooth, plus ACL transport to Dolphin's existing remote-side L2CAP/HID implementation. It reuses trusted remote identities already present in the dumped `BT.DINF` without logging their addresses. If no usable identity exists, a session-only fallback pairing is installed by decrypting, updating, HMAC-authenticating, ECC-correcting, and re-encrypting the affected SFFS cluster in the raw NAND COW overlay. The final LLE-side remote devices are rebound to Dolphin's configured input sources after their NAND identities are installed. ACL delivery waits for the connection-complete event, but unrelated HCI events no longer block the second HID channel and deadlock the L2CAP handshake. The source NAND remains unchanged. - Hollywood `HW_USBFRCRST` reset-domain behavior across an IOS reload. When the original kernel asserts a USB force-reset line, EHCI and both OHCI controllers return to their hardware reset images before the replacement IOS drivers inspect them. This prevents operational state left by IOS80 from making IOS58 reject OHCI0 before it can issue its own host-controller reset. - The internal Wi-Fi SDIO host at `0x0d080000`/`0x0d880000`, including SDIO CMD5/7/52/53, byte/word PIO and DMA transfers, CCCR/FBR/CIS data, clock and interrupt state, and the BCM4318 function-1 backplane aperture. The minimal Sonics core set exposes ChipCommon, D11, PCI and SDIO IDs, the D11 bus-width aliases, G-PHY/radio identity, and the Wii board/MAC/antenna CIS values required by the original Broadcom WL module. IOS80 completes hardware attach and registers its original `/dev/wl`; no host network connection or packet-level 802.11 model is provided yet. - The EXI Broadway boot buffer and its `0xfff00100` reset-vector mapping. The actual IOS-written PPC stub is decoded and executed by Dolphin's normal Broadway core. - Save-state serialization of ARM, SRAM, device, IPC, and scheduler state. ## Validated milestone An isolated boot probe using the local, mutually matching dumps has executed this original chain: 1. `boot0` read 47 raw NAND pages, checked their ECC, decrypted boot1 with the emulated AES engine, hashed it with the emulated SHA engine, compared the result with the console OTP value, and transferred control to boot1. 2. boot1 trained the emulated memory controller, read and authenticated boot2, ran its ELF loader, swapped the SRAM banks, removed the boot0 overlay, and entered the boot2/IOS image at `0xffff0000`. 3. The IOS kernel changed from ARM to Thumb through an interworking `LDR pc`, built its translation table at physical `0x13850000`, set its domain access register, and enabled the MMU with control value `0x1087`. 4. The kernel entered its physical MEM2 code, mapped and ran module code at virtual `0x20000000`/`0x20100000`, dispatched the firmware's intentional undefined-instruction system calls through the high SRAM vectors, and performed thousands of real thread context switches. 5. boot2 created and encrypted `/tmp/launch.sys`, renamed it to `/sys/launch.sys`, and invoked the original `ios_boot` syscall. The reloaded IOS80 mounted the newly written, HMAC- and ECC-valid SFFS superblock and registered its original `/`, `/dev/boot2`, `/dev/es`, `/dev/di`, `/dev/stm/*`, `/dev/usb/oh0`, `/dev/usb/oh1`, and `/dev/flash` resource managers. 6. IOS80 reopened `/sys/launch.sys`, loaded the requested title data, deleted the consumed launch record, updated `/sys/space.sys`, and called `IOS_StartPPC`. The syscall completed successfully, IOS populated the 64-byte EXI boot buffer, and both Broadway reset lines were released. 7. Before releasing reset, IOS had populated both the low-memory bootstrap at physical `0x3400` and the title image backing virtual `0x81000000`. Mnemonic-only inspection confirmed a coherent reset-stub chain (`rfi` to `0x3400`, BAT/MSR setup, then branch to the title entry) without printing firmware bytes. 8. A full MSVC-built `DolphinNoGUI` run, using an isolated user directory and the System Menu boot selector, executed the same chain through Dolphin's normal CoreTiming scheduler. It crossed the 1, 10, and 100 million ARM-instruction milestones, released Broadway through the EXI vector, executed the title's BAT/HID setup, then continued through PowerPC system calls, external interrupts, and periodic decrementer exceptions. The HLE Wii filesystem setup is explicitly skipped when Starlet is active, preventing it from dereferencing or mutating an IOS HLE kernel that intentionally does not exist in this mode. 9. The original PowerPC IPC client closed its initial 32 descriptor slots, opened the IOS80 resource managers `/dev/es`, `/dev/stm/immediate`, `/dev/stm/eventhook`, `/dev/fs`, and `/dev/di`, and received ARM-generated acknowledgements and replies for sustained back-to-back requests. The original filesystem stack read `SYSCONF`, `setting.txt`, `state.dat`, `NANDBOOTINFO`, `loader.ini`, and a multi-megabyte System Menu content from the raw NAND. The subsequently loaded PowerPC code reopened its IOS services and continued through IPC, decrementer, external-interrupt, syscall, and floating-point-unavailable exception handling. 10. Complete runs with both an empty slot and a configured 128 MiB `WiiSD.raw` image reproduced the same boot, multi-megabyte NAND load, second-stage IPC, and persistent PowerPC execution without a regression. Synthetic tests validate reset/clock/status behavior and empty-slot command timeout, while the inserted-card run validates discovery stability. The Menu had not yet reached a `/dev/sdio/slot0` data request before blocking on USB, so original-IOS command-response ordering and DMA remain to be proven end to end. That run observed the original title opening `/dev/usb/oh1/57e/305`. A synthetic OHCI regression now proves endpoint-zero descriptor DMA, done-head writeback, and WDH delivery; original-IOS enumeration is being validated separately because root-hub discovery and device protocol timing remain incomplete. 11. An instrumented IOS80 run initialized both original OHCI drivers, read the emulated `POTPGT=2` value, powered OHCI1 port 1, and waited 4 ms through the original IOS timer queue before performing its initial empty-port scan. After initialization, the delayed internal device attachment asserted Hollywood source 6. The original interrupt handler read and acknowledged `RHSC`, sent its private root-hub-change message, and the original resource-manager task dispatched it. That task observed `CSC|CCS`, acknowledged the connection change, initiated a port reset, waited through its original 2 ms timer path, then observed `CCS|PES|PRSC` and acknowledged reset completion. The same original driver then completed USB descriptor enumeration and initialized the BCM2045 through HCI command/event traffic. 12. The IOS80 Broadcom WL module enumerated the emulated BCM4318 Sonics cores, passed its 32-/16-bit D11 aperture tests, identified the G-PHY and BCM2050 radio, consumed the Wii CIS board and antenna data, and registered `/dev/wl`. This allowed the original KD/NCD services to answer the System Menu's `/dev/net/kd/request` and `/dev/net/kd/time` calls. 13. A headless Direct3D 11 run loaded the remaining System Menu resources through the original ES, FS, DI and network resource managers, initialized VI/GX, and captured consecutive rendered frames. The validated frame is the official French “Attention – Santé et sécurité” screen, proving visible System Menu startup after the original IOS boot and Broadway release. 14. A subsequent run selected two trusted Wii Remote identities from the raw NAND `BT.DINF`, then let the original IOS80 WUD and OHCI1 drivers perform the BCM2045 initialization and incoming connection path. IOS accepted the first L2CAP connection response instead of returning `L2CAP_SECURITY_BLOCK`, completed the HID control and interrupt channels, issued its normal LED/report-mode/extension setup traffic, and received sustained `A1 37` input reports. No IOS IPC resource manager or `/dev/usb/oh1` request was synthesized by the host. 15. A controller-driven run sent the health-screen `A` report through those original IOS80 HID channels, completed the original `/dev/di` status path, and rendered the populated French Wii Menu channel grid. The previous fatal-error path and `dvderror.dat` creation did not recur. 16. Performance work replaced byte-at-a-time instruction/MMU reads, per-instruction device clocking, and repeated page-table/code fetches with safe native-width reads and MEM1/MEM2 writes, sliced device advancement, a software TLB, and an instruction cache. SRAM writes keep their original byte-lane path after an end-to-end regression test showed that the direct host-width shortcut reached Broadway quickly but made the System Menu display its fatal-error screen. This benchmark covers the ARM-active boot path. 17. Interactive profiling measured the populated Wii Menu at 13.00 FPS and 18% speed before the final scheduler optimization. The dominant path was the original IOS Thumb scheduler loop `LDR [Rn] -> CMP #0 -> BEQ`, which polls a shared RAM word while no thread is runnable. The ARM core now recognizes that general side-effect-free shape only when the polled physical address is RAM or SRAM, advances device time without replaying millions of identical instructions, and rechecks the word or any unmasked interrupt every 100 microseconds of Wii time. MMIO polling is never skipped. A clean Direct3D 11 run then held 100% emulation speed and 59.91 FPS on the same populated Menu screen. 18. Launching the installed Homebrew Channel from that Menu exercised a real IOS reload from IOS80 to IOS58. The original kernel asserted `HW_USBFRCRST`; the replacement IOS registered and initialized `/dev/usb/oh0`, `/dev/usb/ehc`, `/dev/usb/usb`, and `/dev/usb/ven`, then released Broadway into the channel. HBC rendered its normal interface at 59.94 FPS without modifying its executable or bypassing the reload. 19. LetterBomb loaded an unmodified HackMii Installer v1.2 from the virtual SD card. The installer enumerated the NAND titles, selected and launched IOS58 revision `0x1820`, completed its preparation and signature-checking work, displayed `Press 1 to continue`, accepted the emulated Wii Remote input, and opened the HackMii installation menu. No HackMii binary, timer, syscall, or detection check was patched. Its preparation phase is currently much slower than on hardware because ARM-heavy IOS transients still run through the Starlet interpreter. 20. The dump's existing BootMii-as-boot2 installation intercepted a cold boot and loaded its original `armboot.bin`/MINI from the virtual SD card. MINI initialized the emulated GPIO and EXI paths, published its EXI Broadway boot vector, released Broadway, and ran the original `ppcboot.elf`. The interactive four-icon BootMii menu rendered without a host-side firmware jump, a patched BootMii binary, or a synthesized SI reply. 21. BootMii exposed two remaining Broadway hardware differences. Its VI setup writes the vertical and horizontal beam-position registers; ignoring those writes let Dolphin's half-line counter escape the active field and prevented the next VI interrupt. The beam writes now reposition the emulated raster and field wrapping tolerates an out-of-range position. BootMii also clears the PI interrupt-cause register before polling the front-panel controls. The reset-button bit is a live active-low input, not an acknowledgeable interrupt latch, so PI acknowledgements now preserve it. This removed the false held-RESET state that selected the Wii icon and issued `IPC_BOOT2_RUN(1, 2)` immediately. Cold-boot BootMii and HBC -> IOS254 -> MINI -> BootMii both remain in the original interactive menu, and keyboard-backed GameCube navigation was validated without modifying `armboot.bin`, `ppcboot.elf`, or `bootmii.ini`. 22. Directional JIT profiling separated slow SRAM reads from writes and counted them per 4 KiB aperture page. During the IOS-to-Menu phase, about 71% of slow SRAM accesses were writes; pages `0x00` and `0x19` dominated those writes, while page `0x1e` dominated the remaining reads. Single reads from the previously validated `0x00`/`0x12`/`0x14`/`0x19` pages and the newly measured `0x1e` page now use guarded split-bank fastmem. Direct writes to `0x00`/`0x19` passed synthetic bounds and canary tests but reproducibly stopped BootMii at its public `hardware setup begin` GPIO marker, so every SRAM write was restored to the exact bus path. The resulting build passed all 61 targeted Starlet/JIT tests and a fresh cold-boot regression: BootMii completed hardware setup, the Wii selection re-entered NAND boot2, original IOS released Broadway 54.1 seconds later, and the populated System Menu rendered without a crash or firmware patch. The still-dominant exact writes are a measured coherency problem, not permission to skip their bus semantics. The probe never prints ROM, NAND, key, or firmware instruction bytes. The committed unit suite covers ARM-to-Thumb loads into PC, high Starlet exception vectors, privileged `LDM ... ^` user-bank transfers, latched bidirectional IPC control bits, the PI reset-button state surviving interrupt acknowledgements, empty-slot SDHCI reset/clock/status behavior, timer equal/future comparator matches with independent IRQ write-one-to-clear acknowledgement, OHCI power-good/root-hub state, and a complete three-TD USB device-descriptor transaction. Targeted development probes additionally exercised NAND read/program/erase and program-time ECC, SEEPROM COW behavior, and AES-CBC encrypt/decrypt FIFO semantics. A separate differential harness compared 330,000 randomized aligned ARM and Thumb cases against an ARM926-configured Unicorn 2.1.4 instance without a mismatch; ARMv5 rotated unaligned word loads were tested separately because modern Unicorn models different semantics. This proves the original `boot0 -> boot1 -> boot2 -> IOS kernel/modules -> title launch -> IOS_StartPPC -> Broadway release` path is executing rather than being bypassed by Dolphin. At 120 million interpreted ARM/Thumb instructions the probe observed no undefined ARM instruction outside IOS's syscall encoding, only the three pre-existing bad-ECC pages in the source dump, a valid EXI reset vector, and `HW_RESETS == 0xffffffff`. The current end-to-end boundary is a rendered, controller-connected and post-health-screen System Menu with its populated channel grid, followed by a successful original IOS80-to-IOS58 reload, a rendered Homebrew Channel, LetterBomb reaching the interactive HackMii Installer menu, and both cold-boot and IOS254 launches reaching a stable, navigable original BootMii UI through MINI and `ppcboot.elf`. The path sustains PPC-to-original-IOS filesystem, DI, Bluetooth HID, SDIO/Wi-Fi and network-service traffic. The stabilized Menu has been measured at 59.91 FPS and HBC at 59.94 FPS. It proves the emulated first Wii Remote's pairing, L2CAP setup, command exchange and input-report path, but not every extension, multiple-controller scenario, reconnection edge case, packet-level networking, resource manager, or timing-sensitive exploit. ## Remaining blockers The next firmware stages need substantially more hardware fidelity: - ARM926 translation faults/aborts, domain and page permissions, replacement-policy fidelity, and exact cache-maintenance timing. Address translation and functional TLB/I-cache invalidation exist, but these protection and cycle-level details remain incomplete. - Remaining memory-controller/AHB coherency behavior needed after the Broadway handoff and by shared-memory DMA devices. - NAND command latency, bad-block/wear behavior, error injection, and less common command variants. The common IOS read/program/erase/ECC path is COW, but it is not yet a cycle-accurate flash model. - Remaining GPIO inputs/interrupt behavior and external devices connected to those pins. - DI, remaining SD command/response fidelity and insertion events, USB EHCI, packet-level Wi-Fi, remaining Bluetooth/Wii Remote extensions, multi-controller and reconnection behavior, and their DMA/interrupt timing. External SD block DMA, Wi-Fi SDIO/D11 attach, OHCI ED/TD DMA, USB enumeration, Bluetooth HCI/ACL, and one paired remote's L2CAP/HID input path are implemented. - Remaining IOS reload/reset edge cases, device timing, and scheduler accuracy needed by timing-sensitive original exploits. - Performance: the Menu's original IOS idle path runs at full speed through safe RAM/SRAM poll fast-forwarding, and the x64 Starlet JIT now executes most ordinary ARM/Thumb instructions natively. Boot and transient driver workloads still cross many architectural side exits for MMIO, CP15 operations and the not-yet-native instruction subset. Those exits must be reduced by proven instruction translations or register-specific MMIO stubs, never by treating every device access as a resumable C helper. Until those items are implemented, this is an end-to-end experimental LLE implementation rather than a drop-in replacement for Dolphin's mature IOS HLE mode. ## Public implementation references - [fail0verflow/mini](https://github.com/fail0verflow/mini) for public Starlet hardware constants, SRAM swapping, MMU setup, and the boot2 ELF-loader shape. - [InvoxiPlayGames/Uniicorn-Wii](https://github.com/InvoxiPlayGames/Uniicorn-Wii) for an independent public Starlet/boot-chain emulator and high-vector behavior. - [WiiBrew External Interface](https://www.wiibrew.org/wiki/Hardware/External_Interface) for the documented EXI boot-buffer and Broadway reset-vector address mapping. - [WiiBrew GPIOs](https://www.wiibrew.org/wiki/Hardware/Hollywood/GPIOs) and [Serial Interface](https://www.wiibrew.org/wiki/Hardware/Serial_Interface) for the public GPIO register and SI communication-RAM behavior. - [WiiBrew NAND Interface](https://www.wiibrew.org/wiki/Hardware/NAND_Interface) and [NAND layout](https://www.wiibrew.org/wiki/Hardware/NAND) for the command register, DMA buffers, chip geometry, and supported device IDs. - [WiiBrew Hollywood IRQs](https://www.wiibrew.org/wiki/Hollywood/IRQs) for the Starlet IRQ/FIQ routing registers and interrupt-source assignments. - [Linux Wii device tree](https://github.com/torvalds/linux/blob/master/arch/powerpc/boot/dts/wii.dts) and [WiiBrew USB host controller](https://wiibrew.org/wiki/Hardware/USB_Host_Controller) for the two OHCI register windows and Hollywood interrupt assignments. - [OpenHCI 1.0a](https://www.cs.usfca.edu/~cruse/cs698s10/hcir1_0a.pdf) for controller, HCCA, endpoint/transfer descriptor, root-hub, power-good-delay, and interrupt semantics. - [WiiBrew IOS syscalls](https://www.wiibrew.org/wiki/IOS/Syscalls) and [IOS kernel](https://www.wiibrew.org/wiki/IOS/Kernel) for the public timer/alarm and message-queue interfaces used while correlating the original driver's control flow. - [ARM926EJ-S Technical Reference Manual](https://developer.arm.com/documentation/ddi0198/latest/) for ARMv5TE, CP15, banked-register, exception, and interworking semantics. ## JIT correctness and BootMii performance model BootMii is two distinct Starlet programs before its Broadway UI appears. The boot2-style loader performs Hollywood setup, mounts the external SD controller and loads `/bootmii/armboot.bin`. MINI then configures the ARM926 MMU/caches and IRQs, initializes NAND, IPC and SDHC, loads `/bootmii/ppcboot.elf`, writes the Broadway EXI reset stub, releases the reset lines and finally sleeps in its IPC loop. MINI has no Wi-Fi stack. Consequently, Wi-Fi SDIO traffic observed later belongs to Nintendo IOS/System Menu startup and is not a valid optimization target for a black screen inside BootMii. The public loader also gives deterministic stage telemetry. `debug_output()` writes one byte to GPIO bits 23:16: `42/43/44` cover entry, stack and BSS setup; `F0/F1` enter and finish loader setup; `F2/F3` select and hand off the SD payload; `C8/C9` fall back and hand off to NAND boot2; `E3/E4` are ELF-loader panics. A panic then alternates its error byte with zero around repeated 500 ms timer delays. Therefore a trace fixed at the loader's `udelay` loop for millions of scheduler slices is a panic, not evidence that SDHC or the GUI merely needs more time. The JIT follows the same invariant used by Dolphin's Broadway JIT and QEMU TCG: a slow access can resume inside a translated block only when all guest architectural state at that instruction is recoverable and the helper cannot change scheduling, interrupt, translation or code-cache state. Dolphin flushes registers before its safe slow loads/stores and checks memory exceptions; QEMU records a host-PC to guest-PC/state map so faults restore the precise instruction boundary. The Starlet JIT does not yet have that per-instruction recovery metadata. Generic MMIO therefore exits to the dispatcher. Future performance work can specialize proven side-effect-free registers (for example read-only status or timer reads), while complex writes, IRQ acknowledgements, IPC and reset transitions must remain exits. The ARM926 manual is also explicit about the boundaries relevant here: wait-for-interrupt drains the write buffer and sleeps until IRQ/FIQ/debug; disabling and re-enabling the MMU preserves TLB contents; D-cache clean, write-buffer drain, I-cache invalidation and TLB invalidation are separate CP15 operations. Collapsing all `c7` maintenance into a code-cache flush is both inaccurate and slow, while ignoring the instruction-cache operations breaks self-modifying boot code. ### IOS syscall execution and evaluated acceleration strategies IOS has two superficially similar software-exception ABIs. Normal kernel calls are deliberately undefined ARM words of the form `0xE6000010 | (syscall_number << 5)`. The Undefined vector saves the complete thread context, extracts bits 12:5, switches to System mode and dispatches through the IOS-version-specific syscall table. ARM/Thumb `SVC 0xAB` is a separate RealView semihosting ABI; production IOS retains essentially only debug-string output (`r0 = 4`, string in `r1`). Replacing either path with host-side IOS HLE would skip the original scheduler, message queues, permission checks and exploit-relevant kernel behavior, so LLE keeps the guest handlers. The JIT only enters the architecturally correct Undefined/Supervisor exception directly, avoiding a redundant generic instruction-decoder fallback. The acceleration options were evaluated as follows: | Method | Expected value here | Decision | |---|---|---| | Per-instruction interpreter | Reference accuracy, very low throughput | Keep as the exact fallback/oracle only | | IOS syscall HLE | Very fast for ordinary titles | Reject for original IOS and exploit compatibility | | QEMU TCG/Unicorn ARM core | Mature ARM system translation | Valuable reference, but integrating Dolphin memory, Hollywood MMIO, CoreTiming, precise cache invalidation and dual-CPU IPC would duplicate most of the current machine model | | LLVM/whole-function recompilation | Strong global optimization | Excessive compile latency and difficult precise MMIO/exception recovery during boot and self-modifying code | | Custom basic-block JIT | Shares Dolphin memory and timing directly | Selected; continue with measured native coverage and exact side exits | | Native ARM predication | Removes common IOS conditional-ALU fallbacks | Implemented for every already-validated data-processing form | | Native Undefined/SVC entry | Removes decoder fallback at each software exception | Implemented without bypassing the guest kernel handler | | Direct block chaining | Removes dispatcher lookup on hot edges | Next high-value CPU optimization, provided TLB/I-cache invalidation unlinks every affected edge | | Wider register allocation / traces | Reduces repeated guest-register loads and stores | Medium-term; add only after branch/memory profiles identify stable hot traces | | Register-specific MMIO fast paths | Can remove very hot safe status reads | Only after sampled effective-address traces; generic MMIO continuation is forbidden | This ordering follows the same split documented by [QEMU TCG](https://github.com/qemu/qemu/blob/master/docs/devel/tcg.rst): RAM/ROM accesses use cached host offsets, MMIO calls device code, and direct block chains must be removable when translated pages change. The current microbenchmark reaches roughly two billion simple translated ARM instructions per host second, while complete IOS traces are orders of magnitude slower. The raw x86 emitter is therefore not the limiting component; remaining work is native coverage, side-exit frequency, guest scheduling/idle detection and device-access cost. ## Code map | Area | Files | |---|---| | ARM CPU | `Core/IOS/Starlet/ARMCore.{h,cpp}` | | x86-64 ARM/Thumb JIT | `Core/IOS/Starlet/ARMJitX64.{h,cpp}` | | Starlet scheduler/lifetime | `Core/IOS/Starlet/Starlet.{h,cpp}` | | Address space and devices | `Core/IOS/Starlet/StarletMemory.{h,cpp}` | | Bluetooth pairing and Wii Remote HID | `Core/IOS/USB/Bluetooth/{BTBase,WiimoteDevice}.{h,cpp}` | | IPC and Broadway reset | `Core/HW/WII_IPC.{h,cpp}` | | Broadway VI and front-panel state | `Core/HW/VideoInterface.cpp`, `Core/HW/ProcessorInterface.{h,cpp}` | | Mode selection/lifetime | `Core/HW/HW.cpp`, `Core/System.{h,cpp}` | | Boot-path separation | `Core/Boot/Boot.cpp`, `Core/ConfigManager.cpp`, `Core/Core.cpp` | | Configuration | `Core/Config/MainSettings.{h,cpp}` | | Starlet CPU/device unit tests | `UnitTests/Core/IOS/Starlet/ARMCoreTest.cpp` | ## Safe development rules 1. Treat all dumps as private console material and never print keys or ROM/NAND bytes in logs. 2. Keep `nand.bin` read-only; implement writes only in a separate copy-on-write overlay. 3. Test new devices first with synthetic data, then with address/PC traces that reveal no secrets. 4. Do not call IOS HLE from LLE code. Missing hardware should fail visibly instead of silently changing the firmware behavior, especially while testing exploits.