IOS LLE: emulate SD CMD6 and document Wii conformance run

This commit is contained in:
Yaya48 committed 2026-09-23 14:31:21 +02:00
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;