Skip to content

Instantly share code, notes, and snippets.

@wwylele
Created July 26, 2018 16:13
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save wwylele/29a8caa6f5e5a7d88a00bedae90472ed to your computer and use it in GitHub Desktop.
Save wwylele/29a8caa6f5e5a7d88a00bedae90472ed to your computer and use it in GitHub Desktop.
WIP 3DS CEC doc

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 ID
  • CecDataPathType is an enum refering to a specific file / folder in the system save. See TODO for the meaning of each value
  • FileOption 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>
    ...

File MBoxList____

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.

File MBoxInfo____

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.

File MBoxData.<3-digit number>

File MBoxData.001

Icon

File MBoxData.010

This is the game title in null-terminated UTF-16 string.

File MBoxData.050

This is 8-byte file containing the title ID.

File BoxInfo_____

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

File _<12-char ID>

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?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment