-
Notifications
You must be signed in to change notification settings - Fork 6
SuperCard DSONE SDHC & DSTT
This page documents a subset of extra card commands found in the DSTT, as well as the SuperCard DSONE SDHC's SD code, herein DSTT and DSONE, respectively. This page was written by lifehackerhansol, based on original research as well as BSD-3-Clause licensed code from SuperCard team and Cluny.
Below are a list of commands found in the DSONE's FOSS driver in u64, as follows:
XXXXXXXX XXXXXXXX
Each two digits, from left to right, is REG_CARD_COMMAND[0]
to REG_CARD_COMMAND[7]
as defined in libnds.
Lowercase x
will imply that this is unused. Any others are explained.
- Seems to read from the device's PSRAM? Not confirmed.
70aaaaaa aaxxxxxx
-
aaaaaaaa
= u32 address (highest bit to lowest bit) - The only known use case of this command is to check whether the DSONE has an SD or SDHC inserted, by passing the address 0x7fa00-0x20.
- This will be important later: When SD, address must be
<<9
. When SDHC, address is verbatim.
- This will be important later: When SD, address must be
- This command seems to always return 1 on the DSTT, according to Taiju Yamada. // likely because there is no PSRAM to be found here
- Instead, DSTT's bootloader writes 1/0 to 0x027FFC24 in main RAM. Very reliable, thank you DSTT team.
This cart uses SDIO. The following commands are SDIO-specific.
Note that reading data from the SD card is handled separately: consider Read-specific commands section down this page.
Some more commands are necessary for writing data to the SD card; consider Write-specific commands section down this page.
51aaaaaa aabbccxx
- SDIO send command
- aaaaaaaa: argument
- bb: SDIO CMD index
- cc: SDIO response
50xxxxxx xxxxxxxx
- Check if the SDIO is busy. CARD_BUSY / CARD_DATA_READY wasn't enough, it seems.
- Returns 0 if false, non-0 if true. It is recommended to loop 0x50 until this value returns 0.
52xxxxxx xxxxxxxx
- Reads SDIO response data from previously sent command.
- This response is delivered in big-endian.
These commands are specifically for reading from the SD.
53aaaaaa aaxxxxxx
-
aaaaaaaa
= u32 sector address (highest bit to lowest bit)- << 9 if non-SDHC
- This command initiates a single-page read: that is, it reads one 0x200 byte chunk.
54aaaaaa aaxxxxxx
-
aaaaaaaa
= u32 sector address (highest bit to lowest bit)- << 9 if non-SDHC
- This command initiates a sequential read: that is, it will read several 0x200 chunks with less delay than 0x53.
80xxxxxx xxxxxxxx
- This command appears to be a wait until the SD is ready to deliver a 0x200 byte chunk.
- This must be sent before every 0x200 chunk read.
81xxxxxx xxxxxxxx
- This command starts the 0x200 chunk read.
- In single-page reads, this is the last command sent.
- In sequential reads, after this command send CMD0 (for some reason) to read the next 0x200 byte, or CMD12 to end sequential read.
56xxxxxx xxxxxxxx
- This command ends any write. (not the same as CMD12 STOP_TRANSMISSION, it seems?)
- If this is a sequential write, make sure the command ran before this was CMD12! Otherwise the hardware will lock up!
- After sending this command, loop 0x50 to wait until hardware is idle.
82xxxxxx xxxxxxxx
- This command starts the 0x200 chunk write.
- From here a reverse cardPolledTransfer can be done; copy a u32 to REG_CARD_DATA_RD, wait for CARD_DATA_READY, loop until 0x200 complete
- After 0x200 bytes are written, loop 0x50 to wait for card ready, then send 0x56 command (detailed usage in its own command subbullet)
- In sequential writes, if the current 0x200 byte chunk is the last chunk, pass CMD12, then pass 0x56 command. Wait and flush both commands.
As you can see, very messy :). Let me know if this needs to be cleared up, because frankly this needs to be shown with actual code...
Free and open-source implemenations of the DSONE SD driver can be found on Chishm's website with the names scdssdhc
and scdssdhc1
. They are also archived in this repository. Both are licensed under BSD-3-Clause. However, these only implement single-page R/W, and this is VERY SLOW.
A bug is present in these drivers: the driver will attempt to save the SD/SDHC check to some place in RAM (rewritable!). Do not do this, just add a global boolean within the driver instead.
A Zlib-licensed implementation, without the above bug, exists in blocksds
directory of this repository, with the platform name scdssdhc
and ttio
. The difference between these two is that scdssdhc
will read the SDHC variable written to the PSRAM by the DSONE bootloader, while ttio
will perform a full SDIO init, as well as implement the necessary workarounds for model quirks (see below.)
- Timebomb clones
- For whatever reason, timebombed carts (r4i-sdhc.com, etc) cannot do both sequential read and single read. You can't do
if num_sectors > 1, then do sequential. else, do single
- Attempts to mix them have shown the cart to infinitely loop on command 0x80.
- To make a DSTT-universal driver, it is recommended to only use sequential reads for all reads.
- For whatever reason, timebombed carts (r4i-sdhc.com, etc) cannot do both sequential read and single read. You can't do
- Some initial R4iTT carts, r4i-gold.com Gold RTS, PK3DS(?)
- In all other cases, for 0x50/0x52/0x80/0x81/0x82 commands can be sent as is.
- However! The old SuperCard and DSTT implementation was to only rewrite the first byte of the card command register. Thus, if a user sent
51 ca fe ba be 00 00 00
, 0x50 and 0x52 commands would retainXX ca fe ba be 00 00 00
. - These carts (unconfirmed list) unfortunately rely on the behaviour of the old drivers; this means
50 00 00 00 00 00 00 00
is an invalid command. - To make a DSTT-universal driver, do not clear the rest of the registers, unless you are sending a brand-new command via 0x51/0x53/0x54.