3DS CEC (StreetPass) Documentation
Overall Model
The CEC system module consists of two main components: mailbox manager and StreetPass communicator. Both work on the system save 00010026, which stores all mailbox information and message data. A simplified diagram of CEC communication model is
Application <=> Mailbox Manager <=> System Save (Mailbox) <=> StreetPass communicator <=> NWM/network <=> StreetPass communicator of another 3DS <=> ...
Many CEC service (cecd:u
and cecd:s
) functions are interfaces exposed from the mailbox manager, which read and write the system save. The mailbox manager is essentially a thick layer over direct file IO, which performances data initialization and verification on top of raw system data read/write.
The StreetPass communicator runs in the background, fetches data from the system save, sends and receives messages, and put new messages in the system save. It only exposed a few interfaces to control its activity, some of which are misc functions in cecd:u
and cecd:s
, and others are in cecd:ndm
(which is ultimately exposed via NDM service ndm:u
).
Mailbox Manager Interfaces
The mailbox manager exposes the following functions via cecd:u
and cecd:s
[0x0001](Result, DataSize) Open(TitleID, CecDataPathType, FileOption, PID);
[0x0002](Result, DataSize) Read(DataSize, DataBuffer);
[0x0003](Result, DataSize) ReadMessage(TitleID, BoxType, MessageIDSize, DataSize, MessageIDBuffer, DataBuffer);
[0x0004](Result, DataSize) ReadMessageWithHmac(TitleID, BoxType, MessageIDSize, DataSize, MessageIDBuffer, HmacKeyBuffer, DataBuffer);
[0x0005](Result ) Write(DataSize, DataBuffer);
[0x0006](Result ) WriteMessage(TitleID, BoxType, MessageIDSize, DataSize, DataBuffer, MessageIDBuffer);
[0x0007](Result ) WriteMessageWithHmac(TitleID, BoxType, MessageIDSize, DataSize, DataBuffer, HmacKeyBuffer, MessageIDBuffer);
[0x0008](Result ) Delete(TitleID, CecDataPathType, BoxType, MessageIDSize, MessageIDBuffer);
[0x0011](Result ) OpenAndWriteFile(DataSize, TitleID, CecDataPathType, FileOption, PID, DataBuffer);
[0x0012](Result, DataSize) OpenAndReadFile(DataSize, TitleID, CecDataPathType, FileOption, PID, DataBuffer);
Function signature convention:
[Function Main ID](Reply list) Name(Param list)
The reply list and param list are ordered according to their apperance in the IPC command buffer. Each param/reply takes one word, except for:
PID
is the process ID descriptor and takes two words.xxxBuffer
is the mapped buffer descriptor and takes two words.
Some notes of different parameter types are listed below
TitleID
is a 32-bit ID as a mailbox identifier of a specific game. It is usually the same as game title IDCecDataPathType
is an enum refering to a specific file / folder in the system save. See TODO for the meaning of each valueFileOption
are bitfields (starting from bit0):- bit1: read
- bit2: write
- bit3: create folder
- bit4: skip some checks?
- bit30: ?
MessageIDSize
is always 8
CEC System Save (00010026) Format
Folder and files `CecDataPathType`
[Root]
├── eventlog.dat
└── CEC 10
├── MacFilter___
├── MBoxList____ 1
├── <8-digit ID> 11
│ ├── MBoxInfo____ 2
│ ├── MBoxData.001 101
│ ├── MBoxData.010 110
│ ├── MBoxData.050 150
│ ├── MBoxData.<3-digit number> 100 + <number>
│ ├── ...
│ ├── InBox___ 12
│ │ ├── BoxInfo_____ 3
│ │ ├── _<12-char ID> 6
│ │ └── ...
│ └── OutBox__ 13
│ ├── BoxInfo_____ 4
│ ├── OBIndex_____ 5
│ ├── _<12-char ID> 7
│ └── ...
├── <8-digit ID>
...
MBoxList____
File Offset | Length | Description |
---|---|---|
0x00 | 2 | Magic 0x6868 |
0x02 | 2 | Padding |
0x04 | 4 | Version? always 1 |
0x08 | 4 | Number of boxes |
0x0C | 16 * 24 | List of box name |
Each box name is 16-char long. However, due to the fact that box name is usually a 8-digit ID, the rest of 8 chars are always null characters. Unused box names are filled with null characters. |
MBoxInfo____
File Offset | Length | Description |
---|---|---|
0x00 | 2 | Magic 0x6363 |
0x02 | 2 | Padding |
0x04 | 4 | Title ID (matches the box directory name) |
0x08 | 4 | Private ID? |
0x0C | 1 | Flags? |
0x0D | 1 | Flags? |
0x0E | 2 | Padding |
0x10 | 32 | HMAC Key |
0x30 | 4 | Zero? |
0x34 | 12 | Timestamp when last accessed |
0x40 | 1 | Flag? |
0x41 | 1 | Flag? |
0x42 | 1 | Flag? |
0x43 | 1 | Flag? |
0x44 | 12 | Timestamp when last received |
0x50 | 16 | Zero? |
Note:
Private ID
seems to be a number chosen by application arbitrarily, possibly for verification. Magic numbers such as 0x00000000, 0x00000001, 0xFFFFFFFF, 0xAABBCCDD and other random numbers have been observed here.
MBoxData.<3-digit number>
File MBoxData.001
File Icon
MBoxData.010
File This is the game title in null-terminated UTF-16 string.
MBoxData.050
File This is 8-byte file containing the title ID.
BoxInfo_____
File This file consists of a 0x20-byte header, and an array of 0x70-byte entry. Each entry is a copy of the message header. See the next section for the message header format. The box info header format is
Offset | Length | Description |
---|---|---|
0x00 | 2 | Magic 0x6262 |
0x02 | 2 | Padding |
0x04 | 4 | Size of this file |
0x08 | 4 | Maximum box size |
0x0C | 4 | Current box size |
0x10 | 4 | Maximum message count |
0x14 | 4 | Current message count / the size of the following array |
0x18 | 4 | Maximum batch size |
0x1C | 4 | Maximum message size |
_<12-char ID>
File Each such file is a message. The ID in the file name is the message ID encoded in base-64. A message file consists of a 0x70-byte header, several extra header, a message body, and a 0x20-byte HMAC(?).
The header format is
Offset | Length | Description |
---|---|---|
0x00 | 2 | Magic 0x6060 |
0x02 | 2 | Padding |
0x04 | 4 | Message size |
0x08 | 4 | Header + extra headers size |
0x0C | 4 | Body size |
0x10 | 4 | Title ID |
0x14 | 4 | Title ID 2? |
0x18 | 4 | Batch ID |
0x1C | 4 | ? ID |
0x20 | 8 | Message ID |
0x28 | 4 | Message version? |
0x2C | 8 | Message ID 2? |
0x34 | 1 | Flags |
0x35 | 1 | Send method |
0x36 | 1 | Is unopen |
0x37 | 1 | Is new |
0x38 | 8 | Sender ID |
0x40 | 8 | Sender ID 2? |
0x48 | 12 | Timestamp when sent |
0x54 | 12 | Timestamp when received |
0x60 | 12 | Timestamp when created |
0x6C | 1 | Send count |
0x6D | 1 | Forward count |
0x6E | 2 | User data |
Each extra header has a format of
Offset | Length | Description |
---|---|---|
0x00 | 4 | Header type |
0x04 | 4 | Data size |
0x08 | Data size | Header data |
The header type can be one of the follows:
Value | Description |
---|---|
1 | ? |
2 | Icon |
3 | Game name |
4 | Info text |
5 | Region? |