The following library allows your application to automatically carry out wireless communication (background communication) in the background.
- StreetPass (CEC)
- SpotPass (BOSS)
- Presence feature (FRIENDS)
This chapter explains programming procedures and other information necessary to develop applications using each of these libraries.
Effect on Applications of Daemons Running in the Background
The term daemon refers to a resident module running in the background. 3DS includes several daemons performing network functions. The network daemon manager (ndm
) serves as a special daemon that integrates these daemons. An NDM library for controlling ndm
has been provided in the SDK.
Because the daemons run in a different CPU core than the one in which the application runs, the daemons never directly take up any application CPU time. However, because the application and the daemons both compete for network (wireless communication) access and NAND access, daemon execution does sometimes affect application performance. Applications can stop daemon execution using the NDM library if network and NAND access performance drops to a fatal level.
SpotPass stops while an application is running unless explicitly instructed otherwise. This does not affect either tasks while sleeping or immediate task execution.
Although daemons can be stopped freely, each plays a specific role and stopping one may limit overall operations. Before you stop a daemon, be sure you understand the possible consequences.
The following table shows the currently known effects of daemons on applications.
Daemon( |
Effect on the Network |
Effect on NAND |
---|---|---|
|
None. (This daemon does not use infrastructure communication.) |
Medium. (When a StreetPass connection is established, there is about 10 KB to 10 MB of NAND access.) |
|
High. (HTTP communications occur when the task executes.) |
High. (Data is written to NAND during task execution.) |
|
High. (HTTP communications occur when the task executes.) |
High. (Data is written to NAND during task execution.) |
|
Low. (UDP communications occur when disconnecting.) |
Low |
When controlling daemons, be sure to also read the information in the CTR-SDK API Reference.
4.1. StreetPass
StreetPass communication on the 3DS system represents improvements in features and ease of use over Chance Encounter Communication on the Nintendo DS.
Communication is performed in the background, allowing you to transmit data by simply passing the data without regard to the state of the running application. However, because this also means that an application cannot implement its own wireless communication processes, it may not be possible to build in certain specialized data transmission methods.
StreetPass requires that a EULA (End-User License Agreement) be set. To use the CEC library, set the Agree Version to a value of 1.0 or greater from EULA Settings in the Config
tool.
Communication via StreetPass cannot be carried out between a development CTR system (debugger or development system) and a retail CTR system.
4.1.1. Overview of Operations
When using StreetPass communication, the communication processes are handled by the StreetPass daemon (a resident process that runs in the background). StreetPass communication can occur if a StreetPass box has been created in the memory region set aside for the 3DS system and if StreetPass data exists in a StreetPass box. The StreetPass daemon automatically handles sending and receiving StreetPass data. The daemon encrypts data before sending it, so there is no need for individual applications to encrypt data.
There are 12 StreetPass boxes available in the system, with one application generally using one box exclusively. You must get the user’s approval before claiming one of the 12 StreetPass boxes to register data for StreetPass. You must get the user’s approval before claiming one of the 12 StreetPass boxes to register data for StreetPass. If all 12 StreetPass box memory slots are already in use, inform the user that the application cannot create its StreetPass settings, and that they must go to the StreetPass management screen in System Settings and delete unneeded StreetPass settings for another application. After the user has opened up at least one of the 12 available memory slots for StreetPass boxes, the application can create a new StreetPass box.
When shared use of one system is being made for multiple 3DS Game Cards of the same title, you must be careful with StreetPass that all processes are performed on the same StreetPass box.
Go to the StreetPass management screen in System Settings to check which applications have StreetPass boxes and delete boxes as needed. Deleting a StreetPass box also deletes any notifications in the notification list for that StreetPass box. You must implement your application such that it can continue running even if any data saved in a StreetPass box is deleted.
Within the StreetPass box, there is an inbox and an outbox, each allocated for received data and data to be transmitted.
When a CTR system with StreetPass activated first finds another system in the vicinity that is also activated, the StreetPass boxes in each system’s system memory are scanned. If the two systems both have a box created by the same application (in other words, the StreetPass IDs match), each system begins transmitting only the StreetPass data to be received or sent. If the StreetPass IDs are the same, communication is performed even if the system regions differ. If StreetPass data is being sent from multiple StreetPass boxes, data items are sent (according to size) starting with the smallest. The two systems will not necessarily stay within range of each other long enough to finish sending and receiving all StreetPass data. If the systems are within range for a short period of time, only the smallest data item may be successfully sent. Consequently, keep the size of the StreetPass data as small as possible to increase the chance of successful transmission. StreetPass data items that are part of a group are not sent individually.
You can specify that StreetPass data be receive-only, but note that two systems do not communicate via StreetPass if the boxes are both set to receive-only or send-only. This also applies to units configured to only send StreetPass data. Specifically, if the first registered data is receive-only or send-only, StreetPass exchange never occurs, no matter how much time passes.
The address used by a system for StreetPass communication is regenerated every eight hours and stored in the system’s address list. The interval for StreetPass communication between known communication partners, therefore, is four hours on average and may be up to eight hours. On a development system, you can clear the address list by calling the function to start StreetPass. A similar mechanism to filter addresses cannot be run on a commercial system, so data changes you make may not immediately take effect.
The system may enter a state while an application is running where StreetPass communication is difficult if connection target settings are registered or there is a surrounding Nintendo Zone. However, even under such conditions, StreetPass communication can be carried out by putting the system into Sleep Mode.
When confirming that StreetPass communication is occurring while an application is running, create an environment where connection target settings are canceled and there is nothing like a Nintendo Zone in the surroundings.
4.1.1.1. Conditions Related to StreetPass Communication
This section covers conditions for starting StreetPass communication, connecting with communication peers, sending StreetPass data, destroying StreetPass data, and turning on the notification LED.
Conditions for Starting StreetPass Communication
A search will not be made for peers and StreetPass communication will not start unless all of the following conditions are met.
- The system is in wireless-enabled mode.
- StreetPass communication has not been restricted by Parental Controls.
- The user has agreed to the EULA.
- A StreetPass box has been set up and there is StreetPass data with a possible send count of 1 or more.
Because the StreetPass daemon also searches for Nintendo Zone, daemon status may show as "scanning" even if the all of these conditions are not met.
Conditions for Connecting with Peers
Connection with a peer cannot be made unless all of the following conditions are met when two systems capable of starting StreetPass communication approach each other.
- The peer has a StreetPass box with the same StreetPass ID.
- The StreetPass data for both systems as arranged to be processed combine to form send/receive modes that allow communication.
- The address used for StreetPass communication with the peer has not been registered in the address filter (a list of addresses of peers with whom StreetPass communication has been performed).
- The peer has not been registered on the blocked-user list.
Addresses for StreetPass communication are regenerated every eight hours. Up to 255 such addresses can be registered in the address filter saved on a system. If a 256th address is registered, the earliest address in the filter is overwritten. In that case, regardless of the status of the StreetPass box, communication with a peer having the overwritten StreetPass address is impossible. StreetPass communication with this same peer remains impossible for an average of four hours and up to eight hours, even if you create a new StreetPass box.
Conditions for Sending StreetPass Data
After connection with a peer is established, the local host will not send StreetPass data to the peer unless data is exchanged beforehand and all of the following conditions have been met.
- The peer is a friend and communication settings include a flag for sending data only to friends. Or, the peer is not a friend and communication settings include a flag for sending data to peers other than friends.
- When StreetPass data has been sent, the data size and count in the peer’s inbox must not exceed the maximum limits allowed.
Even if these conditions are not met, if the send/receive mode is receive-only or send/receive, receipt of StreetPass data from the peer starts as long as the peer meets these conditions.
If send/receive with the peer cannot start because conditions are not met, the address used for StreetPass communication is registered in the address filter at this point. However, the address is not registered if the initial exchange of data conducted beforehand failed.
After data transmission has started, the address for StreetPass communication is registered in the address filter if transmission succeeds. The address is not registered if transmission fails.
Conditions for Destroying Data Received via StreetPass
If either of the following conditions is met, received StreetPass data is destroyed.
- The StreetPass data signature is incorrect.
- StreetPass data having the same message ID already exists in the inbox.
Conditions for Turning on the Notification LED
The notification LED illuminates green if StreetPass data has been received in one of the StreetPass boxes and has not been destroyed.
4.1.2. Initialization and Finalization
The application uses the CEC library for StreetPass. Initialize and finalize this library using the nn::cec::Initialize
and nn::cec::Finalize
functions.
static nn::Result nn::cec::Initialize(nn::fnd::IAllocator& cecAllocFunc); nn::Result nn::cec::Finalize();
Management of memory that the library uses during StreetPass must be performed by the application’s own memory allocator. The library allocates memory from the allocator passed to cecAllocFunc
of approximately twice the maximum size of the StreetPass data, for data processing and other purposes.
Calling Initialize
after already successfully initializing a StreetPass box returns an nn::cec::MakeResultAlreadyInitialized
error indicating that the box is already initialized.
4.1.3. StreetPass Box
Access StreetPass boxes via the nn::cec::MessageBox
class.
4.1.3.1. Start Accessing (Opening and Creating)
To start accessing a StreetPass box, first try opening a box to check whether one already exists. If one does exist, simply begin accessing it. If no box exists, create one. After it is created successfully, a StreetPass box is opened.
When a StreetPass box is opened, the StreetPass daemon stops executing. This status continues until the StreetPass box is closed. If the HOME Menu is displayed while a StreetPass box is open, communication via StreetPass does not occur because the daemon is in a stopped state. If the system enters Sleep Mode while the StreetPass box is open, the daemon resumes operations and returns to stopped status when the system wakes up. Even if StreetPass box contents are updated through StreetPass communication carried out during sleep, updated information is not reflected in the opened MessageBox
class. The box must be reopened to get the latest information. Because the result of accessing the StreetPass box is rolled back, there is a possibility that the result of processes for creating a StreetPass box or adding or deleting StreetPass data will be lost. We recommend that you close or commit open StreetPass boxes before displaying the HOME Menu or transitioning to Sleep Mode.
The creation of a StreetPass box and addition or deletion of StreetPass data is not reflected until the StreetPass box is closed or committed. We recommend that access to StreetPass boxes be carried out as an uninterrupted series of operations from open to close.
To learn whether real-time StreetPass communication has taken place, use GetCecEvent
. (For more information, see 4.1.6. Notifying on Communication Activation.) However, because communication stops each time the StreetPass box is opened, if the box is opened and closed at regular intervals, background communication does not take place.
nn::cec::TitleId nn::cec::MakeCecTitleId(bit32 id, bit8 variation = 0x0); nn::Result nn::cec::MessageBox::OpenMessageBox(const TitleId cecTitleId, const u32 privateId); nn::Result nn::cec::MessageBox::CreateMessageBox( const TitleId cecTitleId, const u32 privateId, const char* hmacKey, const void* icon, size_t iconSize, const wchar_t* name, size_t nameSize, size_t inboxSizeMax = CEC_INBOX_SIZE_DEFAULT, size_t outboxSizeMax = CEC_OUTBOX_SIZE_DEFAULT, size_t inboxMessNumMax = CEC_INBOX_MESSNUM_DEFAULT, size_t outboxMessNumMax = CEC_OUTBOX_MESSNUM_DEFAULT, size_t messageSizeMax = CEC_MESSSIZEMAX_DEFAULT);
cecTitleId
specifies the Nintendo-assigned value for identifying a game title (the StreetPass ID). The StreetPass ID is generated by calling nn::cec::MakeCecTitleId
with a unique 20-bit ID as an argument. This 20-bit ID is assigned by Nintendo. To share StreetPass with multiple titles, specify one of the unique StreetPass IDs as a representative value. The titles will share a single StreetPass box.
privateId
specifies the key value required to access a StreetPass box. Developers may choose this value freely. Depending on how this value is generated, access may be restricted to specific save data or to specific game cards.
A StreetPass box may only be opened if these two parameters specify the same values used when creating that StreetPass box. A "no data" error is returned if no StreetPass box exists for the specified StreetPass ID in the cecTitleId
value, and a "no access permissions" error is returned if a StreetPass box exists but the privateId
value differs.
hmacKey
specifies a 32-byte string used to prevent spoofing. Developers may choose this string freely. This value must be identical for both the sending and receiving units. In other words, applications using StreetPass for the same StreetPass ID must specify the same string value.
For the icon
parameter, specify the icon to display on the StreetPass management screen, and for iconSize
, specify the icon’s size. Icons must be 48×48 pixels in size using the RGB565 PICA native pixel format. You may usually use the game title icon, but for titles in a series, you may use a different icon that makes it clear that this title is part of that series.
For the name
parameter, specify the title to display on the StreetPass management screen, and for nameSize
, specify its length in bytes. Titles must be strings of up to 64 characters, including the terminating character However, the actual display length is equivalent to 17 characters of the internal fonts at maximum width (in Japan, European, U.S. regions: "%"; in other regions: Japanese hiragana characters, Chinese kanji characters, Hangul characters, and so on). The language of the title can be the same as the language configured in the CTR System settings, or as configured in the language settings of the application itself.
The inboxSizeMax
and outboxSizeMax
parameters specify the maximum size of the inbox and outbox. The total size of both boxes cannot exceed 1 MB. Unless propagating StreetPass data, the basic rule is to allocate a substantial size for the inbox. If no values are specified for these parameters, the default size is 512 KB.
The inboxMessNumMax
and outboxMessNumMax
parameters specify the maximum number of messages that can be saved to the inbox and outbox. Specify the value derived by dividing the box capacity by the size of the largest StreetPass message. If no values are specified for these parameters, the default value is 99.
messageSizeMax
specifies the maximum size of a StreetPass message. No StreetPass data larger than the specified value may be saved. In general, omit this argument to use the default value of 100 KB. The maximum size of StreetPass data is fixed at 100 KB on the current CTR-SDK, regardless of the value specified for messageSizeMax
.
The following table lists errors that can be returned by the nn::cec::MessageBox::OpenMessageBox
function, and how to resolve them.
Error |
Cause and Resolution |
---|---|
|
No StreetPass box exists. Create a StreetPass box and reopen. |
|
The StreetPass box cannot be opened because the |
|
This error is not returned unless there has been access from multiple threads. The StreetPass box can be opened by waiting awhile and retrying. |
Any other errors |
If an error not in this table is returned, function execution is treated as having failed. The application must be allowed to advance without using this function. If this function is required for the application to advance, this error may be displayed as a fatal error. |
The following table lists errors that can be returned by the nn::cec::MessageBox::CreateMessageBox
function, and how to resolve them.
Error |
Cause and Resolution |
---|---|
|
A StreetPass box having the same If the |
|
There are already twelve StreetPass boxes. A new box cannot be created. Instruct the user to delete an unneeded StreetPass box on the StreetPass Management screen. |
|
This error is not returned unless there has been access from multiple threads. The StreetPass box can be opened by waiting awhile and retrying. |
|
An argument has been specified incorrectly. |
|
An icon or name has been specified incorrectly. |
Any other errors |
If an error not in this table is returned, function execution is treated as having failed. The application must be allowed to advance without using this function. If this function is required in order for the application to advance, this error may be displayed as a fatal error. |
4.1.3.2. Setting Related Data
You can change the icon and title displayed on the StreetPass Management screen. Open the StreetPass box and set the new icon and title as related data.
nn::Result nn::cec::MessageBox::SetMessageBoxData( u32 datatype, const void* data, size_t dataSize);
datatype
specifies the type of related data. If setting an icon, use the value nn::cec::BOXDATA_TYPE_ICON
, and if setting the title, use the value nn::cec::BOXDATA_TYPE_NAME_1
. Specify the starting address of the related data and its size in the data
and dataSize
parameters.
Icons must be 48×48 pixels in size using the RGB565 PICA native pixel format. You may usually use the game title icon, but for titles in a series, you may use a different icon that makes it clear that this title is part of that series.
Titles must be strings of up to 64 characters, including the string terminator. The actual display length is equivalent to 17 characters of the internal fonts at maximum width (in Japan, European, U.S. regions: "%"; in other regions: Japanese hiragana characters, Chinese kanji characters, Hangul characters, and so on). The language of the title can be the same as the language configured in the CTR System settings, or as configured in the language settings of the application itself.
4.1.3.3. Inbox and Outbox Information
You can get information about the inbox and outbox, such as the capacity or maximum number of messages specified at box creation, the currently used capacity, or the number of messages currently saved.
u32 nn::cec::MessageBox::GetBoxSizeMax(nn::cec::CecBoxType boxType) const; u32 nn::cec::MessageBox::GetBoxSize(nn::cec::CecBoxType boxType) const; u32 nn::cec::MessageBox::GetBoxMessageNumMax(nn::cec::CecBoxType boxType) const; u32 nn::cec::MessageBox::GetBoxMessageNum(nn::cec::CecBoxType boxType) const;
All of these functions can be used for either the inbox or outbox, specifying which one by passing an nn::cec::CecBoxType
enumerator as an argument. Specify CEC_BOXTYPE_INBOX
for the inbox and CEC_BOXTYPE_OUTBOX
for the outbox.
Use the GetBoxSizeMax
and GetBoxSize
functions to get the capacity and used capacity of the specified box.
Use the GetBoxMessageNumMax
and GetBoxMessageNum
functions to get the maximum number of StreetPass messages and the current number of saved messages for the specified box.
You can scan the data in a StreetPass box by constructing a loop over the number of messages currently saved in it, using the nn::cec::MessageBox
class’s GetMessageId
functions to get the message ID corresponding to the index.
nn::Result nn::cec::MessageBox::GetMessageId(MessageId* messId, const CecBoxType boxType, const u32 messIndex);
Call the ReadMessage
function passing the obtained message ID as an argument to get a StreetPass message, and then access that message via the nn::cec::Message
class.
u32 nn::cec::MessageBox::GetMessageSize(const CecBoxType boxType, const u32 messIndex) const; nn::Result nn::cec::MessageBox::ReadMessage( nn::cec::Message& cecMessage, void* buf, const size_t bufLen, const CecBoxType boxType, const MessageId& messageId);
cecMessage
takes an instance of the nn::cec::Message
class.
The buf
and bufLen
parameters must specify a buffer of the size returned by a call to GetMessageSize
, and the size, respectively. This is because the message is first read as a binary array, and then the information is set in the class instance passed in cecMessage
.
For more information about accessing StreetPass data via the nn::cec::Message
class, see 4.1.4.3. Getting Information.
4.1.3.4. Deleting
StreetPass boxes are a limited resource with only 12 available on the system. Be sure to delete boxes that contain no StreetPass data, or when users are not engaging in StreetPass to allow other applications to create StreetPass boxes.
nn::Result nn::cec::MessageBox::DeleteMessageBox(); nn::Result nn::cec::MessageBox::DeleteMessageBox(const TitleId cecTitleId);
cecTitleId
specifies the StreetPass ID of the StreetPass box to delete. If this parameter is omitted, the box currently opened by the nn::cec::MessageBox
class is deleted.
Do not delete StreetPass boxes other than created by the application.
Only delete StreetPass boxes with the specified StreetPass ID that can no longer be opened because they are broken.
4.1.3.5. Ending Access (Close and Commit)
After access to a StreetPass box has ended, the daemon must be returned to executing status. To restore execution status, call nn::cec::MessageBox::CloseMessageBox
to close an open StreetPass box.
void nn::cec::MessageBox::CloseMessageBox();
Changes to a StreetPass box are not written into save memory until they are committed. If an application exits before committing this data, content may rewind to data committed in the past. Call nn::cec::MessageBox::CommitMessageBox
to commit, but not that it is also committed when closing the StreetPass box.
nn::Result nn::cec::MessageBox::CommitMessageBox();
4.1.3.6. Relationship With the StreetPass Daemon
When a StreetPass box is opened by an application, the StreetPass daemon stops execution. If this happens during the execution of a daemon process, the process is canceled and any received data may be lost completely. StreetPass boxes can be safely accessed by using the nn::cec::CecControl::GetCecState
function to check if the daemon is busy (DAEMON_STATE_BUSY
) or communicating (DAEMON_STATE_COMMUNICATING
) before opening a StreetPass box.
4.1.3.7. StreetPass-Exclusive Mode (for Debugging Only)
You can set the system to use only StreetPass for background communication by using the following functions. Note that these are only to be used for debugging purposes.
static nn::Result nn::cec::CecControl::EnterExclusiveState(); static nn::Result nn::cec::CecControl::LeaveExclusiveState();
These functions produce an error when switching to StreetPass-exclusive mode if the system is either already using exclusive background communication or is carrying out local communication.
4.1.4. StreetPass Data
All access to StreetPass data is carried out via the nn::cec::Message
class.
4.1.4.1. Creating New Data
To create new StreetPass data, prepare an instance of the nn::cec::Message
class and call its NewMessage
member function.
nn::Result nn::cec::Message::NewMessage(TitleId cecTitleId, u32 groupId, u8 messageTypeFlag, u8 sendMode, u8 sendCount, u8 propagationCount); nn::Result nn::cec::Message::NewMessage(TitleId cecTitleId, u32 groupId, u8 messageTypeFlag, u8 sendMode, u8 sendCount, u8 propagationCount, const void* icon, size_t iconSize, const wchar_t* infoTextData, size_t infoTextSize);
cecTitleId
specifies the StreetPass ID specified when the StreetPass box was opened.
groupId
specifies the group number when grouping StreetPass data. Note that the total size for a single group cannot exceed the maximum size for a single transmission (100 KB). Specify 0 for this parameter to not group data and to send messages individually, even if a data group with a number of 0 actually exists.
messageTypeFlag
specifies a bitwise OR of flags indicating the recipients of the data. Using a combination of flags, you can restrict the StreetPass data to be sent only to friends or only to non-friends, or allow it to be sent to both. This setting makes it possible to send different StreetPass messages to friends and non-friends and, by registering StreetPass data with different flags in the same group, send additional comments to friends or otherwise control how data is sent. These flags are only considered when data is sent. You cannot make a user’s status as a friend (or not) a condition for receiving data.
Flag |
Description |
---|---|
Bitwise OR of the following two flags |
Set when sending without differentiating between friends and non-friends. This setting is the default, and it sends to everyone. |
|
Sends data only to communication partners who are not friends. Set this flag when sending different comments for friends and non-friends in the StreetPass data for the same group, or in similar situations. |
|
Sends data only to communication partners who are friends. Set this flag when adding comments to be sent just to friends included in the same group as StreetPass data to send to everyone, or in similar situations. |
If you specify only MESSAGE_TYPEFLAG_FRIEND
, make sure that the different StreetPass Relay process does not cause any problems for your application's specifications. For more information, see 9. Appendix: StreetPass Relay.
sendMode
specifies the transmission mode for controlling StreetPass data transmission. The combination of transmission modes for communication partners controls whether StreetPass data is sent and received during communication.
Transmission Mode |
Description |
---|---|
|
Receive only. Data is received when the communication partner is in send only or send/receive mode. We recommend not using this setting because it prevents StreetPass communication with peers who are using the same setting. StreetPass data is registered in the outbox. |
|
Send only. Data is sent when the communication partner is in receive only or send/receive mode. We recommend not using this setting because it prevents StreetPass communication with peers who are using the same setting. |
|
Send/receive. Data is sent when the communication partner is in receive only mode, received when the communication partner is in send only mode, and sent and received when the communication partner is in send/receive mode. Specify this mode for one-way communication (only sending or only receiving data), such as when users distribute their own creations, invitations to in-game houses, or similar situations. |
|
Exchange. Data is sent and received when the communication partner is also in exchange mode. StreetPass communication is not successfully established if either party cannot properly send and receive. Specify this mode when specific data must be exchanged, such as when swapping in-game pets or engaging in StreetPass matches. |
A (Row) |
Receive Only |
Send Only |
Send/Receive |
Exchange |
---|---|---|---|---|
Receive Only |
× |
A ← B |
A ← B |
× |
Send Only |
A → B |
× |
A → B |
× |
Send/Receive |
A → B |
A ← B |
A ⇔ B |
× |
Exchange |
× |
× |
× |
A ⇔ B |
There is no guarantee that StreetPass data has been successfully sent. Because grouping is performed even if the send/receive mode differs, use the same send/receive mode for data associated with the same group whenever possible, while making sure that the send/receive mode does not include receive only data.
When the transmission mode is Exchange, communications are only carried out between systems that are set to the same Exchange mode. If there is a mix of transmission modes set for the same StreetPass box, the probability of StreetPass occurrences will decline.
sendCount
specifies the number of times to send a StreetPass message. Specify MESSAGE_SENDCOUNT_UNLIMITED
to not limit the number of times a message can be sent. The sendCount
value is decremented by 1 every time a message is sent and sending stops when the counter reaches 0. The sendable count decrements at the point data is sent, regardless of whether data received by the receiver has been registered in the inbox. The value decrements when data is sent, and does not decrement when the communication peer is in send only mode, even if the local system is in send/receive mode. This value will also not decrement when the communication peer’s box is full and data cannot be sent, such as after reaching the maximum number of times a message can be received. However, data can still be received from this peer so long as there is room in the local inbox. The sendCount
value acts as a limit on the number of times data can be received when in receive only mode (CEC_SENDMOD_RECV
), decrementing by 1 every time data is received until reaching 0.
If the same StreetPass data is received, the newer StreetPass data is destroyed. Even if StreetPass data is destroyed, the sendCount
of the sender is decremented by one.
There is no guarantee that sent data will actually reach the communication peer. A power loss immediately after StreetPass communication is established and while in the middle of saving data or decrementing the sendCount
value can cause an irreconcilable inconsistency between the remaining sendCount
value and the number of data items received.
propagationCount
specifies the number of times a StreetPass message is propagated. This value is decremented by 1 every time the message is received, and a message with a propagation value of at least 1 is copied to the outbox after receipt. In other words, specify a value of at least 2 to propagate a StreetPass message. Note that received data can be saved in both the inbox and outbox, and that you may receive StreetPass data that you sent yourself, depending on the route through which it is propagated. The library imposes a restriction that either the sendCount
or propagationCount
parameters must be set to 1
to prevent the risk that a single StreetPass message could multiply exponentially.
If StreetPass data for which a propagation count has been set is received, and the same data already exists in the inbox, the data will not be propagated further because the new data is destroyed. Even if the data is received, and the same data does not already exist in the inbox, it will not be propagated if there is not enough capacity in the outbox. However, if the same data has already been received and copied to the outbox, propagation continues to update the propagation count and possible send count (which must be 1) to match the new data.
The NewMessage
function mainly sets the conditions for sending and receiving a message. However, other information such as the data to display in the notification (icon, text) and the actual data to send must also be set. To specify such additional information at the time of message creation, use the overloaded version of NewMessage
and specify values for the icon
, iconSize
, infoTextData
, and infoTextSize
parameters. The language configured for the description in infoTextData
can be the same as the language configured in the CTR System settings, or as configured in the language settings of the application itself. But text for only one language can be configured, so if the settings are different for the sender and receiver, the description could be displayed for the receiver in a language different from the receiver’s configured language.
Use the SetaExHeader
function to set the data to display in the notification as extended header information.
nn::Result nn::cec::Message::SetExHeader( const u32 exhType, const size_t exhLen, const void* exhBody);
exhType
specifies the type of extended header information.
Type |
Description |
---|---|
|
Icon. Its size must be 40×40 pixels using the RGB565 PICA native pixel format. |
|
Descriptive text. Up to two lines each having a width equal to 16 characters (in Japan, European, U.S. regions: "%"; in other regions: Japanese hiragana characters, Chinese kanji characters, Hangul characters, and so on) of the internal font at maximum width may be displayed. Maximum length of 128 characters, including newlines and the string terminator. Encoded as UTF16-LE. |
The exhBody
and exhLen
parameters specify the data for the extended header information and its size.
You can set the icon data by calling the SetIcon
function and set the descriptive text by calling the SetInfoText
function.
Set the data to send in a StreetPass message by calling the SetMessageBody
function.
nn::Result nn::cec::Message::SetMessageBody( const void* dataBody, const size_t size);
The dataBody
and size
parameters specify the data to send and its size. This size must be a multiple of 4.
The total size of the header information, extended header information, and data to send cannot exceed the maximum StreetPass data size specified when creating the StreetPass box (default size of 100 KB). The maximum size of send data is MESSAGE_BODY_SIZE_MAX
(96 KB). However, the larger the data size, the later a message is positioned in the StreetPass box sending queue and the longer the time required to send it, which may reduce the chances of successfully transmitting the message.
You do not need to configure receive-only StreetPass data with extended header information and data to send.
You can also call the SetTag
function to set an optional 16 bits of data. Use this as convenient, such as for a short message identifier that would be seen when accessing just a message header without reading the data portion.
4.1.4.2. Registering to the Outbox
After a StreetPass message is composed, it must be saved to the outbox using the WriteMessage
member function of the nn::cec::MessageBox
class.
nn::Result nn::cec::MessageBox::WriteMessage(const nn::cec::Message& cecMessage, const CecBoxType boxType, MessageId& messageIdOut);
cecMessage
specifies an instance of the nn::cec::Message
class representing the created StreetPass data.
boxType
usually specifies the outbox (CEC_BOXTYPE_OUTBOX
). Applications are not required to perform operations to specify the inbox.
messageIdOut
specifies the variable that the message ID is written to after the StreetPass data is saved by a call to this function.
A check for the EULA agreement is made when StreetPass data is saved, so the FS library must be initialized beforehand. The error ResultNotAgreeEula
is returned if the user has not agreed to the EULA, or if an icon file has not been set in the application. The error ResultParentalControlCec
is returned if StreetPass has been restricted by Parental Controls.
The maximum size of StreetPass data is fixed at 100 KB. An excessive size error (ResultMessTooLarge
) does not occur unless data exceeds 100 KB.
Order of Registering StreetPass Data in the Outbox and Processing It
A list is created in a StreetPass box in the same order that data was registered with the outbox. The data at the start of this list is generally processed first unless its allowable send count is 0, in which case the next data in the list (in order) is processed. The send/receive mode of the data to be processed determines whether it is actually sent and received. If data whose send/receive mode has been set to receive only is included in a group, that data is sent to the communicating peer. Be sure to place data so that groups are formed from data having the same send/receive mode.
If a nonzero group ID is set for the data to be processed and there is other data with the same group in the list, that data is processed together until either the end of the list is reached or the total data size reaches the maximum amount that can be sent in a single transmission. The data from the same group as at start is then moved to the end of the list, and the data at the start of the list is replaced. All data (processed or not) with the same group as this processed data have their sendCount
values decremented by 1.
When the group ID for the data to be processed is set to 0, only that data is processed. Any other data with a group ID of 0 is not treated as part of the same group. Only the processed data is appended to the end of the list, and the sendCount
value is decremented by 1.
When you register new StreetPass data, it is appended to the end of the list. Any received messages that have propagationCount
values of at least 1 after decrementing are appended to the end of the list (added to the outbox), with such messages received from other systems then being sent out at the next opportunity for StreetPass communication.
4.1.4.3. Getting Information
Get required information via the nn::cec::Message
class to access received data obtained by scanning the inbox.
u32 nn::cec::Message::GetBodySize() const; u32 nn::cec::Message::GetMessageBody(void* dataBody, size_t size) const; MessageId nn::cec::Message::GetMessageId_Pair(MessageId* messIdPair) const; u16 nn::cec::Message::GetTag() const;
Call the GetMessageBody
member function to get the sent data in the StreetPass message.
The dataBody
and size
parameters specify a buffer to store the sent data and the buffer size. Use the GetBodySize
function to get the required size of the buffer.
If the StreetPass message transmission mode was set to CEC_SENDMODE_EXCHANGE
, access data by getting the message ID of the data sent from the communication partner in the GetMessageId_Pair
function.
Use the GetTag
function to get the tag information in the StreetPass message.
4.1.4.4. Deleting
Sent or received StreetPass messages are not automatically deleted. The amount of data and number of messages that may be saved in the outbox or inbox is limited. An application must delete StreetPass messages that are no longer needed, such as data to send that has a sendCount
value of 0, or received data that has already been applied to the application. Delete messages using the DeleteMessage
member function of the nn::cec::MessageBox
class. To delete all StreetPass data in the StreetPass box, call the DeleteAllMessages
member function of the nn::cec::MessageBox
class.
nn::Result nn::cec::MessageBox::DeleteMessage( const CecBoxType boxType, const MessageId& messageId); nn::Result nn::cec::MessageBox::DeleteAllMessages(const CecBoxType boxType);
Specify the ID of the message to delete in the messageId
parameter, and the type of message box where the message is saved in the boxType
parameter.
If the StreetPass box holds two or more messages, and you want to delete all of them, it is faster to use DeleteAllMessages
than to delete them individually using DeleteMessage
.
4.1.5. Accessing Header Information
You can use the nn::cec::MessageBox
class to access just the header information for a StreetPass box or StreetPass message to extract limited information without having to open the data portion. Note that this class cannot be used to access the data to send, nor the extended header information.
Use the following member functions to get the StreetPass message total size and other information.
u32 nn::cec::MessageBox::GetMessageSize( const CecBoxType boxType, const u32 messIndex) const; u32 nn::cec::MessageBox::GetMessageBodySize( const CecBoxType boxType, const u32 messIndex) const; u32 nn::cec::MessageBox::GetMessageGroupId( const CecBoxType boxType, const u32 messIndex) const; u32 nn::cec::MessageBox::GetMessageSessionId( const CecBoxType boxType, const u32 messIndex) const; u8 nn::cec::MessageBox::GetMessageTypeFlag( const CecBoxType boxType, const u32 messIndex) const; u8 nn::cec::MessageBox::GetMessageSendMode( const CecBoxType boxType, const u32 messIndex) const; u8 nn::cec::MessageBox::GetMessageSendCount( const CecBoxType boxType, const u32 messIndex) const; u8 nn::cec::MessageBox::GetMessagePropagationCount( const CecBoxType boxType, const u32 messIndex) const; bit16 nn::cec::MessageBox::GetMessageTag( const CecBoxType boxType, const u32 messIndex) const; nn::fnd::DateTimeParameters nn::cec::MessageBox::GetMessageSendDate( const CecBoxType boxType, const u32 messIndex) const; nn::fnd::DateTimeParameters nn::cec::MessageBox::GetMessageRecvDate( const CecBoxType boxType, const u32 messIndex) const; nn::fnd::DateTimeParameters nn::cec::MessageBox::GetMessageCreateDate( const CecBoxType boxType, const u32 messIndex) const; MessageId nn::cec::MessageBox::GetMessageIdPair( const CecBoxType boxType, const u32 messIndex) const; nn::Result nn::cec::MessageBox::GetMessageIdPair( MessageId* messId, const CecBoxType boxType, const u32 messIndex) const; MessageId nn::cec::MessageBox::GetMessageId( const CecBoxType boxType, const u32 messIndex) const; nn::Result nn::cec::MessageBox::GetMessageId( MessageId* messId, const CecBoxType boxType, const u32 messIndex) const; u32 nn::cec::MessageBox::GetMessageIndex( CecBoxType boxType, const MessageId& messId) const; u32 nn::cec::MessageBox::GetMessageIndex(CecBoxType boxType, u8* messId) const;
4.1.6. Notifying on Communication Activation
You can receive a notification event indicating that the communication has been activated for StreetPass data. You can also get information about the most recent received data.
nn::Result nn::cec::GetCecEvent(nn::os::Event* event); nn::Result nn::cec::GetCecInfoBuffer( u32 cecTitleId, u8 pCecInfoBuffer[], size_t size);
For the nn::os::Event
class instance specified in the event
parameter, specify an instance that has not been initialized. Note that this event is signaled when the StreetPass box registered by an application that has obtained the event receives StreetPass data, and also when any StreetPass box registered by any other application receives StreetPass data or when StreetPass data was sent. Use this event for immediate notification on the reception of StreetPass data during background StreetPass communication while an application is running.
Call the nn::cec::GetCecInfoBuffer
function to get information about the most recent received data. This function stores information about the last StreetPass communication in the buffer specified by the pCecInfoBuffer
parameter. In general, call this function passing a value for cecTitleId
to determine whether data has been received in the local inbox after detecting communication activation by means of the previously mentioned Event
object. You can call this function without stopping the StreetPass daemon process.
The data is stored as a nn::cec::CecNotificationData
structure, so specify a buffer large enough to hold this structure in the pCecInfoBuffer
and size
parameters.
The num
member of the nn::cec::CecNotificationData
structure stores the number of information items in the structure. The count
member stores the number of instances of StreetPass communication activated since the system was last booted. The param
member stores information about the StreetPass data stored in the nn::cec::CecNotificationParam
structure at position num
from the start.
The recvDate
member of the nn::cec::CecNotificationParam
structure stores the date and time when the StreetPass data was received. The cecTitleId
member stores the StreetPass ID, and the messageId
member stores the StreetPass data’s message ID.
The messageId
member of the CecNotificationParam
structure stores the message ID of the latest StreetPass data received in that StreetPass box. However, even when you receive the grouped StreetPass data, information for only one data item is stored.
You must open the StreetPass box or take some similar action to actually access the received data.
4.1.7. Example of Sending and Receiving StreetPass Data
The following figure shows an example of how data would be sent and received if you passed two other users and multiple applications had registered StreetPass data in StreetPass boxes.
The blue lines show how data is sent, the red lines show how data is received, and the yellow boxes indicate the StreetPass data. The transmission mode for all of the StreetPass data is send/receive. Each StreetPass data item is given as a letter followed by: a number that represents a group, a hyphen and a letter that represents different data within the same group, and an asterisk and a number that represents the transmission count. The transmission counts on your system show the values that were registered along with the data. The transmission counts on the other users' systems show the values at the moment they passed by you.
Application A had been registered by both of the users you encountered, so its data was sent and received twice.
Application B had been registered by both of the users you encountered. The first user had a transmission count of 0, however, so data was only sent from your system. Both you and the second user did not have a transmission count of 0, so data was both sent and received.
Application C had been registered only by the first user you encountered, so its data was neither sent nor received.
Data for application D was both sent and received with the second user you encountered, but you each received different data because your next item to send was D1 and the other user's next item to send was D2.
4.1.8. Efficient Settings
Because 3DS communication via StreetPass is handled as a background process, there may be StreetPass opportunities unrelated to the application currently running. However, the StreetPass settings include many items that are complicated and need to be tweaked to efficiently send and receive StreetPass data. This section explains the settings related to sending and receiving data when an opportunity for StreetPass communication arises.
It also describes how to make effective use of the various settings. Features for a variety of purposes are provided by the library. To use these features, developers must constantly keep track of how often data is sent and received and between how many users.
4.1.8.1. Recommended Settings
Consider the normal case, where users select which data to exchange through StreetPass and register the data themselves. We recommend that you use the following settings so that it is easier for users to understand the results of StreetPass and to boost StreetPass transmission activity.
(1) Register only one data item.
You can avoid many of the restrictions inherent in the StreetPass specifications to make it more understandable to users.
If you want to register what seem to be many data items, first consolidate them into one item and register that item. Another way is to use grouping. If you do not use grouping and just register multiple items of data, only one data item ends up being sent and received in any one StreetPass.
(2) Set the transmission mode to Send/Receive.
When the transmission mode is set to Send/Receive, no opportunities will be lost because data is sent and received regardless of the state of either StreetPass inbox. Exchange mode has almost the same conditions for sending and receiving, but StreetPass is not established if there is no free space in either system’s inbox or in some other cases unless both parties succeed in communication. In other words, the party with free space available will miss the opportunity to receive StreetPass data.
When the mode is Send-only or Receive-only, StreetPass will not occur even though two systems set to the same mode encounter one another. When users can select either of these modes, they are likely to tend to choose one mode over the other, resulting in missed opportunities for sending and receiving StreetPass data.
(3) Put no limit on number of times data can be sent.
If StreetPass is always operating, there are no lost opportunities. It is easier for users to understand the StreetPass settings when registered data remain effective until deleted.
When a restriction is set, at some point the number of times that data can be sent will become 0, and the user may be unaware that distribution has ended. Because it is hard for a user to know when distribution has ended, other users will miss opportunities to receive StreetPass data when a user’s transmission count has reached 0.
(4) Send to both friends and non-friends.
If there are no restrictions on who to send data to, no StreetPass opportunities are lost.
While you might consider limiting sending to non-friends to increase opportunities with new people you happen to meet, data would no longer be exchanged with users with whom you have established friendships. Conversely, if you limit sending to only friends, your StreetPass can no longer be carried out with other regular users.
4.1.8.2. Registering Multiple Sets of Data
If you want to send multiple pieces of data to a single other user, we recommend not grouping them but rather packing them together into a single data item. By gathering the data this way instead of grouping, you can eliminate wasteful header information and reduce the overall size of the data.
When registering multiple pieces of data, you must note that only one item of data is sent at a time and that subsequent data items are not sent until the first has been sent. In other words, if the opportunity of StreetPass sending/receiving for the first data item is very low, subsequent data items will end up having to wait a long time for their turns.
The next StreetPass with the same other system will not occur until an average of 4 hours later, and the interval can be as long as 8 hours. For this reason, the second and subsequent data items will not reach that other system in series. If the user has registered multiple data items, the items that reach this other system depend on the items that were first in line on all occasions when the two systems made StreetPass encounters. Chance is a big factor, and the user may have trouble figuring out what’s going on.
4.1.8.3. Using the Send-Target Setting
You can configure the send targets to limit who gets sent the StreetPass data. Combining this setting with grouping, you can send different data to friends and to non-friends.
To provide a specific example, set the data at the start of a group as data to be shared by all send targets, and then add two more data items (one to be sent to friends and the other to be sent to non-friends). StreetPass transmits that first data item first. Configure it in the way that minimizes lost opportunities.
4.1.8.4. Using the Propagation-Count Setting
One interesting aspect of StreetPass is that data registered by a distant user may be received after passing through multiple other users. This occurs when the propagation count for StreetPass data has been set to more than one. However, propagation ceases if data is deleted during its propagation, there is not enough available space in the outbox, or if the same data has already been received. There is also a possibility that data registered by the user may not be sent immediately depending on the send order due to registration of another user's data in the outbox.
You can use propagated data when you only want to disseminate special data inside a certain region, such as special deliveries from limited users such as operators or when applications register data at a low probability.
There is no special setting for data that is being distributed as StreetPass data registered by the user. If grouping is used, you can send it together with data registered by the user.
Note that you need to register dummy data in a CTR system that is waiting for the arrival of propagating data if you are waiting to accept data being propagated without the user registering StreetPass data. For example, if an operator will be using this feature for special deliveries, set the operator side to send-only transmission mode, with a propagation count of 2 or more and a transmission count of 1, and set the side waiting for the propagating data to receive-only, with a propagation count of 1 and a transmission count of 1. This allows the registration of data being propagated to other users from operators and users encountered via StreetPass as an operator.
4.2. SpotPass
SpotPass is the name of a type of communication that uses the feature called BOSS (an acronym for "Background Online Service System"). Applications can use BOSS to handle background communication with Nintendo’s BOSS data servers.
An application uses BOSS by registering a task (which is a set of information describing the communication operations you want to perform) with BOSS and then starting the task. Tasks include data such as execution interval and the execution count (number of remaining times to execute the task). BOSS then runs tasks regularly in the background based on this data.
The term background in this case refers to Sleep Mode and HOME Menu display. In other words, it refers to states where the application is not running.
If the user has not accepted the EULA, tasks registered with BOSS will not run until the EULA has been accepted.
An application can find out whether a new data download task has finished by checking its task status, checking the task’s execution result, or using notifications for newly arrived data events. This data can also be read via BOSS.
The following tasks are currently available.
- Nintendo Archive Download (NADL) tasks (4.2.2. Nintendo Archive Download (NADL) Tasks)
- Data upload tasks (4.2.4. Data Upload Tasks)
- Data Store upload tasks (4.2.5. Data Store Upload Tasks)
- Data Store download tasks (4.2.6. Data Store Download Tasks)
Data upload tasks and Data Store upload/download tasks require a server environment to be set up. Contact Nintendo (support@noa.com) before using this in a product.
Tasks are generally run in the background, but an application can prompt BOSS to run a registered task at any time. Note that this causes the task to run in the foreground.
In addition, a dedicated task registration function is provided to perform foreground execution of these tasks (for example, registering the tasks and executing immediately while the application is running). This function registers tasks for immediate execution.
The following can be considered basic service examples of the use of BOSS.
- Regularly distributing notifications and extra data in the background (as NADL tasks)
- Distributing data that varies by region or company, using Nintendo Zone (as NADL tasks)
- Performing data exchanges between users in the background (as Data Store upload and download tasks)
4.2.1. Common Processes for All Tasks
This section describes common operations carried out for all task types.
Applications must carry out the following operations when using tasks.
- Initialize the BOSS library. (4.2.1.1. Initializing the BOSS Library)
- Prepare to register tasks. (4.2.1.2. Setting Task Properties and 4.2.1.3. Task Action Settings)
- Register and run tasks. (4.2.1.4. Registering and Running Tasks)
- Wait for tasks to complete. (4.2.1.5. Task Information and 4.2.1.6. Getting a Task List)
- Handle task results:
- Have the application handle the results (such as downloaded data).
- Change task registration information. (4.2.1.7. Changing a Task)
- Unregister tasks. (4.2.1.8. Unregistering a Task)
- Finalize the BOSS library. (4.2.1.9. Finalizing the BOSS Library)
In general, implement applications to follow these steps in the listed order.
4.2.1.1. Initializing the BOSS Library
You must first initialize the BOSS library by calling nn::boss::Initialize
before using any BOSS features.
nn::Result nn::boss::Initialize(void);
If you call the BOSS library functions before initializing the library, the functions return nn::boss::ResultIpcNotSessionInitialized
.
4.2.1.2. Setting Task Properties
Set task properties using three classes. Then call the nn::boss::RegisterTask
function, passing in the three configured class instances as arguments, to register one task with the BOSS daemon.
- Basic information (
nn::boss::Task
class) - Execution policy (
nn::boss::TaskPolicy
class) - Actions (
nn::boss::TaskAction
class)
There are restrictions on the property values that may actually be used by the application.
The following table lists the restrictions that apply when registering NADL tasks.
Property |
Restrictions on Valid Values |
---|---|
|
Use the task ID from your application to Nintendo. |
|
Use a value from 1 hour to 168 hours (one week). To pass Lotcheck, your application must not use the function version provided for debugging purposes that allows you to set the execution interval in seconds. |
|
Set an execution count from 1 to 100. |
|
Enter the default value ( Contact Nintendo (support@noa.com) if you need to set this to some other value. |
|
Enter the default value ( When resetting properties using the |
|
On normal tasks, do not set this to a value that provides access point information. Individual data specific to particular Nintendo Zone locations and retail outlets can be distributed by providing the access point information. If you are using an NADL task that provides access point information, contact Nintendo (support@noa.com) in the early planning stages. |
Basic Information (nn::boss::Task class)
The nn::boss::Task
class for setting the basic information of a task includes a property for the task ID. Create an instance of the nn::boss::Task
class and then call Initialize
to set the task ID.
class nn::boss::Task { nn::Result Initialize(const char* pTaskId); }
The task ID is a string of up to seven characters (not including the string terminator), and it can include uppercase and lowercase alphanumeric characters, the underscore, and the hyphen. This ID must be unique among all tasks belonging to the same application, so specify this value accordingly. Task IDs cannot be changed after they are assigned.
Be sure to apply to Nintendo (support@noa.com) for a task ID, and always use that approved task ID. If an unapproved task ID is set, the product will not pass Lotcheck.
Execution Policy (nn::boss::TaskPolicy class)
The nn::boss::TaskPolicy
class for setting a task’s execution policy includes properties for the task execution interval and execution count. Create an instance of the nn::boss::TaskPolicy
class and then call Initialize
to set these properties. These values can be changed after initialization. For more information about changing the execution interval and execution count, see 4.2.1.7. Changing a Task.
class nn::boss::TaskPolicy { nn::Result Initialize(u32 interval, u32 count); }
Specify the execution interval for the interval
parameter and the execution count for the count
parameter. Interval values are in hours and can be from 1 to 168 (or 7 days). Count values can be from 1 to 100. Do not set UNLIMITED_COUNT
as the count value. The count value is decremented every time the task is run. The task is no longer run after this value reaches 0.
The execution count is decremented whenever communication with the server completes and a response is received, regardless of whether that response indicates success or failure. It is not decremented if the connection is interrupted during task execution.
The CTR-SDK also includes the debugging-only function InitializeWithSecInterval
, allowing you to set the interval value in seconds. Note that any code setting this value in seconds will not pass Lotcheck.
Set and get all properties using the SetProperty
and GetProperty
member functions.
class nn::boss::TaskPolicy { nn::Result SetProperty(PropertyType type, void* pValue, size_t size); nn::Result GetProperty(PropertyType type, void* pValue, size_t size); }
Specify the property to set or get in the type
parameter. Specify a variable storing the property value for pValue
, and specify its size in size
.
Property ID |
Type |
Property |
---|---|---|
|
|
Execution interval (in seconds). |
|
|
Execution count. |
|
|
See the description following this table. |
The TASK_PERMISSION
property identifier is accessed to restrict operations when Internet communication with other users ("Online Interaction") is restricted by Parental Controls. If a task has nothing set for this property, the task does not execute if Online Interaction is restricted by Parental Controls.
NADL tasks do not involve the exchange of data between users, so TASK_PERMISSION_IN_PARENTAL_CONTROL
is added to the TASK_PERMISSION
identifier value by default. Consequently, leaving this value at the default ensures that NADL tasks will be processed even when Online Interaction is restricted by Parental Controls.
Any code in which the TASK_PERMISSION
property identifier is not set to TASK_PERMISSION_IN_PARENTAL CONTROL
in a NADL task will not pass Lotcheck. When you change the TASK_PERMISSION
identifier setting, you must include TASK_PERMISSION_IN_PARENTAL_CONTROL
.
Although the TASK_PERMISSION
property identifier can be used to set actions to perform when the EULA has not been accepted, make sure that tasks registered by the application do not perform actions when the EULA has not been accepted. If you register a task without setting actions, the task is not processed unless the EULA is accepted.
Actions (nn::boss::TaskAction Class)
Use the relevant class derived from nn::boss::TaskAction
to set properties related to the operations to be carried out. The following tasks are currently available.
Derived Class |
Task Type |
---|---|
|
Nintendo Archive Download (NADL) task |
|
Upload task |
|
Data Store upload task |
|
Data Store download task |
For more information about using tasks, and the valid property settings to use, see the individual task descriptions.
Upload tasks are provided on an individual basis. For this service, contact support@noa.com.
4.2.1.3. Task Action Settings
Settings can be performed for information provided when connecting to a server and certificates using the nn::boss::TaskAction
class, which perform settings specific to task actions.
class nn::boss::TaskAction { nn::Result SetApInfo(ApInfoType info); nn::Result SetCfgInfo(CfgInfoType info); nn::Result AddHeaderField(const char* pLabel, const char* pValue); nn::Result SetLastModifiedTime(const char* pLastModifiedTime); nn::Result SetRootCa(u32 inCaCertId); nn::Result SetClientCert(u32 inClientCertId); }
All properties of the nn::boss::TaskAction
class can be set and acquired using the SetProperty
and GetProperty
functions. These functions can be defined in the same way as the nn::boss::TaskPolicy
class definition.
Providing Access Point Information
Call the SetApInfo
function to specify information to be provided to an access point (AP) for an HTTP query. This allows you to select AP information to be sent from the Nintendo Zone access point to the BOSS data server, when infrastructure communication is occurring via a Nintendo Zone access point using AP information provided in the form of an HTTP request query. The query which is provided can be used only when you need to add changes to the task processing when connecting via the Nintendo Zone. One example would be downloading different data only when connecting to the Nintendo Zone.
Items with access point information provided do not pass through Lotcheck. If you are using tasks with access point information provided, be sure to contact support@noa.com early in the product planning process.
Query |
Information Provided |
---|---|
|
Information that can be identified at the access point group level (such as company name). |
|
Information that can be identified at the access point location level (such as state or prefecture). |
|
Information that can be identified at the access point level. |
Specify access point information to provide from the following definitions (select only one).
Definition |
Description |
---|---|
|
Provide Specify if applying to distribute according to Nintendo Zone operators. |
|
Provide Specify if applying to distribute according to Nintendo Zone area. |
|
Provide Specify if applying to distribute according to Nintendo Zone, other than according to Nintendo Zone operator or Nintendo Zone area. |
Providing System Settings Information
Call the SetCfgInfo
function to specify the provision of System Settings information to an HTTP query. This allows you to provide system information to a query from an HTTP request. This may be used (for example) for downloading different data using the language setting of a system connected to the client server.
This feature is specific to the BOSS service, using a client server. Providing System Settings information with a BOSS service, using a Nintendo server, has no effect.
If you are considering an independent server using the provided information, consult with Nintendo (support@noa.com).
The definitions listed below are used in specifying system information to be provided. Multiple information items can be granted simultaneously, by setting multiple values using a bitwise OR.
Definition |
Description |
---|---|
|
Do not provide System Settings information. |
|
Provide country code in System Settings information. |
|
Provide the language code in System Settings information. |
Adding an HTTP Request Header
You can include a proprietary HTTP request header in the connection, by calling the AddHeaderField
function. To add an HTTP request header, its label must have a maximum length of 32 characters and its value a maximum length of 256 characters. The maximum number of headers allowable is 3.
Specifying Final Update Time at the First Execution
Call the SetLastModifiedTime
function to specify the string value to enter in the If-Modified-Since header field for the first time the task is executed. When this specification is not performed, an If-Modified-Since header field is not provided the first time the task is executed. For the second execution and thereafter, an If-Modified-Since header field is provided containing the time of the last update for data acquired during the prior execution (the value in the HTTP response’s Last-Modified field). When executing, if the task does not result in acquiring the data due to its not having been updated (for example, if a "304 Not Modified" status is returned by the server), the execution count is reduced by 1.
In addition, properties setting functions specific to device-internal certificates may also be used. (These functions are inherited from the nn::boss::TaskAction
class.)
class nn::boss::TaskAction { nn::Result SetRootCa(u32 inCaCertId); nn::Result SetClientCert(u32 inClientCertId); }
You can configure the settings that determine which certificates embedded in a device are used by using the SetRootCa
and SetClientCert
functions. Up to three root CA certificates can be set, whereas only one client certificate can be set.
Setting Proprietary Certificates
The functions shown below can be used to set a proprietary certificate when using a proprietary root CA certificate or client certificate to connect when executing a task. There is no need to call them when not using proprietary certificates.
nn::Result nn::boss::RegisterPrivateRootCa( const u8* pCertData, size_t certDataSize); nn::Result nn::boss::RegisterPrivateClientCert( const u8* pCertData, size_t certDataSize, const u8* pPrivateKeyData, size_t privateKeyDataSize);
A proprietary certificate and a certificate embedded in a device can be used in combination. Only one certificate (either the root CA certificate or the client certificate) can be set as the proprietary certificate. When duplicate settings occur, the last certificate set will be enabled.
To use a proprietary certificate, call the SetPrivateRootCa
or SetPrivateClientCert
member function from the TaskActionBase
class. Only the root CA certificate can be used in combination with a certificate embedded in a device.
Registering tasks to connect to servers other than the BOSS data server provided by Nintendo is currently not permitted.
4.2.1.4. Registering and Running Tasks
Call nn::boss::RegisterTask
with each of the four task property classes as arguments to register a task.
nn::Result nn::boss::RegisterTask(nn::boss::Task* pTask, nn::boss::TaskPolicy* pPolicy, nn::boss::TaskAction* pAction, nn::boss::TaskOption* pOption=NULL, u8 taskStep=DEFAULT_STEP_ID);
The pOption
and taskStep
parameters are for future expansion and are currently unsupported. Do not specify anything for these arguments.
Just registering a task will not cause it to be executed. You must also call the nn::boss::Task
class’s Start
or StartImmediate
member functions to tell the BOSS daemon to run the task.
class nn::boss::Task { nn::Result Start(void); nn::Result StartBgImmediate(void); nn::Result StartImmediate(void); nn::Result Cancel(void); nn::Result WaitFinish(void); nn::Result WaitFinish(const nn::fnd::TimeSpan& timeout); }
Tasks marked for execution with the Start
function are scheduled and run by the BOSS daemon in the background. The daemon automatically handles Internet connections for tasks run in the background. If a connection is lost while a background task is running, the daemon pauses the task. Tasks in a resume state are resumed from the point of interruption the next time an Internet connection can be made.
Tasks begun with the Start
function can be halted or removed from the scheduling queue by calling the Cancel
function. Call Start
again to tell the daemon to add a halted task back into the scheduling queue.
Call StartImmediate
to tell the daemon to run a task in the foreground. Tasks marked for execution with the StartImmediate
function are run right away. Because such tasks are run in the foreground, the application must handle connecting to the Internet, as the BOSS daemon does not handle these connections. Unlike running with the Start
function, tasks run using StartImmediate
return an error when the connection is lost while the task is running. Interrupted tasks cannot be resumed.
You can also use StartImmediate
to run a task already queued up using the Start
function, without having to wait until the execution interval has passed. However, note that this again runs the task in the foreground, and that the application must handle connecting to the Internet.
While a task is executing, other tasks will not execute (even if the start-execution date of another task has been reached). However, if you execute a task immediately using StartImmediate
, tasks executing in the background are stopped and resume after the immediate-execution task is finished.
When a task originally started with an instruction from the Start
function is executed using the StartImmediate
function, the task transitions to the retry state if its original execution is still in progress. This does not cause a problem as BOSS normally does not execute tasks while the application is running. However, when BOSS has been authorized to run while the application is running (this can be set in the NDM library), programmers must take this into consideration. Handle applications of this sort as follows.
- Cancel the task by calling the
Cancel
function, and then execute theStartImmediate
function.
Call the StartBgImmediate
function to tell the daemon to start tasks in the background immediately. Use this function to begin a task’s first scheduled execution immediately. If you call the StartBgImmediate
function on a task that was previously scheduled to run as the result of a call to the Start
or StartImmediate
functions, the task is not run immediately a second time. If you want the task to run immediately every time it is called, use the StartImmediate
function instead. If you need to give additional background instruction for immediate execution to a task that has already been scheduled, cancel its execution using the Cancel
function, and then call the StartBgImmediate
function. Note that calling StartImmediate
cancels the execution of other tasks, whereas StartBgImmediate
runs the targeted task after any currently running tasks complete.
Call the WaitFinish
function to wait for one execution of a task to complete. Use this for the application to wait for task completion in cases, such as: tasks with an execution count of one, or tasks run immediately with StartImmediate
. Calling the StartImmediate
function cancels execution of other tasks, while the StartBgImmediate
function executes the task after other tasks have completed execution. We recommend calling WaitFinish
using either a dedicated thread or using the overloaded version and specifying a value for the timeout
parameter. When specifying a timeout value, the function returns with ResultWaitFinishTimeout
if the task has not completed within the timeout period, passing control back to the application.
The arrival of new data can be used as a method of waiting for task execution to complete. Use nn::boss::GetNewArrivalFlag
or nn::boss::RegisterNewArrivalEvent
to check newly arrived data. For more information about these functions, see 4.2.2.6. Checking the New Arrival Flag and Waiting for a Data New Arrival Event.
There are also methods of polling task status using nn::boss::GetState
and nn::boss::GetStateDetail.
Registering Immediate Execution Tasks
The nn::boss::RegisterImmediateTask
function is provided for registering tasks that can only be executed immediately. Always register immediate execution tasks using this function, and execute them in the foreground. The guidelines restrict the number of tasks that can be registered in one application, but immediate execution tasks registered with this function are not counted among those tasks.
nn::Result nn::boss::RegisterImmediateTask( nn::boss::Task* pTask, nn::boss::TaskAction* pAction, nn::boss::TaskPolicy* pPolicy=NULL, nn::boss::TaskOption* pOption=NULL, u8 taskStep=DEFAULT_STEP_ID);
For pTask
instead of using the nn::boss:Task
class, specify its subclass, the nn::boss::FgOnlyTask
class. When this class is used, task IDs registered for immediate execution defined in nn::boss::FG_ONLY_TASK_ID
are automatically specified. It is not necessary to specify the task ID. Even if execution count and execution intervals have been set in pPolicy
, these settings are disabled.
Task execution must occur with the nn::boss::FgOnlyTask::StartImmediate
function. Executing a task with any other function returns an error.
The Maximum Number of Tasks That Can Be Registered and Automatic Deletion
The maximum number of tasks that can be registered in BOSS is 127. (Tasks for immediate execution are not included.) This number represents the maximum value of the total number of tasks registered by all applications (including embedded applications). The maximum number of tasks that can be registered by a single application is limited by the CTR Guidelines. If an application attempts to register a new task when the number of registered tasks has already reached the maximum, BOSS automatically deletes a task for which the execution count is 0 and accepts the registration of the new task. This is not just limited to tasks of the application attempting registration. A search is made among all tasks for a task to delete. If there is no task with an execution count of 0, the product of execution counts and execution interval is calculated, the task with the smallest result is deleted, and registration of the new task is accepted.
If an application is not started up for a long time, there is a possibility that its previously registered tasks have been deleted by BOSS using this automatic deletion process. So applications that use BOSS must be able to handle cases where their own tasks have been deleted. You must implement a process that (for example) checks whether an application has any registered tasks when that application starts up and, if tasks are not registered, prompts for user confirmation to register the tasks.
4.2.1.5. Task Information
Use the member functions of the nn::boss::Task
class to get information about a task, such as its state or execution result.
class nn::boss::Task { TaskServiceStatus GetServiceStatus(void); TaskStateCode GetState(bool acknowledge=false, u32* pCount=NULL, u8* pStepID=NULL); u32 GetHttpStatusCode(u32* pCount=NULL, u8* pStepID=NULL); TaskResultCode GetResult(u32* pCount=NULL, u8* pStepID=NULL); nn::Result GetStateDetail(TaskStatus* pStatus, bool acknowledge=false, u8* pStepID=NULL, u8 taskStep=CURRENT_STEP_ID); nn::Result GetError(TaskError* pTaskError, u8* pStepID=NULL, u8 taskStep=CURRENT_STEP_ID); nn::Result GetInfo(TaskPolicy* pPolicy, TaskAction* pAction, TaskOption* pOption, u8 taskStep=CURRENT_STEP_ID); nn::Result GetActivePriority(TaskPriority* pPriority); }
For the functions above that have a pCount
parameter, pass a pointer to a u32
variable instead of NULL
to have the function return the execution count for a task. The pStepID
parameter cannot be used in the current version.
The task execution count and information for tasks acquired returned in pCount
can be individually obtained in the library. There is a slight time lag as a result, so information does not necessarily match precisely.
Call the GetServiceStatus
function to get the state of the server the task is connecting to (such as SERVICE_AVAILABLE
or SERVICE_TERMINATED
). The server sends its state when the task runs.
A return value of SERVICE_AVAILABLE
indicates that the service is running. A return value of SERVICE_TERMINATED
indicates that the service is running. The function returns a value of SERVICE_UNKNOWN
when a task has not yet been executed or when a connection attempt fails out in a network error. If the function itself fails, it returns a value of GET_SERVICE_STATUS_ERROR
.
The system checks whether a service has terminated by checking the response from the server when the task runs to determine whether the response includes a flag indicating that the service has terminated (the service termination flag). This flag is set by the application developer using the BOSS data server.
Call the GetState
function to get the state of the task. If the function itself fails, it returns a value of GET_TASK_STATE_ERROR
. To ensure that accurate execution results for a task can be obtained, task execution results are stored from the time a task completes execution until the next task executes (in other words, while the status is TASK_WAITING_TIMER
). The GetState
function returns the execution result of the last task (TASK_DONE
, TASK_ERROR
, or TASK_RETRY
) even though the actual current status is TASK_WAITING_TIMER
.
To get the actual current status (rather than the result being stored) call the GetState
function while specifying true
in the acknowledge
parameter. Note that the stored result is released and the actual status (TASK_WAITING_TIMER
) can be obtained when the task result is obtained using the GetState
function afterward.
Definition |
Description |
---|---|
|
Stopped, and excluded from scheduling. |
|
Waiting for the task execution interval to pass. |
|
The task execution interval has passed, but the task is still waiting to run for some reason (such as not being connected to the Internet or because another higher-priority task is running). |
|
The task is now running. |
|
Task execution is paused. |
|
The state right after registering a task, but before starting it. |
|
The task has finished. |
|
An unrecoverable error occurred while the task was running. |
|
Connection was lost during execution and the task is now waiting to retry (resume). |
Call the GetHTTPStatusCode
function to get the HTTP status code when a task is running. If the function itself fails, it returns a value of U32_CANNOT_GET_DATA
.
Call the GetResult
function to get the result of a task. If the function itself fails, it returns a value of GET_TASK_RESULT_ERROR
. For the return value definitions, see the definition of the TaskResultCode
enumerated type in the nn/boss/boss_Const.h
file. The return value called during the BOSS library and returned as an error by functions from other libraries becomes a value larger than the value that exists in the TaskResultCode
enumerated type UNKNOWN_ERROR
+ the module ID for the module that generated the error. For the module ID definitions, see nn/Result.h
. FS_UNKNOWN_ERROR
is returned when an error occurs for file operations at task execution due to any of the following reasons.
- There is no space available on the SD card.
- The SD card is write-protected.
- An SD card is not inserted.
- A different SD card than the one used at the time the task was registered is inserted, meaning that BOSS storage for writing and reading task data is not available. (BOSS storage is covered in the sections that follow.)
- The SD card is damaged.
Call the GetStateDetail
function to get a task’s state. The difference between this function and the GetState
function is that you can use the GetProperty
function as an instance of the nn::boss::TaskStatus
class returned in the pStatus
parameter to get more detailed state information.
Property ID |
Type |
Property |
---|---|---|
|
|
Task state (same as for |
|
|
Execution result (same as for |
|
|
Communication error code (same as for |
|
|
Current task execution priority. |
|
|
Current task execution count. (It takes some time for this to reflect the most recent value, so we recommend getting the property of the same name from the |
|
|
Time in the task execution interval (in seconds). |
|
|
Task start time (in seconds, starting from 2000-01-01). |
|
|
Size of downloaded data. |
|
|
Total size of the data to download (value of the |
|
|
Service availability status. |
|
|
Service-terminated flag. |
|
|
Last time data to download was modified (value of the |
Call the GetError
function to get any error that occurred during task execution. The difference between the GetCommErrorCode
and GetResult
functions is that you can use the GetProperty
function as an instance of the nn::boss::TaskError
class, returned in the pTaskError
parameter, to get more detailed information.
Property ID |
Type |
Property |
---|---|---|
|
|
Task result (only for errors; same as for |
|
|
Cause of an error in task execution. |
|
|
Communication error message during task execution. |
Call the GetActivePriority
function to get a task's current execution priority.
4.2.1.6. Getting a Task List
Call the nn::boss::GetTaskIdList
function to get a list of tasks registered by the application.
nn::Result nn::boss::GetTaskIdList(nn::boss::TaskIdList* pTaskIdList);
For the pTaskIdList
parameter, specify a pointer to an instance of the nn::boss:TaskIdList
class (generated by the application). An instance is roughly 1 KB in size, so take note of the stack and heap sizes when generating an instance. The nn::boss::TaskIdList
class is defined as follows.
class nn::boss::TaskIdList { explicit TaskIdList(void); virtual ~TaskIdList(void); u16 GetSize(void); char* GetTaskId(u16 index); }
Call the GetSize
function to get the number of tasks stored in a list. Call the GetTaskId
function and specify an index to get the ID of a task stored in a list. The function returns NULL
if the specified index is out of bounds.
The nn::boss::GetStepIdList
function is not currently usable.
4.2.1.7. Changing a Task
Call the nn::boss::ReconfigureTask
function to change a task’s property settings. You can only change those properties that can be set by the nn::boss::TaskPolicy
function. Do not specify a step ID.
nn::Result nn::boss::ReconfigureTask(nn::boss::Task* pTask, nn::boss::TaskPolicy* pPolicy, u8 taskStep=DEFAULT_STEP_ID);
Use the nn::boss::Task
member functions to change a task’s execution count or execution interval.
class nn::boss::Task { nn::Result UpdateInterval(u32 interval); nn::Result UpdateIntervalWithSec(u32 intervalSec); nn::Result UpdateCount(u32 count); u32 GetInterval(void); u32 GetIntervalSec(void); u32 GetCount(void); }
You can call the UpdateIntervalWithSec
function to specify an execution interval in seconds, but note that this function is only for debugging purposes.
4.2.1.8. Unregistering a Task
Call the nn::boss::UnregisterTask
function to unregister a task.
nn::Result nn::boss::UnregisterTask(nn::boss::Task* pTask, u8 taskStep=DEFAULT_STEP_ID);
When you unregister a task, the working files created for that task in BOSS storage are deleted. The function returns an error (nn::boss::ResultFileAccess
) if it fails to delete the working files (for example, because the SD card was removed), but the task itself will be successfully unregistered. You are not required to handle this error because the working files will still be deleted when the expanded save data is deleted. Although you cannot delete working files directly, you can delete them by reregistering a task with the same task ID and then unregistering it.
The taskStep
parameter cannot be used at present. Do not specify anything for this parameter.
4.2.1.9. Finalizing the BOSS Library
4.2.2. Nintendo Archive Download (NADL) Tasks
An NADL task is a BOSS task that downloads data from the BOSS data server via HTTP or HTTPS.
Data must be registered on the BOSS data server for an application to download it. Data registered on the BOSS data server is converted to the proprietary Nintendo Serendipitous (NS) archive format. NS archives can contain multiple data files. Accordingly, you can register multiple data files in a single archive on the BOSS server, so that users can download multiple files (such as application data files and related notifications) by running a single task.
For more information about using the BOSS Data Server, see the BOSS Management Tool Operations Manual. The manual can be downloaded from the Help link on the screen that is displayed after you log in to the BOSS Data Server. The manual also includes information about distributed data and operations, so read it before operating the BOSS Data Server.
Following are the primary operations performed with the management tool.
- Creation of notifications and distributed data
- Management of the distribution schedule for notifications and distributed data
- Test distributions during application development
- Obtaining the distribution log that is sent to users after the actual start
To use the BOSS Data Server, apply to be a "User who Can Access the BOSS Data Server" when applying to use BOSS tasks on the Online title MAnagement System (OMAS). Upon approval of your application, access information for the BOSS Data Server is sent in an email.
4.2.2.1. NS Archives and NS Data
All data included in an NS archive (NS data) is encrypted, signed, and hashed. As a result, BOSS can handle not only NS data decryption, but also data verification to check for tampering or spoofing (to ensure that no invalid data is downloaded).
You can set a new arrival flag for an NS archive. Once this flag is set, applications display an update indicator on their icons after downloading the archive. The new arrival flag is set separately for each application managed using BOSS, and the system checks for the new arrival flag and displays the update indicator accordingly. The system handles all of this, so applications do not need to do anything about this update indicator display.
When the system downloads NS data that includes notifications, it displays the update indicator on the Notifications applet (even if the new arrival flag is OFF, disabled). However, this only applies to the update indicator on the Notifications applet; the update indicator behavior for the application's icon is still controlled by the new arrival flag.
NS data can include the following.
Type |
Description |
---|---|
Extra data. |
Data for various extras used in an application, such as extra items or game levels. |
Notifications |
Notifications sent via BOSS. |
Downloaded contextual banner data. |
Data for replacing the text or textures displayed in CTR title banners. |
Data Store data |
Data downloaded with the Data Store download task. |
Each NS data file includes a 32-bit data type designator. The data type consists of two types. The most-significant 16 bits specify the global data type indicating an NS data file, and the least-significant 16 bits specify the private data type. Global data types are shared among all applications and must be specified from the table above. Private data type values can be freely assigned by each application. This private data type is used as a search term when searching NS data, as explained in 4.2.2.6. Checking the New Arrival Flag and Waiting for a Data New Arrival Event. Properly planned private data types allow you to search NS data more efficiently.
Note that NS data is discarded if there is no BOSS storage for the receiving application when the BOSS library distributes the NS data to its various storage locations. For example, this situation applies when the application has never been started, the application has been started before but has never registered BOSS storage, or when the user has deleted the application’s extra data. NS data also includes the unique ID of the target application embedded within it. In the NS data’s unique ID, the unique ID of the application using BOSS is embedded based on the server. For that reason, developers cannot specify an arbitrary unique ID (target) to data. Downloaded NS data is stored in the BOSS storage of the application whose unique ID is embedded within, regardless of which application downloaded the task that was used to download.
Be sure to avoid specifying the wrong URL upon task registration or downloading NS data targeting other applications.
Each NS data file is also assigned a serial ID, which must be unique among all NS data for a specific application, and a version number. Both are 32-bit values. Serial IDs are used by applications to specify NS data to read or delete. Versions are used by BOSS when deciding whether to update NS data. When BOSS downloads data with the same serial ID as existing NS data, BOSS then compares version numbers and only updates (that is, overwrites) the NS data if the downloaded data’s version number is newer.
The serial ID and version for NS data can be set on the BOSS management site. However, because the serial ID and version for Notifications and Data Store data are set automatically, there is nothing the developer can do to set them. For more information, see the manual available on the BOSS management site.
Serial IDs in the range from 4294901760 through 4294967295 (0xFFFF0000
through 0xFFFFFFFF
) are reserved for the system and are prohibited from use by general applications. Use a value outside of this range (1 through 4294901759 (0xFFFEFFFF
)) when setting a serial ID on the BOSS data server's BOSS management website.
NS data includes various properties that can be accessed by the application, such as the data’s serial ID, data type, and size. However, notifications are automatically processed by the system and cannot be directly loaded by applications. Although downloaded contextual banner data is also processed automatically by the system, it can be loaded by applications.
NS archives can contain notifications. You can set the OptOut
flag separately for each BOSS storage location to prevent such notifications from being processed and displayed in the Notifications applet.
Call the nn::boss::SetOptoutFlag
and nn::boss::GetOptoutFlag
functions to set and get the OptOut
flag.
nn::Result nn::boss::SetOptoutFlag(bool flag); nn::Result nn::boss::GetOptoutFlag(bool* pFlag);
Call nn::boss::SetOptoutFlag
and pass true
for the flag
parameter to set the OptOut
flag and ignore any notifications that might be included in downloaded NS archives. (BOSS discards any such notifications.) Call the nn::boss::GetOptoutFlag
function to get the current setting.
4.2.2.2. BOSS Storage
Extra data and downloaded contextual banner data files are saved to an archive memory region called BOSS storage, which is created in the expanded save data region specified by the application. Although BOSS storage is created in the application’s expanded save data region, applications cannot access it directly. Applications specify to BOSS how much of the expanded save data memory region to use for BOSS storage.
After BOSS storage is full, BOSS automatically deletes data starting from the earliest (the data with the lowest serial ID) so that downloaded data does not exceed the specified storage capacity. You can also specify the maximum number of data files when registering BOSS storage from within the application. When you attempt to save data in excess of the maximum number of data files, BOSS deletes data, starting with the earliest data first, so that the amount of data in storage never exceeds the maximum amount. The maximum number of data files defaults to 2000 unless otherwise specified. Applications must factor this in when specifying the size and number of files for BOSS storage, to accommodate both the size and number of files of downloaded data. In addition, when BOSS storage has been newly created in expanded save data, a maximum value is set for the number of files that can be created in the expanded save data. Because the NS data files in BOSS storage also count toward the total number of files in expanded save data, be sure to set a value that takes the number of instances of NS data being saved in BOSS storage into account when setting the maximum number of files to be created in expanded save data.
If even the deletion of earlier data would not free enough memory to store the data to be downloaded, the task is canceled and an error is generated (NSA_ERROR_STORAGE_INSUFFICIENCY
). This can occur in the following scenarios.
- The size of data to download exceeds the size of BOSS storage.
- The data to download is a newer version of data already downloaded, and the size of the old and new versions combined exceeds the size of BOSS storage.
This first scenario is obvious, but you need to be careful about the second scenario for data that might be updated to a newer version. When you download a newer version of downloaded data, the new version of the data is first downloaded as a temporary file, the old version is then deleted, and the temporary file is renamed with the official filename. In other words, both the old and new versions temporarily exist in BOSS storage, so their combined size must be less than the size of BOSS storage.
This error does not occur if BOSS storage is greater than double the size of the maximum size of NS data.
Downloaded NS data is saved temporarily to the application's BOSS storage before the different parts of the data are saved to their final destinations. Consequently, notification data is briefly stored in the application's BOSS storage, as shown in Figure 4-7, even though it will ultimately be saved to the system's BOSS storage. If there are already N NS data files in a BOSS storage region and N is its maximum number of data files, notification data downloaded to that region may cause an existing NS data file to be deleted to make room for temporarily saving the new notification data. That temporary data could then be deleted after being saved to its final destination. Consequently, the number of NS data files in that application's BOSS storage is decreased by one (N-1) after downloading new notification data. If your tasks distribute or download notification data, take this behavior into account when configuring your BOSS storage.
Notifications data that is temporarily saved in BOSS storage is immediately moved to expanded save data on the console. Notifications are not received more than once as long as the task is not removed and re-registered. Previously downloaded data remains on the system and the serial ID and version are compared.
If the number of files in expanded save data (including the number of instances of NS data) reaches the maximum value, NS data downloaded after that point cannot be saved, and an error results upon execution of each task.
NS data saved to BOSS storage has a header of 52 bytes added to the front of the file. Consequently, when specifying the size of BOSS storage, be sure to take this into consideration.
BOSS storage is only meant to serve as the BOSS working memory region, and data might be automatically deleted. Consequently, do not leave any data that you want to keep permanently as extra data in BOSS storage as NS data. Instead, we recommend loading this NS data via BOSS and saving a copy as a separate file in the expanded save data region. Also, when a lot of data is being stored in BOSS storage, routines that target all data in BOSS storage become less efficient. We also strongly recommend that you delete data that will no longer be used from BOSS storage. As described above, you can also delete data from BOSS storage if you permanently save the NS data outside BOSS storage.
When an expanded save data region is shared among multiple titles in a series, an application in that series can access downloaded data for any title in the same series.
Developers must submit an application to Nintendo (support@noa.com) to use the BOSS service. In response, Nintendo will provide dedicated URLs for each application. BOSS communication is via the HTTPS protocol using the 3DS system’s built-in CA certificates.
Lotcheck will verify whether applications that use BOSS services register tasks using the settings that were specified in the application to use BOSS services that was submitted to Nintendo.
The NS data file serial ID must be unique within the group of files belonging to the same application (or to the same series for series data).
Downloading Notifications Only
Because notifications are stored in the expanded save data of the system, NS data does not accumulate in BOSS storage for applications that download only notifications. However, even in such cases, you must register for BOSS storage for the amount needed to temporarily store notification data. This requirement occurs because hash and signature authentication is carried out after NS data is temporarily stored in BOSS storage. These processes must succeed first, and then NS data is moved into the BOSS storage where it will be temporarily stored. In other words, because the BOSS storage used to store the data is the same as that used to store data for applications that have registered tasks, the NS data remains behind unchanged. In the case of notification data, it is moved to the expanded save data of the system.
60 KB of BOSS storage is required in order to download the maximum amount of notification data (when using 50 KB of attachment data).
When using expanded save data only to distribute notifications, check at regular intervals (such as on startup) to make sure that the expanded save data can be mounted normally. Downloaded data is temporarily saved to the expanded save data region, and if the expanded save data is corrupted or deleted, notifications will no longer be received, even if the task still exists.
4.2.2.3. Required Steps to Process an NADL Task
The following figure shows the required steps from registering an NADL task using BOSS through processing the downloaded data.
The following table gives an overview of each step.
Processing Step |
Description |
---|---|
Create Expanded Save Data |
The application must first create an expanded save data region before it can register BOSS storage in which to save data downloaded by NADL tasks. For more information about creating expanded save data regions, see the 3DS Programming Manual: System. |
Register BOSS Storage |
Register the BOSS storage for saving the data downloaded by an NADL task. For more information, see 4.2.2.4. Preparing to use BOSS. |
Register an NADL Task |
Configure the actions for an NADL task and register the task with BOSS. For more information, see 4.2.2.5. Registering a Nintendo Archive Download (NADL) Task. |
Check the New Arrival Flag |
Check the new arrival flags managed by the library. For more information, see 4.2.2.6. Checking the New Arrival Flag and Waiting for a Data New Arrival Event. |
Check for Downloaded Data |
Get a list of the downloaded data and check whether there is any newly downloaded data. For already-processed data, the application must handle any other operations as necessary: deletion, serial ID recording, setting the data’s status from unread to read, and so on. For more information, see 4.2.2.7. Checking for Downloaded Data. |
Poll Task State |
Poll the state of the NADL task to determine whether the state is "completed." For more information, see 4.2.1.5. Task Information. |
Wait for a Data New Arrival Event |
Register an event with the library and wait for that event to enter the signaled state. For more information, see 4.2.2.6. Checking the New Arrival Flag and Waiting for a Data New Arrival Event. |
Wait for Task Execution to Complete |
Run the NADL task in the foreground and wait for it to complete. For more information, see 4.2.1.4. Registering and Running Tasks. |
Load Downloaded Data |
Access the NS data saved in BOSS storage and load it into a buffer allocated by the application. For more information, see 4.2.2.8. Loading Downloaded Data. |
Process Downloaded Data |
Process the obtained downloaded data in the application. |
4.2.2.4. Preparing to Use BOSS
BOSS storage must already be registered before you can register and run NADL tasks.
nn::Result nn::boss::GetStorageInfo(size_t* pStorageSize=NULL); nn::Result nn::boss::GetStorageInfo(size_t* pStorageSize, u16* pEntryCount); nn::Result nn::boss::RegisterStorage( bit32 storageId, size_t storageSize, nn::boss::StorageType storageType=nn::boss::USER_EXT_SAVEDATA_STORAGE); nn::Result nn::boss::RegisterStorage( bit32 storageId, size_t storageSize, u16 entryCount, nn::boss::StorageType storageType=nn::boss::USER_EXT_SAVEDATA_STORAGE); nn::Result nn::boss::UnregisterStorage(void);
Before registering BOSS storage, check whether BOSS storage has been created by calling nn::boss::GetStorageInfo
. If it has not yet been created, the function returns nn::boss::ResultStorageNotFound
. For pStorageSize
and pEntryCount
, specify pointers to variables that store, respectively, the size and maximum number of data files for the BOSS storage.
Call nn::boss:RegisterStorage
to create BOSS storage in the expanded save data memory region specified by storageId
. This created BOSS storage can store up to an all-files combined total size of storageSize
. Use the overloaded version that has an entryCount
parameter to specify the maximum number of data files that can be registered to the BOSS storage.
Call nn::boss:UnregisterStorage
to unregister BOSS storage. Attempting to register BOSS storage in an expanded save data region to which the application does not have access permission returns an nn::boss::ResultStorageAccessPermission
error.
Each application can only register one BOSS storage area. To change the expanded save data region used as BOSS storage by an application, first call nn::boss::UnregisterStorage
to unregister, and then call nn::boss::RegisterStorage
again to create a new BOSS storage area.
After changing the expanded save data memory region used for BOSS storage, you can no longer access any NS data saved in the previous BOSS storage area.
We recommend creating BOSS storage in one expanded save data region and keeping it there.
For more information about accessing the expanded save data memory region, see the 3DS Programming Manual: System.
For more information about notification data, see the Applet Specification. For more information about downloaded contextual banner data, see Banner Overview and ctr_makedlexbanner.
Handling the Deletion of Expanded Save Data by Users
Note the possibility that a user may delete expanded save data in System Settings. If such data is deleted, the application must re-create the expanded save data to use BOSS again. An application that uses BOSS must always be able to handle the deletion of expanded save data by users. Applications are required to implement some process for handling this situation. One example for handling this is to check for expanded save data when the application starts, and if none exists, prompt for user confirmation to create expanded save data.
4.2.2.5. Registering a Nintendo Archive Download (NADL) Task
Use the nn::boss::NsaDownloadAction
class to set the actions for an NADL task. Create an instance of the class and then call Initialize
to set its URL property.
class nn::boss::NsaDownloadAction : public nn::boss::TaskAction { nn::Result Initialize(const char* pUrl); }
For pUrl
, specify the URL of the NS archive to download. This URL value can be up to 512 characters, including the NULL
terminator.
The URL for the NS archive takes the following format.
https://<CDN domain>/<environment ID>/<common parameter>/<BOSS code>/<task ID>/<optional filename>
To distribute NS archives in different languages, you must use a format that contains language information (ISO 639-1 alpha-2).
https://<CDN domain>/<environment ID>/<common parameter>/<BOSS code>/<task ID>/<language information>/<optional filename>
To distribute NS archives in different languages and also to use both simplified and traditional Chinese characters in notifications, you must use a format that contains not only language information but also country information (ISO 3166-1 alpha-2).This is because simplified and traditional Chinese are both defined as Chinese (zh) in ISO 639-1 alpha-2, so the language information alone is not enough for the BOSS data server to determine which character set to use for the distribution.
https://<CDN domain>/<environment ID>/<common parameter>/<BOSS code>/<task ID>/<country information>/<language information>/<optional filename>
If the user has changed the language setting or country setting in System Settings and tasks are not reregistered, a task that is distributed in different languages will download data in a language different from what is set in System Settings.
You must apply on OMAS to use the feature to distribute in different languages. If you intend to distribute using both simplified and traditional Chinese characters, indicate that fact in the relevant field on the application form.
Systems set to the China region (mainland China) display notifications using simplified Chinese characters, whereas systems set to the Taiwan region (Taiwan/Hong Kong) display notifications using traditional Chinese characters.
The NsaDownloadAction
class inherits from the nn::boss::TaskAction
class and also has member functions for setting common task actions.
Property ID |
Type |
Property |
---|---|---|
|
|
Destination URL. |
|
|
Additional HTTP request header. |
|
|
Built-in client certificate ID. |
|
|
Built-in root CA certificate ID. |
|
|
AP information added to the HTTP request. |
|
|
Number of built-in client certificates to register. |
|
|
Number of built-in root CA certificates to register. |
Unique NADL task action settings are described below.
Usable Root CA Certificates
The library automatically registers the NADL task’s root CA certificate, so the application does not need to do this.
The library registers two root CA certificates, specifically a root CA certificate used to connect to the BOSS data server for live distribution to retail products, and a root CA certificate used to connect to the BOSS data server for test distribution. Data for live distribution can only be downloaded from the BOSS data server using the retail (production) hardware. However, an exception is made for the library sample demos, and so data for live distribution can also be downloaded using the development hardware. Data for test distribution can be downloaded using both the development hardware and retail (production) hardware, but only if the DNS setting has been set to 210.128.103.149
.
4.2.2.6. Checking the New Arrival Flag and Waiting for a Data New Arrival Event
Use the following functions to check whether any new data has been downloaded.
nn::Result nn::boss::GetNewArrivalFlag(bool* pFlag); nn::Result nn::boss::RegisterNewArrivalEvent(nn::os::Event* event);
The nn::boss::GetNewArrivalFlag
function returns true
in its pFlag
parameter if there is new data.
The nn::boss::RegisterNewArrivalEvent
function signals the event class passed in its event
parameter when new data is downloaded. The application must initialize this event class in advance.
Any downloaded data is not treated as new data if the NS archive’s new arrival flag is cleared. After downloading such data, the GetNewArrivalFlag
function continues to return false
, but the event passed to RegisterNewArrivalEvent
is signaled.
4.2.2.7. Checking for Downloaded Data
After the task has finished running, the downloaded NS data is saved to the BOSS storage area of the expanded save data region specified in the task. You must first get a list of NS data serial IDs before you can access the NS data saved to BOSS storage.
nn::Result nn::boss::GetNsDataIdList( u32 dataType, nn::boss::NsDataIdList* pNsDataId); nn::Result nn::boss::GetNewDataNsDataIdList( u32 dataType, nn::boss::NsDataIdList* pNsDataId);
Call the nn::boss::GetNsDataIdList
and nn::boss::GetNewDataNsDataIdList
functions to get a list of the NS data files that the application can load. GetNsDataIdList
gets a list of all such data in the descending order of the serial IDs, and GetNewDataNsDataIdList
gets a list of only unread data.
The update indicator displayed on the application’s icon is cleared after calling either of these functions (that is, the new arrival flag obtained by nn::boss::GetNewArrivalFlag
is set to false
). Newly downloaded NS data is marked as unread. Call the nn::boss::NsData::SetReadFlag
function to mark NS data as either read or unread. NS data is left as unread unless this setting is changed by the application.
When using the list of serial IDs to determine whether downloaded data must be processed, your application must identify the processed data in some way, such as by always deleting the data after processing, recording the serial IDs of processed data, or setting the processed NS data to read status.
When multiple titles in a series share a single expanded save data region, NS data downloaded via a task registered by a series title can be accessed by other titles in that same series. For more information, see Sharing NS Data.
Because these functions search through all data in BOSS storage, the more data stored in BOSS storage, the more time execution requires. To maintain efficiency of execution, we recommend that you regularly delete data in BOSS storage that is no longer being used.
For each of these functions, specify the NS data search conditions in the dataType
parameter, and specify a pointer to an instance of the nn::boss::NsDataIdList
class to store the NS data serial ID list in the pNsDataId
parameter.
Specify the NS data search conditions as follows.
Specify DATA_TYPE_ALL
to include all NS data in the search targets.
Otherwise, specify the search targets using a bitwise OR of the global data type and private data type. This stores on the list only NS data IDs that have a matching global data type and a private data type that results in a match when masked.
The global data types fall into three categories, as shown below.
Definition |
Description |
---|---|
|
Extra data. |
|
Data displayed in the notification (the application cannot get this data). |
|
Downloaded contextual banner data. |
|
Data obtained with a Data Store download task. |
The private data type is a 16-bit value and is used as the mask value for NS data (the least-significant 16 bits of the data type). NS data that has even one bit set to 1
that matches the corresponding bit in the specified private data type (in other words, bits where a bitwise AND of the two private data type values is not 0
) is included in the list. For example, to include all extra data in the serial ID list, set the dataType
parameter to a value of DATA_TYPE_APPDATA | 0x0000FFFF
. Applications can use NS data types to get extra data that is sorted into custom categories.
If BOSS storage cannot be accessed normally—for example, because the SD card has been removed—the nn::boss::GetNsDataIdList
function returns an nn::boss::ResultFileAccess
error. The application cannot recover from this situation, so you must display the error code to the user. The BOSS sample demo sample_nadl_simple
(CTR-SDK 7.1 and later) provides sample implementation of the display of error codes for this error and other unanticipated errors.
To instantiate the nn::boss::NsDataIdList
class, you need a u32
array to store the serial IDs. The array must be big enough to contain all the serial IDs that can be obtained in a single search.
The search function returns nn:boss::ResultNsDataListSizeShortage
if the array is not big enough to hold all of the serial IDs found in a search. If this happens, you can search again using the same instance (run the same function again) to get a list of serial IDs starting where the previous execution left off.
The search function returns nn::boss::ResultNsDataListUpdated
if new NS data is added to BOSS storage while searching. If this happens, first call the Initialize
member function of the nn::boss::NsDataIdList
class instance to initialize the list, and then search to get the serial ID list starting again from the beginning.
The IsSuccess
method on the nn::Result
instance returned by the search function returns true
after it has listed all NS data files matching the search terms.
class nn::boss::NsDataIdList { explicit NsDataIdList(u32* pSerial, u16 size); virtual ~NsDataIdList(void); void Initialize(void); u16 GetSize(void); u32 GetNsDataId(u16 index); }
You must call Initialize
after generating an instance. Call Initialize
on an instance that you have already used for a search to reset the search to get the list of serial IDs again from the beginning.
Call GetSize
to get the number of serial IDs obtained.
Call GetNsDataId
and specify the array index to get a serial ID. The function returns INVALID_SERIAL_ID
if the specified index is out of bounds.
Sharing NS Data
When multiple titles in a single series share an expanded save data region, any application in that series can call nn::boss::GetNsDataIdList
or nn::boss::GetNewDataNsDataIdList
to search the NS data downloaded by any application in that series, and use the nn::boss::NsData
class to access that NS data. In other words, NS data downloaded by an NADL task registered by one series title is shared among all titles in that series. NS data for one title in a series is shared among all titles in that series.
Consequently, NS data serial IDs must be unique not just among files downloaded by that application but also among all NS data files downloaded by any application in that whole series.
If you do not need to work with NS data downloaded by other titles in a series, you can call the nn::boss::GetOwnNsDataIdList
or nn::boss::GetOwnNewDataNsDataIdList
functions to search for and list just the NS data downloaded by tasks registered by the calling application.
nn::Result nn::boss::GetOwnNsDataIdList( u32 dataType, nn::boss::NsDataIdList* pNsDataId); nn::Result nn::boss::GetOwnNewDataNsDataIdList( u32 dataType, nn::boss::NsDataIdList* pNsDataId);
These two functions differ from nn::boss::GetNsDataIdList
and nn::boss::GetNewDataNsDataIdList
only in which NS data files they search for. They otherwise operate identically. However, note that these functions incur an increased processing load because they check if an NS data file was downloaded via a task registered by the calling application.
4.2.2.8. Loading Downloaded Data
Access NS data by generating an instance of the nn::boss::NsData
class and calling Initialize
using the obtained serial ID as an argument.
class nn::boss::NsData { nn::Result Initialize(u32 serial); nn::Result GetHeaderInfo(HeaderInfoType type, void* pValue, size_t size); nn::Result SetReadDataPosition(s64 position, PositionBase base); s32 ReadData(u8* pDataBuf, size_t bufLen); nn::Result SetReadFlag(bool flag); nn::Result GetReadFlag(bool* pFlag); }
NS data properties can be obtained from the header information returned by the GetHeaderInfo
function. The header information type in the type
parameter specifies which header information is obtained. For the pValue
and size
parameters, specify a variable to hold the header information and its size in bytes (which depends on the data type of the header information).
Header Information Type |
Type |
Description |
---|---|---|
|
|
Title ID. |
|
|
NSD flag (not used). |
|
|
Data type. |
|
|
Data length. |
|
|
Serial ID. |
|
|
Version number. |
Call the ReadData
function to load (read) the NS data. Specify a read buffer in pDataBuf
and its size in bufLen
. The function returns the number of bytes read. A return value of 0
indicates that the function has already read all the data. An error occurs and the function returns a negative number if it attempts to read data that does not exist, which could happen if data was automatically deleted to allocate a save region. An error occurs and the function returns NN_BOSS_NSDATA_READ_ERROR_UPDATED
if the data is overwritten by new download data while it is being read.
Call the SetReadDataPosition
function to specify where in the NS data to read (equivalent to the file system Seek
function).
Like the file system Seek
function, NS data read operations are substantially slower when the read position set by the SetReadDataPosition
function is not a multiple of 4 from the start of the file.
Call the SetReadFlag
function specifying true
for the flag
parameter to mark NS data as read. Call the GetReadFlag
function to check whether NS data has been read. The function returns a value of true
in the pFlag
parameter if the NS data is marked as read.
You can also use the following functions to work with NS data.
class nn::boss::NsData { nn::Result SetAdditionalInfo(u32 info); nn::Result GetAdditionalInfo(u32* pInfo); nn::Result GetLastUpdated(nn::fnd::DateTime* PTime); nn::Result Delete(void); }
Call the SetAdditionalInfo
and GetAdditionalInfo
functions to set and get additional information as a u32
value that applications can freely add to NS data. Note that this additional information is lost when the NS data is overwritten with a new version.
Call the GetLastUpdated
function to get the date and time when an NS data file was created. This indicates the last time the NS data was overwritten with a new version.
Call the Delete
function to delete NS data from BOSS storage. Even without explicitly calling the Delete
function, the BOSS daemon automatically deletes data starting from the earliest (the data with the lowest serial ID) after the storage area is full (that is, after the total size of the NS data exceeds the size specified to the nn::boss::RegisterStorage
function) to open up some free space. You can explicitly call the Delete
function to get rid of unneeded NS data and keep the BOSS daemon from having to manage that data, thereby improving processing efficiency. Deleted data, for example, is no longer processed when searching NS data to get serial ID lists, making for more efficient searching.
Preventing Duplicate Downloads
BOSS uses the If-Modified-Since
HTTP request field to keep from downloading the same NS archive multiple times.
However, the same NS archive is downloaded multiple times if the following conditions are all fulfilled simultaneously.
- After previously downloading the NS archive, 50 or more other NS archives have been downloaded in the same task.
- A newer NS archive is registered on the server than the last downloaded NS archive. In other words, the update time of the NS archive on the server is more recent than the
LastModifiedTime
of the last downloaded NS archive.
There is no need for applications to build in a way to track this information, but each NS archive is assigned its own ID, which is used to control NS archive downloads to prevent downloading duplicates. Each task can only record the last 50 IDs, so distributing an NS archive after a system has downloaded 50 other NS archives can result in an archive being downloaded again. However, so long as the LastModifiedTime
of the NS archive is not updated to be more recent than the last downloaded NS archive, the If-Modified-Since
field prevents that archive from being downloaded again.
Even when these conditions are not fulfilled during regular use, data write operation errors or other unexpected bugs on the BOSS data server can potentially cause the same NS archive to be downloaded multiple times. Consequently, make sure that such a situation does not cause any fatal errors in your application. For example, an application could keep track of the serial IDs of the data already obtained, and then delete any earlier data if data with the same serial ID is obtained again later.
Be cautious when a task has been deleted and re-registered. In general, functionality to prevent multiple receives does not work because previously downloaded information has already been deleted.
To prevent the repeated receipt of notifications, implement programming such that tasks that receive notifications do not need to be deleted. For example, avoid an implementation that deletes and reregisters tasks every time the application starts.
Interrupted Downloads
The download will be interrupted if the user turns the power off, the battery becomes low, or the connection to the access point is lost due to a poor communication environment. Although the system ordinarily tries the download again after 10 minutes, if the communication environment is poor, the system may not always be able to retry before the task is executed again.
Sleep Mode
Although an ongoing download will be interrupted if the system goes into Sleep Mode, the system will resume the download as soon as it finds an access point. After returning from Sleep Mode, if the system connects to the same access point as before it went into Sleep Mode, it continues the download where it left off. If the system was offline before entering Sleep Mode (but was connected during Sleep Mode), it disconnects from the access point but resumes the download the next time that it connects to an access point.
NS Data That Has Been Corrupted or Tampered With
Use the following procedure to check whether NS data has been corrupted or tampered with.
- Get the NS data ID with the
nn::boss::GetNsDataIdList
function. - If an error other than an illegal use error is returned with the
nn::boss::NsData::GetHeaderInfo
ornn::boss::NsData::ReadData
function (which, for theGetHeaderInfo
function, is either aResultInvalidNsDataValue
,ResultIpcNotSessionInitialized
, orResultStorageAccessPermission
error), NS data can be determined to have been corrupted.
Perform the following when corruption or tampering is detected in NS data.
- Delete NS data that has been corrupted or tampered with using the
nn::boss::NsData::Delete
function. - Notify the user that data has been corrupted and instruct the user to immediately delete the data if a notification has arrived at the same time, or when there has already been advance notice of arrival of data in the application.
As a rule, because of the feature to prevent duplicate downloads, the system cannot download the same archive for the same task again (unless all the right conditions are present), even when NS data is deleted. To download deleted NS data again, first cancel registration for the task using the nn::boss::UnregisterTask
function, and then use the nn::boss::RegisterTask
function to reregister the task. Note that data downloaded may differ from the data that was deleted if NS data has been updated on the server. Keep this in mind when implementing the re-download process.
4.2.3. NSA List
The NSA list is a feature for retrieving listings of the NS archives on the BOSS data server. You can perform searches by specifying the BOSS code assigned when requesting the use of SpotPass, the task ID, or other attributes. A list of NS archive records matching the conditions is returned.
For more information about the settings methods for BOSS code and the NSA List, see OMAS Help.
4.2.3.1. NsaList Class
NSA list features are defined in the nn::boss::NsaList
class.
class nn::boss::NsaList { NsaList(const char* nsaListFilePath); ~NsaList(void); }
The path for storing the retrieved NSA list file is specified in the nsaListFilePath
parameter of the constructor. Specify a path within an archive that can be written by the application, as with expanded save data.
4.2.3.2. Getting an NSA Listing
Use the Download
function to get the NSA listing for a specific BOSS code and task ID. The function is executed in the foreground as an immediate task, so a connection to the Internet must be established using the AC library in advance.
When getting this information, the country and language information set in System Settings is automatically embedded in the query string.
nn::Result nn::boss::NsaList::Download( const char* bossCode, const char* taskId, const nn::boss::NsaList::SearchAttributes* attributes = NULL, u32 waitTimeoutSec = NN_BOSS_NSALIST_WAIT_FINISH_TIMEOUT_DEFAULT_SEC, s64 fileSize = NN_BOSS_NSALIST_MAX_SIZE); nn::Result nn::boss::NsaList::Cancel(void);
Specify the BOSS code in bossCode
and the task ID in taskId
.
Specify a download timeout time in seconds in waitTimeoutSec
. If this parameter is omitted, nn:: boss::NN_BOSS_NSALIST_WAIT_FINISH_TIMEOUT_DEFAULT_SEC
(currently 30 seconds) is specified. The call does not time out if a value of zero is specified.
Search conditions are specified using three attributes (attribute 1 to attribute 3; each attribute has an ASCII string of up to nine characters) in the attributes
parameter. NS archive entries are retrieved if the entry attributes are the same as those specified in the call to the Download
function. Each attribute is handled by sequence, not by combination. If attribute 1 retrieves the NSA list of the archive called "item," even if "item" is specified in attribute 2 or attribute 3, the archive is not a target for listing unless attribute 1 is not "item." If the NSA list is retrieved with conditions of attribute 1 = "A," attribute 2 = "B," and attribute 3 = "C," all of the conditions are connected by a logical AND, and only the archive that matches the sequences for all attributes is the target for listing. Entries matching these attributes are retrieved, and entries without them (NULL
or empty string) are not. However, archive entries that do not specify an attribute that is specified in a Download
call are not included in the NS archive list.
A decision, as shown below, is made for each of the three attributes. If the decision in all three cases is to get the archive entry, it is added to the list.
Attribute in Archive |
Attribute in Download Call |
Get Decision |
---|---|---|
Not specified |
Not specified |
Get |
Not specified |
Specified |
Do not get |
Specified |
Not specified |
Get |
Specified |
Specified |
Get if values match |
The attributes specified in the Download
call are the conditions used to extract data when creating the list. Only one condition can be specified per attribute. To specify more than one condition for a single attribute, the list must be retrieved without that attribute and the content of the list parsed later.
In fileSize
, specify the maximum size of the NSA List that is to be created. After creating a blank file of this size, the NSA List feature writes the NS archive list acquired by the file. When omitted, the value for the maximum size of the NSA List saved in nn::boss::NN_BOSS_NSALIST_MAX_SIZE
is set automatically.
The NSA List size is calculated using the following formula.
NSA List Size = 54 + 236 * number of NS archives included in the list
Lists including a maximum of 1000 pieces of NS archive information are acquired, so the maximum size of an NSA List is 236,054 bytes. This value can also be set explicitly only if it is not expected that lists with a maximum number of NS archive information will be acquired, or when you want to reduce the capacity of files allocated for NSA lists.
The Download
process can be canceled with the Cancel
function. Cancel
requests are processed asynchronously, so calling this function always succeeds.
4.2.3.3. Checking the Retrieved Results
The GetResult
function can be used to confirm whether the NSA list has been retrieved.
nn::boss::TaskResultCode nn::boss::NsaList::GetResult(void); u32 nn::boss::NsaList::GetHttpStatusCode(void);
The value returned by the GetResult
function is the execution result from the task used to download the NSA list. A value of TASK_SUCCESS
indicates that retrieval of the list has completed.
If GetResult
returns HTTP_ERROR_*
or SSL_ERROR_*
, a communications error has occurred. You can get the HTTP status code returned from the server using the GetHttpStatusCode
function. You can also use this to get detailed information on status when an error occurs.
4.2.3.4. Checking Validity and Updates
Use the CheckValidity
function to check the validity of the downloaded NSA list. Use the GetDigest
function to get a digest value that can be used to confirm updates to the NSA list.
bool nn::boss::NsaList::CheckValidity(void* pWorkBuf, size_t workBufSize); nn::Result nn::boss::NsaList::GetDigest(u8* pDigestBuf, size_t digestBufSize);
Specify a working buffer and its size in pWorkBuf
and workBufSize
. The size of the working buffer must be at least 256 bytes. Also, when the retrieved NSA list is large, processing may be faster if the size allocated for the buffer is larger. When the CheckValidity
function returns false
, the list content may have been corrupted.
The digest value obtained by the GetDigest
function can be used to confirm NSA list updates. The digest value is a 40-character alphanumeric string, so the buffer specified with pDigestBuf
and digestBufSize
must be at least 41 bytes.
If there have been no updates to the list obtained specifying the same attributes, the digest value will be the same. It can be used to determine whether the entire list has changed, but not whether individual NS archive entries have changed.
4.2.3.5. Parsing the NSA List
The Parse
function can be used to parse a retrieved NSA list.
nn::boss::NsaList::ParseResult nn::boss::NsaList::Parse( u32* pOutParseCount, nn::boss::NsaList::NsaInformation pNsaInformationArray[], u32 nsaInformationArraySize, void* pWorkBuf, size_t workBufSize, u32 nsaFirstPos = 0);
pNsaInformationArray
and nsaInformationArraySize
specify an array of NsaInformation
structures that store the parsing results and the number of elements in the array. The number of list entries stored in the array is stored in pOutParseCount
.
Specify a working buffer used for parsing and its size in pWorkbuf
and workBufSize
respectively. The size of the working buffer must be at least 256 bytes. Also, when the retrieved NSA list has many elements, processing can be faster if the size allocated for the buffer is larger.
When the return value is zero, all of the list entries have already been parsed. A negative return result indicates that an error has occurred. A positive result indicates that the pNsaInformationArray
was too small, and all entries could not be parsed in one call. In this case, the Parse
function can be called repeatedly, passing the previous return result in nsaFirstPos
to continue parsing.
The NsaInformation
structure is defined as follows.
struct nn::boss::NsaList::NsaInformation { char fileName[32]; u32 fileSize; u32 updateEpochTime; char attribute1[10]; char attribute2[10]; char attribute3[10]; u8 caption[150]; };
NS archive information is stored in each of these members.
Member |
Stored Information |
---|---|
|
Filename. |
|
File size. |
|
Update time (Number of seconds since 1970/01/01 00:00:00 GMT). |
|
Contents of attributes 1 to 3 set in the archive. |
|
Description (UTF-8 encoded, up to 50 characters). |
NS Archive URL
The URL specified for the NADL task has the following structure.
https://npdl.cdn.nintendowifi.net/p01/nsa/(BOSS code)/(Task ID) /(File name)?(query string)
There is an "lm
" in the query string parameter. If an archive is retrieved using a NADL task with an update time (the updateEpochTime
value) specified in this parameter and the update time is different, a value of 404 (Not Found) is returned. This is specified to avoid producing inconsistencies between the content retrieved in the NSA list and the archive content during the period when the NS archive is being replaced and the contents of the CDN cache and the NS archive are not the same.
Use for Cache Control
The NS archive cache can be controlled easily by comparing the updateEpochTime
member content in the NsaInformation
structure saved from the previous time it was retrieved with the current value. However, the time measured by the 3DS system can change due to error or user action, so update times must be compared using two updateEpochTime
values.
4.2.4. Data Upload Tasks
Data upload tasks are tasks in which data uploads are performed via an HTTP/HTTPS connection to an arbitrary data server.
Tasks that have already been registered cannot be reused with data upload tasks. When uploading again using a task with the same task ID, the task that has already been registered must first be deleted.
The new task can then be registered. Implement so that the task executes (the start instruction) immediately after registration. If power is interrupted while registering a task, the information for the task and its data become invalid. Tasks that could not begin due to a power interruption can be identified when the nn::boss::Task::GetState
function returns TASK_REGISTERED
. To re-register a task, first delete the task if it falls under the UnregisterTask
function.
You must contact support@noa.com before using data upload tasks.
4.2.5. Data Store Upload Tasks
Data Store upload tasks are tasks that upload data using the NEX library’s data store features.
Users can be specified, allowing them to view data that has been uploaded. Users can also exchange data among themselves.
A Data Store upload task can use the NEX library data store features, even when the application is not running (such as when it is in Sleep Mode) by communicating via SpotPass.
A task that has already been registered cannot be reused for a Data Store upload task. When uploading again using a task with the same task ID, the task that has already been registered must first be deleted.
The new task can then be registered. Implement so that the task executes (the start instruction) immediately after registration. If power is interrupted while registering a task, the information for the task and its data become invalid. Tasks that could not begin due to a power interruption can be identified when the nn::boss::Task::GetState
function returns TASK_REGISTERED
. To re-register a task, first delete the task if it falls under the UnregisterTask
function.
There is a maximum time lag of 20 seconds before data that has been uploaded can be downloaded.
This feature uses the NEX library, but you do not need to include the NEX library in the application.
For more information about data store features, see the NEX Library documentation.
4.2.6. Data Store Download Tasks
Data Store download tasks are tasks that download data using the NEX library’s data store features.
Because information for the data that has been downloaded is recorded, only that data viewable by the user which has not yet been downloaded is included in the download.
A Data Store download task can use the NEX library Data Store features, even when the application is not running (such as when it is in Sleep Mode) by communicating via SpotPass.
Data that has been downloaded is saved in BOSS storage in NSD format. For this reason, the same function is used for loading data as was used for the data that was downloaded using the NADL task. When BOSS storage is full, data is automatically deleted starting with the earliest data (data with earlier serial numbers). This process is also the same as is used on data downloaded using an NADL task.
By performing notification issue settings when a task is registered, a notification can be posted to the notifications list when new data is downloaded.
This feature uses the NEX library, but you do not need to include the NEX library in the application.
For more information about data store features, see the NEX Library documentation.
4.3. Presence Feature
With Nintendo DS NITRO-DWC and TWL-DWC, friend-to-friend communications had to be managed by separate implementation into each application. With 3DS, these features are supported by the SDK.
For more information about the presence features, see the System Application and Applet Specification.
4.3.1. Overview
With 3DS, systems have a shared friend list available to all games from which users can add and remove other users from the HOME Menu by standard system functions. The user does not need to independently implement an interface for management of the friend list by each application.
Also, the user does not need to add other users separately for each application. Other functionality for getting and displaying information such as friends’ Mii characters, status messages, and the title of the game currently being played is now built into the system. Applications can get or set some part of this data by calling the appropriate API function, and information about oneself and one’s friends is automatically synchronized. Because this communication process is executed by daemons running in the background, applications do not need to keep track of detailed information for sending and receiving.
The Join-In feature expands on network functionality. This feature supports inviting friends to join your group while an online game is in progress or to join a friend’s group by virtue of linkage with the NEX library. For more information about using the Join-In function, see the NEX Programming Manual: Server Services.
4.3.2. User Accounts
The presence feature includes individual accounts. Information in those accounts is shared with friends. The account ID is automatically assigned by the system.
4.3.2.1. Types of User IDs
Two types of IDs are used to identify a user of the presence feature: the principal ID and the local friend code. Both IDs are assigned different values each time the system is initialized.
Principal ID
A completely unique ID assigned upon first connection to the friend server. Although the ID will not collide with other IDs, the value is invalid and cannot be used until you connect to the friend server for the first time.
Local friend code
This user ID is used to identify users for the presence features. It is generated based on the system’s unique ID. Although extremely rare, collisions cannot be entirely avoided.
There are also two secondary IDs, friend keys and friend codes, that are generated based on these IDs.
Friend key
The concept of this ID is to handle both the principal ID and local friend code. As a rule, this ID uses the local friend code until a principal ID is issued, and then it uses the principal ID from then on.
Friend code
This 12-digit number is generated from the principal ID that is meant to be user-friendly in its format. It is generated based on the principal ID. Because it has a one-to-one correspondence with principal IDs, the two codes can be mutually converted. It includes simple error detection capability.
4.3.2.2. Account Information
The following information can be obtained from friends or made available to friends using the presence feature.
- Friend key
- The title of the Currently Playing game
- Game mode description string
- Join-in information for the Currently Playing game (for linking with the NEX library)
- Mii character
- Screen name (Mii name)
- System profile information (country and region settings)
- Friendships
- Favorite title
- Status message
Applications can set or get some part of the information in this table. In addition, some items that cannot be directly set or obtained by applications can have their setting configured or checked by the other system features, such as the HOME Menu.
Item |
Setting/Editing Local Information |
Getting/Checking Friend Information |
||
---|---|---|---|---|
Application |
System Features |
Application |
System Features |
|
Friend code |
No |
No |
No |
Yes |
Friend key |
No |
No |
Yes |
No |
The title of the Currently Playing game |
No |
Yes |
No |
Yes |
Game mode description string |
Yes |
No |
No |
Yes |
Join-in information about the Currently Playing game |
Yes |
No |
Yes |
No |
Mii character |
No |
Yes |
Yes |
Yes |
Screen name (Mii name) |
No |
Yes |
Yes |
Yes |
System profile information |
No |
Yes |
Yes |
No |
Friendships |
No |
Yes |
Yes |
Yes |
Favorite title |
No |
Yes |
No |
Yes |
Status message |
No |
Yes |
No |
Yes |
4.3.3. Managing the Friend List
With 3DS, you can add users to and remove users from the friend list by using the Friend List system applet and then saving it on the system.
This friend list can be used in common with all 3DS game titles.
4.3.3.1. Registering Friends on the Friend List
There are three methods of registering another user on the friend list. These methods are described below.
Entering a Friend Code
You can register another party by entering their friend code on the Friend List system applet. When entered, the validity of the friend code is verified by connecting to the friend server. The environment must allow connection to the Internet. The user can check the user’s friend code on the Friend List system applet.
The side entering the friend code for the other party enters a wait state to establish friendship with that other party until the other party adds you to their friend list. Friendship is established after both parties have confirmed registration of each other.
Registering Using Local Communication
You can register another party in your friend list using local communication by selecting Local on the Friend List system applet. Connection to the Internet is not required in this case.
The friendship is established without waiting under this method, because parties are added to each other’s friend lists immediately.
Registering Within an Application
You can also register another party in your friend list within an application by sending and receiving the required registration information.
When performing registration this way, confirmation must be obtained to ensure that both parties consent to friend registration before proceeding.
For more information about registration within an application, see 4.3.9. Friend Registration. The UI associated with registration must be implemented in the application.
Friend registration within an application that is performed via StreetPass or local communication, where it is not possible to identify the other party in advance, is prohibited.
For more information, see the Friend Registration section in 3DS Guidelines: Internet Communication.
4.3.3.2. Friendship Status
Friendships are established when two parties register each other on their friend lists. Friendships transition through the following states, depending on their respective registration status.
Waiting to Establish Friendship
In this state, one party has added another to his or her friend list and is waiting to be added to the other party’s friend list. When the other party adds the first party to the friend list, that fact is registered on the friend server. After the other party adds the first party to his or her friend list, the state changes to friendship established the next time a connection is made to the friend server.
Friendship Established
In this state, both parties have registered the other as a friend. Friendships must be in this status to share information such as connection status and the game title that is currently being played in real-time.
The friend server maintains a list of users that are registered in each user’s friend list. Two users who are registered on each other’s friend list are treated as being in the friendship established state. As such, friendships that have been established using local communication are not treated as being in the friendship established state until both users have gone online at least once after establishing the friendship. Usually, there is no reason to recognize this status, but it is called local friend status to distinguish it.
Friendship Canceled
This is the state, for example, when you have been removed from the friend list of another party with whom you had established a friendship. Although the other party is not just removed unexpectedly from your own friend list, once this state results, the other party appears as if offline, even if they are actually online. Follow-up access is still possible for information received from the other party before the friendship was canceled. Friendship established status can be restored if the other party registers your friend code again.
4.3.4. Initialization and Finalization
You must initialize the library by first calling nn::friends::Initialize
to use API functions in the FRIENDS library. Also, call nn::friends::Finalize
to finalize the library when it is not going to be used anymore.
The FRIENDS library has a counter for keeping the initialization count internally. If nn::friends::Initialize
has been called multiple times, you must call nn::friends::Finalize
the same number of times to completely shut down the library. Use nn::friends::IsInitialized
to check whether the library has already been initialized.
nn::Result nn::friends::Initialize(); nn::Result nn::friends::Finalize(); bool nn::friends::IsInitialized();
4.3.5. Online and Offline
The term online refers to the status when 3DS is connected to the friend server, while offline is used to describe the status when not connected. In online mode, not only can you share information with your friends, such as the title you are currently playing and the game mode, you can also receive the same information from friends who are also online. In offline mode, though you can get some information such as your friends’ names, their Mii characters, and profile information, there is no guarantee that the information is the latest available.
4.3.5.1. Autonomous Connection and Login
There are two methods of putting the 3DS in online mode.
Autonomous Connection
Even without an explicit request from the application, the friend presence daemon autonomously attempts to connect to the friend server and enter online mode if possible. This behavior is managed by the daemon manager and may stop without confirmation, as determined by the daemon manager.
In addition, if you want the application to explicitly stop this behavior, you must instruct the daemon manager to stop execution of the friend presence daemon.
Login
If the application is actively using the presence feature, you can issue a login request to enter online mode regardless of autonomous connection status.
Use nn::friends::Login
to issue a login request. If this function succeeds, a connection process runs in the background, and the nn::os::Event
object passed in pEvent
at the time the process exits enters signal status. Results of asynchronous processing can be obtained using nn::friends::GetLastResponseResult
. If a login request is issued and the system is already online, nn::friends::HasLoggedIn
returns true
.
Note: Do not, however, issue a login request for titles that do not support online play. To issue a login request, you must have already established an Internet connection using the AC (automatic connection) library. For this reason, be sure that login requests are performed only when applications also request an Internet connection.
Even if login is not required, you can cancel a login request by logging out. Again, even without logging out explicitly, login requests are canceled when the FRIENDS library is closed or when an application exits. If autonomous connection is still enabled even after logout, online status will be maintained.
nn::Result nn::friends::Login(nn::os::Event* pEvent); nn::Result nn::friends::Logout(); nn::Result nn::friends::GetLastResponseResult(); bool nn::friends::HasLoggedIn();
nn::Result result; nn::os::Event event(false); result = nn::friends::Login(&event); if (result.IsSuccess()) { // Generates an asynchronous process if Login succeeds. if (event.Wait(nn::fnd::TimeSpan::FromMinutes(2))) { result = nn::friends::GetLastResponseResult(); if (result.IsSuccess()) { // Login succeeded. } else { // Error handling. } } else { // Request must be canceled because failure of the login process has not been established. nn::friends::Logout(); } } else { // Error handling. } event.Finalize();
Asynchronous processes started by nn::friends::Login
processes terminate immediately if online status has been established by autonomous connection. The system takes several seconds to several dozen seconds to transition to online status by asynchronous process. If the user cancels the login request without waiting for this asynchronous process to end, explicitly call nn::friends::Logout
to cancel the login request or the process of connecting to the friend server connection will continue to run in the background.
4.3.5.2. Synchronizing Information With the Friend Server and Friends
User information is sent to the friend server while online and then shared with friends via the friend server.
Although local information can be updated even offline, it is not sent immediately to the friend server. Updating local information offline is synchronized by sending the information to the friend server when the system goes online and connects to the friend server.
On the other hand, updates conducted while online are immediately sent to the friend server by a friend presence daemon running in the background. However, because the library restricts the send interval to the friend server to once per 10 seconds at most for any single item, even if information is updated at a shorter interval than this, immediate synchronization with the friend server and friend is impossible. Do not communicate with the friend server at a very high frequency. For more information, see the CTR Guidelines.
nn::Result nn::friends::UpdateGameModeDescription( const char16 description[nn::friends::MODE_DESCRIPTION_SIZE]);
The nn::friends::UpdateGameModeDescription
function updates the text string describing your own game mode.
The string specified by description
is applied to what is displayed on your own friend card. Up to two lines of text having a length equal to 16 characters (in Japan, European, U.S. regions: "%"; in other regions: Japanese hiragana characters, Chinese kanji characters, Hangul characters, and so on) of the internal font at maximum width can be displayed on the friend card. The characters that can be used for this string differ depending on the system region, as shown in the following table. Characters that cannot be displayed are converted to question marks (0xE011).
Region |
Characters That Can Be Displayed |
---|---|
Japan, US, Europe |
Characters included in the internal font Japanese and Western characters |
China |
Characters included in the internal font simplified Chinese characters |
South Korea |
Characters included in the internal font Hangul characters |
Taiwan |
Characters included in the internal font traditional Chinese characters |
Some user information is saved on the friend server. Even if your friend is not online at the same time you are, this allows information in effect the last time your friend was online to be obtained from the friend server when you go online. Because the friend information obtained most recently is saved by the 3DS, you can even get friend information when you are offline. However, the friend information obtained when offline may not be the latest information. Information that is meaningless unless both you and your friend are online at the same time, such as the game mode being played, is not saved on the friend server and cannot be obtained unless both you and your friend are online.
- Information that can be obtained only when both parties are online:
- The title of the Currently Playing game
- Game mode description string
- Join-in information about the Currently Playing game
- Information that can be obtained at any time:
- Friend key
- Mii
- Screen name (Mii name)
- System profile information (country and region settings)
- Friendships
- Favorite title
- Status message
For more information about the API functions used to get friend information, see 4.3.6. Getting Friend Information.
4.3.5.3. Private Mode
Local information can be set as private from the Friend List system applet.
There are two disclosure levels.
- Only the Currently Playing game is kept private.
- All presence information is kept private.
If you keep all presence information private, you can make it appear to friends that you are offline even though you are online. In other words, information such as your Currently Playing game is not sent to your friends, and your connection status is handled as if you are offline. In addition, because even the friend server will not update your information, settings made the last time you were online with public settings will be used by the friend server for items such as your Mii character and system profile information. Friend information can be obtained in the same way as when presence information has been made public.
4.3.5.4. Getting Local System Information
Use the following functions to get the local system’s own information.
nn::friends::PrincipalId nn::friends::GetMyPrincipalId(); bool nn::friends::IsMyPreferenceValid(); nn::Result nn::friends::GetMyPreference( bool* pIsPublicMode, bool* pIsShowGameName); nn::Result nn::friends::GetMyProfile(nn::friends::Profile* pProfile); nn::Result nn::friends::GetMyPresence(nn::friends::MyPresence* pMyPresence); nn::Result nn::friends::GetMyScreenName(char16 screenName[SCREEN_NAME_SIZE]); nn::Result nn::friends::GetMyMii(nn::mii::StoreData* pMiiData);
If you have never connected to the friend server, INVALID_PRINCIPAL_ID
is returned as the principal ID.
If you have never started the friend list (a system applet), the IsMyPreferenceValid
function returns false
, because you have never touched the friend notification settings. In addition, the default value (true
) is stored for the various arguments of the GetMyPreference
function.
If you have not created a Personal Mii and you have never started the Friend List system applet, the system profile information obtained by the GetMyProfile
function reflects either the settings of the system at initial setup, or the current System Settings.
If you have not used Mii Maker to create a Personal Mii, the GetMyScreenName
function returns an empty string starting with NULL
(meaning that the second and subsequent characters are undefined). The GetMyMii
function returns empty Mii data. You must use the CFL library to determine whether the obtained Mii data is valid and to display the data.
4.3.6. Getting Friend Information
When getting friend information using the FRIENDS library, specify the friend using the friend's friend key or principal ID. You can get friend keys for users registered in your friend list using nn::friends::GetFriendKeyList
, or you can specify friend keys and principal IDs obtained externally via other communication.
4.3.6.1. Getting a Friend Key
To get the friend key of a user registered on the friend list, use nn::friends::GetFriendKeyList
. This function attempts to get the friend keys for the number of users specified by size
in order, beginning from the offset
friend in the friend list, and stores them in the buffer pointed to by pFriendKeyList
. It returns the number of friend keys actually stored in a buffer pointed to by pNum
. If the number of friend keys obtained is less than that specified by size
, the values in the buffer for friend keys that could not be stored cannot be guaranteed.
nn::Result nn::friends::GetFriendKeyList( nn::friends::FriendKey* pFriendKeyList, size_t* pNum, size_t offset = 0, size_t size = nn::friends::FRIEND_LIST_SIZE);
The local friend codes obtained through local communications are scrambled to protect privacy, so they cannot be used as is to specify friends. The FRIENDS library has prepared an API for unscrambling these local friend codes.
nn::Result nn::friends::UnscrambleLocalFriendCode( nn::friends::LocalFriendCode* pLocalFriendCodeList, const nn::uds::ScrambledLocalFriendCode* pScrambledLocalFriendCodeList, size_t size = 1);
For pScrambledLocalFriendCodeList
and size
, specify the list of (scrambled) local friend codes that was obtained through local communications and the number of entries in the list.
The result after unscrambling is stored in pLocalFriendCodeList
, so set this parameter to a value large enough to hold the number of entries specified by size
. Only the codes for friends can be unscrambled. The local friend codes for users that have not been registered to the friend list are treated as INVALID_LOCAL_FRIEND_CODE
.
When implementing your application, note the possibility that friends may have the same local friend code. The unscrambled local friend codes are not unique values, so in extremely rare instances the friend list may contain multiple friends with the same local friend code.
4.3.6.2. Getting Friend Information
Pass a list of friend keys or principal IDs to the API function used to get the friend information. As a result, friend information will be stored in a buffer passed to the first argument of each function in the same number and order as the list of friend keys or principal IDs passed to the function. If the user corresponding to the specified friend key or principal ID is not included in the friend list, invalid data is returned.
There is no API for getting friend information by specifying a list of local friend codes. Although it is possible to store a local friend code in a friend key and pass that, collisions, while extremely rare, cannot be completely avoided due to the nature of local friend codes. More than one user having the same local friend code could be registered in the friend list. As long as the friend key has been obtained from the friend list, the user in the list can be uniquely identified even if there is more than one user having the same friend code in the list, because there is never more than one user in the list without a principal ID (when there is a collision prior to establishing a friendship, the last-registered user is the one who remains).
nn::Result nn::friends::GetFriendPresence( nn::friends::FriendPresence* pFriendPresenceList, const nn::friends::FriendKey* pFriendKeyList, size_t size = 1); nn::Result nn::friends::GetFriendPresence( nn::friends::FriendPresence* pFriendPresenceList, const nn::friends::PrincipalId* pPrincipalIdList, size_t size = 1); nn::Result nn::friends::GetFriendScreenName( char16 (*pScreenNameList)[nn::friends::SCREEN_NAME_SIZE], const nn::friends::FriendKey* pFriendKeyList, size_t size = 1, bool replaceForeignCharacters = true, u8* pFontRegionList = NULL); nn::Result nn::friends::GetFriendScreenName( char16 (*pScreenNameList)[nn::friends::SCREEN_NAME_SIZE], const nn::friends::PrincipalId* pPrincipalIdList, size_t size = 1, bool replaceForeignCharacters = true, u8* pFontRegionList = NULL); nn::Result nn::friends::GetFriendMii( nn::mii::StoreData* pMiiDataList, const nn::friends::FriendKey* pFriendKeyList, size_t size = 1); nn::Result nn::friends::GetFriendMii( nn::mii::StoreData* pMiiDataList, const nn::friends::PrincipalId* pPrincipalIdList, size_t size = 1); nn::Result nn::friends::GetFriendProfile( nn::friends::Profile* pProfileList, const nn::friends::FriendKey* pFriendKeyList, size_t size = 1); nn::Result nn::friends::GetFriendProfile( nn::friends::Profile* pProfileList, const nn::friends::PrincipalId* pPrincipalIdList, size_t size = 1); nn::Result nn::friends::GetFriendAttributeFlags( bit32* pAttributeFlagsList, const nn::friends::FriendKey* pFriendKeyList, size_t size = 1); nn::Result nn::friends::GetFriendAttributeFlags( bit32* pAttributeFlagsList, const nn::friends::PrincipalId* pPrincipalIdList, size_t size = 1);
4.3.7. Notifications
To find changes in connection status with the friend server and updates to friend information without polling, you can get change notifications from the friend presence daemon by specifying the items required by the application. (Note that these notifications are separate from the user-facing messages delivered to the Notifications built-in application.)
4.3.7.1. Types of Notifications
Applications can accept the nine types of notifications listed below. In addition to the types of changes, the friend key of the friend is also notified if notification is related to friends. When a notification arrives, friend information previously obtained by a function call may have become out-of-date. Be sure to refresh this information when convenient for the application.
Definition |
Description (including functions that must be called again to refresh the data) |
---|---|
|
Indicates that the local system came online. An invalid value is stored in the friend key. |
|
Indicates that the local system went offline. An invalid value is stored in the friend key. |
|
Indicates that a friend has come online.
|
|
Indicates that the friend’s game mode has changed.
|
|
Indicates that the friend’s Mii character has changed.
|
|
Indicates that the friend’s profile has changed.
|
|
Indicates that a friend has gone offline.
|
|
Indicates that a friendship has been established with a user.
|
|
Indicates that the local system has received an invitation from a friend.
|
4.3.7.2. Notification-Related Functions
Use the following functions to get notifications from the friend presence daemon.
nn::Result nn::friends::AttachToEventNotification(nn::os::Event* pEvent); nn::Result nn::friends::SetNotificationMask(bit32 mask); u32 nn::friends::GetEventNotification( nn::friends::EventNotification* pEventNotificationList, size_t size = 1, bool* pHasOverflowed = NULL);
Event Registration
If you call nn::friends::AttachToEventNotification
and pass a pointer to an initialized nn::os::Event
object in the pEvent
parameter, that event is signaled when a notification occurs.
Setting a Notification Mask
To specify the types of notifications you want to receive, pass a bitwise OR of your desired values of the nn::friends::NotificationMask
enumerated type in the mask
parameter of the nn::friends::SetNotificationMask
function. If the daemon sends notifications of types not enabled by this mask, the nn::os::Event
object passed to nn::friends::AttachToEventNotification
is not signaled and these notifications are excluded from the notification history you can get with the nn::friends::GetEventNotification
function.
Getting Notification Details
Get notification details using the nn::friends::GetEventNotification
function. The return value is the number of notifications obtained by the call. Call this function until it returns zero to get all of the notifications accumulated in the daemon’s buffer in the same order the notifications occurred.
Notifications start accumulating when the FRIENDS library is initialized using nn::friends::Initialize
. If you want notifications to start accumulating from zero (that is, to start accumulating only notifications that are newer than the current time), you can exclude all notifications by passing 0
in the mask
parameter of the nn::friends::SetNotificationMask
function and then delete all notifications received in the past by calling the nn::friends::GetEventNotification
function once.
The notification history (the daemon’s buffer) stores up to 128 previous notifications, including private notifications sent to the system. If this buffer overflows, the earliest notification in the list is deleted first. If this buffer does overflow and earlier notifications are discarded, your application will no longer be able to track what portions of the friend presence information are out of date. In this case, the application must immediately call the functions to get the local system’s connection status and friend information again.
4.3.8. Error Handling
If a function in the FRIENDS library fails when called to get the error code, call the nn::friends::ResultToErrorCode
function, passing the nn::Result
object as the result
parameter.
u32 ResultToErrorCode(const nn::Result& result);
If this function returns zero, there is no need to display the error code. There is also no need to display the error code if the user can continue playing without experiencing any problems, such as when login fails but the application will immediately retry automatically.
When converting the content of the nn::Result
object into an error code, the nn::friends::ResultToErrorCode
function sometimes appends information related to current daemon status. Consequently, when getting an error code, call nn::friends::ResultToErrorCode
immediately after receiving a failed result.
4.3.9. Friend Registration
Friend registration within an application can be performed by mutually receiving the information for registration that the nn::friends::GetMyApproachContext
function gets, after which both parties pass the received information to the nn::friends::AddFriendWithApproach
function.
nn::Result nn::friends::GetMyApproachContext( nn::friends::ApproachContext* pApproachContext); nn::Result nn::friends::AddFriendWithApproach( nn::os::Event* pEvent, const nn::friends::ApproachContext& approachContext);
To use these functions, the FRIENDS library must be initialized. It is not necessary to log in to a friend’s server. In addition, the CFG Library must also be initialized in advance using the nn::cfg::Initialize
function.
The nn::friends::ApproachContext
structure acquired by the GetMyApproachContext
function is already encrypted, so it is not necessary to encrypt the data for sending and receiving on the application side.
Friend registration completes when calling the AddFriendWithApproach
function is successful (for example, when the Result returned for the IsSuccess
function is true
). Asynchronous processing then occurs. Asynchronous processing does not occur for any other Result
. When asynchronous processing completes, the event is passed to pEvent
and the application is notified of the signaled state. You can get the results of asynchronous processing with the nn::friends::GetLastResponseResult
function. Note that library specifications do not support simultaneous handling of multiple instances of asynchronous processing.
Friends registered with this function are local friends, and you cannot get presence information until both parties connect to the Internet and the friend relationship can be established on the friend server. Asynchronous processing merely tests the registration process on the friend server. Even when registration succeeds with both users online, presence information may not be immediately available after asynchronous processing completes.
To display information for friend registration that has been received in the application (the ApproachContext
structure), you can get the display name and Mii data using the functions shown below.
nn::Result nn::friends::GetApproachContextScreenName( char16 screenName[nn::friends::SCREEN_NAME_SIZE], const nn::friends::ApproachContext& approachContext, bool replaceForeignCharacters, u8* pFontRegion); nn::Result nn::friends::GetApproachContextMii( nn::mii::StoreData* pMiiData, const nn::friends::ApproachContext& approachContext);
The GetApproachContextScreenName
function returns the friend display name passed to screenName
to the buffer. If true
is specified for replaceForeignCharacters
at this point, characters that cannot be displayed in the system region standard font (which are included in the display name acquired) are replaced by question marks and acquired in that form. To display these characters in another region without replacing them with question marks, specify false
and then pass the pointer to the u8
type variable to pFontRegion
. The region with the standard font that can display the characters is returned to pFontRegion
by the value set in the nn::friends::FontRegion
enumerator.
The GetApproachContextMii
function returns the information required for displaying the friend’s Mii to the buffer passed to pMiiData
. The separately available Face library is also required in order to handle the Mii information acquired.