IOS LLE: emulate SD CMD6 and document Wii conformance run
This commit is contained in:
1 parent
c230971f07
commit
a8dbbab62d
3 files changed
+68
-1
No files matched your search
@@ -274,6 +274,7 @@ constexpr u16 SDHC_ERROR_DATA_TIMEOUT = 1U << 4;
|
||||
constexpr u32 SD_CARD_GO_IDLE = 0;
|
||||
constexpr u32 SD_CARD_ALL_SEND_CID = 2;
|
||||
constexpr u32 SD_CARD_SEND_RELATIVE_ADDRESS = 3;
|
||||
constexpr u32 SD_CARD_SWITCH_FUNCTION = 6;
|
||||
constexpr u32 SD_CARD_SELECT = 7;
|
||||
constexpr u32 SD_CARD_SEND_IF_CONDITION = 8;
|
||||
constexpr u32 SD_CARD_SEND_CSD = 9;
|
||||
@@ -608,6 +609,7 @@ void StarletMemory::InitSDCard()
|
||||
m_sd_card.Close();
|
||||
m_sd_card_inserted = false;
|
||||
m_sd_card_high_capacity = false;
|
||||
m_sd_high_speed = false;
|
||||
m_sd_block_length = 512;
|
||||
if (!Config::Get(Config::MAIN_WII_SD_CARD))
|
||||
return;
|
||||
@@ -673,6 +675,7 @@ void StarletMemory::Reset()
|
||||
m_seeprom_write_all = false;
|
||||
m_sd_app_command = false;
|
||||
m_sd_card_selected = false;
|
||||
m_sd_high_speed = false;
|
||||
m_sd_block_length = 512;
|
||||
m_sdhc_status_before_write = 0;
|
||||
m_wifi_sdio_status_before_write = 0;
|
||||
@@ -748,6 +751,7 @@ void StarletMemory::DoState(PointerWrap& p)
|
||||
p.Do(m_sd_card_high_capacity);
|
||||
p.Do(m_sd_app_command);
|
||||
p.Do(m_sd_card_selected);
|
||||
p.Do(m_sd_high_speed);
|
||||
p.Do(m_sd_block_length);
|
||||
p.Do(m_sdhc_status_before_write);
|
||||
p.Do(m_wifi_sdio_status_before_write);
|
||||
@@ -3204,8 +3208,49 @@ void StarletMemory::ExecuteSDHCCommand(u32 command_and_mode)
|
||||
{
|
||||
case SD_CARD_GO_IDLE:
|
||||
m_sd_card_selected = false;
|
||||
m_sd_high_speed = false;
|
||||
m_sd_block_length = 512;
|
||||
break;
|
||||
case SD_CARD_SWITCH_FUNCTION:
|
||||
{
|
||||
// CMD6 returns a 512-bit status block, distinct from ACMD6 (bus width).
|
||||
// Offer default and high-speed access modes in function group 1. The
|
||||
// other groups have only their mandatory default and no-change functions.
|
||||
if (!data_command || (transfer_mode & SDHC_TRANSFER_DMA_ENABLE) == 0 || block_size < 64)
|
||||
{
|
||||
succeeded = false;
|
||||
break;
|
||||
}
|
||||
|
||||
std::array<u8, 64> status{};
|
||||
status[1] = 64; // Maximum current consumption: 64 mA.
|
||||
bool function_error = false;
|
||||
for (u32 group = 0; group < 6; ++group)
|
||||
{
|
||||
const u16 supported = group == 0 ? 0x8003 : 0x8001;
|
||||
status[2 + (5 - group) * 2] = static_cast<u8>(supported >> 8);
|
||||
status[3 + (5 - group) * 2] = static_cast<u8>(supported);
|
||||
|
||||
const u32 requested = (argument >> (group * 4)) & 0xf;
|
||||
u8 selected = group == 0 && m_sd_high_speed ? 1 : 0;
|
||||
if (requested != 0xf)
|
||||
selected = requested == 0 || (group == 0 && requested == 1) ?
|
||||
static_cast<u8>(requested) :
|
||||
0xf;
|
||||
function_error |= selected == 0xf;
|
||||
const u32 status_byte = 16 - group / 2;
|
||||
status[status_byte] |= static_cast<u8>(selected << ((group & 1) * 4));
|
||||
}
|
||||
status[17] = 1; // Busy-status fields are defined and all functions are ready.
|
||||
for (u32 i = 0; i < status.size(); ++i)
|
||||
WriteDMA8(dma_address + i, status[i]);
|
||||
WriteRegister(SDHC_DMA_ADDRESS, dma_address + static_cast<u32>(status.size()));
|
||||
WriteRegister(SDHC_RESPONSE, 0x900);
|
||||
transfer_complete = true;
|
||||
if ((argument & 0x80000000) != 0 && !function_error && (argument & 0xf) <= 1)
|
||||
m_sd_high_speed = (argument & 0xf) == 1;
|
||||
break;
|
||||
}
|
||||
case SD_CARD_ALL_SEND_CID:
|
||||
case SD_CARD_SEND_CID:
|
||||
{
|
||||
|
||||
@@ -250,6 +250,7 @@ private:
|
||||
bool m_sd_card_high_capacity = false;
|
||||
bool m_sd_app_command = false;
|
||||
bool m_sd_card_selected = false;
|
||||
bool m_sd_high_speed = false;
|
||||
u32 m_sd_block_length = 512;
|
||||
u32 m_sdhc_status_before_write = 0;
|
||||
u32 m_wifi_sdio_status_before_write = 0;
|
||||
|
||||
@@ -21,7 +21,7 @@ successfully from this directory in PowerShell:
|
||||
```
|
||||
|
||||
The ready-to-copy Homebrew Channel folder is `apps/wii-conformance/`, containing
|
||||
`boot.dol` and `meta.xml`. This build has not yet been run on a physical Wii.
|
||||
`boot.dol` and `meta.xml`.
|
||||
|
||||
## Capture
|
||||
|
||||
@@ -57,3 +57,24 @@ shared-memory cache visibility, DMA, IRQ ordering, and individual devices.
|
||||
PPC homebrew cannot inspect every Starlet register while Nintendo IOS is
|
||||
running. A separate Starlet-side probe under MINI/BootMii can test raw
|
||||
hardware registers, but its results must be labeled as MINI-mode tests.
|
||||
|
||||
## 2026-09-23 IOS58 comparison
|
||||
|
||||
The same DOL (SHA-256
|
||||
`28EB2F51CB12B302D736518232CAB59715877A81CD0AABC1A938EF16CF0ADFC4`)
|
||||
ran on a physical Wii and in this fork's Starlet LLE mode under IOS58 revision
|
||||
6176. Both captures contain all 1,860 observations. The SD tests in LLE first
|
||||
failed during card initialization because Starlet SDHC did not implement CMD6
|
||||
(Switch Function). After adding its 64-byte status response, all SD operations
|
||||
completed and the CSV closed successfully.
|
||||
|
||||
The comparison finds 64 differences, all repeats of `es_title_count`: 111 on
|
||||
the Wii versus 101 in the Dolphin profile. A read-only walk of the Dolphin raw
|
||||
NAND and its journal found exactly 101 installed title TMDs. The remaining
|
||||
1,796 observations match. This result covers the tested IOS58 paths only; it
|
||||
cannot establish an overall emulator accuracy percentage.
|
||||
|
||||
Local captures are `captures/wii-ios58-r6176.csv` (SHA-256
|
||||
`C08E49B0ADCF1F0EF30FFE16775E3A354D269923028C9B775BBB189E7E2FF3E6`)
|
||||
and `captures/dolphin-lle-ios58-r6176.csv` (SHA-256
|
||||
`64D2E00EAE67370578BE2A15FC0951E7051E3468252B0D2533F5B968A0E14AD8`).
|
||||
Reference in new issue
Block a user