BOOL OSRunThread(OSThread *thread, ThreadEntryPoint entry, uint32_t argc, p32<void> argv) { BOOL result = false; OSLockScheduler(); if (OSIsThreadTerminated(thread)) { InitialiseThreadState(thread, entry, argc, argv); OSResumeThreadNoLock(thread, 1); OSRescheduleNoLock(); } OSUnlockScheduler(); return result; }
void _start() { asm( "lis %r1, 0x1ab5 ;" "ori %r1, %r1, 0xd138 ;" ); unsigned int coreinit_handle, gx2_handle; OSDynLoad_Acquire("coreinit", &coreinit_handle); OSDynLoad_Acquire("gx2", &gx2_handle); //OS Memory functions void*(*memset)(void * dest, unsigned int value, unsigned int bytes); void*(*OSAllocFromSystem)(unsigned int size, int align); void(*OSFreeToSystem)(void *ptr); //IM functions int(*IM_Open)(); int(*IM_Close)(int fd); int(*IM_SetDeviceState)(int fd, void *mem, int state, int a, int b); //OS Memory functions OSDynLoad_FindExport(coreinit_handle, 0, "memset", &memset); OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem); OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem); //IM functions 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); //Restart system to get lib access int fd = IM_Open(); void *mem = OSAllocFromSystem(0x100, 64); memset(mem, 0, 0x100); //set restart flag to force quit browser IM_SetDeviceState(fd, mem, 3, 0, 0); IM_Close(fd); OSFreeToSystem(mem); //wait a bit for browser end unsigned int t1 = 0x1FFFFFFF; while(t1--) ; /* Get the framebuffer of the TV or DRC */ void(*GX2SwapScanBuffers)(); OSDynLoad_FindExport(gx2_handle, 0, "GX2SwapScanBuffers", &GX2SwapScanBuffers); unsigned char *abuseFunc = (unsigned char*)GX2SwapScanBuffers; unsigned short f_hi = *(unsigned short*)(abuseFunc+0x12); unsigned short f_lo = *(unsigned short*)(abuseFunc+0x16); unsigned int gx2settingBase = (((f_lo & 0x8000) ? (f_hi-1) : f_hi) << 16) | f_lo; unsigned int args[2]; args[0] = *((unsigned int*)(gx2settingBase + 0x304)); args[1] = *((unsigned int*)(gx2settingBase + 0x304 + 0x20)); int(*OSGetCoreId)(); OSDynLoad_FindExport(coreinit_handle, 0, "OSGetCoreId", &OSGetCoreId); void(*OSTestThreadCancel)(); OSDynLoad_FindExport(coreinit_handle, 0, "OSTestThreadCancel", &OSTestThreadCancel); void(*GX2Shutdown)(); OSDynLoad_FindExport(gx2_handle, 0, "GX2Shutdown", &GX2Shutdown); int(*GX2GetMainCoreId)(); OSDynLoad_FindExport(gx2_handle, 0, "GX2GetMainCoreId", &GX2GetMainCoreId); /* Prepare for our own death */ void*(*OSGetCurrentThread)(); OSDynLoad_FindExport(coreinit_handle, 0, "OSGetCurrentThread", &OSGetCurrentThread); void *myBorkedThread = OSGetCurrentThread(); int (*OSSuspendThread)(void *thread); OSDynLoad_FindExport(coreinit_handle, 0, "OSSuspendThread", &OSSuspendThread); /* 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 (*OSResumeThread)(void *thread); int (*OSIsThreadTerminated)(void *thread); OSDynLoad_FindExport(coreinit_handle, 0, "OSCreateThread", &OSCreateThread); OSDynLoad_FindExport(coreinit_handle, 0, "OSResumeThread", &OSResumeThread); OSDynLoad_FindExport(coreinit_handle, 0, "OSIsThreadTerminated", &OSIsThreadTerminated); /* Allocate a stack for the thread */ unsigned int stack = (unsigned int) OSAllocFromSystem(0x1000, 0x10); stack += 0x1000; /* Create the thread */ void *thread = OSAllocFromSystem(OSTHREAD_SIZE, 8); if(OSGetCoreId() != GX2GetMainCoreId()) //needed for access without crashing { int ret = OSCreateThread(thread, GX2Shutdown, 0, (void*)0, stack, 0x1000, 0, 0x10 | (1<<GX2GetMainCoreId())); if (ret == 0) OSFatal("Failed to create thread"); /* Schedule it for execution */ OSResumeThread(thread); while(OSIsThreadTerminated(thread) == 0) ; } else //same core, easy GX2Shutdown(); //current thread is broken, switch to a working one in core 1 int ret = OSCreateThread(thread, myGXthread, 2, args, stack, 0x1000, 0, 0xA); if (ret == 0) OSFatal("Failed to create thread"); /* Schedule it for execution */ OSResumeThread(thread); /* SO UGLY but it works magically */ while(1) ; //would be better but again, crashes 5.3.2 //OSSuspendThread(myBorkedThread); //OSFatal("I am still not dead!"); }