-
Notifications
You must be signed in to change notification settings - Fork 6
Original R4 and M3 Simply
This page documents the extra card commands supported by the original R4, as well as the 1:1 clone, M3 DS Simply (herein OG R4). This page was written in collaboration between Gericom and lifehackerhansol.
Note that the OG R4 only supported non-HC SD cards. As such the commands can only address up to 4GB on a SD card.
All extra card commands for the R4 are for game mode and use the scrambler for both command and data as is usual for game mode commands. Write data (not command) send from the DS to the card appears never to be scrambled by the DS card hardware, although the scrambler state itself does advance.
It appears that all R4 commands use 0 cycles of initial latency (L1) and 24 cycles of page latency (L2), with the 6.7 MHz clock.
Card ID commands are not patched and use the timings from the retail game ROM header, but without L1 latency (that's what the SDK does). Those can be as fast as a single cycle of L2 latency, depending on the game.
Failing to respond to card ID reads will trigger a card pull-out response in retail games. The card ID should never be adapted to the retail game being played and should stay equal to the one that the console received the very first time at boot in normal mode. The actual value of the card ID does not seem to matter much, as long as bit 31 reflects the protocol version that should be used.
Below are a list of commands in u64. From left to right is REG_CARD_COMMAND[0]
to REG_CARD_COMMAND[7]
as defined in libnds.
-
0000000000000000
- No idea what it does, sending back
0x00000000
works.
- No idea what it does, sending back
-
B000000000000000
- Get card info. Normally returns
0x000001F4
.
- The DLDI driver checks for
returnValue & 7 == 4
in theisInserted
function.
- Get card info. Normally returns
-
B2XXXXXXXX000000
- Start save read at address
0xXXXXXXXX
.
- Address should most likely be 512 byte aligned. Returns
0x00000001
while the card is busy performing the read and0x00000000
once the data is available. This command is polled as long as the return value is 1.
- Start save read at address
-
B3XXXXXXXX000000
- Get save data at address
0xXXXXXXXX
that was previously requested by commandB2
.
- Not sure if the address is actually used by the card or can be any dummy value. Returns the 512 byte block of save data.
- Get save data at address
-
B4XXXXXXXX000000
- Sets the address (
0xXXXXXXXX
) of the FAT entry for ROM (lsb of address is 0) or save (lsb of address is 1).
- This is a 2-byte aligned SD address. Returns
0x00000001
while the card is busy initializing the cluster map and0x00000000
once ready. This command is polled as long as the return value is 1.
- Sets the address (
-
B6XXXXXXXX000000
- Start ROM read at address
0xXXXXXXXX
.
- Address should be 512 byte aligned. Returns
0x00000001
while the card is busy performing the read and0x00000000
once the data is available. This command is polled as long as the return value is 1. The data can then be read with the standardB7
command.
- Start ROM read at address
-
B9XXXXXXXX000000
- Start SD read at address
0xXXXXXXXX
.
- Address is in bytes, but should be 512 byte aligned. Returns
0x00000001
while the card is busy performing the read and0x00000000
once the data is available. This command is polled as long as the return value is 1.
- Start SD read at address
-
BA00000000000000
- Get SD data that was previously requested by command
B9
.
- Returns the 512 byte block of SD data.
- Get SD data that was previously requested by command
-
BBXXXXXXXX000000
- Start SD write to address
0xXXXXXXXX
.
- Address is in bytes, but should be 512 byte aligned. The command expects 512 bytes of data that will be written to the SD card.
- Start SD write to address
-
BCXXXXXXXX000000
- Get SD write status for address
0xXXXXXXXX
previously requested by commandBC
.
- Returns
0x00000001
while the card is busy performing the write and0x00000000
once done. This command is polled as long as the return value is 1.
- Without sending the address, the SD card corrupts.
- Get SD write status for address
-
BDXXXXXXXX000000
- Start save write to address
0xXXXXXXXX
.
- Address should most likely be 512 byte aligned. The command expects 512 bytes of data that will be written to the save.
- Start save write to address
-
BEXXXXXXXX000000
- Get save write status.
- Not sure if the address is actually used by the card or can be any dummy value. Returns
0x00000001
while the card is busy performing the write and0x00000000
once done. This command is polled as long as the return value is 1.
-
BF00000000000000
- Read R4-obfuscated data. Same as ROM read data, and thus needs 0xB4 and 0xB6 respectively.
- A writeup of the obfuscation mechanism was done by asiekierka
- This is used by the stage 1 loader to decrypt _DS_MENU.DAT.
When initializing the R4 for retail ROM use it seems there are some 0000000000000000
dummy commands send. Not sure if that is actually needed to make it work.
After that B4
is used to initialize the cluster map for ROM and save file. The save file should have already been created on the SD card by the software on the DS side. The retail game is patched by the DS side software to perform ROM reads using the requesting mechanism (B6
/B7
) and to perform save reads and writes using the corresponding card commands (B2
/B3
and BD
/BE
) instead of SPI.
The advantage of the requesting/feedback mechanism for ROM reads is that the data can be read as soon as it is ready. SD cards can have varying read latency and without a feedback mechanism you'd always have to account for the worst case, which can be more than the maximum amount of latency that can be specified in the IO registers and would be awful for the performance.