Files
RetroArch/os/ctr/exec-3dsx/exec_3dsx.c
T
LibretroAdmin bae87174dc 3DS: the runtime moves to os/ctr, linear allocator in C
The tree's 3DS layer (the custom crt0 and link spec, system and memory
setup, svchax, the old GPU command layer and the 3dsx/CIA launchers)
lives under os/ctr, beside os/gekko and os/wiiu.

The linear heap allocator is C: the same first-fit pool, so buffers
land where they did, with live allocations found by address in an
open-addressing table instead of a per-allocation tree node, and list
nodes taken from cache-line-aligned slabs and reused. On the same
trace it runs about half the instructions and practically no
malloc/free calls. With the whole heap allocated, a further allocation
now fails instead of starting the heap over and handing out its first
address again, and the free-space queries no longer fault.

samples/frontend/ctr_linear checks placement, alignment, coalescing,
the full-heap case and pages handed back from the heap's end.
2026-10-29 18:10:30 +01:00

92 lines
2.0 KiB
C

#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include "mini-hb-menu/common.h"
extern const loaderFuncs_s loader_Ninjhax2;
extern const loaderFuncs_s loader_Rosalina;
static void (*launch_3dsx)(const char* path,
argData_s* args, executableMetadata_s* em);
static int exec_3dsx_actual(const char* path,
const char** args, bool appendPath)
{
bool inited;
bool fileExists;
struct stat sBuff;
argData_s newProgramArgs;
unsigned int argChars = 0;
unsigned int argNum = 0;
if (!path || path[0] == '\0')
{
errno = EINVAL;
return -1;
}
fileExists = stat(path, &sBuff) == 0;
if (!fileExists)
{
errno = ENOENT;
return -1;
}
else if (S_ISDIR(sBuff.st_mode))
{
errno = EINVAL;
return -1;
}
/* args the string functions write to the passed string,
* this will cause a write to read only memory,
* so the string must be cloned */
memset(newProgramArgs.buf, '\0', sizeof(newProgramArgs.buf));
newProgramArgs.dst = (char*)&newProgramArgs.buf[1];
if (appendPath)
{
strcpy(newProgramArgs.dst, path);
newProgramArgs.dst += strlen(path) + 1;
newProgramArgs.buf[0]++;
}
while(args[argNum])
{
strcpy(newProgramArgs.dst, args[argNum]);
newProgramArgs.dst += strlen(args[argNum]) + 1;
newProgramArgs.buf[0]++;
argNum++;
}
inited = loader_Rosalina.init();
launch_3dsx = loader_Rosalina.launchFile;
if (!inited)
{
inited = loader_Ninjhax2.init();
launch_3dsx = loader_Ninjhax2.launchFile;
}
if (inited)
{
osSetSpeedupEnable(false);
launch_3dsx(path, &newProgramArgs, NULL);
exit(0);
}
/* should never be reached */
errno = ENOTSUP;
return -1;
}
int exec_3dsx(const char* path, const char** args)
{
return exec_3dsx_actual(path, args, true/*appendPath*/);
}
int exec_3dsx_no_path_in_args(const char* path, const char** args)
{
return exec_3dsx_actual(path, args, false/*appendPath*/);
}