@@ -237,18 +237,23 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
237237 case SEND_CSD:
238238 {
239239 const std::array<u32 , 4 > csd = m_protocol == SDProtocol::V1 ? GetCSDv1 () : GetCSDv2 ();
240- memory.CopyToEmuSwapped (buffer_out, csd.data (), csd.size () * sizeof (u32 ));
240+ memory.Write_U32 (csd[0 ], buffer_out + 12 );
241+ memory.Write_U32 (csd[1 ], buffer_out + 8 );
242+ memory.Write_U32 (csd[2 ], buffer_out + 4 );
243+ memory.Write_U32 (csd[3 ], buffer_out + 0 );
241244 }
242245 break ;
243246
244247 case ALL_SEND_CID:
245248 case SEND_CID:
249+ {
246250 INFO_LOG_FMT (IOS_SD, " (ALL_)SEND_CID" );
247- memory.Write_U32 (0x80114d1c , buffer_out);
248- memory.Write_U32 (0x80080000 , buffer_out + 4 );
249- memory.Write_U32 (0x8007b520 , buffer_out + 8 );
250- memory.Write_U32 (0x80080000 , buffer_out + 12 );
251- break ;
251+ memory.Write_U32 (0x00D0444F , buffer_out + 12 );
252+ memory.Write_U32 (0x4C504849 , buffer_out + 8 );
253+ memory.Write_U32 (0x4E430403 , buffer_out + 4 );
254+ memory.Write_U32 (0xAC68006B , buffer_out + 0 );
255+ }
256+ break ;
252257
253258 case SET_BLOCKLEN:
254259 m_block_length = req.arg ;
@@ -279,24 +284,21 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
279284 INFO_LOG_FMT (IOS_SD, " {}Read {} Block(s) from {:#010x} bsize {} into {:#010x}!" ,
280285 req.isDMA ? " DMA " : " " , req.blocks , req.arg , req.bsize , req.addr );
281286
282- if (m_card)
283- {
284- const u32 size = req.bsize * req.blocks ;
285- const u64 address = GetAddressFromRequest (req.arg );
287+ const u32 size = req.bsize * req.blocks ;
288+ const u64 address = GetAddressFromRequest (req.arg );
286289
287- if (!m_card.Seek (address, File::SeekOrigin::Begin))
288- ERROR_LOG_FMT (IOS_SD, " Seek failed" );
290+ if (!m_card.Seek (address, File::SeekOrigin::Begin))
291+ ERROR_LOG_FMT (IOS_SD, " Seek failed" );
289292
290- if (m_card.ReadBytes (memory.GetPointerForRange (req.addr , size), size))
291- {
292- DEBUG_LOG_FMT (IOS_SD, " Outbuffer size {} got {}" , rw_buffer_size, size);
293- }
294- else
295- {
296- ERROR_LOG_FMT (IOS_SD, " Read Failed - error: {}, eof: {}" , std::ferror (m_card.GetHandle ()),
297- std::feof (m_card.GetHandle ()));
298- ret = RET_FAIL;
299- }
293+ if (m_card.ReadBytes (memory.GetPointerForRange (req.addr , size), size))
294+ {
295+ DEBUG_LOG_FMT (IOS_SD, " Outbuffer size {} got {}" , rw_buffer_size, size);
296+ }
297+ else
298+ {
299+ ERROR_LOG_FMT (IOS_SD, " Read Failed - error: {}, eof: {}" , std::ferror (m_card.GetHandle ()),
300+ std::feof (m_card.GetHandle ()));
301+ ret = RET_FAIL;
300302 }
301303 }
302304 memory.Write_U32 (0x900 , buffer_out);
@@ -309,7 +311,12 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
309311 INFO_LOG_FMT (IOS_SD, " {}Write {} Block(s) from {:#010x} bsize {} to offset {:#010x}!" ,
310312 req.isDMA ? " DMA " : " " , req.blocks , req.addr , req.bsize , req.arg );
311313
312- if (m_card && Config::Get (Config::MAIN_ALLOW_SD_WRITES))
314+ if (!Config::Get (Config::MAIN_ALLOW_SD_WRITES))
315+ {
316+ ERROR_LOG_FMT (IOS_SD, " Write attempted while locked." );
317+ ret = RET_LOCKED;
318+ }
319+ else
313320 {
314321 const u32 size = req.bsize * req.blocks ;
315322 const u64 address = GetAddressFromRequest (req.arg );
@@ -465,34 +472,35 @@ std::optional<IPCReply> SDIOSlot0Device::SendCommand(const IOCtlRequest& request
465472IPCReply SDIOSlot0Device::GetStatus (const IOCtlRequest& request)
466473{
467474 // Since IOS does the SD initialization itself, we just say we're always initialized.
468- if (m_card)
475+ if (m_card. GetSize () <= SDSC_MAX_SIZE )
469476 {
470- if (m_card.GetSize () <= SDSC_MAX_SIZE)
471- {
472- // No further initialization required.
473- m_status |= CARD_INITIALIZED;
474- }
475- else
477+ // No further initialization required.
478+ m_status |= CARD_INITIALIZED;
479+ }
480+ else
481+ {
482+ // Some IOS versions support SDHC.
483+ // Others will work if they are manually initialized (SEND_IF_COND)
484+ if (m_sdhc_supported)
476485 {
477- // Some IOS versions support SDHC.
478- // Others will work if they are manually initialized (SEND_IF_COND)
479- if (m_sdhc_supported)
480- {
481- // All of the initialization is done internally by IOS, so we get to skip some steps.
482- InitSDHC ();
483- }
484- m_status |= CARD_SDHC;
486+ // All of the initialization is done internally by IOS, so we get to skip some steps.
487+ InitSDHC ();
485488 }
489+ m_status |= CARD_SDHC;
486490 }
487491
488492 // Evaluate whether a card is currently inserted (config value).
489493 // Make sure we don't modify m_status so we don't lose track of whether the card is SDHC.
490494 const bool sd_card_inserted = Config::Get (Config::MAIN_WII_SD_CARD);
491- const u32 status = sd_card_inserted ? (m_status | CARD_INSERTED) : CARD_NOT_EXIST;
495+ const bool sd_card_locked = !Config::Get (Config::MAIN_ALLOW_SD_WRITES);
496+ const u32 status = sd_card_inserted ?
497+ (m_status | CARD_INSERTED | (sd_card_locked ? CARD_LOCKED : 0 )) :
498+ CARD_NOT_EXIST;
492499
493- INFO_LOG_FMT (IOS_SD, " IOCTL_GETSTATUS. Replying that {} card is {}{}" ,
500+ INFO_LOG_FMT (IOS_SD, " IOCTL_GETSTATUS. Replying that {} card is {}{}{} " ,
494501 (status & CARD_SDHC) ? " SDHC" : " SD" ,
495502 (status & CARD_INSERTED) ? " inserted" : " not present" ,
503+ (status & CARD_LOCKED) ? " and locked" : " " ,
496504 (status & CARD_INITIALIZED) ? " and initialized" : " " );
497505
498506 auto & system = GetSystem ();
@@ -543,9 +551,8 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv1() const
543551{
544552 u64 size = m_card.GetSize ();
545553
546- // 2048 bytes/sector
547- // We could make this dynamic to support a wider range of file sizes
548- constexpr u32 read_bl_len = 11 ;
554+ // 512 bytes/sector. A 2GB card should only ever have to bump this up to 10
555+ u32 read_bl_len = 9 ;
549556
550557 // size = (c_size + 1) * (1 << (2 + c_size_mult + read_bl_len))
551558 u32 c_size_mult = 0 ;
@@ -554,7 +561,7 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv1() const
554561 {
555562 invalid_size |= size & 1 ;
556563 size >>= 1 ;
557- if (++c_size_mult >= 8 + 2 + read_bl_len)
564+ if (++c_size_mult > 7 + 2 + read_bl_len && ++read_bl_len > 15 )
558565 {
559566 ERROR_LOG_FMT (IOS_SD, " SD Card is too big!" );
560567 // Set max values
@@ -567,9 +574,14 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv1() const
567574 const u32 c_size (size);
568575
569576 if (invalid_size)
577+ {
570578 WARN_LOG_FMT (IOS_SD, " SD Card size is invalid" );
579+ }
571580 else
572- INFO_LOG_FMT (IOS_SD, " SD C_SIZE = {}, C_SIZE_MULT = {}" , c_size, c_size_mult);
581+ {
582+ INFO_LOG_FMT (IOS_SD, " SD C_SIZE = {}, C_SIZE_MULT = {}, READ_BL_LEN = {}" , c_size, c_size_mult,
583+ read_bl_len);
584+ }
573585
574586 // 0b00 CSD_STRUCTURE (SDv1)
575587 // 0b000000 reserved
@@ -578,7 +590,7 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv1() const
578590 // 0b00110010 TRAN_SPEED (2.5 * 10 Mbit/s, max operating frequency)
579591
580592 // 0b010110110101 CCC
581- // 0b1111 READ_BL_LEN (2048 bytes)
593+ // 0b???? READ_BL_LEN
582594 // 0b1 READ_BL_PARTIAL
583595 // 0b0 WRITE_BL_MISALIGN
584596 // 0b0 READ_BLK_MISALIGN
@@ -599,7 +611,7 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv1() const
599611 // 0b0 WP_GRP_ENABLE (no write protection)
600612 // 0b00 reserved
601613 // 0b001 R2W_FACTOR (write half as fast as read)
602- // 0b1111 WRITE_BL_LEN (= READ_BL_LEN)
614+ // 0b???? WRITE_BL_LEN (= READ_BL_LEN)
603615 // 0b0 WRITE_BL_PARTIAL (no partial block writes)
604616 // 0b00000 reserved
605617 // 0b0 FILE_FORMAT_GRP (default)
@@ -612,14 +624,16 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv1() const
612624 // 0b1 reserved
613625
614626 // TODO: CRC7 (but so far it looks like nobody is actually verifying this)
615- constexpr u32 crc = 0 ;
627+ // constexpr u32 crc = 0; // The CRC doesn't seem to be sent any at all.
628+ // Additionally, the entire response seems to be shifted to the right by 8 bits. Or the entire CSD
629+ // was sent in reverse and IOS is only flipping the endianness of the four words.... It's weird.
616630
617631 // Form the csd using the description above
618632 return {{
619- 0x007f003 ,
620- 0x5b5f8000 | (c_size >> 2 ),
621- 0x3ffc7f80 | (c_size << 30 ) | (c_size_mult << 15 ),
622- 0x07c04001 | (crc << 1 ),
633+ 0x000007f0 ,
634+ 0x035b5080 | (read_bl_len << 8 ) | ( c_size >> 10 ),
635+ 0x003ffc7f | (c_size << 22 ) | (c_size_mult << 7 ),
636+ 0x80040040 | (read_bl_len << 18 ),
623637 }};
624638}
625639
@@ -668,15 +682,16 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv2() const
668682 // 0b0000000 CRC
669683 // 0b1 reserved
670684
671- // TODO: CRC7 (but so far it looks like nobody is actually verifying this)
672- constexpr u32 crc = 0 ;
685+ // TODO: CRC7 (but so far it looks like nobody is actually verifying this) // See GetCSDv1 notes
686+ // on this
687+ // constexpr u32 crc = 0;
673688
674689 // Form the csd using the description above
675690 return {{
676- 0x400e005a ,
677- 0x5f590000 | (c_size >> 16 ) ,
678- 0x00007f80 | (c_size << 16 ),
679- 0x0a400001 | (crc << 1 ) ,
691+ 0x00400e00 ,
692+ 0x5a5f5900 ,
693+ 0x0000007f | (c_size << 8 ),
694+ 0x800a4000 ,
680695 }};
681696}
682697
0 commit comments