network/boss/source/main.c
#include <string.h>
#include <stdio.h>
#include <3ds.h>
char regionids_table[7][4] = {//https://3dbrew.org/wiki/Nandrw/sys/SecureInfo_A
"JPN",
"USA",
"EUR",
"JPN", //"AUS"
"CHN",
"KOR",
"TWN"
};
Result setup_boss()
{
Result ret=0;
u32 test_NsDataId = 0x57524248;//This can be anything.
u8 region=0;
bossContext ctx;
u8 status=0;
u32 tmp=0;
u32 contentsize=0;
char *taskID = "tmptask";//Should be unique per task(and unique per homebrew when running under *hax payload >=v2.8), unless the task is deleted afterwards.
char tmpstr[256];
printf("Running BOSS setup...\n");
ret = cfguInit();
if(ret!=0)
{
printf("Failed to init cfg: 0x%08x.\n", (unsigned int)ret);
return ret;
}
ret = CFGU_SecureInfoGetRegion(&region);
if(ret!=0)
{
printf("Failed to get region from cfg: 0x%08x.\n", (unsigned int)ret);
return ret;
}
if(region>=7)
{
printf("Region value from cfg is invalid: 0x%02x.\n", (unsigned int)region);
ret = -9;
return ret;
}
cfguExit();
ret = bossInit(0, false);
if(R_FAILED(ret))return ret;
//If you're using background tasks you should check whether the task exists first, and skip task setup if so.
bossDeleteTask(taskID, 0);
bossDeleteNsData(test_NsDataId);
//HTTP is used here since it's currently unknown how to setup a non-default rootCA cert for BOSS.
//This uses a 60-second interval, with background tasks you will probably want to change that.
//You can change the below URL to your own, the URL should include region info(see README).
memset(tmpstr, 0, sizeof(tmpstr));
snprintf(tmpstr, sizeof(tmpstr)-1, "http://yls8.mtheall.com/boss/libctru_example/%s_bossdata0.bin", regionids_table[region]);
bossSetupContextDefault(&ctx, 60, tmpstr);
ret = bossSendContextConfig(&ctx);
if(R_FAILED(ret))printf("bossSendContextConfig returned 0x%08x.\n", (unsigned int)ret);
if(R_SUCCEEDED(ret))
{
ret = bossRegisterTask(taskID, 0, 0);
if(R_FAILED(ret))printf("bossRegisterTask returned 0x%08x.\n", (unsigned int)ret);
if(R_SUCCEEDED(ret))
{
ret = bossStartTaskImmediate(taskID);
if(R_FAILED(ret))printf("bossStartTaskImmediate returned 0x%08x.\n", (unsigned int)ret);
//The below is only needed if you want to process the content immediately.
if(R_SUCCEEDED(ret))
{
printf("Waiting for the task to finish running...\n");
while(1)
{
ret = bossGetTaskState(taskID, 0, &status, NULL, NULL);
if(R_FAILED(ret))
{
printf("bossGetTaskState returned 0x%08x.\n", (unsigned int)ret);
break;
}
if(R_SUCCEEDED(ret))
{
printf("...\n");
}
if(status!=BOSSTASKSTATUS_STARTED)break;
svcSleepThread(1000000000LL);//Delay 1s.
}
}
if(R_SUCCEEDED(ret) && status==BOSSTASKSTATUS_ERROR)
{
printf("BOSS task failed. This usually indicates a network failure.\n");
ret = -9;
}
if(R_SUCCEEDED(ret))
{
printf("Reading BOSS content...\n");
ret = bossGetNsDataHeaderInfo(test_NsDataId, bossNsDataHeaderInfoType_ContentSize, &contentsize, bossNsDataHeaderInfoTypeSize_ContentSize);
if(R_FAILED(ret))printf("bossGetNsDataHeaderInfo returned 0x%08x.\n", (unsigned int)ret);
if(R_SUCCEEDED(ret))
{
printf("Content size: 0x%x.\n", (unsigned int)contentsize);
if(contentsize > sizeof(tmpstr)-1)contentsize = sizeof(tmpstr)-1;
tmp = 0;
memset(tmpstr, 0, sizeof(tmpstr));
ret = bossReadNsData(test_NsDataId, 0, tmpstr, contentsize, &tmp, NULL);
if(R_FAILED(ret))printf("bossReadNsData returned 0x%08x, transfer_total=0x%x.\n", (unsigned int)ret, (unsigned int)tmp);
}
if(R_SUCCEEDED(ret) && tmp!=contentsize)ret = -10;
//This verifies that the first 4-bytes matches the expected data, but you can do whatever with the loaded content here.
if(R_SUCCEEDED(ret) && strncmp(tmpstr, "Test", 4))ret = -11;
if(R_SUCCEEDED(ret))printf("Content data at offset 0x4: %s\n", &tmpstr[4]);
if(R_FAILED(ret))printf("BOSS data reading failed: 0x%08x.\n", (unsigned int)ret);
}
bossDeleteTask(taskID, 0);//Don't run this if you want a background task.
bossDeleteNsData(test_NsDataId);//Don't run this if the SpotPass content will be used again later.
}
}
if(R_SUCCEEDED(ret))printf("Done.\n");
bossExit();
return ret;
}
int main(int argc, char **argv) {
Result ret = 0;
gfxInitDefault();
consoleInit(GFX_TOP, NULL);
ret = setup_boss();
if(R_FAILED(ret))printf("setup_boss() failed: 0x%08x.\n", (unsigned int)ret);
printf("Press START to exit.\n");
// Main loop
while (aptMainLoop()) {
gspWaitForVBlank();
hidScanInput();
// Your code goes here
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
}
gfxExit();
return 0;
}
3ds.h
Central 3DS header.
aptMainLoop
bool aptMainLoop(void)
Main function which handles sleep mode and HOME/power buttons - call this at the beginning of every f...
bossGetTaskState
Result bossGetTaskState(const char *taskID, s8 inval, u8 *status, u32 *out1, u8 *out2)
Returns task state.
bossSetupContextDefault
void bossSetupContextDefault(bossContext *ctx, u32 seconds_interval, const char *url)
Setup a BOSS context with the default config.
bossSendContextConfig
Result bossSendContextConfig(bossContext *ctx)
Sends the config stored in the context.
bossInit
Result bossInit(u64 programID, bool force_user)
Initializes BOSS.
bossReadNsData
Result bossReadNsData(u32 NsDataId, u64 offset, void *buffer, u32 size, u32 *transfer_total, u32 *unk_out)
Reads data from the content for the specified NsDataId.
bossExit
void bossExit(void)
Exits BOSS.
bossStartTaskImmediate
Result bossStartTaskImmediate(const char *taskID)
Starts a task soon after running this command.
bossDeleteTask
Result bossDeleteTask(const char *taskID, u32 unk)
Deletes a task by using CancelTask and UnregisterTask internally.
bossDeleteNsData
Result bossDeleteNsData(u32 NsDataId)
Deletes the content file for the specified NsDataId.
bossGetNsDataHeaderInfo
Result bossGetNsDataHeaderInfo(u32 NsDataId, u8 type, void *buffer, u32 size)
Gets header info for the specified NsDataId.
bossRegisterTask
Result bossRegisterTask(const char *taskID, u8 unk0, u8 unk1)
Register a task.
cfguInit
Result cfguInit(void)
Initializes CFGU.
CFGU_SecureInfoGetRegion
Result CFGU_SecureInfoGetRegion(u8 *region)
Gets the system's region from secure info.
cfguExit
void cfguExit(void)
Exits CFGU.
consoleInit
PrintConsole * consoleInit(gfxScreen_t screen, PrintConsole *console)
Initialise the console.
gfxSwapBuffers
void gfxSwapBuffers(void)
Updates the configuration of both screens.
gfxInitDefault
void gfxInitDefault(void)
Initializes the LCD framebuffers with default parameters This is equivalent to calling:
GFX_TOP
@ GFX_TOP
Top screen.
Definition: gfx.h:26
gfxExit
void gfxExit(void)
Deinitializes and frees the LCD framebuffers.
gfxFlushBuffers
void gfxFlushBuffers(void)
Flushes the data cache for the current framebuffers.
gspWaitForVBlank
#define gspWaitForVBlank()
Waits for VBlank.
Definition: gspgpu.h:151
KEY_START
@ KEY_START
Start.
Definition: hid.h:15
hidKeysDown
u32 hidKeysDown(void)
Returns a bitmask of newly pressed buttons, this frame.
hidScanInput
void hidScanInput(void)
Scans HID for input data.
R_FAILED
#define R_FAILED(res)
Checks whether a result code indicates failure.
Definition: result.h:11
R_SUCCEEDED
#define R_SUCCEEDED(res)
Checks whether a result code indicates success.
Definition: result.h:9
bossContext
BOSS context.
Definition: boss.h:9
svcSleepThread
void svcSleepThread(s64 ns)
Puts the current thread to sleep.
u8
uint8_t u8
would be nice if newlib had this already
Definition: types.h:21
Result
s32 Result
Function result.
Definition: types.h:42
u32
uint32_t u32
32-bit unsigned integer
Definition: types.h:23