notes:flashcart:r4ds
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
notes:flashcart:r4ds [2023/10/15 06:21] – asie | notes:flashcart:r4ds [2023/10/16 15:03] (current) – asie | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== R4 (NDS) programming ====== | ====== R4 (NDS) programming ====== | ||
- | Original research provided mostly by lifehackerhansol. | + | Original research provided mostly |
===== Control flags ===== | ===== Control flags ===== | ||
Line 13: | Line 13: | ||
===== Commands ===== | ===== Commands ===== | ||
- | ==== Get card information | + | ==== Get card status |
- | If bit 0-2 are equal to 0x4, the card is an R4. | + | < |
+ | 31 bit | ||
+ | ???? ???? ???? ???? ???? ???L LLml lsss | ||
+ | | |||| |||| | ||
+ | | |||| |+++- Initialization status: | ||
+ | | |||| | 0 - (in progress) | ||
+ | | |||| | 1 - SD/TF card not found | ||
+ | | |||| | | ||
+ | | |||| | 3 - could not find _DS_MENU.DAT | ||
+ | | |||| | 4 - success | ||
+ | | |||+-+---- Language: | ||
+ | | ||| 1 - Japanese | ||
+ | | ||| 2 - English | ||
+ | | ||| 3 - Chinese | ||
+ | | ||+------- Model: | ||
+ | | || 0 - M3DS Simply | ||
+ | | || 1 - R4 Revolution for DS | ||
+ | | ||
+ | | ||
+ | | ||
+ | 3:0? - Simplified Chinese | ||
+ | 3:1? - Traditional Chinese | ||
+ | </ | ||
- | ==== Save read request (B2 ?? ?? ?? ?? ?? ?? ??) ==== | + | ==== Save read request (B2 sd sc sb sa 00 00 00) ==== |
- | Possibly works the same as SD read request, but in save data space? | + | SD read request, but using the "save" FAT entry table. |
- | ==== Save read data (B3 ?? ?? ?? ?? ?? ?? ??) ==== | + | ==== Save read data (B3 00 00 00 00 00 00 00) ==== |
- | Possibly works the same as SD read data, but in save data space? | + | SD read data, but using the "save" FAT entry table. |
==== Set FAT table entry (B4 sd sc sb sa 00 00 00) ==== | ==== Set FAT table entry (B4 sd sc sb sa 00 00 00) ==== | ||
Line 40: | Line 62: | ||
</ | </ | ||
- | ==== ROM read request (B6 ?? ?? ?? ?? ?? ?? ??) ==== | + | ==== ROM read request (B6 sd sc sb sa 00 00 00) ==== |
- | Possibly works the same as SD read request, but in ROM space? | + | SD read request, but using the "ROM" FAT entry table. |
- | ==== ROM read data (B7 ad ac ab aa ?? ?? ??) ==== | + | Points to _DS_MENU.DAT on initialization. |
- | Possibly works the same as SD read data, but in ROM space? | + | ==== ROM read data (B7 00 00 00 00 00 00 00) ==== |
- | ==== ? Reset ? (B8 ?? ?? ?? ?? ?? ?? ??) ==== | + | SD read data, but using the " |
+ | |||
+ | ==== Get card ID (B8 00 00 00 00 00 00 00) ==== | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | > Card ID commands are not patched and use the timings from the retail game ROM header, but without L1 latency (that' | ||
==== SD read request (B9 sd sc sb sa 00 00 00) ==== | ==== SD read request (B9 sd sc sb sa 00 00 00) ==== | ||
Line 54: | Line 82: | ||
* (MSB) sd sc sb sa (LSB) - sector address, in bytes | * (MSB) sd sc sb sa (LSB) - sector address, in bytes | ||
- | Returns | + | Returns |
==== SD read data (BA 00 00 00 00 00 00 00) ==== | ==== SD read data (BA 00 00 00 00 00 00 00) ==== | ||
Line 70: | Line 98: | ||
* (MSB) sd sc sb sa (LSB) - sector address, in bytes | * (MSB) sd sc sb sa (LSB) - sector address, in bytes | ||
- | Returns | + | Returns |
- | ==== Save write start (BD ?? ?? ?? ?? ?? ?? ??) ==== | + | ==== Save write start (BD sd sc sb sa 00 00 00) ==== |
- | Possibly works the same as SD write start, but in save data space? | + | SD write start, but using the "save" FAT entry table. |
- | ==== Save write status (BE ?? ?? ?? ?? ?? ?? ??) ==== | + | ==== Save write status (BE sd sc sb sa 00 00 00) ==== |
- | Possibly works the same as SD write status, but in save data space? | + | SD write status, but using the "save" FAT entry table. |
- | ==== ? ROM read decrypted data ? (BF ?? ?? ?? ?? ?? ?? ??) ==== | + | ==== ROM read decrypted data (BF 00 00 00 00 00 00 00) ==== |
+ | |||
+ | Same as SD read data, but applying a XOR-based obfuscation algorithm to the buffer' | ||
+ | |||
+ | 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 '' | ||
+ | |||
+ | < | ||
+ | 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.1697350904.txt.gz · Last modified: 2023/10/15 06:21 by asie