Merge pull request #1 from switchbrew/master

Update fork
This commit is contained in:
Mike H 2018-02-19 20:24:32 +00:00 committed by GitHub
commit fe940d2f4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 182 additions and 187 deletions

View File

@ -4,10 +4,7 @@ Based on libctru.
[![Build status](https://doozer.io/badge/switchbrew/libnx/buildstatus/master)](https://doozer.io/switchbrew/libnx) [![Build status](https://doozer.io/badge/switchbrew/libnx/buildstatus/master)](https://doozer.io/switchbrew/libnx)
# Install instructions # Install instructions
* Install [devkitA64](https://sourceforge.net/projects/devkitpro/files/devkitA64/) to `$DEVKITPRO/devkitA64`. See [Switchbrew](http://switchbrew.org/index.php?title=Setting_up_Development_Environment).
* `make install`
See also the [switch-tools](https://github.com/switchbrew/switch-tools) repo if you want to manually build those.
# Icon # Icon

View File

@ -97,7 +97,7 @@ dist-bin: all
@tar --exclude=*~ -cjf libnx-$(VERSION).tar.bz2 include lib default_icon.jpg switch_rules switch.ld switch.specs @tar --exclude=*~ -cjf libnx-$(VERSION).tar.bz2 include lib default_icon.jpg switch_rules switch.ld switch.specs
dist-src: dist-src:
@tar --exclude=*~ -cjf libnx-src-$(VERSION).tar.bz2 include source data Makefile switch_rules switch.ld switch.specs @tar --exclude=*~ -cjf libnx-src-$(VERSION).tar.bz2 include source data Makefile default_icon.jpg switch_rules switch.ld switch.specs
dist: dist-src dist-bin dist: dist-src dist-bin

View File

@ -45,42 +45,38 @@ typedef struct {
u32 numFds; u32 numFds;
u32 numInts; u32 numInts;
union { struct {//Actual size is numFds*4 + numInts*4.
u32 rawdata[0x144>>2];//Actual size is numFds*4 + numInts*4. u32 unk_x0;
u32 nvmap_handle0;
struct { u32 unk_x8;
u32 unk_x0; u32 unk_xc;
u32 nvmap_handle0; u32 unk_x10;
u32 unk_x8; u32 unk_x14;
u32 unk_xc; u32 unk_x18;
u32 unk_x10; u32 unk_x1c;
u32 unk_x14; u32 unk_x20;
u32 unk_x18; u32 width_unk0;
u32 unk_x1c; u32 buffer_size0;
u32 unk_x20; u32 unk_x2c;
u32 width_unk0; u32 unk_x30;
u32 buffer_size0; u32 width_unk1;
u32 unk_x2c; u32 height_unk;
u32 unk_x30; u32 flags;
u32 width_unk1; u32 unk_x40;
u32 height_unk; u32 unk_x44;
u32 flags; u32 byte_stride;
u32 unk_x40; u32 nvmap_handle1;
u32 unk_x44; u32 buffer_offset;
u32 byte_stride; u32 unk_x54;
u32 nvmap_handle1; u32 unk_x58;
u32 buffer_offset; u32 unk_x5c;
u32 unk_x54; u32 unk_x60;
u32 unk_x58; u32 unk_x64;
u32 unk_x5c; u32 unk_x68;
u32 unk_x60; u32 buffer_size1;
u32 unk_x64; u32 unk_x70[0x33];//Normally all-zero.
u32 unk_x68; u64 timestamp;
u32 buffer_size1; } PACKED data;
u32 unk_x70[0x33];//Normally all-zero.
u64 timestamp;//Unknown, some timestamp perhaps?
} data;
};
} PACKED bufferProducerGraphicBuffer; } PACKED bufferProducerGraphicBuffer;
//From Android window.h. //From Android window.h.

View File

@ -41,6 +41,7 @@ void gfxExit(void);
* @note The default resolution is 720p. * @note The default resolution is 720p.
* @note This can only be used before calling \ref gfxInitDefault, this will use \ref fatalSimple otherwise. If the input is 0, the default resolution will be used during \ref gfxInitDefault. This sets the maximum resolution for the framebuffer, used during \ref gfxInitDefault. This is also used as the current resolution when crop isn't set. The width/height are reset to the default when \ref gfxExit is used. * @note This can only be used before calling \ref gfxInitDefault, this will use \ref fatalSimple otherwise. If the input is 0, the default resolution will be used during \ref gfxInitDefault. This sets the maximum resolution for the framebuffer, used during \ref gfxInitDefault. This is also used as the current resolution when crop isn't set. The width/height are reset to the default when \ref gfxExit is used.
* @note Normally you should only use this when you need a maximum resolution larger than the default, see above. * @note Normally you should only use this when you need a maximum resolution larger than the default, see above.
* @note The width and height are aligned to 4.
*/ */
void gfxInitResolution(u32 width, u32 height); void gfxInitResolution(u32 width, u32 height);
@ -52,6 +53,7 @@ void gfxInitResolutionDefault(void);
/// This will update the display width/height returned by \ref gfxGetFramebuffer, with that width/height being reset to the default when required. /// This will update the display width/height returned by \ref gfxGetFramebuffer, with that width/height being reset to the default when required.
/// \ref gfxGetFramebufferDisplayOffset uses absolute x/y, it will not adjust for non-zero crop left/top. /// \ref gfxGetFramebufferDisplayOffset uses absolute x/y, it will not adjust for non-zero crop left/top.
/// The new crop config will not take affect with double-buffering disabled. When used during frame-drawing, this should be called before \ref gfxGetFramebuffer. /// The new crop config will not take affect with double-buffering disabled. When used during frame-drawing, this should be called before \ref gfxGetFramebuffer.
/// The right and bottom params are aligned to 4.
void gfxConfigureCrop(s32 left, s32 top, s32 right, s32 bottom); void gfxConfigureCrop(s32 left, s32 top, s32 right, s32 bottom);
/// Wrapper for \ref gfxConfigureCrop. Use this to set the resolution, within the bounds of the maximum resolution. Use all-zero input to reset to default. /// Wrapper for \ref gfxConfigureCrop. Use this to set the resolution, within the bounds of the maximum resolution. Use all-zero input to reset to default.

View File

@ -16,39 +16,40 @@
/// RomFS header. /// RomFS header.
typedef struct typedef struct
{ {
u64 headerSize; ///< Size of the header. u64 headerSize; ///< Size of the header.
u64 dirHashTableOff; ///< Offset of the directory hash table. u64 dirHashTableOff; ///< Offset of the directory hash table.
u64 dirHashTableSize; ///< Size of the directory hash table. u64 dirHashTableSize; ///< Size of the directory hash table.
u64 dirTableOff; ///< Offset of the directory table. u64 dirTableOff; ///< Offset of the directory table.
u64 dirTableSize; ///< Size of the directory table. u64 dirTableSize; ///< Size of the directory table.
u64 fileHashTableOff; ///< Offset of the file hash table. u64 fileHashTableOff; ///< Offset of the file hash table.
u64 fileHashTableSize; ///< Size of the file hash table. u64 fileHashTableSize; ///< Size of the file hash table.
u64 fileTableOff; ///< Offset of the file table. u64 fileTableOff; ///< Offset of the file table.
u64 fileTableSize; ///< Size of the file table. u64 fileTableSize; ///< Size of the file table.
u64 fileDataOff; ///< Offset of the file data. u64 fileDataOff; ///< Offset of the file data.
} romfs_header; } romfs_header;
/// RomFS directory. /// RomFS directory.
typedef struct typedef struct
{ {
u32 sibling; ///< Offset of the next sibling directory. u32 parent; ///< Offset of the parent directory.
u32 childDir; ///< Offset of the first child directory. u32 sibling; ///< Offset of the next sibling directory.
u32 childFile; ///< Offset of the first file. u32 childDir; ///< Offset of the first child directory.
u32 nextHash; ///< Directory hash table pointer. u32 childFile; ///< Offset of the first file.
u32 nameLen; ///< Name length. u32 nextHash; ///< Directory hash table pointer.
uint8_t name[]; ///< Name. (UTF-8) u32 nameLen; ///< Name length.
uint8_t name[]; ///< Name. (UTF-8)
} romfs_dir; } romfs_dir;
/// RomFS file. /// RomFS file.
typedef struct typedef struct
{ {
u32 parent; ///< Offset of the parent directory. u32 parent; ///< Offset of the parent directory.
u32 sibling; ///< Offset of the next sibling file. u32 sibling; ///< Offset of the next sibling file.
u64 dataOff; ///< Offset of the file's data. u64 dataOff; ///< Offset of the file's data.
u64 dataSize; ///< Length of the file's data. u64 dataSize; ///< Length of the file's data.
u32 nextHash; ///< File hash table pointer. u32 nextHash; ///< File hash table pointer.
u32 nameLen; ///< Name length. u32 nameLen; ///< Name length.
uint8_t name[]; ///< Name. (UTF-8) uint8_t name[]; ///< Name. (UTF-8)
} romfs_file; } romfs_file;
struct romfs_mount; struct romfs_mount;
@ -60,7 +61,7 @@ struct romfs_mount;
Result romfsMount(struct romfs_mount **mount); Result romfsMount(struct romfs_mount **mount);
static inline Result romfsInit(void) static inline Result romfsInit(void)
{ {
return romfsMount(NULL); return romfsMount(NULL);
} }
/** /**
@ -72,7 +73,7 @@ static inline Result romfsInit(void)
Result romfsMountFromFile(FsFile file, u64 offset, struct romfs_mount **mount); Result romfsMountFromFile(FsFile file, u64 offset, struct romfs_mount **mount);
static inline Result romfsInitFromFile(FsFile file, u64 offset) static inline Result romfsInitFromFile(FsFile file, u64 offset)
{ {
return romfsMountFromFile(file, offset, NULL); return romfsMountFromFile(file, offset, NULL);
} }
/// Bind the RomFS mount /// Bind the RomFS mount
@ -82,6 +83,6 @@ Result romfsBind(struct romfs_mount *mount);
Result romfsUnmount(struct romfs_mount *mount); Result romfsUnmount(struct romfs_mount *mount);
static inline Result romfsExit(void) static inline Result romfsExit(void)
{ {
return romfsUnmount(NULL); return romfsUnmount(NULL);
} }

View File

@ -60,8 +60,6 @@ u64 envGetHeapOverrideSize(void);
/// Returns true if the environment has an argv array. /// Returns true if the environment has an argv array.
bool envHasArgv(void); bool envHasArgv(void);
/// Returns the number of arguments in the argv array.
u64 envGetArgc(void);
/// Returns the pointer to the argv array. /// Returns the pointer to the argv array.
void* envGetArgv(void); void* envGetArgv(void);

View File

@ -78,7 +78,6 @@ static bufferProducerQueueBufferInput g_gfxQueueBufferData = {
}; };
//Some of this struct is based on tegra_dc_ext_flip_windowattr. //Some of this struct is based on tegra_dc_ext_flip_windowattr.
//TODO: How much of this struct do official apps really set? Most of it seems to be used as-is from the bufferProducerRequestBuffer() output.
static bufferProducerGraphicBuffer g_gfx_BufferInitData = { static bufferProducerGraphicBuffer g_gfx_BufferInitData = {
.magic = 0x47424652,//"RFBG"/'GBFR' .magic = 0x47424652,//"RFBG"/'GBFR'
.format = 0x1, .format = 0x1,
@ -397,8 +396,8 @@ void gfxExit(void)
void gfxInitResolution(u32 width, u32 height) { void gfxInitResolution(u32 width, u32 height) {
if (g_gfxInitialized) fatalSimple(MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized)); if (g_gfxInitialized) fatalSimple(MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized));
g_gfx_framebuf_width = width; g_gfx_framebuf_width = (width+3) & ~3;
g_gfx_framebuf_height = height; g_gfx_framebuf_height = (height+3) & ~3;
} }
void gfxInitResolutionDefault(void) { void gfxInitResolutionDefault(void) {
@ -412,6 +411,10 @@ void gfxConfigureCrop(s32 left, s32 top, s32 right, s32 bottom) {
} }
if (left < 0 || top < 0 || right < 0 || bottom < 0) return; if (left < 0 || top < 0 || right < 0 || bottom < 0) return;
right = (right+3) & ~3;
bottom = (bottom+3) & ~3;
if (right < left || bottom < top) return; if (right < left || bottom < top) return;
if (left > g_gfx_framebuf_width || top > g_gfx_framebuf_height) return; if (left > g_gfx_framebuf_width || top > g_gfx_framebuf_height) return;
if (right > g_gfx_framebuf_width || bottom > g_gfx_framebuf_height) return; if (right > g_gfx_framebuf_width || bottom > g_gfx_framebuf_height) return;
@ -540,26 +543,14 @@ void gfxFlushBuffers(void) {
u32 *actual_framebuf = (u32*)&g_gfxFramebuf[g_gfxCurrentBuffer*g_gfx_singleframebuf_size]; u32 *actual_framebuf = (u32*)&g_gfxFramebuf[g_gfxCurrentBuffer*g_gfx_singleframebuf_size];
if (g_gfxMode == GfxMode_LinearDouble) { if (g_gfxMode == GfxMode_LinearDouble) {
//TODO: Implement block-linear here without re-calculating the entire offset with gfxGetFramebufferDisplayOffset(). size_t x, y;
size_t x, y, j, tmpoff;
size_t width = g_gfx_framebuf_display_width; size_t width = g_gfx_framebuf_display_width;
size_t height = g_gfx_framebuf_display_height; size_t height = g_gfx_framebuf_display_height;
u32 *in_framebuf = (u32*)g_gfxFramebufLinear; u32 *in_framebuf = (u32*)g_gfxFramebufLinear;
for (y=0; y<height; y++) { for (y=0; y<height; y++) {
for (x=0; x<width; x+=4) { for (x=0; x<width; x+=4) {
tmpoff = gfxGetFramebufferDisplayOffset(x, y); *((u128*)&actual_framebuf[gfxGetFramebufferDisplayOffset(x, y)]) = *((u128*)&in_framebuf[y * width + x]);
if(width & 3) {
for(j=0; j<4; j++) {
if (x+j >= width)
break;
actual_framebuf[tmpoff+j] = in_framebuf[y * width + x+j];
}
}
else {
*((u128*)&actual_framebuf[tmpoff]) = *((u128*)&in_framebuf[y * width + x]);
}
} }
} }
} }

View File

@ -13,6 +13,8 @@ extern char* fake_heap_end;
extern u32 __argdata__; extern u32 __argdata__;
static char* g_argv_empty = NULL;
void argvSetup(void) void argvSetup(void)
{ {
Result rc=0; Result rc=0;
@ -21,22 +23,20 @@ void argvSetup(void)
u8 *argdata = (u8*)&__argdata__; u8 *argdata = (u8*)&__argdata__;
u32 *arg32 = (u32*)argdata; u32 *arg32 = (u32*)argdata;
u64 argdata_allocsize; u64 argdata_allocsize=0;
u64 argdata_strsize; u64 argdata_strsize=0;
u32 argvptr_pos; u32 argvptr_pos=0;
u32 max_argv; u32 max_argv;
u32 argi; u32 argi;
u32 arglen=0; u32 arglen=0;
bool quote_flag=0; bool quote_flag=0;
bool end_flag=0; bool end_flag=0;
char *args; char *args = NULL;
char *argstart; char *argstart;
char *argstorage; char *argstorage;
__system_argc = 0; __system_argc = 0;
__system_argv = NULL; __system_argv = &g_argv_empty;
// TODO: Use envHasArgv() here for the NRO case.
if (envIsNso()) { if (envIsNso()) {
memset(&meminfo, 0, sizeof(meminfo)); memset(&meminfo, 0, sizeof(meminfo));
@ -57,67 +57,84 @@ void argvSetup(void)
argvptr_pos = 0x20 + argdata_strsize+1; argvptr_pos = 0x20 + argdata_strsize+1;
if (argvptr_pos >= argdata_allocsize) return; if (argvptr_pos >= argdata_allocsize) return;
argstorage = (char*)&argdata[argvptr_pos];
argvptr_pos += (argdata_strsize+1 + 0x9) & ~0x7;
if (argvptr_pos >= argdata_allocsize) return;
max_argv = (argdata_allocsize - argvptr_pos) >> 3;
if (max_argv < 2) return;
__system_argv = (char**)&argdata[argvptr_pos];
argstart = NULL;
for(argi=0; argi<argdata_strsize; argi++) {
if (argstart == NULL && isspace(args[argi])) continue;
if (argstart == NULL) {
if (args[argi] == '"') {
argstart = &args[argi+1];
quote_flag = 1;
}
else if(args[argi]!=0) {
argstart = &args[argi];
arglen++;
}
}
else {
end_flag = 0;
if (quote_flag && args[argi] == '"') {
end_flag = 1;
}
else if (isspace(args[argi])) {
end_flag = 1;
}
else if(args[argi]!=0) {
arglen++;
}
if ((args[argi]==0 || end_flag) && arglen) {
strncpy(argstorage, argstart, arglen);
argstorage[arglen] = 0;
__system_argv[__system_argc] = argstorage;
__system_argc++;
argstart = NULL;
quote_flag = 0;
argstorage+= arglen+1;
arglen = 0;
if (__system_argc >= max_argv) break;
}
}
}
if (arglen && __system_argc < max_argv) {
strncpy(argstorage, argstart, arglen);
argstorage[arglen] = 0;
__system_argv[__system_argc] = argstorage;
__system_argc++;
}
__system_argv[__system_argc] = NULL;
} }
else if (envHasArgv()) {
args = envGetArgv();
argdata_allocsize = 0x9000;//Use the same size as NSO.
argdata_strsize = strlen(args);
argdata = (u8*)fake_heap_start;
if (argdata_strsize==0) return;
if (fake_heap_end - fake_heap_start < argdata_allocsize) return;
fake_heap_start += argdata_allocsize;
argvptr_pos = 0;
memset(argdata, 0, argdata_allocsize);
}
argstorage = (char*)&argdata[argvptr_pos];
argvptr_pos += (argdata_strsize+1 + 0x9) & ~0x7;
if (argvptr_pos >= argdata_allocsize) return;
max_argv = (argdata_allocsize - argvptr_pos) >> 3;
if (max_argv < 2) return;
__system_argv = (char**)&argdata[argvptr_pos];
argstart = NULL;
for(argi=0; argi<argdata_strsize; argi++) {
if (argstart == NULL && isspace(args[argi])) continue;
if (argstart == NULL) {
if (args[argi] == '"') {
argstart = &args[argi+1];
quote_flag = 1;
}
else if(args[argi]!=0) {
argstart = &args[argi];
arglen++;
}
}
else {
end_flag = 0;
if (quote_flag && args[argi] == '"') {
end_flag = 1;
}
else if (isspace(args[argi])) {
end_flag = 1;
}
else if(args[argi]!=0) {
arglen++;
}
if ((args[argi]==0 || end_flag) && arglen) {
strncpy(argstorage, argstart, arglen);
argstorage[arglen] = 0;
__system_argv[__system_argc] = argstorage;
__system_argc++;
argstart = NULL;
quote_flag = 0;
argstorage+= arglen+1;
arglen = 0;
if (__system_argc >= max_argv) break;
}
}
}
if (arglen && __system_argc < max_argv) {
strncpy(argstorage, argstart, arglen);
argstorage[arglen] = 0;
__system_argv[__system_argc] = argstorage;
__system_argc++;
}
__system_argv[__system_argc] = NULL;
} }

View File

@ -294,7 +294,7 @@ Result romfsMountCommon(romfs_mount *mount)
mount->dirTable = malloc(mount->header.dirTableSize); mount->dirTable = malloc(mount->header.dirTableSize);
if (!mount->dirTable) if (!mount->dirTable)
goto fail; goto fail;
if (!_romfs_read_chk(mount, mount->header.dirTableOff + 4, mount->dirTable, mount->header.dirTableSize)) if (!_romfs_read_chk(mount, mount->header.dirTableOff, mount->dirTable, mount->header.dirTableSize))
goto fail; goto fail;
mount->fileHashTable = (u32*)malloc(mount->header.fileHashTableSize); mount->fileHashTable = (u32*)malloc(mount->header.fileHashTableSize);
@ -411,7 +411,7 @@ static romfs_dir* searchForDir(romfs_mount *mount, romfs_dir* parent, const uint
for (curOff = mount->dirHashTable[hash]; curOff != romFS_none; curOff = curDir->nextHash) for (curOff = mount->dirHashTable[hash]; curOff != romFS_none; curOff = curDir->nextHash)
{ {
curDir = romFS_dir(mount, curOff); curDir = romFS_dir(mount, curOff);
//if (curDir->parent != parentOff) continue;//TODO: How to handle parent here? if (curDir->parent != parentOff) continue;
if (curDir->nameLen != namelen) continue; if (curDir->nameLen != namelen) continue;
if (memcmp(curDir->name, name, namelen) != 0) continue; if (memcmp(curDir->name, name, namelen) != 0) continue;
return curDir; return curDir;
@ -478,7 +478,7 @@ static int navigateToDir(romfs_mount *mount, romfs_dir** ppDir, const char** pPa
if (!component[1]) continue; if (!component[1]) continue;
if (component[1]=='.' && !component[2]) if (component[1]=='.' && !component[2])
{ {
//*ppDir = romFS_dir(mount, (*ppDir)->parent);//TODO: How to handle parent here? *ppDir = romFS_dir(mount, (*ppDir)->parent);
continue; continue;
} }
} }
@ -762,10 +762,10 @@ int romfs_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename, struct s
else if(iter->state == 1) else if(iter->state == 1)
{ {
/* '..' entry */ /* '..' entry */
//romfs_dir* dir = romFS_dir(iter->mount, iter->dir->parent);//TODO: How to handle parent here? romfs_dir* dir = romFS_dir(iter->mount, iter->dir->parent);
memset(filestat, 0, sizeof(*filestat)); memset(filestat, 0, sizeof(*filestat));
//filestat->st_ino = dir_inode(iter->mount, dir); filestat->st_ino = dir_inode(iter->mount, dir);
filestat->st_mode = romFS_dir_mode; filestat->st_mode = romFS_dir_mode;
strcpy(filename, ".."); strcpy(filename, "..");

View File

@ -11,7 +11,6 @@ static Handle g_mainThreadHandle = INVALID_HANDLE;
static LoaderReturnFn g_loaderRetAddr = NULL; static LoaderReturnFn g_loaderRetAddr = NULL;
static void* g_overrideHeapAddr = NULL; static void* g_overrideHeapAddr = NULL;
static u64 g_overrideHeapSize = 0; static u64 g_overrideHeapSize = 0;
static u64 g_overrideArgc = 0;
static void* g_overrideArgv = NULL; static void* g_overrideArgv = NULL;
static u64 g_syscallHints[2]; static u64 g_syscallHints[2];
static Handle g_processHandle = INVALID_HANDLE; static Handle g_processHandle = INVALID_HANDLE;
@ -69,7 +68,6 @@ void envSetup(void* ctx, Handle main_thread, LoaderReturnFn saved_lr)
break; break;
case EntryType_Argv: case EntryType_Argv:
g_overrideArgc = ent->Value[0];
g_overrideArgv = (void*) ent->Value[1]; g_overrideArgv = (void*) ent->Value[1];
break; break;
@ -129,10 +127,6 @@ bool envHasArgv(void) {
return g_overrideArgv != NULL; return g_overrideArgv != NULL;
} }
u64 envGetArgc(void) {
return g_overrideArgc;
}
void* envGetArgv(void) { void* envGetArgv(void) {
return g_overrideArgv; return g_overrideArgv;
} }

View File

@ -157,36 +157,35 @@ Result appletInitialize(void)
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
rc = _appletGetSession(&g_appletProxySession, &g_appletIDebugFunctions, 1000); rc = _appletGetSession(&g_appletProxySession, &g_appletIDebugFunctions, 1000);
if (R_SUCCEEDED(rc) && (__nx_applet_type == AppletType_Application)) // ICommonStateGetter::GetEventHandle
{ if (R_SUCCEEDED(rc))
// ICommonStateGetter::GetEventHandle
rc = _appletGetHandle(&g_appletICommonStateGetter, &g_appletMessageEventHandle, 0); rc = _appletGetHandle(&g_appletICommonStateGetter, &g_appletMessageEventHandle, 0);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc) && (__nx_applet_type == AppletType_Application))
do { {
svcWaitSynchronizationSingle(g_appletMessageEventHandle, U64_MAX); do {
svcWaitSynchronizationSingle(g_appletMessageEventHandle, U64_MAX);
u32 msg; u32 msg;
rc = _appletReceiveMessage(&msg); rc = _appletReceiveMessage(&msg);
if (R_FAILED(rc)) if (R_FAILED(rc))
{ {
if ((rc & 0x3fffff) == 0x680) if ((rc & 0x3fffff) == 0x680)
continue;
break;
}
if (msg != 0xF)
continue; continue;
rc = _appletGetCurrentFocusState(&g_appletFocusState); break;
}
if (R_FAILED(rc)) if (msg != 0xF)
break; continue;
} while(g_appletFocusState!=1); rc = _appletGetCurrentFocusState(&g_appletFocusState);
}
if (R_FAILED(rc))
break;
} while(g_appletFocusState!=1);
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
rc = _appletAcquireForegroundRights(); rc = _appletAcquireForegroundRights();