mirror of
https://github.com/switchbrew/libnx.git
synced 2025-07-04 10:32:15 +02:00
commit
fe940d2f4b
@ -4,10 +4,7 @@ Based on libctru.
|
|||||||
[](https://doozer.io/switchbrew/libnx)
|
[](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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -45,10 +45,7 @@ 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.
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u32 unk_x0;
|
u32 unk_x0;
|
||||||
u32 nvmap_handle0;
|
u32 nvmap_handle0;
|
||||||
u32 unk_x8;
|
u32 unk_x8;
|
||||||
@ -78,9 +75,8 @@ typedef struct {
|
|||||||
u32 unk_x68;
|
u32 unk_x68;
|
||||||
u32 buffer_size1;
|
u32 buffer_size1;
|
||||||
u32 unk_x70[0x33];//Normally all-zero.
|
u32 unk_x70[0x33];//Normally all-zero.
|
||||||
u64 timestamp;//Unknown, some timestamp perhaps?
|
u64 timestamp;
|
||||||
} data;
|
} PACKED data;
|
||||||
};
|
|
||||||
} PACKED bufferProducerGraphicBuffer;
|
} PACKED bufferProducerGraphicBuffer;
|
||||||
|
|
||||||
//From Android window.h.
|
//From Android window.h.
|
||||||
|
@ -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.
|
||||||
|
@ -31,6 +31,7 @@ typedef struct
|
|||||||
/// RomFS directory.
|
/// RomFS directory.
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
u32 parent; ///< Offset of the parent directory.
|
||||||
u32 sibling; ///< Offset of the next sibling directory.
|
u32 sibling; ///< Offset of the next sibling directory.
|
||||||
u32 childDir; ///< Offset of the first child directory.
|
u32 childDir; ///< Offset of the first child directory.
|
||||||
u32 childFile; ///< Offset of the first file.
|
u32 childFile; ///< Offset of the first 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);
|
||||||
|
|
||||||
|
@ -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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,6 +57,24 @@ 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;
|
||||||
|
}
|
||||||
|
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];
|
argstorage = (char*)&argdata[argvptr_pos];
|
||||||
|
|
||||||
argvptr_pos += (argdata_strsize+1 + 0x9) & ~0x7;
|
argvptr_pos += (argdata_strsize+1 + 0x9) & ~0x7;
|
||||||
@ -118,6 +136,5 @@ void argvSetup(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
__system_argv[__system_argc] = NULL;
|
__system_argv[__system_argc] = NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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, "..");
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -157,12 +157,12 @@ 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
|
// ICommonStateGetter::GetEventHandle
|
||||||
|
if (R_SUCCEEDED(rc))
|
||||||
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 {
|
do {
|
||||||
svcWaitSynchronizationSingle(g_appletMessageEventHandle, U64_MAX);
|
svcWaitSynchronizationSingle(g_appletMessageEventHandle, U64_MAX);
|
||||||
|
|
||||||
@ -186,7 +186,6 @@ Result appletInitialize(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
} while(g_appletFocusState!=1);
|
} while(g_appletFocusState!=1);
|
||||||
}
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc))
|
if (R_SUCCEEDED(rc))
|
||||||
rc = _appletAcquireForegroundRights();
|
rc = _appletAcquireForegroundRights();
|
||||||
|
Loading…
Reference in New Issue
Block a user