(CTR) Stylistic cleanups

This commit is contained in:
twinaphex 2020-03-05 15:50:39 +01:00
parent dc24530382
commit 860f94e914
13 changed files with 330 additions and 290 deletions

View File

@ -24,4 +24,4 @@ void dump_result_value(Result val);
#define PRINTFPOS_STR(X,Y) "\x1b["X";"Y"H" #define PRINTFPOS_STR(X,Y) "\x1b["X";"Y"H"
#define PRINTF_LINE(X) "\x1b["X";0H" #define PRINTF_LINE(X) "\x1b["X";0H"
#endif //_CTR_DEBUG_H__ #endif /* _CTR_DEBUG_H__ */

View File

@ -88,7 +88,9 @@ struct MemPool
last = nullptr; last = nullptr;
} }
//void Dump(const char* title); #if 0
void Dump(const char* title);
#endif
u32 GetFreeSpace(); u32 GetFreeSpace();
}; };
@ -159,25 +161,25 @@ static bool linearInit(void)
void* linearMemAlign(size_t size, size_t alignment) void* linearMemAlign(size_t size, size_t alignment)
{ {
// Enforce minimum alignment int shift;
/* Enforce minimum alignment */
if (alignment < 16) if (alignment < 16)
alignment = 16; alignment = 16;
// Convert alignment to shift amount /* Convert alignment to shift amount */
int shift;
for (shift = 4; shift < 32; shift ++) for (shift = 4; shift < 32; shift ++)
{ {
if ((1U<<shift) == alignment) if ((1U<<shift) == alignment)
break; break;
} }
if (shift == 32) // Invalid alignment if (shift == 32) /* Invalid alignment */
return nullptr; return nullptr;
// Initialize the pool if it is not ready /* Initialize the pool if it is not ready */
if (!sLinearPool.Ready() && !linearInit()) if (!sLinearPool.Ready() && !linearInit())
return nullptr; return nullptr;
// Allocate the chunk /* Allocate the chunk */
MemChunk chunk; MemChunk chunk;
if (!sLinearPool.Allocate(chunk, size, shift)) if (!sLinearPool.Allocate(chunk, size, shift))
return nullptr; return nullptr;
@ -211,23 +213,24 @@ void* linearAlloc(size_t size)
void* linearRealloc(void* mem, size_t size) void* linearRealloc(void* mem, size_t size)
{ {
// TODO /* TODO */
return NULL; return NULL;
} }
void linearFree(void* mem) void linearFree(void* mem)
{ {
auto node = getNode(mem); auto node = getNode(mem);
if (!node) return; if (!node)
return;
// Free the chunk /* Free the chunk */
sLinearPool.Deallocate(node->chunk); sLinearPool.Deallocate(node->chunk);
// Free the node /* Free the node */
delNode(node); delNode(node);
} }
u32 linearSpaceFree() u32 linearSpaceFree(void)
{ {
return sLinearPool.GetFreeSpace(); return sLinearPool.GetFreeSpace();
} }

View File

@ -17,8 +17,8 @@ u32 ctr_get_linear_unused(void);
u32 ctr_get_stack_free(void) u32 ctr_get_stack_free(void)
{ {
extern u32 __stack_bottom; extern u32 __stack_bottom;
uint32_t* stack_bottom_current = (u32*)__stack_bottom; uint32_t* stack_bottom_current = (u32*)__stack_bottom;
while(*stack_bottom_current++ == 0xFCFCFCFC); while(*stack_bottom_current++ == 0xFCFCFCFC);
stack_bottom_current--; stack_bottom_current--;
@ -110,12 +110,11 @@ void ctr_request_free_pages(u32 pages)
void* _sbrk_r(struct _reent *ptr, ptrdiff_t incr) void* _sbrk_r(struct _reent *ptr, ptrdiff_t incr)
{ {
static u32 sbrk_top = 0; static u32 sbrk_top = 0;
u32 tmp;
if (!sbrk_top) if (!sbrk_top)
sbrk_top = __heapBase; sbrk_top = __heapBase;
u32 tmp;
int diff = ((sbrk_top + incr + 0xFFF) & ~0xFFF) int diff = ((sbrk_top + incr + 0xFFF) & ~0xFFF)
- (__heapBase + __heap_size); - (__heapBase + __heap_size);

View File

@ -23,7 +23,7 @@ extern void* __service_ptr;
typedef u32(*backdoor_fn)(u32 arg0, u32 arg1); typedef u32(*backdoor_fn)(u32 arg0, u32 arg1);
__attribute((naked)) __attribute((naked))
static u32 svc_7b(backdoor_fn entry_fn, ...) // can pass up to two arguments to entry_fn(...) static u32 svc_7b(backdoor_fn entry_fn, ...) /* can pass up to two arguments to entry_fn(...) */
{ {
__asm__ volatile( __asm__ volatile(
"push {r0, r1, r2} \n\t" "push {r0, r1, r2} \n\t"
@ -161,19 +161,17 @@ static void target_thread_entry(mch2_thread_args_t* args)
static u32 get_first_free_basemem_page(bool isNew3DS) static u32 get_first_free_basemem_page(bool isNew3DS)
{ {
s64 v1; s64 v1;
int memused_base; int memused_base_linear; /* guessed */
int memused_base_linear; // guessed int memused_base = osGetMemRegionUsed(MEMREGION_BASE);
memused_base = osGetMemRegionUsed(MEMREGION_BASE);
svcGetSystemInfo(&v1, 2, 0); svcGetSystemInfo(&v1, 2, 0);
memused_base_linear = 0x6C000 + v1 + memused_base_linear = 0x6C000 + v1 +
(osGetKernelVersion() > SYSTEM_VERSION(2, 49, 0) ? (isNew3DS ? 0x2000 : 0x1000) : 0x0); (osGetKernelVersion() > SYSTEM_VERSION(2, 49, 0) ? (isNew3DS ? 0x2000 : 0x1000) : 0x0);
return (osGetKernelVersion() > SYSTEM_VERSION(2, 40, 0) ? 0xE0000000 : 0xF0000000) // kernel FCRAM mapping return (osGetKernelVersion() > SYSTEM_VERSION(2, 40, 0) ? 0xE0000000 : 0xF0000000) /* kernel FCRAM mapping */
+ (isNew3DS ? 0x10000000 : 0x08000000) // FCRAM size + (isNew3DS ? 0x10000000 : 0x08000000) /* FCRAM size */
- (memused_base - memused_base_linear) // memory usage for pages allocated without the MEMOP_LINEAR flag - (memused_base - memused_base_linear) /* memory usage for pages allocated without the MEMOP_LINEAR flag */
- 0x1000; // skip to the start addr of the next free page - 0x1000; /* skip to the start addr of the next free page */
} }
@ -280,7 +278,7 @@ static void do_memchunkhax2(void)
u32 alloc_address_kaddr = osConvertVirtToPhys((void*)linear_address) + mch2.kernel_fcram_mapping_offset; u32 alloc_address_kaddr = osConvertVirtToPhys((void*)linear_address) + mch2.kernel_fcram_mapping_offset;
mch2.thread_page_kva = get_first_free_basemem_page(mch2.isNew3DS) - 0x10000; // skip down 16 pages mch2.thread_page_kva = get_first_free_basemem_page(mch2.isNew3DS) - 0x10000; /* skip down 16 pages */
((u32*)linear_buffer)[0] = 1; ((u32*)linear_buffer)[0] = 1;
((u32*)linear_buffer)[1] = mch2.thread_page_kva; ((u32*)linear_buffer)[1] = mch2.thread_page_kva;
((u32*)linear_buffer)[2] = alloc_address_kaddr + (((mch2.alloc_size >> 12) - 3) << 13) + (skip_pages << 12); ((u32*)linear_buffer)[2] = alloc_address_kaddr + (((mch2.alloc_size >> 12) - 3) << 13) + (skip_pages << 12);
@ -404,8 +402,9 @@ static void gspwn(u32 dst, u32 src, u32 size, u8* flush_buffer)
* *(u32*)val1 = 0x0; * *(u32*)val1 = 0x0;
*/ */
// X-X--X-X /* X-X--X-X
// X-XXXX-X * X-XXXX-X
*/
static void memchunkhax1_write_pair(u32 val1, u32 val2) static void memchunkhax1_write_pair(u32 val1, u32 val2)
{ {
@ -458,23 +457,24 @@ static void do_memchunkhax1(void)
{ {
u32 saved_vram_value = *(u32*)0x1F000008; u32 saved_vram_value = *(u32*)0x1F000008;
// 0x1F000000 contains the enable bit for svc 0x7B /* 0x1F000000 contains the enable bit for svc 0x7B */
memchunkhax1_write_pair(get_thread_page() + THREAD_PAGE_ACL_OFFSET + SVC_ACL_OFFSET(0x7B), 0x1F000000); memchunkhax1_write_pair(get_thread_page() + THREAD_PAGE_ACL_OFFSET + SVC_ACL_OFFSET(0x7B), 0x1F000000);
write_kaddr(0x1F000008, saved_vram_value); write_kaddr(0x1F000008, saved_vram_value);
} }
Result get_luma_version(u32 *major, u32 *minor) { Result get_luma_version(u32 *major, u32 *minor)
s64 out; {
u32 version; s64 out;
u32 version;
if (R_FAILED(svcGetSystemInfo(&out, 0x10000, 0))) if (R_FAILED(svcGetSystemInfo(&out, 0x10000, 0)))
return -1; return -1;
version = (u32)out; version = (u32)out;
*major = GET_VERSION_MAJOR(version); *major = GET_VERSION_MAJOR(version);
*minor = GET_VERSION_MINOR(version); *minor = GET_VERSION_MINOR(version);
return 0; return 0;
} }
Result svchax_init(bool patch_srv) Result svchax_init(bool patch_srv)

View File

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

View File

@ -1,9 +1,14 @@
#ifndef EXEC_3DSX_H #ifndef EXEC_3DSX_H
#define EXEC_3DSX_H #define EXEC_3DSX_H
//since 3dsx programs are not guaranteed access to the OS, the 3dsx bootloader run by the exploit must run the next program /* since 3dsx programs are not guaranteed access to the OS,
//your program must have no extra threads running when this is called, these limits do not apply to exec_cia * the 3dsx bootloader run by the exploit must run the next program
*
* your program must have no extra threads running when this is called,
* these limits do not apply to exec_cia
*/
int exec_3dsx_no_path_in_args(const char* path, const char** args); int exec_3dsx_no_path_in_args(const char* path, const char** args);
int exec_3dsx(const char* path, const char** args); int exec_3dsx(const char* path, const char** args);
#endif #endif

View File

@ -13,188 +13,204 @@ typedef struct{
char argvHmac[0x20] = {0x1d, 0x78, 0xff, 0xb9, 0xc5, 0xbc, 0x78, 0xb7, 0xac, 0x29, 0x1d, 0x3e, 0x16, 0xd0, 0xcf, 0x53, 0xef, 0x12, 0x58, 0x83, 0xb6, 0x9e, 0x2f, 0x79, 0x47, 0xf9, 0x35, 0x61, 0xeb, 0x50, 0xd7, 0x67}; char argvHmac[0x20] = {0x1d, 0x78, 0xff, 0xb9, 0xc5, 0xbc, 0x78, 0xb7, 0xac, 0x29, 0x1d, 0x3e, 0x16, 0xd0, 0xcf, 0x53, 0xef, 0x12, 0x58, 0x83, 0xb6, 0x9e, 0x2f, 0x79, 0x47, 0xf9, 0x35, 0x61, 0xeb, 0x50, 0xd7, 0x67};
static void errorAndQuit(const char* errorStr){ static void errorAndQuit(const char* errorStr)
errorConf error; {
errorConf error;
errorInit(&error, ERROR_TEXT, CFG_LANGUAGE_EN); errorInit(&error, ERROR_TEXT, CFG_LANGUAGE_EN);
errorText(&error, errorStr); errorText(&error, errorStr);
errorDisp(&error); errorDisp(&error);
exit(0); exit(0);
} }
static int isCiaInstalled(u64 titleId, u16 version){ static int isCiaInstalled(u64 titleId, u16 version)
u32 titlesToRetrieve; {
u32 titlesRetrieved; u32 titlesToRetrieve;
u64* titleIds; u32 titlesRetrieved;
bool titleExists = false; u64* titleIds;
AM_TitleEntry titleInfo; bool titleExists = false;
Result failed; AM_TitleEntry titleInfo;
Result failed;
failed = AM_GetTitleCount(MEDIATYPE_SD, &titlesToRetrieve); failed = AM_GetTitleCount(MEDIATYPE_SD, &titlesToRetrieve);
if(R_FAILED(failed)) if (R_FAILED(failed))
return -1; return -1;
titleIds = malloc(titlesToRetrieve * sizeof(uint64_t)); titleIds = malloc(titlesToRetrieve * sizeof(uint64_t));
if (!titleIds) if (!titleIds)
return -1; return -1;
failed = AM_GetTitleList(&titlesRetrieved, MEDIATYPE_SD, titlesToRetrieve, titleIds); failed = AM_GetTitleList(&titlesRetrieved, MEDIATYPE_SD, titlesToRetrieve, titleIds);
if(R_FAILED(failed)) if (R_FAILED(failed))
return -1; return -1;
for(u32 titlesToCheck = 0; titlesToCheck < titlesRetrieved; titlesToCheck++){ for(u32 titlesToCheck = 0; titlesToCheck < titlesRetrieved; titlesToCheck++)
if(titleIds[titlesToCheck] == titleId){ {
titleExists = true; if (titleIds[titlesToCheck] == titleId)
break; {
} titleExists = true;
} break;
}
}
free(titleIds); free(titleIds);
if(titleExists){ if (titleExists)
failed = AM_GetTitleInfo(MEDIATYPE_SD, 1 /*titleCount*/, &titleId, &titleInfo); {
if(R_FAILED(failed)) failed = AM_GetTitleInfo(MEDIATYPE_SD, 1 /*titleCount*/, &titleId, &titleInfo);
return -1; if (R_FAILED(failed))
return -1;
if(titleInfo.version == version) if (titleInfo.version == version)
return 1; return 1;
} }
return 0; return 0;
} }
static int installCia(Handle ciaFile){ static int installCia(Handle ciaFile)
Result failed; {
Handle outputHandle; Result failed;
u64 fileSize; Handle outputHandle;
u64 fileOffset = 0; u64 fileSize;
u32 bytesRead; u64 fileOffset = 0;
u32 bytesWritten; u32 bytesRead;
u8 transferBuffer[FILE_CHUNK_SIZE]; u32 bytesWritten;
u8 transferBuffer[FILE_CHUNK_SIZE];
failed = AM_StartCiaInstall(MEDIATYPE_SD, &outputHandle); failed = AM_StartCiaInstall(MEDIATYPE_SD, &outputHandle);
if(R_FAILED(failed)) if (R_FAILED(failed))
return -1; return -1;
failed = FSFILE_GetSize(ciaFile, &fileSize); failed = FSFILE_GetSize(ciaFile, &fileSize);
if(R_FAILED(failed)) if (R_FAILED(failed))
return -1; return -1;
while(fileOffset < fileSize){ while(fileOffset < fileSize)
u64 bytesRemaining = fileSize - fileOffset; {
failed = FSFILE_Read(ciaFile, &bytesRead, fileOffset, transferBuffer, bytesRemaining < FILE_CHUNK_SIZE ? bytesRemaining : FILE_CHUNK_SIZE); u64 bytesRemaining = fileSize - fileOffset;
if(R_FAILED(failed)){ failed = FSFILE_Read(ciaFile, &bytesRead, fileOffset, transferBuffer, bytesRemaining < FILE_CHUNK_SIZE ? bytesRemaining : FILE_CHUNK_SIZE);
AM_CancelCIAInstall(outputHandle); if (R_FAILED(failed))
return -1; {
} AM_CancelCIAInstall(outputHandle);
return -1;
}
failed = FSFILE_Write(outputHandle, &bytesWritten, fileOffset, transferBuffer, bytesRead, 0); failed = FSFILE_Write(outputHandle, &bytesWritten, fileOffset, transferBuffer, bytesRead, 0);
if(R_FAILED(failed)){ if (R_FAILED(failed))
AM_CancelCIAInstall(outputHandle); {
if(R_DESCRIPTION(failed) == RD_ALREADY_EXISTS) AM_CancelCIAInstall(outputHandle);
return 1; if (R_DESCRIPTION(failed) == RD_ALREADY_EXISTS)
return -1; return 1;
} return -1;
}
if(bytesWritten != bytesRead){ if (bytesWritten != bytesRead)
AM_CancelCIAInstall(outputHandle); {
return -1; AM_CancelCIAInstall(outputHandle);
} return -1;
}
fileOffset += bytesWritten; fileOffset += bytesWritten;
} }
failed = AM_FinishCiaInstall(outputHandle); failed = AM_FinishCiaInstall(outputHandle);
if(R_FAILED(failed)) if (R_FAILED(failed))
return -1; return -1;
return 1; return 1;
} }
int exec_cia(const char* path, const char** args){ int exec_cia(const char* path, const char** args)
struct stat sBuff; {
bool fileExists; struct stat sBuff;
bool inited; bool fileExists;
bool inited;
if (!path || path[0] == '\0') if (!path || path[0] == '\0')
{ {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
fileExists = stat(path, &sBuff) == 0; fileExists = stat(path, &sBuff) == 0;
if(!fileExists){ if (!fileExists)
errno = ENOENT; {
return -1; errno = ENOENT;
} return -1;
else if(S_ISDIR(sBuff.st_mode)){ }
errno = EINVAL; else if (S_ISDIR(sBuff.st_mode))
return -1; {
} errno = EINVAL;
return -1;
}
inited = R_SUCCEEDED(amInit()) && R_SUCCEEDED(fsInit()); inited = R_SUCCEEDED(amInit()) && R_SUCCEEDED(fsInit());
if(inited){ if (inited)
Result res; {
AM_TitleEntry ciaInfo; AM_TitleEntry ciaInfo;
FS_Archive ciaArchive; FS_Archive ciaArchive;
Handle ciaFile; Handle ciaFile;
int ciaInstalled; int ciaInstalled;
ciaParam param; ciaParam param;
int argsLength; int argsLength;
/* open CIA file */
Result res = FSUSER_OpenArchive(&ciaArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
//open cia file if (R_FAILED(res))
res = FSUSER_OpenArchive(&ciaArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")); errorAndQuit("Cant open SD FS archive.");
if(R_FAILED(res))
errorAndQuit("Cant open SD FS archive.");
res = FSUSER_OpenFile(&ciaFile, ciaArchive, fsMakePath(PATH_ASCII, path + 5/*skip "sdmc:"*/), FS_OPEN_READ, 0); res = FSUSER_OpenFile(&ciaFile, ciaArchive, fsMakePath(PATH_ASCII, path + 5/*skip "sdmc:"*/), FS_OPEN_READ, 0);
if(R_FAILED(res)) if (R_FAILED(res))
errorAndQuit("Cant open CIA file."); errorAndQuit("Cant open CIA file.");
res = AM_GetCiaFileInfo(MEDIATYPE_SD, &ciaInfo, ciaFile); res = AM_GetCiaFileInfo(MEDIATYPE_SD, &ciaInfo, ciaFile);
if(R_FAILED(res)) if (R_FAILED(res))
errorAndQuit("Cant get CIA file info."); errorAndQuit("Cant get CIA file info.");
ciaInstalled = isCiaInstalled(ciaInfo.titleID, ciaInfo.version); ciaInstalled = isCiaInstalled(ciaInfo.titleID, ciaInfo.version);
if(ciaInstalled == -1){ if (ciaInstalled == -1)
//error {
errorAndQuit("Could not read title id list."); /* error */
} errorAndQuit("Could not read title ID list.");
else if(ciaInstalled == 0){ }
//not installed else if (ciaInstalled == 0)
int error = installCia(ciaFile); {
if(error == -1) /* not installed */
errorAndQuit("Cant install CIA."); int error = installCia(ciaFile);
} if (error == -1)
errorAndQuit("Cant install CIA.");
}
FSFILE_Close(ciaFile); FSFILE_Close(ciaFile);
FSUSER_CloseArchive(ciaArchive); FSUSER_CloseArchive(ciaArchive);
param.argc = 0; param.argc = 0;
argsLength = 0; argsLength = 0;
char* argLocation = param.args; char* argLocation = param.args;
while(args[param.argc] != NULL){ while(args[param.argc] != NULL)
strcpy(argLocation, args[param.argc]); {
argLocation += strlen(args[param.argc]) + 1; strcpy(argLocation, args[param.argc]);
argsLength += strlen(args[param.argc]) + 1; argLocation += strlen(args[param.argc]) + 1;
param.argc++; argsLength += strlen(args[param.argc]) + 1;
} param.argc++;
}
res = APT_PrepareToDoApplicationJump(0, ciaInfo.titleID, 0x1); res = APT_PrepareToDoApplicationJump(0, ciaInfo.titleID, 0x1);
if(R_FAILED(res)) if (R_FAILED(res))
errorAndQuit("CIA cant run, cant prepare."); errorAndQuit("CIA cant run, cant prepare.");
res = APT_DoApplicationJump(&param, sizeof(param.argc) + argsLength, argvHmac); res = APT_DoApplicationJump(&param, sizeof(param.argc) + argsLength, argvHmac);
if(R_FAILED(res)) if (R_FAILED(res))
errorAndQuit("CIA cant run, cant jump."); errorAndQuit("CIA cant run, cant jump.");
//wait for application jump, for some reason its not instant /* wait for application jump, for some reason its not instant */
while(1); while(1);
} }
//should never be reached /* should never be reached */
amExit(); amExit();
fsExit(); fsExit();
errno = ENOTSUP; errno = ENOTSUP;
return -1; return -1;
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
// C stdlib includes /* C stdlib includes */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -10,7 +10,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
// 3DS includes /* 3DS includes */
#include <3ds.h> #include <3ds.h>
#define ENTRY_ARGBUFSIZE 0x400 #define ENTRY_ARGBUFSIZE 0x400
@ -73,7 +73,7 @@ typedef struct
u32 processAppCodeAddress; u32 processAppCodeAddress;
u32 processHookTidLow, processHookTidHigh; u32 processHookTidLow, processHookTidHigh;
u32 mediatype; u32 mediatype;
bool capabilities[0x10]; // {socuAccess, csndAccess, qtmAccess, nfcAccess, httpcAccess, reserved...} bool capabilities[0x10]; /* {socuAccess, csndAccess, qtmAccess, nfcAccess, httpcAccess, reserved...} */
} memmap_header_t; } memmap_header_t;
typedef struct typedef struct

View File

@ -2,21 +2,21 @@
Handle launchOpenFile(const char* path) Handle launchOpenFile(const char* path)
{ {
if (strncmp(path, "sdmc:/", 6) == 0) Handle file;
path += 5; if (strncmp(path, "sdmc:/", 6) == 0)
else if (*path != '/') path += 5;
return 0; else if (*path != '/')
return 0;
// Convert the executable path to UTF-16 /* Convert the executable path to UTF-16 */
static uint16_t __utf16path[PATH_MAX+1]; static uint16_t __utf16path[PATH_MAX+1];
ssize_t units = utf8_to_utf16(__utf16path, (const uint8_t*)path, PATH_MAX); ssize_t units = utf8_to_utf16(__utf16path, (const uint8_t*)path, PATH_MAX);
if (units < 0 || units >= PATH_MAX) return 0; if (units < 0 || units >= PATH_MAX) return 0;
__utf16path[units] = 0; __utf16path[units] = 0;
// Open the file directly /* Open the file directly */
FS_Path apath = { PATH_EMPTY, 1, (u8*)"" }; FS_Path apath = { PATH_EMPTY, 1, (u8*)"" };
FS_Path fpath = { PATH_UTF16, (units+1)*2, (u8*)__utf16path }; FS_Path fpath = { PATH_UTF16, (units+1)*2, (u8*)__utf16path };
Handle file; Result res = FSUSER_OpenFileDirectly(&file, ARCHIVE_SDMC, apath, fpath, FS_OPEN_READ, 0);
Result res = FSUSER_OpenFileDirectly(&file, ARCHIVE_SDMC, apath, fpath, FS_OPEN_READ, 0); return R_SUCCEEDED(res) ? file : 0;
return R_SUCCEEDED(res) ? file : 0;
} }

View File

@ -12,15 +12,15 @@ enum
typedef struct typedef struct
{ {
// Mandatory fields /* Mandatory fields */
const char* name; const char* name;
u32 flags; u32 flags;
bool (* init)(void); bool (* init)(void);
void (* deinit)(void); void (* deinit)(void);
void (* launchFile)(const char* path, argData_s* args, executableMetadata_s* em); void (* launchFile)(const char* path, argData_s* args, executableMetadata_s* em);
// Optional fields /* Optional fields */
void (* useTitle)(u64 tid, u8 mediatype); void (* useTitle)(u64 tid, u8 mediatype);
} loaderFuncs_s; } loaderFuncs_s;
Handle launchOpenFile(const char* path); Handle launchOpenFile(const char* path);

View File

@ -69,5 +69,7 @@ const loaderFuncs_s loader_Ninjhax2 =
.init = init, .init = init,
.deinit = deinit, .deinit = deinit,
.launchFile = launchFile, .launchFile = launchFile,
//.useTitle = useTitle, #if 0
.useTitle = useTitle,
#endif
}; };

View File

@ -12,7 +12,7 @@ static Result HBLDR_SetTarget(const char* path)
u32 pathLen = strlen(path) + 1; u32 pathLen = strlen(path) + 1;
u32* cmdbuf = getThreadCommandBuffer(); u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(2, 0, 2); //0x20002 cmdbuf[0] = IPC_MakeHeader(2, 0, 2); /* 0x20002 */
cmdbuf[1] = IPC_Desc_StaticBuffer(pathLen, 0); cmdbuf[1] = IPC_Desc_StaticBuffer(pathLen, 0);
cmdbuf[2] = (u32)path; cmdbuf[2] = (u32)path;
@ -25,7 +25,7 @@ static Result HBLDR_SetArgv(const void* buffer, u32 size)
{ {
u32* cmdbuf = getThreadCommandBuffer(); u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(3, 0, 2); //0x30002 cmdbuf[0] = IPC_MakeHeader(3, 0, 2); /* 0x30002 */
cmdbuf[1] = IPC_Desc_StaticBuffer(size, 1); cmdbuf[1] = IPC_Desc_StaticBuffer(size, 1);
cmdbuf[2] = (u32)buffer; cmdbuf[2] = (u32)buffer;

View File

@ -15,9 +15,9 @@
void GPU_Init(Handle *gsphandle) void GPU_Init(Handle *gsphandle)
{ {
gpuCmdBuf=NULL; gpuCmdBuf = NULL;
gpuCmdBufSize=0; gpuCmdBufSize = 0;
gpuCmdBufOffset=0; gpuCmdBufOffset = 0;
} }
void GPU_Reset(u32* gxbuf, u32* gpuBuf, u32 gpuBufSize) void GPU_Reset(u32* gxbuf, u32* gpuBuf, u32 gpuBufSize)
@ -27,16 +27,18 @@ void GPU_Reset(u32* gxbuf, u32* gpuBuf, u32 gpuBufSize)
void GPU_SetFloatUniform(GPU_SHADER_TYPE type, u32 startreg, u32* data, u32 numreg) void GPU_SetFloatUniform(GPU_SHADER_TYPE type, u32 startreg, u32* data, u32 numreg)
{ {
if(!data)return; if(!data)
return;
int regOffset=(type==GPU_GEOMETRY_SHADER)?(-0x30):(0x0); int regOffset = (type == GPU_GEOMETRY_SHADER) ? (-0x30) : (0x0);
GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG+regOffset, 0x80000000|startreg); GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG+regOffset, 0x80000000|startreg);
GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA+regOffset, data, numreg*4); GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA+regOffset, data, numreg*4);
} }
//takes PAs as arguments /* takes PAs as arguments */
void GPU_SetViewport(u32* depthBuffer, u32* colorBuffer, u32 x, u32 y, u32 w, u32 h) void GPU_SetViewport(u32* depthBuffer, u32* colorBuffer,
u32 x, u32 y, u32 w, u32 h)
{ {
u32 param[0x4]; u32 param[0x4];
float fw=(float)w; float fw=(float)w;
@ -53,9 +55,9 @@ void GPU_SetViewport(u32* depthBuffer, u32* colorBuffer, u32 x, u32 y, u32 w, u3
GPUCMD_AddIncrementalWrites(GPUREG_DEPTHBUFFER_LOC, param, 0x00000003); GPUCMD_AddIncrementalWrites(GPUREG_DEPTHBUFFER_LOC, param, 0x00000003);
GPUCMD_AddWrite(GPUREG_RENDERBUF_DIM, f116e); GPUCMD_AddWrite(GPUREG_RENDERBUF_DIM, f116e);
GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, 0x00000003); //depth buffer format GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, 0x00000003); /* depth buffer format */
GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, 0x00000002); //color buffer format GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, 0x00000002); /* color buffer format */
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_BLOCK32, 0x00000000); //? GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_BLOCK32, 0x00000000); /* ? */
param[0x0]=f32tof24(fw/2); param[0x0]=f32tof24(fw/2);
param[0x1]=f32tof31(2.0f / fw) << 1; param[0x1]=f32tof31(2.0f / fw) << 1;
@ -70,7 +72,7 @@ void GPU_SetViewport(u32* depthBuffer, u32* colorBuffer, u32 x, u32 y, u32 w, u3
param[0x2]=((h-1)<<16)|((w-1)&0xFFFF); param[0x2]=((h-1)<<16)|((w-1)&0xFFFF);
GPUCMD_AddIncrementalWrites(GPUREG_SCISSORTEST_MODE, param, 0x00000003); GPUCMD_AddIncrementalWrites(GPUREG_SCISSORTEST_MODE, param, 0x00000003);
//enable depth buffer /* enable depth buffer */
param[0x0]=0x0000000F; param[0x0]=0x0000000F;
param[0x1]=0x0000000F; param[0x1]=0x0000000F;
param[0x2]=0x00000002; param[0x2]=0x00000002;
@ -136,8 +138,8 @@ void GPU_SetBlendingColor(u8 r, u8 g, u8 b, u8 a)
void GPU_SetTextureEnable(GPU_TEXUNIT units) void GPU_SetTextureEnable(GPU_TEXUNIT units)
{ {
GPUCMD_AddMaskedWrite(GPUREG_SH_OUTATTR_CLOCK, 0x2, units<<8); // enables texcoord outputs GPUCMD_AddMaskedWrite(GPUREG_SH_OUTATTR_CLOCK, 0x2, units<<8); /* enables texcoord outputs */
GPUCMD_AddWrite(GPUREG_TEXUNIT_CONFIG, 0x00011000|units); // enables texture units GPUCMD_AddWrite(GPUREG_TEXUNIT_CONFIG, 0x00011000|units); /* enables texture units */
} }
void GPU_SetTexture(GPU_TEXUNIT unit, u32* data, u16 width, u16 height, u32 param, GPU_TEXCOLOR colorType) void GPU_SetTexture(GPU_TEXUNIT unit, u32* data, u16 width, u16 height, u32 param, GPU_TEXCOLOR colorType)
@ -250,24 +252,24 @@ void GPU_SetTexEnv(u8 id, u16 rgbSources, u16 alphaSources, u16 rgbOperands, u16
param[0x1]=(alphaOperands<<12)|(rgbOperands); param[0x1]=(alphaOperands<<12)|(rgbOperands);
param[0x2]=(alphaCombine<<16)|(rgbCombine); param[0x2]=(alphaCombine<<16)|(rgbCombine);
param[0x3]=constantColor; param[0x3]=constantColor;
param[0x4]=0x00000000; // ? param[0x4]=0x00000000; /* ? */
GPUCMD_AddIncrementalWrites(GPUREG_0000|GPU_TEVID[id], param, 0x00000005); GPUCMD_AddIncrementalWrites(GPUREG_0000|GPU_TEVID[id], param, 0x00000005);
} }
void GPU_DrawArray(GPU_Primitive_t primitive, u32 first, u32 count) void GPU_DrawArray(GPU_Primitive_t primitive, u32 first, u32 count)
{ {
//set primitive type /* set primitive type */
GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 0x2, primitive); GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 0x2, primitive);
GPUCMD_AddMaskedWrite(GPUREG_RESTART_PRIMITIVE, 0x2, 0x00000001); GPUCMD_AddMaskedWrite(GPUREG_RESTART_PRIMITIVE, 0x2, 0x00000001);
//index buffer address register should be cleared (except bit 31) before drawing /* index buffer address register should be cleared (except bit 31) before drawing */
GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, 0x80000000); GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, 0x80000000);
//pass number of vertices /* pass number of vertices */
GPUCMD_AddWrite(GPUREG_NUMVERTICES, count); GPUCMD_AddWrite(GPUREG_NUMVERTICES, count);
//set first vertex /* set first vertex */
GPUCMD_AddWrite(GPUREG_VERTEX_OFFSET, first); GPUCMD_AddWrite(GPUREG_VERTEX_OFFSET, first);
//all the following except 0x000F022E might be useless /* all the following except 0x000F022E might be useless */
GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG2, 0x1, 0x00000001); GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG2, 0x1, 0x00000001);
GPUCMD_AddMaskedWrite(GPUREG_START_DRAW_FUNC0, 0x1, 0x00000000); GPUCMD_AddMaskedWrite(GPUREG_START_DRAW_FUNC0, 0x1, 0x00000000);
GPUCMD_AddWrite(GPUREG_DRAWARRAYS, 0x00000001); GPUCMD_AddWrite(GPUREG_DRAWARRAYS, 0x00000001);
@ -278,12 +280,12 @@ void GPU_DrawArray(GPU_Primitive_t primitive, u32 first, u32 count)
void GPU_DrawElements(GPU_Primitive_t primitive, u32* indexArray, u32 n) void GPU_DrawElements(GPU_Primitive_t primitive, u32* indexArray, u32 n)
{ {
//set primitive type /* set primitive type */
GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 0x2, primitive); GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 0x2, primitive);
GPUCMD_AddMaskedWrite(GPUREG_RESTART_PRIMITIVE, 0x2, 0x00000001); GPUCMD_AddMaskedWrite(GPUREG_RESTART_PRIMITIVE, 0x2, 0x00000001);
//index buffer (TODO : support multiple types) /* index buffer (TODO : support multiple types) */
GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, 0x80000000|((u32)indexArray)); GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, 0x80000000|((u32)indexArray));
//pass number of vertices /* pass number of vertices */
GPUCMD_AddWrite(GPUREG_NUMVERTICES, n); GPUCMD_AddWrite(GPUREG_NUMVERTICES, n);
GPUCMD_AddWrite(GPUREG_VERTEX_OFFSET, 0x00000000); GPUCMD_AddWrite(GPUREG_VERTEX_OFFSET, 0x00000000);
@ -296,7 +298,7 @@ void GPU_DrawElements(GPU_Primitive_t primitive, u32* indexArray, u32 n)
GPUCMD_AddMaskedWrite(GPUREG_START_DRAW_FUNC0, 0x1, 0x00000001); GPUCMD_AddMaskedWrite(GPUREG_START_DRAW_FUNC0, 0x1, 0x00000001);
GPUCMD_AddWrite(GPUREG_VTX_FUNC, 0x00000001); GPUCMD_AddWrite(GPUREG_VTX_FUNC, 0x00000001);
// CHECKME: does this one also require GPUREG_FRAMEBUFFER_FLUSH at the end? /* CHECKME: does this one also require GPUREG_FRAMEBUFFER_FLUSH at the end? */
} }
void GPU_FinishDrawing() void GPU_FinishDrawing()
@ -315,7 +317,7 @@ void GPU_Finalize(void)
GPUCMD_Split(NULL, NULL); GPUCMD_Split(NULL, NULL);
#else #else
GPUCMD_AddWrite(GPUREG_FINALIZE, 0x12345678); GPUCMD_AddWrite(GPUREG_FINALIZE, 0x12345678);
//not the cleanest way of guaranteeing 0x10-byte size but whatever good enough for now /* not the cleanest way of guaranteeing 0x10-byte size but whatever good enough for now */
GPUCMD_AddWrite(GPUREG_FINALIZE,0x12345678); GPUCMD_AddWrite(GPUREG_FINALIZE,0x12345678);
#endif #endif
} }