User Tools

Site Tools


notes:flashcart:r4ds

This is an old revision of the document!


R4 (NDS) programming

Original research provided mostly by lifehackerhansol.

Control flags

  • KEY1 gap1 length: 0
  • KEY1 gap2 length: 24
  • KEY2 encryption: Enabled for data and commands
  • Transfer clock rate: 6.7 MHz
  • Data block size: 4 bytes (512 bytes for SD commands)

Commands

Get card status (B0 ?? ?? ?? ?? ?? ?? ??)

31                 bit                 0
 ???? ???? ???? ???? ???? ???m mmmm msss
                             | |||| ||||
                             | |||| |+++- Initialization status:
                             | |||| |      0 - (in progress)
                             | |||| |      1 - SD/TF card not found
                             | |||| |      2 - SD/TF card read error
                             | |||| |      3 - could not find _DS_MENU.DAT
                             | |||| |      4 - success
                             +-++++-+---- Model:
                                           0x3A - M3DS Simply
                                           0x3E - R4 Revolution for DS

Save read request (B2 sd sc sb sa ?? ?? ??)

SD read request, but using the “save” FAT entry table.

Save read data (B3 ?? ?? ?? ?? ?? ?? ??)

SD read data, but using the “save” FAT entry table.

Set FAT table entry (B4 sd sc sb sa 00 00 00)

  • (MSB) sd sc sb sa (LSB) - as follows:
31                 bit                 0
 ssss ssss ssss ssss ssss ssss sss? ???t
 |||| |||| |||| |||| |||| |||| |||     |
 |||| |||| |||| |||| |||| |||| |||     +- Type:
 |||| |||| |||| |||| |||| |||| |||         0 - ROM
 |||| |||| |||| |||| |||| |||| |||         1 - Save
 ++++-++++-++++-++++-++++-++++-+++------- Directory table address
                                           (aligned to 0x20 per FAT spec)

ROM read request (B6 sd sc sb sa 00 00 00)

SD read request, but using the “ROM” FAT entry table.

Points to _DS_MENU.DAT on initialization.

ROM read data (B7 ?? ?? ?? ?? ?? ?? ??)

SD read data, but using the “ROM” FAT entry table.

? Get card ID ? (B8 ?? ?? ?? ?? ?? ?? ??)

SD read request (B9 sd sc sb sa 00 00 00)

  • (MSB) sd sc sb sa (LSB) - sector address, in bytes

Returns zero when data is ready to access, non-zero if ongoing.

SD read data (BA 00 00 00 00 00 00 00)

Returns the 512 bytes read via the “SD read start” command.

SD write start (BB sd sc sb sa 00 00 00)

  • (MSB) sd sc sb sa (LSB) - sector address, in bytes

Followed by 512 bytes of SD card data.

SD write status (BC sd sc sb sa 00 00 00)

  • (MSB) sd sc sb sa (LSB) - sector address, in bytes

Returns zero if done, non-zero if ongoing.

Save write start (BD sd sc sb sa 00 00 00)

SD write start, but using the “save” FAT entry table.

Save write status (BE sd sc sb sa 00 00 00)

SD write status, but using the “save” FAT entry table.

ROM read decrypted data (BF ?? ?? ?? ?? ?? ?? ??)

Same as SD read data, but applying a XOR-based obfuscation algorithm to the buffer's contents.

This is used by the stage 1 loader to decrypt _DS_MENU.DAT.

The algorithm was initially discovered by Yasu in 2007, and example source code is provided as follows, where key is a 16-bit constant:

uint8_t[512] in;
uint8_t[512] out;
uint16_t key1 = key ^ currentSector;
    
for (int i = 0; i < 512; i++)
{
    // Derive key2 from key1.
    uint8_t key2 = ((key1 >> 7) & 0x80)
        | ((key1 >> 6) & 0x60)
        | ((key1 >> 5) & 0x10)
        | ((key1 >> 4) & 0x0C)
        | (key1 & 0x03);
        
    // Decrypt byte.
    dest[i] = src[i] ^ key2;

    // Derive next key1 from key2.
    uint16_t tmp = ((src[i] << 8) ^ key1);
    uint16_t tmpXor = 0;
    for (int ii = 0; ii < 16; ii++)
        tmpXor ^= (tmp >> ii);

    uint16_t newKey1 = 0;
    newKey1 |= ((tmpXor & 0x80) | (tmp & 0x7C)) << 8;
    newKey1 |= ((tmp ^ (tmpXor >> 14)) << 8) & 0x0300;
    newKey1 |= (((tmp >> 1) ^ tmp) >> 6) & 0xFC;
    newKey1 |= ((tmp ^ (tmpXor >> 1)) >> 8) & 0x03;

    key1 = newKey1;
}
notes/flashcart/r4ds.1697466403.txt.gz · Last modified: 2023/10/16 14:26 by asie