mirror of
https://github.com/wiiu-env/homebrew_launcher.git
synced 2024-11-27 23:24:16 +01:00
installer: changed to single link launch (TODO: clean up the code)
This commit is contained in:
parent
f712a697ad
commit
40908f5d8f
@ -88,6 +88,12 @@
|
|||||||
dcbf 0, r3 ; \
|
dcbf 0, r3 ; \
|
||||||
icbi 0, r3 ;
|
icbi 0, r3 ;
|
||||||
|
|
||||||
|
.globl SC_0x25_KernelCopyData
|
||||||
|
SC_0x25_KernelCopyData:
|
||||||
|
li r0, 0x2500
|
||||||
|
sc
|
||||||
|
blr
|
||||||
|
|
||||||
.globl Syscall_0x36
|
.globl Syscall_0x36
|
||||||
Syscall_0x36:
|
Syscall_0x36:
|
||||||
mflr r0
|
mflr r0
|
||||||
|
@ -357,10 +357,17 @@ void run_kexploit(private_data_t *private_data)
|
|||||||
//give that memory area read/write permissions
|
//give that memory area read/write permissions
|
||||||
kern_write((void*)(KERN_ADDRESS_TBL + (0x13 * 4)), 0x28305800);
|
kern_write((void*)(KERN_ADDRESS_TBL + (0x13 * 4)), 0x28305800);
|
||||||
|
|
||||||
printOSScreenMsg(coreinit_handle, "Success! Re-launch HBL again...",2);
|
private_data->MEMFreeToDefaultHeap(thread0);
|
||||||
wait(0x1FFFFFFF);
|
private_data->MEMFreeToDefaultHeap(thread1);
|
||||||
callSysExit(coreinit_handle,SYSSwitchToBrowser);
|
private_data->MEMFreeToDefaultHeap(thread2);
|
||||||
exitOSScreen(coreinit_handle);
|
private_data->MEMFreeToDefaultHeap((void*)stack0);
|
||||||
|
private_data->MEMFreeToDefaultHeap((void*)stack1);
|
||||||
|
private_data->MEMFreeToDefaultHeap((void*)stack2);
|
||||||
|
|
||||||
|
//printOSScreenMsg(coreinit_handle, "Success! Re-launch HBL again...",2);
|
||||||
|
//wait(0x1FFFFFFF);
|
||||||
|
//callSysExit(coreinit_handle,SYSSwitchToBrowser);
|
||||||
|
//exitOSScreen(coreinit_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait(unsigned int t)
|
void wait(unsigned int t)
|
||||||
|
@ -61,8 +61,10 @@ static int show_install_menu(unsigned int coreinit_handle, unsigned int *ip_addr
|
|||||||
static void thread_callback(int argc, void *argv);
|
static void thread_callback(int argc, void *argv);
|
||||||
|
|
||||||
static void SetupKernelSyscall(unsigned int addr);
|
static void SetupKernelSyscall(unsigned int addr);
|
||||||
|
static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len);
|
||||||
|
|
||||||
/* assembly functions */
|
/* assembly functions */
|
||||||
|
extern void SC_0x25_KernelCopyData(void* addr, void* src, unsigned int len);
|
||||||
extern void Syscall_0x36(void);
|
extern void Syscall_0x36(void);
|
||||||
extern void KernelPatches(void);
|
extern void KernelPatches(void);
|
||||||
|
|
||||||
@ -101,38 +103,39 @@ void __main(void)
|
|||||||
if (private_data.OSEffectiveToPhysical((void *)0xa0000000) != (void *)0x10000000)
|
if (private_data.OSEffectiveToPhysical((void *)0xa0000000) != (void *)0x10000000)
|
||||||
{
|
{
|
||||||
run_kexploit(&private_data);
|
run_kexploit(&private_data);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Get functions to send restart signal */
|
||||||
|
int(*IM_Open)();
|
||||||
|
int(*IM_Close)(int fd);
|
||||||
|
int(*IM_SetDeviceState)(int fd, void *mem, int state, int a, int b);
|
||||||
|
void*(*OSAllocFromSystem)(unsigned int size, int align);
|
||||||
|
void(*OSFreeToSystem)(void *ptr);
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "IM_Open", &IM_Open);
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "IM_Close", &IM_Close);
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "IM_SetDeviceState", &IM_SetDeviceState);
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem);
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem);
|
||||||
|
|
||||||
/* Get functions to send restart signal */
|
/* Send restart signal to get rid of uneeded threads */
|
||||||
int(*IM_Open)();
|
/* Cause the other browser threads to exit */
|
||||||
int(*IM_Close)(int fd);
|
int fd = IM_Open();
|
||||||
int(*IM_SetDeviceState)(int fd, void *mem, int state, int a, int b);
|
void *mem = OSAllocFromSystem(0x100, 64);
|
||||||
void*(*OSAllocFromSystem)(unsigned int size, int align);
|
if(!mem)
|
||||||
void(*OSFreeToSystem)(void *ptr);
|
ExitFailure(&private_data, "Not enough memory. Exit and re-enter browser.");
|
||||||
OSDynLoad_FindExport(coreinit_handle, 0, "IM_Open", &IM_Open);
|
|
||||||
OSDynLoad_FindExport(coreinit_handle, 0, "IM_Close", &IM_Close);
|
|
||||||
OSDynLoad_FindExport(coreinit_handle, 0, "IM_SetDeviceState", &IM_SetDeviceState);
|
|
||||||
OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem);
|
|
||||||
OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem);
|
|
||||||
|
|
||||||
/* Send restart signal to get rid of uneeded threads */
|
private_data.memset(mem, 0, 0x100);
|
||||||
/* Cause the other browser threads to exit */
|
|
||||||
int fd = IM_Open();
|
|
||||||
void *mem = OSAllocFromSystem(0x100, 64);
|
|
||||||
if(!mem)
|
|
||||||
ExitFailure(&private_data, "Not enough memory. Exit and re-enter browser.");
|
|
||||||
|
|
||||||
private_data.memset(mem, 0, 0x100);
|
/* Sets wanted flag */
|
||||||
|
IM_SetDeviceState(fd, mem, 3, 0, 0);
|
||||||
|
IM_Close(fd);
|
||||||
|
OSFreeToSystem(mem);
|
||||||
|
|
||||||
/* Sets wanted flag */
|
/* Waits for thread exits */
|
||||||
IM_SetDeviceState(fd, mem, 3, 0, 0);
|
unsigned int t1 = 0x1FFFFFFF;
|
||||||
IM_Close(fd);
|
while(t1--) ;
|
||||||
OSFreeToSystem(mem);
|
}
|
||||||
|
|
||||||
/* Waits for thread exits */
|
|
||||||
unsigned int t1 = 0x1FFFFFFF;
|
|
||||||
while(t1--) ;
|
|
||||||
|
|
||||||
/* Prepare for thread startups */
|
/* Prepare for thread startups */
|
||||||
int (*OSCreateThread)(void *thread, void *entry, int argc, void *args, unsigned int stack, unsigned int stack_size, int priority, unsigned short attr);
|
int (*OSCreateThread)(void *thread, void *entry, int argc, void *args, unsigned int stack, unsigned int stack_size, int priority, unsigned short attr);
|
||||||
@ -177,6 +180,9 @@ void __main(void)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* setup kernel copy data syscall */
|
||||||
|
kern_write((void*)(KERN_SYSCALL_TBL_5 + (0x25 * 4)), (unsigned int)KernelCopyData);
|
||||||
|
|
||||||
/* Install our code now */
|
/* Install our code now */
|
||||||
InstallMain(&private_data);
|
InstallMain(&private_data);
|
||||||
|
|
||||||
@ -272,6 +278,43 @@ static void SetupKernelSyscall(unsigned int address)
|
|||||||
kern_write((void*)(KERN_SYSCALL_TBL_4 + (0x35 * 4)), KERN_CODE_WRITE);
|
kern_write((void*)(KERN_SYSCALL_TBL_4 + (0x35 * 4)), KERN_CODE_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Setup a DBAT access for our 0xC0800000 area and our 0xBC000000 area which hold our variables like GAME_LAUNCHED and our BSS/rodata section
|
||||||
|
*/
|
||||||
|
register int dbatu0, dbatl0;
|
||||||
|
// save the original DBAT value
|
||||||
|
asm volatile("mfdbatu %0, 0" : "=r" (dbatu0));
|
||||||
|
asm volatile("mfdbatl %0, 0" : "=r" (dbatl0));
|
||||||
|
asm volatile("mtdbatu 0, %0" : : "r" (0xC0001FFF));
|
||||||
|
asm volatile("mtdbatl 0, %0" : : "r" (0x30000012));
|
||||||
|
asm volatile("eieio; isync");
|
||||||
|
|
||||||
|
unsigned char *src_p = (unsigned char*)src;
|
||||||
|
unsigned char *dst_p = (unsigned char*)addr;
|
||||||
|
|
||||||
|
unsigned int i;
|
||||||
|
for(i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
dst_p[i] = src_p[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int flushAddr = addr & ~31;
|
||||||
|
|
||||||
|
while(flushAddr < (addr + len))
|
||||||
|
{
|
||||||
|
asm volatile("dcbf 0, %0; sync" : : "r"(flushAddr));
|
||||||
|
flushAddr += 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restore original DBAT value
|
||||||
|
*/
|
||||||
|
asm volatile("mtdbatu 0, %0" : : "r" (dbatu0));
|
||||||
|
asm volatile("mtdbatl 0, %0" : : "r" (dbatl0));
|
||||||
|
asm volatile("eieio; isync");
|
||||||
|
}
|
||||||
|
|
||||||
static void thread_callback(int argc, void *argv)
|
static void thread_callback(int argc, void *argv)
|
||||||
{
|
{
|
||||||
@ -347,9 +390,9 @@ static void InstallMain(private_data_t *private_data)
|
|||||||
/* Copy main .text to memory */
|
/* Copy main .text to memory */
|
||||||
if(section_offset > 0)
|
if(section_offset > 0)
|
||||||
{
|
{
|
||||||
private_data->memcpy((void*)(CODE_RW_BASE_OFFSET + main_text_addr), main_text, main_text_len);
|
SC_0x25_KernelCopyData((void*)(CODE_RW_BASE_OFFSET + main_text_addr), main_text, main_text_len);
|
||||||
private_data->DCFlushRange((void*)(CODE_RW_BASE_OFFSET + main_text_addr), main_text_len);
|
//private_data->DCFlushRange((void*)(CODE_RW_BASE_OFFSET + main_text_addr), main_text_len);
|
||||||
private_data->ICInvalidateRange((void*)(main_text_addr), main_text_len);
|
//private_data->ICInvalidateRange((void*)(main_text_addr), main_text_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the .rodata section
|
// get the .rodata section
|
||||||
@ -360,8 +403,8 @@ static void InstallMain(private_data_t *private_data)
|
|||||||
{
|
{
|
||||||
unsigned char *main_rodata = private_data->data_elf + section_offset;
|
unsigned char *main_rodata = private_data->data_elf + section_offset;
|
||||||
/* Copy main rodata to memory */
|
/* Copy main rodata to memory */
|
||||||
private_data->memcpy((void*)(DATA_RW_BASE_OFFSET + main_rodata_addr), main_rodata, main_rodata_len);
|
SC_0x25_KernelCopyData((void*)(DATA_RW_BASE_OFFSET + main_rodata_addr), main_rodata, main_rodata_len);
|
||||||
private_data->DCFlushRange((void*)(DATA_RW_BASE_OFFSET + main_rodata_addr), main_rodata_len);
|
//private_data->DCFlushRange((void*)(DATA_RW_BASE_OFFSET + main_rodata_addr), main_rodata_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the .data section
|
// get the .data section
|
||||||
@ -372,8 +415,8 @@ static void InstallMain(private_data_t *private_data)
|
|||||||
{
|
{
|
||||||
unsigned char *main_data = private_data->data_elf + section_offset;
|
unsigned char *main_data = private_data->data_elf + section_offset;
|
||||||
/* Copy main data to memory */
|
/* Copy main data to memory */
|
||||||
private_data->memcpy((void*)(DATA_RW_BASE_OFFSET + main_data_addr), main_data, main_data_len);
|
SC_0x25_KernelCopyData((void*)(DATA_RW_BASE_OFFSET + main_data_addr), main_data, main_data_len);
|
||||||
private_data->DCFlushRange((void*)(DATA_RW_BASE_OFFSET + main_data_addr), main_data_len);
|
//private_data->DCFlushRange((void*)(DATA_RW_BASE_OFFSET + main_data_addr), main_data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the .bss section
|
// get the .bss section
|
||||||
@ -382,9 +425,10 @@ static void InstallMain(private_data_t *private_data)
|
|||||||
section_offset = get_section(private_data, private_data->data_elf, ".bss", &main_bss_len, &main_bss_addr, 0);
|
section_offset = get_section(private_data, private_data->data_elf, ".bss", &main_bss_len, &main_bss_addr, 0);
|
||||||
if(section_offset > 0)
|
if(section_offset > 0)
|
||||||
{
|
{
|
||||||
|
unsigned char *main_bss = private_data->data_elf + section_offset;
|
||||||
/* Copy main data to memory */
|
/* Copy main data to memory */
|
||||||
private_data->memset((void*)(DATA_RW_BASE_OFFSET + main_bss_addr), 0, main_bss_len);
|
SC_0x25_KernelCopyData((void*)(DATA_RW_BASE_OFFSET + main_bss_addr), main_bss, main_bss_len);
|
||||||
private_data->DCFlushRange((void*)(DATA_RW_BASE_OFFSET + main_bss_addr), main_bss_len);
|
//private_data->DCFlushRange((void*)(DATA_RW_BASE_OFFSET + main_bss_addr), main_bss_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,26 +438,32 @@ static void InstallMain(private_data_t *private_data)
|
|||||||
/* ****************************************************************** */
|
/* ****************************************************************** */
|
||||||
static void InstallPatches(private_data_t *private_data)
|
static void InstallPatches(private_data_t *private_data)
|
||||||
{
|
{
|
||||||
OsSpecifics * osSpecificFunctions = OS_SPECIFICS;
|
OsSpecifics osSpecificFunctions;
|
||||||
private_data->memset(osSpecificFunctions, 0, sizeof(OsSpecifics));
|
private_data->memset(&osSpecificFunctions, 0, sizeof(OsSpecifics));
|
||||||
|
|
||||||
|
unsigned int bufferU32;
|
||||||
/* Pre-setup a few options to defined values */
|
/* Pre-setup a few options to defined values */
|
||||||
OS_FIRMWARE = VER;
|
bufferU32 = VER;
|
||||||
MAIN_ENTRY_ADDR = 0xDEADC0DE;
|
SC_0x25_KernelCopyData((void*)&OS_FIRMWARE, &bufferU32, sizeof(bufferU32));
|
||||||
ELF_DATA_ADDR = 0xDEADC0DE;
|
bufferU32 = 0xDEADC0DE;
|
||||||
ELF_DATA_SIZE = 0;
|
SC_0x25_KernelCopyData((void*)&MAIN_ENTRY_ADDR, &bufferU32, sizeof(bufferU32));
|
||||||
|
SC_0x25_KernelCopyData((void*)&ELF_DATA_ADDR, &bufferU32, sizeof(bufferU32));
|
||||||
|
bufferU32 = 0;
|
||||||
|
SC_0x25_KernelCopyData((void*)&ELF_DATA_SIZE, &bufferU32, sizeof(bufferU32));
|
||||||
|
|
||||||
unsigned int jump_main_hook = 0;
|
unsigned int jump_main_hook = 0;
|
||||||
osSpecificFunctions->addr_OSDynLoad_Acquire = (unsigned int)OSDynLoad_Acquire;
|
osSpecificFunctions.addr_OSDynLoad_Acquire = (unsigned int)OSDynLoad_Acquire;
|
||||||
osSpecificFunctions->addr_OSDynLoad_FindExport = (unsigned int)OSDynLoad_FindExport;
|
osSpecificFunctions.addr_OSDynLoad_FindExport = (unsigned int)OSDynLoad_FindExport;
|
||||||
|
|
||||||
osSpecificFunctions->addr_KernSyscallTbl1 = KERN_SYSCALL_TBL_1;
|
osSpecificFunctions.addr_KernSyscallTbl1 = KERN_SYSCALL_TBL_1;
|
||||||
osSpecificFunctions->addr_KernSyscallTbl2 = KERN_SYSCALL_TBL_2;
|
osSpecificFunctions.addr_KernSyscallTbl2 = KERN_SYSCALL_TBL_2;
|
||||||
osSpecificFunctions->addr_KernSyscallTbl3 = KERN_SYSCALL_TBL_3;
|
osSpecificFunctions.addr_KernSyscallTbl3 = KERN_SYSCALL_TBL_3;
|
||||||
osSpecificFunctions->addr_KernSyscallTbl4 = KERN_SYSCALL_TBL_4;
|
osSpecificFunctions.addr_KernSyscallTbl4 = KERN_SYSCALL_TBL_4;
|
||||||
osSpecificFunctions->addr_KernSyscallTbl5 = KERN_SYSCALL_TBL_5;
|
osSpecificFunctions.addr_KernSyscallTbl5 = KERN_SYSCALL_TBL_5;
|
||||||
//! pointer to main entry point of a title
|
//! pointer to main entry point of a title
|
||||||
osSpecificFunctions->addr_OSTitle_main_entry = ADDRESS_OSTitle_main_entry_ptr;
|
osSpecificFunctions.addr_OSTitle_main_entry = ADDRESS_OSTitle_main_entry_ptr;
|
||||||
|
|
||||||
|
SC_0x25_KernelCopyData((void*)OS_SPECIFICS, &osSpecificFunctions, sizeof(OsSpecifics));
|
||||||
|
|
||||||
//! at this point we dont need to check header and stuff as it is sure to be OK
|
//! at this point we dont need to check header and stuff as it is sure to be OK
|
||||||
Elf32_Ehdr *ehdr = (Elf32_Ehdr *) private_data->data_elf;
|
Elf32_Ehdr *ehdr = (Elf32_Ehdr *) private_data->data_elf;
|
||||||
@ -422,8 +472,9 @@ static void InstallPatches(private_data_t *private_data)
|
|||||||
//! Install our entry point hook
|
//! Install our entry point hook
|
||||||
unsigned int repl_addr = ADDRESS_main_entry_hook;
|
unsigned int repl_addr = ADDRESS_main_entry_hook;
|
||||||
unsigned int jump_addr = mainEntryPoint & 0x03fffffc;
|
unsigned int jump_addr = mainEntryPoint & 0x03fffffc;
|
||||||
*((volatile unsigned int *)(LIB_CODE_RW_BASE_OFFSET + repl_addr)) = 0x48000003 | jump_addr;
|
bufferU32 = 0x48000003 | jump_addr;
|
||||||
|
SC_0x25_KernelCopyData((void*)(LIB_CODE_RW_BASE_OFFSET + repl_addr), &bufferU32, sizeof(bufferU32));
|
||||||
// flush caches and invalidate instruction cache
|
// flush caches and invalidate instruction cache
|
||||||
private_data->DCFlushRange((void*)(LIB_CODE_RW_BASE_OFFSET + repl_addr), 4);
|
//private_data->DCFlushRange((void*)(LIB_CODE_RW_BASE_OFFSET + repl_addr), 4);
|
||||||
private_data->ICInvalidateRange((void*)(repl_addr), 4);
|
private_data->ICInvalidateRange((void*)(repl_addr), 4);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ typedef struct _private_data_t
|
|||||||
EXPORT_DECL(void, DCFlushRange, const void *addr, u32 length);
|
EXPORT_DECL(void, DCFlushRange, const void *addr, u32 length);
|
||||||
EXPORT_DECL(void, ICInvalidateRange, const void *addr, u32 length);
|
EXPORT_DECL(void, ICInvalidateRange, const void *addr, u32 length);
|
||||||
EXPORT_DECL(int, __os_snprintf, char* s, int n, const char * format, ...);
|
EXPORT_DECL(int, __os_snprintf, char* s, int n, const char * format, ...);
|
||||||
EXPORT_DECL(void, __Exit, void);
|
EXPORT_DECL(void, exit, void);
|
||||||
|
|
||||||
EXPORT_DECL(int, FSInit, void);
|
EXPORT_DECL(int, FSInit, void);
|
||||||
EXPORT_DECL(int, FSAddClientEx, void *pClient, int unk_zero_param, int errHandling);
|
EXPORT_DECL(int, FSAddClientEx, void *pClient, int unk_zero_param, int errHandling);
|
||||||
@ -36,7 +36,7 @@ typedef struct _private_data_t
|
|||||||
EXPORT_DECL(int, FSReadFile, void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling);
|
EXPORT_DECL(int, FSReadFile, void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling);
|
||||||
EXPORT_DECL(int, FSCloseFile, void *pClient, void *pCmd, int fd, int errHandling);
|
EXPORT_DECL(int, FSCloseFile, void *pClient, void *pCmd, int fd, int errHandling);
|
||||||
|
|
||||||
EXPORT_DECL(int, SYSRelaunchTitle, int argc, char* argv);
|
EXPORT_DECL(int, SYSRelaunchTitle, int argc, char** argv);
|
||||||
} private_data_t;
|
} private_data_t;
|
||||||
|
|
||||||
static int LoadFileToMem(private_data_t *private_data, const char *filepath, unsigned char **fileOut, unsigned int * sizeOut)
|
static int LoadFileToMem(private_data_t *private_data, const char *filepath, unsigned char **fileOut, unsigned int * sizeOut)
|
||||||
@ -216,7 +216,7 @@ static void loadFunctionPointers(private_data_t * private_data)
|
|||||||
OS_FIND_EXPORT(coreinit_handle, "DCFlushRange", private_data->DCFlushRange);
|
OS_FIND_EXPORT(coreinit_handle, "DCFlushRange", private_data->DCFlushRange);
|
||||||
OS_FIND_EXPORT(coreinit_handle, "ICInvalidateRange", private_data->ICInvalidateRange);
|
OS_FIND_EXPORT(coreinit_handle, "ICInvalidateRange", private_data->ICInvalidateRange);
|
||||||
OS_FIND_EXPORT(coreinit_handle, "__os_snprintf", private_data->__os_snprintf);
|
OS_FIND_EXPORT(coreinit_handle, "__os_snprintf", private_data->__os_snprintf);
|
||||||
OS_FIND_EXPORT(coreinit_handle, "_Exit", private_data->__Exit);
|
OS_FIND_EXPORT(coreinit_handle, "exit", private_data->exit);
|
||||||
|
|
||||||
OS_FIND_EXPORT(coreinit_handle, "FSInit", private_data->FSInit);
|
OS_FIND_EXPORT(coreinit_handle, "FSInit", private_data->FSInit);
|
||||||
OS_FIND_EXPORT(coreinit_handle, "FSAddClientEx", private_data->FSAddClientEx);
|
OS_FIND_EXPORT(coreinit_handle, "FSAddClientEx", private_data->FSAddClientEx);
|
||||||
@ -293,7 +293,7 @@ int _start(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
MAIN_ENTRY_ADDR = 0xDEADC0DE;
|
MAIN_ENTRY_ADDR = 0xDEADC0DE;
|
||||||
private_data.SYSRelaunchTitle(0, 0);
|
private_data.SYSRelaunchTitle(0, 0);
|
||||||
private_data.__Exit();
|
private_data.exit();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user